string AIHints::constraintsNotFulfilled(AIAction * action, AIHint * hint, ManaCost * potentialMana) { std::stringstream out; if (!action) { if (hint->mCombatAttackTip.size()) { out << "to see if this can attack[" << hint->mCombatAttackTip << "]"; return out.str(); } if (hint->mSourceId && !findSource(hint->mSourceId)) { out << "needcardinplay[" << hint->mSourceId << "]"; return out.str(); } out << "needability[" << hint->mAction << "]"; return out.str(); } MTGAbility * a = action->ability; if (!a) return "not supported"; MTGCardInstance * card = action->click; if (!card) return "not supported"; //dummy test: would the ability work if we were sure to fulfill its mana requirements? if (!a->isReactingToClick(card, a->getCost())) { DebugTrace("This shouldn't happen, this AIAction doesn't seem like a good choice"); return "not supported"; } if (!a->isReactingToClick(card, potentialMana)) { //Not enough Mana, try to find which mana we should get in priority ManaCost * diff = potentialMana->Diff(a->getCost()); for (int i = 0; i < Constants::NB_Colors; i++) { if(diff->getCost(i) < 0) { out << "needmana[" << Constants::MTGColorChars[i] << "]"; if (Constants::MTGColorChars[i] == 'r') DebugTrace("Got it"); SAFE_DELETE(diff); return out.str(); } } //TODO, handle more cases where the cost cannot be paid return "not supported, can't afford cost for some reason"; } //No problem found, we believe this is a good action to perform return ""; }
//Finds a mtgAbility matching the Hint description, and returns a valid AIAction matching this mtgability RankingContainer AIHints::findActions(AIHint * hint) { RankingContainer ranking; vector<MTGAbility *> abilities = findAbilities(hint); for (size_t i = 0; i < abilities.size(); ++i) { MTGAbility * a = abilities[i]; for (int j = 0; j < mPlayer->game->inPlay->nb_cards; j++) { MTGCardInstance * card = mPlayer->game->inPlay->cards[j]; if (a->isReactingToClick(card, a->getCost())) { mPlayer->createAbilityTargets(a, card, ranking); //TODO make that function static? break; //For performance... ? } } } return ranking; }
int AIMomirPlayer::momir() { if (!game->hand->nb_cards) return 0; //nothing to discard :/ int result = 0; int opponentCreatures = getCreaturesInfo(opponent(), INFO_NBCREATURES); int myCreatures = getCreaturesInfo(this, INFO_NBCREATURES ); ManaCost * potentialMana = getPotentialMana(); int converted = potentialMana->getConvertedCost(); SAFE_DELETE(potentialMana); int efficiency = 100; int chance = 1 + (randomGenerator.random() % 100); if (converted == 5 && myCreatures > opponentCreatures && game->hand->nb_cards < 4) efficiency = 5; //Strategy: skip 5 drop if (converted == 7 && myCreatures > opponentCreatures && game->hand->nb_cards < 2) efficiency = 50; //Strategy: 7 drops have bad upkeep costs and the AI doesn't handle those right now... if (converted > 8) converted = 8; if (converted == 8) efficiency = 100 - (myCreatures - opponentCreatures); if (efficiency >= chance) { std::vector<int16_t> _cost; _cost.push_back(Constants::MTG_COLOR_ARTIFACT); _cost.push_back(converted); ManaCost * cost = NEW ManaCost(_cost); MTGAbility * ability = getMomirAbility(); MTGCardInstance * card = game->hand->cards[0]; if (ability->isReactingToClick(card, cost)) { payTheManaCost(cost); AIAction * a = NEW AIAction(this, ability, card); clickstream.push(a); result = 1; } delete cost; } return result; }