#include "../include/config.h" #include "../include/OptionItem.h" #include "../include/PlayerData.h" #include "../include/Translate.h" #include "../include/PriceList.h" #include "../include/Subtypes.h" #include //WSyncable bool WSyncable::Hook(WSyncable* s){ if(hooked) return false; hooked = s; return true; } int WSyncable::getPos(){ if(hooked) return hooked->getPos()+currentPos; return currentPos; } bool WSyncable::next(){ if(hooked) return hooked->next(); ++currentPos; return true; } bool WSyncable::prev(){ if(hooked) return hooked->prev(); --currentPos; return true; } //WSrcImage JQuad * WSrcImage::getImage( int offset){ return resources.RetrieveTempQuad(filename); } WSrcImage::WSrcImage(string s){ filename = s; } //WSrcCards WSrcCards::WSrcCards(float delay){ mDelay = delay; mLastInput = 0; currentPos = 0; filtersRoot=NULL; } JQuad * WSrcCards::getImage( int offset){ #if defined WIN32 || defined LINUX //Loading delay only on PSP. #else if(mDelay && mLastInput < mDelay){ return resources.RetrieveCard(getCard(offset),RETRIEVE_EXISTING); } #endif return resources.RetrieveCard(getCard(offset)); } JQuad * WSrcCards::getThumb( int offset){ return resources.RetrieveCard(getCard(offset),RETRIEVE_THUMB); } WSrcCards::~WSrcCards(){ clearFilters(); cards.clear(); } void WSrcCards::bakeFilters(){ vector temp; setOffset(0); for(int t=0;tisMatch(c); } int WSrcCards::Size(bool all){ if(!all && filtersRoot) return (int) validated.size(); return (int) cards.size(); } MTGCard * WSrcCards::getCard(int offset, bool ignore){ int oldpos; int size = (int) cards.size(); MTGCard * c = NULL; if(!ignore && filtersRoot) size = (int) validated.size(); if(!size) return NULL; oldpos = currentPos; if(offset != 0) currentPos += offset; while(currentPos < 0) currentPos = size+currentPos; currentPos = currentPos % size; if(!ignore && filtersRoot) c = cards[validated[currentPos]]; else c = cards[currentPos]; currentPos = oldpos; return c; } int WSrcCards::loadMatches(MTGAllCards* ac){ map::iterator it; int count = 0; if(!ac) return count; for(it=ac->collection.begin();it!=ac->collection.end();it++){ if(it->second && (matchesFilters(it->second))){ cards.push_back(it->second); count++; } } validate(); updateCounts(); return count; } int WSrcCards::loadMatches(MTGDeck * deck){ map::iterator it; int count = 0; if(!deck) return count; for(it=deck->cards.begin();it!=deck->cards.end();it++){ MTGCard * c = deck->getCardById(it->first); if(c && (matchesFilters(c))){ cards.push_back(c); count++; } } validate(); updateCounts(); return count; } int WSrcCards::loadMatches(WSrcCards* src, bool all){ int count = 0; if(!src) return count; MTGCard * c = NULL; size_t t = 0; int oldp = src->getOffset(); src->setOffset(0); for(int t=0;tSize(all);t++){ c = src->getCard(t,all); if(matchesFilters(c)){ cards.push_back(c); count++; } } src->setOffset(oldp); validate(); updateCounts(); return count; } int WSrcCards::addRandomCards(MTGDeck * i, int howmany){ if(!cards.size() || (filtersRoot && !validated.size())) return howmany; for(int x=0;xadd(c); } else{ size_t pos = rand() % cards.size(); i->add(cards[pos]); } } return 0; } int WSrcCards::addToDeck(MTGDeck * i, int num){ int oldpos = getOffset(); int added = 0; int cycles = 0; if(!i){ if(num < 0) return 0; return num; } setOffset(0); if(num < 0){ //Add it all; MTGCard * c; for(;;){ c = getCard(); if(!c || !next()) break; i->add(c); } }else while(added < num){ MTGCard * c = getCard(); if(!next() || !c){ if(++cycles == WSrcCards::MAX_CYCLES){ //Abort the search, too many cycles. setOffset(oldpos); return num - added; } setOffset(0); continue; }else{ i->add(c); added++; } } setOffset(oldpos); return 0; } bool WSrcCards::next(){ int oldpos = currentPos; bool bMatch = true; int size = (int)cards.size(); if(filtersRoot) size = (int)validated.size(); if(currentPos+1 >= size) return false; currentPos++; return true; } bool WSrcCards::prev(){ int oldpos = currentPos; bool bMatch = true; if(currentPos == 0) return false; currentPos--; return true; } bool WSrcCards::setOffset(int pos){ if(pos < 0 || pos >= (int) cards.size()) return false; currentPos = pos; if(!matchesFilters(cards[currentPos])) return next(); return true; } void WSrcCards::Shuffle(){ vector a; MTGCard * temp; vector::iterator k; while(cards.size()){ k = cards.begin(); k += rand() % cards.size(); temp = *k; cards.erase(k); a.push_back(temp); } #if defined WIN32 || defined LINUX //PC performs a double shuffle for less streaking. while(a.size()){ k = a.begin(); k += rand() % a.size(); temp = *k; a.erase(k); cards.push_back(temp); } #else //PSP does a straight swap for speed. cards.swap(a); #endif validate(); } void WSrcCards::validate(){ validated.clear(); if(!filtersRoot) return; for(size_t t=0;tgetId() == mtgid){ currentPos = (int) t; return matchesFilters(cards[currentPos]); } } return false; } bool WSrcCards::isEmptySet(WCardFilter * f){ size_t max = cards.size(); if(validated.size()) max = validated.size(); if(!f) return (max > 0); for(size_t t=0;tisMatch(cards[validated[t]])) return false; }else if(f->isMatch(cards[t])) return false; } return true; } void WSrcCards::addFilter(WCardFilter * f) { if(filtersRoot == NULL) filtersRoot = f; else filtersRoot = NEW WCFilterAND(f,filtersRoot); validate(); updateCounts(); currentPos = 0; } float WSrcCards::filterFee(){ if(filtersRoot) return filtersRoot->filterFee(); return 0; }; void WSrcCards::clearFilters() { SAFE_DELETE(filtersRoot); validated.clear(); } WCardFilter* WSrcCards::unhookFilters(){ WCardFilter* temp = filtersRoot; filtersRoot = NULL; clearFilters(); return temp; } void WSrcCards::Sort(int method){ switch(method){ case WSrcCards::SORT_COLLECTOR: std::sort(cards.begin(),cards.end(),WCSortCollector()); break; case WSrcCards::SORT_RARITY: std::sort(cards.begin(),cards.end(),WCSortRarity()); break; case WSrcCards::SORT_ALPHA: default: std::sort(cards.begin(),cards.end(),WCSortAlpha()); break; } validate(); } //WSrcUnlockedCards WSrcUnlockedCards::WSrcUnlockedCards(float delay): WSrcCards(delay){ MTGAllCards * ac = GameApp::collection; map::iterator it; char * unlocked = NULL; unlocked = (char *)calloc(setlist.size(),sizeof(char)); //Figure out which sets are available. for (int i = 0; i < setlist.size(); i++){ unlocked[i] = options[Options::optionSet(i)].number; } for(it=ac->collection.begin();it!=ac->collection.end();it++){ if(it->second && unlocked[it->second->setId]) cards.push_back(it->second); } if(unlocked){ free(unlocked); unlocked = NULL; } if(cards.size()){ Shuffle(); currentPos = 0; } } //WSrcDeck int WSrcDeck::loadMatches(MTGDeck * deck){ map::iterator it; int count = 0; if(!deck) return count; for(it=deck->cards.begin();it!=deck->cards.end();it++){ MTGCard * c = deck->getCardById(it->first); if(c && matchesFilters(c)){ Add(c,it->second); count++; } } validate(); updateCounts(); return count; } void WSrcDeck::updateCounts(){ vector::iterator it; map::iterator ccount; clearCounts(); for(it=cards.begin();it!=cards.end();it++){ ccount = copies.find((*it)->getMTGId()); if(ccount == copies.end()) continue; addCount((*it),ccount->second); } } void WSrcDeck::clearCounts(){ counts[UNFILTERED_MIN_COPIES] = -1; counts[UNFILTERED_MAX_COPIES] = 0; for(int i=0;idata) return; if(matchesFilters(c)){ counts[FILTERED_COPIES]+=qty; counts[FILTERED_UNIQUE]++; } counts[UNFILTERED_COPIES] += qty; counts[UNFILTERED_UNIQUE]++; for(int i=Constants::MTG_COLOR_GREEN;i<=Constants::MTG_COLOR_WHITE;i++) if (c->data->hasColor(i)) counts[i]+= qty; if(counts[UNFILTERED_MIN_COPIES] < 0 || qty < counts[UNFILTERED_MIN_COPIES]) counts[UNFILTERED_MIN_COPIES] = qty; if(qty > counts[UNFILTERED_MAX_COPIES]) counts[UNFILTERED_MAX_COPIES] = qty; } int WSrcDeck::Add(MTGCard * c, int quantity){ if(!c) return 0; if(copies.find(c->getMTGId()) == copies.end()) cards.push_back(c); //FIXME Make sure these two stay synced. copies[c->getMTGId()] += quantity; addCount(c,quantity); validate(); return 1; } int WSrcDeck::Remove(MTGCard * c, int quantity, bool erase){ if(!c) return 0; map::iterator it = copies.find(c->getMTGId()); if(it == copies.end()) return 0; int amt = it->second; if(amt < quantity) return 0; amt -= quantity; it->second = amt; if(erase && amt == 0){ copies.erase(it); vector::iterator i = find(cards.begin(),cards.end(),c); if(i != cards.end()) cards.erase(i); } validate(); addCount(c,-quantity); return 1; } void WSrcDeck::Rebuild(MTGDeck * d){ d->removeAll(); map::iterator it; for ( it=copies.begin() ; it != copies.end(); it++ ){ for (int i = 0; i < it->second; i++){ d->add(it->first); } } } int WSrcDeck::count(MTGCard * c){ if(!c) return counts[UNFILTERED_COPIES]; if(copies.find(c->getMTGId()) == copies.end()) return 0; return copies[c->getMTGId()]; } int WSrcDeck::countByName(MTGCard * card, bool editions){ string name = card->data->getLCName(); int total = 0; vector::iterator it; for(it = cards.begin();it!=cards.end();it++){ if(*it && (*it)->data->getLCName() == name){ if(editions) total++; else{ map::iterator mi = copies.find((*it)->getMTGId()); if(mi != copies.end()) total += mi->second; } } } return total; } int WSrcDeck::getCount(int count){ if(count < 0 || count >=MAX_COUNTS) return counts[UNFILTERED_COPIES]; return counts[count]; } int WSrcDeck::totalPrice(){ int total = 0; PriceList * pricelist = NEW PriceList(RESPATH"/settings/prices.dat",GameApp::collection); map::iterator it; for ( it=copies.begin() ; it != copies.end(); it++ ){ int nb = it->second; if (nb) total += pricelist->getPrice(it->first); } SAFE_DELETE(pricelist); return total; } //Sorting methods: int WCSortRarity::rareToInt(char r){ switch(r){ default: case Constants::RARITY_T: return 0; case Constants::RARITY_L: return 1; case Constants::RARITY_C: return 2; case Constants::RARITY_U: return 3; case Constants::RARITY_R: return 4; case Constants::RARITY_M: return 5; case Constants::RARITY_S: return 6; } } bool WCSortRarity::operator()(const MTGCard*l, const MTGCard*r){ if(!l || !r || !l->data || !r->data) return false; return (rareToInt(l->getRarity()) < rareToInt(r->getRarity())); } bool WCSortAlpha::operator()(const MTGCard*l, const MTGCard*r){ if(!l || !r || !l->data || !r->data) return false; string ln = l->data->getLCName(); string rn = r->data->getLCName(); if(ln == rn) return l->getMTGId() < r->getMTGId(); return (ln < rn); } bool WCSortCollector::operator()(const MTGCard*l, const MTGCard*r){ if(!l || !r || !l->data || !r->data) return false; if(l->setId != r->setId) return (l->setId < r->setId); int lc, rc; lc = l->data->countColors(); rc = r->data->countColors(); if(lc == 0) lc = 999; if(rc == 0) rc = 999; int isW = (int)l->data->hasColor(Constants::MTG_COLOR_WHITE) - (int) r->data->hasColor(Constants::MTG_COLOR_WHITE); int isU = (int)l->data->hasColor(Constants::MTG_COLOR_BLUE) - (int) r->data->hasColor(Constants::MTG_COLOR_BLUE); int isB = (int)l->data->hasColor(Constants::MTG_COLOR_BLACK) - (int) r->data->hasColor(Constants::MTG_COLOR_BLACK); int isR = (int)l->data->hasColor(Constants::MTG_COLOR_RED) - (int) r->data->hasColor(Constants::MTG_COLOR_RED); int isG = (int)l->data->hasColor(Constants::MTG_COLOR_GREEN) - (int) r->data->hasColor(Constants::MTG_COLOR_GREEN); int isArt = (int)l->data->hasType(Subtypes::TYPE_ARTIFACT) - (int) r->data->hasType(Subtypes::TYPE_ARTIFACT); int isLand = (int)l->data->hasType(Subtypes::TYPE_LAND) - (int) r->data->hasType(Subtypes::TYPE_LAND); //Nested if hell. TODO: Farm these out to their own objects as a user-defined filter/sort system. if(!isLand){ int isBasic = (int)l->data->hasType("Basic") - (int) r->data->hasType("Basic"); if(!isBasic){ if(!isArt){ if(lc == rc){ if(!isG){ if(!isR){ if(!isB){ if(!isU){ if(!isW){ string ln = l->data->getLCName(); string rn = r->data->getLCName(); if(ln.substr(0,4) == "the ") ln = ln.substr(4); if(rn.substr(0,4) == "the ") rn = rn.substr(4); return (ln < rn); } return (isW < 0); } return (isU < 0); } return (isB < 0); } return (isR < 0); } return (isG < 0); } return (lc < rc); } return (isArt < 0); } else return(isBasic < 0); } return (isLand < 0); }