diff --git a/projects/mtg/include/AIPlayerBaka.h b/projects/mtg/include/AIPlayerBaka.h index 65816c015..e2275ce7b 100644 --- a/projects/mtg/include/AIPlayerBaka.h +++ b/projects/mtg/include/AIPlayerBaka.h @@ -107,7 +107,7 @@ class AIPlayerBaka: public AIPlayer{ virtual bool payTheManaCost(ManaCost * cost, MTGCardInstance * card = NULL,vector gotPayment = vector()); virtual int getCreaturesInfo(Player * player, int neededInfo = INFO_NBCREATURES , int untapMode = 0, int canAttack = 0); virtual ManaCost * getPotentialMana(MTGCardInstance * card = NULL); - virtual int selectAbility(); + virtual int selectAbility(MTGAbility * Specific = NULL); public: enum { diff --git a/projects/mtg/include/AllAbilities.h b/projects/mtg/include/AllAbilities.h index 259df7f82..60cb22ec0 100644 --- a/projects/mtg/include/AllAbilities.h +++ b/projects/mtg/include/AllAbilities.h @@ -6200,8 +6200,10 @@ class AADepleter: public ActivatedAbilityTP public: string nbcardsStr; bool toexile; + bool colorrepeat; + bool namerepeat; AADepleter(GameObserver* observer, int _id, MTGCardInstance * card, Targetable * _target,string nbcardsStr, ManaCost * _cost = NULL, - int who = TargetChooser::UNSET, bool toexile = false); + int who = TargetChooser::UNSET, bool toexile = false, bool colorrepeat = false, bool namerepeat = false); int resolve(); const string getMenuText(); AADepleter * clone() const; diff --git a/projects/mtg/include/WResourceManagerImpl.h b/projects/mtg/include/WResourceManagerImpl.h index b44da2728..c460be262 100644 --- a/projects/mtg/include/WResourceManagerImpl.h +++ b/projects/mtg/include/WResourceManagerImpl.h @@ -11,7 +11,7 @@ #include #if defined (PSP) -#define HUGE_CACHE_LIMIT 28000000 // Size of the cache for PSP (in bytes) - old value is 20mb increased to 28mb +#define HUGE_CACHE_LIMIT 20000000 // Size of the cache for PSP (in bytes) - old value is 20mb - reverted #else #define HUGE_CACHE_LIMIT 60000000 // Size of the cache for Windows and Linux (in bytes) - old value is 20mb increased to 60mb #endif diff --git a/projects/mtg/src/AIPlayerBaka.cpp b/projects/mtg/src/AIPlayerBaka.cpp index a4d437c08..1b2595510 100644 --- a/projects/mtg/src/AIPlayerBaka.cpp +++ b/projects/mtg/src/AIPlayerBaka.cpp @@ -62,8 +62,9 @@ int OrderedAIAction::getEfficiency(AADamager * aad) // I can't remember as I type this in which condition we use one or the other for this function, if you find out please replace this comment int OrderedAIAction::getEfficiency() { - if (efficiency > -1) - return efficiency; + //commented out the below becuase I noticed it prevented ai from updating the given abilities with new eff %. + //if (efficiency > -1) + // return efficiency; if (!ability) return 0; GameObserver * g = owner->getObserver(); @@ -335,6 +336,16 @@ int OrderedAIAction::getEfficiency() } case MTGAbility::MANA_PRODUCER://only way to hit this condition is nested manaabilities, ai skips manaproducers by defualt when finding an ability to use. { + AManaProducer * manamaker = dynamic_cast(a); + GenericActivatedAbility * GAA = dynamic_cast(ability); + AForeach * forMana = dynamic_cast(GAA->ability); + if (manamaker && forMana) + { + int outPut = forMana->checkActivation(); + if (ability->getCost() && outPut > int(ability->getCost()->getConvertedCost() +1) && currentPhase == MTG_PHASE_FIRSTMAIN && ability->source->controller()->game->hand->nb_cards > 1) + efficiency = 90;//might be a bit random, but better than never using them. + } + else efficiency = 0; break; } @@ -635,6 +646,10 @@ int OrderedAIAction::getEfficiency() { efficiency += 55; } + else if (dynamic_cast(a)) + { + efficiency += 55; + } SAFE_DELETE(transAbility); return efficiency; } @@ -1354,7 +1369,7 @@ int AIPlayerBaka::selectHintAbility() return 0; } -int AIPlayerBaka::selectAbility() +int AIPlayerBaka::selectAbility(MTGAbility * Specific) { if(observer->mExtraPayment && observer->mExtraPayment->source && observer->mExtraPayment->source->controller() == this) { @@ -1395,12 +1410,14 @@ int AIPlayerBaka::selectAbility() for (size_t i = 1; i < observer->mLayers->actionLayer()->mObjects.size(); i++) { //0 is not a mtgability...hackish MTGAbility * a = ((MTGAbility *) observer->mLayers->actionLayer()->mObjects[i]); + if (Specific && Specific != a) + continue; //Skip mana abilities for performance if (dynamic_cast (a)) continue; //Make sure we can use the ability for (int j = 0; j < game->inPlay->nb_cards; j++) - { + {//zeth fox: note to self, this is where I can teach it suspend and other cost types. MTGCardInstance * card = game->inPlay->cards[j]; if(a->getCost() && !a->isReactingToClick(card, totalPotentialMana))//for performance reason only look for specific mana if the payment couldnt be made with potential. { @@ -1429,7 +1446,32 @@ int AIPlayerBaka::selectAbility() ManaCost * pMana = getPotentialMana(card); pMana->add(this->getManaPool()); if (a->isReactingToClick(card, pMana)) + { createAbilityTargets(a, card, ranking); + if (Specific) + { + if (!Specific->getCost()) + { + //attackcost, blockcost + if (a->aType == MTGAbility::ATTACK_COST) + { + ManaCost * specificCost = NEW ManaCost(ManaCost::parseManaCost("{0}", NULL, NULL)); + specificCost->add(0, card->attackCostBackup); + abilityPayment = canPayMana(card, specificCost); + SAFE_DELETE(specificCost); + } + else if (a->aType == MTGAbility::BLOCK_COST) + { + ManaCost * specificCost = NEW ManaCost(ManaCost::parseManaCost("{0}", NULL, NULL)); + specificCost->add(0, card->blockCostBackup); + abilityPayment = canPayMana(card, specificCost); + SAFE_DELETE(specificCost); + } + } + delete (pMana); + break; + } + } delete (pMana); } } @@ -1443,6 +1485,8 @@ int AIPlayerBaka::selectAbility() if (!forceBestAbilityUse) chance = 1 + randomGenerator.random() % 100; int actionScore = action.getEfficiency(); + if (Specific) + actionScore = 95; if(action.ability->getCost() && action.ability->getCost()->hasX() && this->game->hand->cards.size()) actionScore = actionScore/int(this->game->hand->cards.size());//reduce chance for "x" abilities if cards are in hand. if (actionScore >= chance) @@ -1454,6 +1498,35 @@ int AIPlayerBaka::selectAbility() DebugTrace(" Ai knows exactly what mana to use for this ability."); } DebugTrace("AIPlayer:Using Activated ability"); + if (Specific) + { + if (!Specific->getCost()) + { + //attackcost, blockcost + if (action.ability->aType == MTGAbility::ATTACK_COST) + { + ManaCost * specificCost = NEW ManaCost(ManaCost::parseManaCost("{0}", NULL, NULL)); + specificCost->add(0, action.click->attackCostBackup); + if (payTheManaCost(specificCost, action.click, abilityPayment)) + clickstream.push(NEW AIAction(action)); + SAFE_DELETE(specificCost); + } + else if (action.ability->aType == MTGAbility::BLOCK_COST) + { + ManaCost * specificCost = NEW ManaCost(ManaCost::parseManaCost("{0}", NULL, NULL)); + specificCost->add(0, action.click->blockCostBackup); + if (payTheManaCost(specificCost, action.click, abilityPayment)) + clickstream.push(NEW AIAction(action)); + SAFE_DELETE(specificCost); + } + } + else + { + if (payTheManaCost(action.ability->getCost(), action.click, abilityPayment)) + clickstream.push(NEW AIAction(action)); + } + } + else if (payTheManaCost(action.ability->getCost(), action.click,abilityPayment)) clickstream.push(NEW AIAction(action)); } @@ -2609,8 +2682,19 @@ int AIPlayerBaka::chooseAttackers() MTGCardInstance * card = NULL; while ((card = cd.nextmatch(game->inPlay, card))) { - if(hints && hints->HintSaysAlwaysAttack(observer,card)) - observer->cardClick(card, MTGAbility::MTG_ATTACK_RULE); + if (hints && hints->HintSaysAlwaysAttack(observer, card)) + { + if (!card->isAttacker()) + { + if (card->attackCost) + { + MTGAbility * a = observer->mLayers->actionLayer()->getAbility(MTGAbility::ATTACK_COST); + selectAbility(a); + observer->cardClick(card, MTGAbility::ATTACK_COST); + } + } + observer->cardClick(card, MTGAbility::MTG_ATTACK_RULE); + } } if (attack) @@ -2623,8 +2707,16 @@ int AIPlayerBaka::chooseAttackers() { if(hints && hints->HintSaysDontAttack(observer,card)) continue; - if(!card->isAttacker()) + if (!card->isAttacker()) + { + if (card->attackCost) + { + MTGAbility * a = observer->mLayers->actionLayer()->getAbility(MTGAbility::ATTACK_COST); + selectAbility(a); + observer->cardClick(card, MTGAbility::ATTACK_COST); + } observer->cardClick(card, MTGAbility::MTG_ATTACK_RULE); + } } } return 1; @@ -2701,6 +2793,12 @@ int AIPlayerBaka::chooseBlockers() } else { + if (card->blockCost) + { + MTGAbility * a = observer->mLayers->actionLayer()->getAbility(MTGAbility::BLOCK_COST); + selectAbility(a); + observer->cardClick(card, MTGAbility::BLOCK_COST); + } observer->cardClick(card, MTGAbility::MTG_BLOCK_RULE); } } @@ -2731,6 +2829,11 @@ int AIPlayerBaka::chooseBlockers() continue; if (!card->defenser) { + if (card->blockCost) + { + MTGAbility * a = observer->mLayers->actionLayer()->getAbility(MTGAbility::BLOCK_COST); + selectAbility(a); + } observer->cardClick(card, MTGAbility::MTG_BLOCK_RULE); int set = 0; while (!set) @@ -2745,6 +2848,11 @@ int AIPlayerBaka::chooseBlockers() if (opponentsToughness[attacker] <= 0 || (card->toughness <= attacker->power && opponentForce * 2 < life && !canFirstStrikeKill(card, attacker)) || attacker->nbOpponents() > 1) { + if (card->blockCost) + { + MTGAbility * a = observer->mLayers->actionLayer()->getAbility(MTGAbility::BLOCK_COST); + selectAbility(a); + } observer->cardClick(card, MTGAbility::MTG_BLOCK_RULE); } else diff --git a/projects/mtg/src/AllAbilities.cpp b/projects/mtg/src/AllAbilities.cpp index e5ced563c..4cf600791 100644 --- a/projects/mtg/src/AllAbilities.cpp +++ b/projects/mtg/src/AllAbilities.cpp @@ -1099,8 +1099,8 @@ AADamager * AADamager::clone() const //AADepleter -AADepleter::AADepleter(GameObserver* observer, int _id, MTGCardInstance * card, Targetable * _target,string nbcardsStr, ManaCost * _cost, int who, bool toexile) : - ActivatedAbilityTP(observer, _id, card, _target, _cost, who),nbcardsStr(nbcardsStr),toexile(toexile) +AADepleter::AADepleter(GameObserver* observer, int _id, MTGCardInstance * card, Targetable * _target,string nbcardsStr, ManaCost * _cost, int who, bool toexile, bool colorrepeat, bool namerepeat) : + ActivatedAbilityTP(observer, _id, card, _target, _cost, who),nbcardsStr(nbcardsStr),toexile(toexile), colorrepeat(colorrepeat), namerepeat(namerepeat) { } int AADepleter::resolve() @@ -1110,16 +1110,124 @@ AADepleter::AADepleter(GameObserver* observer, int _id, MTGCardInstance * card, { WParsedInt numCards(nbcardsStr, NULL, source); MTGLibrary * library = player->game->library; - for (int i = 0; i < numCards.getValue(); i++) + if (colorrepeat && library->nb_cards) { - if (library->nb_cards) + bool repeating = false; + do { - if(toexile) - player->game->putInZone(library->cards[library->nb_cards - 1], library, player->game->exile); - else - player->game->putInZone(library->cards[library->nb_cards - 1], library, player->game->graveyard); + repeating = false; + vectorfound; + for (int i = 0; i < numCards.getValue(); i++) + { + if (library->nb_cards) + { + if(library->nb_cards > i) + found.push_back(library->cards[(library->nb_cards - 1) - i]); + } + } + + for (vector::iterator it = found.begin(); it != found.end(); it++) + { + MTGCardInstance * cardFirst = *it; + if (cardFirst->isLand()) + continue; + for (int i = Constants::MTG_COLOR_GREEN; i <= Constants::MTG_COLOR_WHITE; ++i) + { + if (cardFirst->hasColor(i)) + { + for (vector::iterator secondit = found.begin(); secondit != found.end(); secondit++) + { + MTGCardInstance * cardSecond = *secondit; + if (cardSecond->isLand()) + continue; + if (cardSecond->hasColor(i) && cardFirst != cardSecond) + { + repeating = true; + } + } + } + } + } + + do + { + if (found.size()) + { + MTGCardInstance * toMove = found.back(); + if (toMove) + { + if (toexile) + player->game->putInZone(toMove, library, player->game->exile); + else + player->game->putInZone(toMove, library, player->game->graveyard); + found.pop_back(); + } + } + } while (found.size()); + + } while (repeating); + } + else if (namerepeat && library->nb_cards) + { + bool repeating = false; + do + { + repeating = false; + vectorfound; + for (int i = 0; i < numCards.getValue(); i++) + { + if (library->nb_cards) + { + if (library->nb_cards > i) + found.push_back(library->cards[(library->nb_cards - 1) - i]); + } + } + + for (vector::iterator it = found.begin(); it != found.end(); it++) + { + MTGCardInstance * cardFirst = *it; + for (vector::iterator secondit = found.begin(); secondit != found.end(); secondit++) + { + MTGCardInstance * cardSecond = *secondit; + if (cardSecond->name == cardFirst->name && cardFirst != cardSecond) + { + repeating = true; + } + } + + } + + do + { + if (found.size()) + { + MTGCardInstance * toMove = found.back(); + if (toMove) + { + if (toexile) + player->game->putInZone(toMove, library, player->game->exile); + else + player->game->putInZone(toMove, library, player->game->graveyard); + found.pop_back(); + } + } + } while (found.size()); + } while (repeating); + } + else + { + for (int i = 0; i < numCards.getValue(); i++) + { + if (library->nb_cards) + { + if (toexile) + player->game->putInZone(library->cards[library->nb_cards - 1], library, player->game->exile); + else + player->game->putInZone(library->cards[library->nb_cards - 1], library, player->game->graveyard); + } } } + } return 1; } diff --git a/projects/mtg/src/GuiPhaseBar.cpp b/projects/mtg/src/GuiPhaseBar.cpp index 9f879ecbb..c96fc78ab 100644 --- a/projects/mtg/src/GuiPhaseBar.cpp +++ b/projects/mtg/src/GuiPhaseBar.cpp @@ -151,10 +151,11 @@ void GuiPhaseBar::Render() sprintf(buf, _("(%s%s) %s").c_str(), currentP.c_str(), interrupt.c_str(),phaseNameToTranslate.c_str()); if(phaseinfo.get()) { - phaseinfo->SetHotSpot(phaseinfo->mWidth-2.f,0); - //phaseinfo->mWidth = font->GetStringWidth(buf)+12.f; + + phaseinfo->mWidth = font->GetStringWidth(buf)+12.f; + phaseinfo->SetHotSpot(phaseinfo->mWidth -4, 0); //phaseinfo->mHeight = font->GetHeight()+5.f; - JRenderer::GetInstance()->RenderQuad(phaseinfo.get(),SCREEN_WIDTH_F,0,0,SCREEN_WIDTH_F / phaseinfo->mWidth, SCREEN_HEIGHT_F / phaseinfo->mHeight); + JRenderer::GetInstance()->RenderQuad(phaseinfo.get(),SCREEN_WIDTH_F,0,0,2.2f, SCREEN_HEIGHT_F / phaseinfo->mHeight); } font->DrawString(buf, SCREEN_WIDTH - 5, 2, JGETEXT_RIGHT); } diff --git a/projects/mtg/src/MTGAbility.cpp b/projects/mtg/src/MTGAbility.cpp index 005b028c6..ea7def80b 100644 --- a/projects/mtg/src/MTGAbility.cpp +++ b/projects/mtg/src/MTGAbility.cpp @@ -2820,8 +2820,14 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG vector splitDeplete = parseBetween(s, "deplete:", " ", false); if (splitDeplete.size()) { + bool namerepeat = false; + bool colorrepeat = false; + if (splitDeplete[0].find("color") != string::npos) + colorrepeat = true; + if (splitDeplete[0].find("name") != string::npos) + namerepeat = true; Targetable * t = spell ? spell->getNextTarget() : NULL; - MTGAbility * a = NEW AADepleter(observer, id, card, t , splitDeplete[1], NULL, who, false); + MTGAbility * a = NEW AADepleter(observer, id, card, t , splitDeplete[1], NULL, who, false, colorrepeat, namerepeat); a->oneShot = 1; return a; } @@ -2830,8 +2836,14 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG vector splitIngest = parseBetween(s, "ingest:", " ", false); if (splitIngest.size()) { + bool namerepeat = false; + bool colorrepeat = false; + if (splitIngest[0].find("coloringest") != string::npos) + colorrepeat = true; + if (splitIngest[0].find("nameingest") != string::npos) + namerepeat = true; Targetable * t = spell ? spell->getNextTarget() : NULL; - MTGAbility * a = NEW AADepleter(observer, id, card, t , splitIngest[1], NULL, who, true); + MTGAbility * a = NEW AADepleter(observer, id, card, t , splitIngest[1], NULL, who, true, colorrepeat, namerepeat); a->oneShot = 1; return a; } diff --git a/projects/mtg/src/MTGRules.cpp b/projects/mtg/src/MTGRules.cpp index 2cab2b17f..995fb30bb 100644 --- a/projects/mtg/src/MTGRules.cpp +++ b/projects/mtg/src/MTGRules.cpp @@ -1553,7 +1553,7 @@ MTGAttackCostRule::MTGAttackCostRule(GameObserver* observer, int _id) : scost = "Pay to attack"; } -int MTGAttackCostRule::isReactingToClick(MTGCardInstance * card, ManaCost *) +int MTGAttackCostRule::isReactingToClick(MTGCardInstance * card, ManaCost * aiCheck) { if (currentPhase == MTG_PHASE_COMBATATTACKERS && card->controller() == game->currentPlayer && card->controller() == game->currentlyActing())//on my turn and when I am the acting player. @@ -1571,8 +1571,12 @@ int MTGAttackCostRule::isReactingToClick(MTGCardInstance * card, ManaCost *) attackcost->extraCosts->costs[i]->setSource(card); } scost = attackcost->getConvertedCost(); - if (playerMana->canAfford(attackcost)) + if ((aiCheck && aiCheck->canAfford(attackcost)) || playerMana->canAfford(attackcost)) + { + SAFE_DELETE(attackcost); return 1; + } + SAFE_DELETE(attackcost); } return 0; } @@ -1588,6 +1592,7 @@ int MTGAttackCostRule::reactToClick(MTGCardInstance * card) playerMana->pay(attackcost);//I think you can't pay partial cost to attack cost so you pay full (508.1i) card->attackCost = 0; card->attackPlaneswalkerCost = 0; + SAFE_DELETE(attackcost); return 1; /* 508.1g: If any of the chosen creatures require paying costs to attack, the active player determines the total cost to attack. @@ -1622,7 +1627,7 @@ MTGBlockCostRule::MTGBlockCostRule(GameObserver* observer, int _id) : aType = MTGAbility::BLOCK_COST; scost = "Pay to block"; } -int MTGBlockCostRule::isReactingToClick(MTGCardInstance * card, ManaCost *) +int MTGBlockCostRule::isReactingToClick(MTGCardInstance * card, ManaCost * aiCheck) { if (currentPhase == MTG_PHASE_COMBATBLOCKERS && !game->isInterrupting && card->controller() != game->currentPlayer @@ -1642,8 +1647,12 @@ int MTGBlockCostRule::isReactingToClick(MTGCardInstance * card, ManaCost *) blockcost->extraCosts->costs[i]->setSource(card); } scost = blockcost->getConvertedCost(); - if (playerMana->canAfford(blockcost)) + if ((aiCheck && aiCheck->canAfford(blockcost)) || playerMana->canAfford(blockcost)) + { + SAFE_DELETE(blockcost); return 1; + } + SAFE_DELETE(blockcost); } return 0; } @@ -1658,6 +1667,7 @@ int MTGBlockCostRule::reactToClick(MTGCardInstance * card) ManaCost * playerMana = player->getManaPool(); playerMana->pay(blockcost);//I think you can't pay partial cost to block cost so you pay full (509.1f) card->blockCost = 0; + SAFE_DELETE(blockcost); return 1; /* 509.1d: If any of the chosen creatures require paying costs to block, the defending player determines the total cost to block.