Set limited game mode, AI changes, primitives and _cards.dat corrections

New set limited ,where you get a deck two random sets.

Still playing with the AI values and hueristics.

Cards fixes. Masters Edition should be named ME1 and the Mythic Edition is MED, the cards multiverse ids are still the same so the decks and references should not change.
This commit is contained in:
Eduardo
2019-04-20 15:51:52 -05:00
parent 1c6b0bdfd5
commit 5db6b807ba
14 changed files with 231 additions and 1088 deletions
+21 -26
View File
@@ -50,11 +50,12 @@ int OrderedAIAction::getEfficiency(AADamager * aad)
if(p == target->controller())
return 0;
if (dTarget && aad && (aad->getDamage() >= dTarget->toughness))
if (dTarget && aad && (aad->getDamage() == dTarget->toughness))
return 100;
if (dTarget && dTarget->toughness)
return (10 * aad->getDamage()) / dTarget->toughness; // Don't waste damage spells
else if (dTarget && aad && (aad->getDamage() > dTarget->toughness))
return 10 * (10 - (aad->getDamage() - dTarget->toughness)); //less eff the more dmg above toughness
else
return 10;
return 0;
}
@@ -130,11 +131,7 @@ int OrderedAIAction::getEfficiency()
{
efficiency = 95;
}
//TODO If the card is the target of a damage spell
if (!coreAbilityCardTarget->regenerateTokens && (MTGCardInstance*)target == a->source)
{
efficiency = 95;
}
//TODO If the card is the target of a damage spell
break;
}
case MTGAbility::STANDARD_PREVENT:
@@ -285,6 +282,10 @@ int OrderedAIAction::getEfficiency()
coreAbilityCardTarget = a->source->target; //TODO use intermediate value?
target = a->source;
}
else //if(how to know cards like Basking Rootwalla that pump themselves)
{
target = a->source;
}
if (!target && !dynamic_cast<ALord*> (a))
break;
if(dynamic_cast<ALord*> (a) && !target)
@@ -296,9 +297,9 @@ int OrderedAIAction::getEfficiency()
int suggestion = af.abilityEfficiency(a, p, MODE_ABILITY);
//i do not set a starting eff. on this ability, this allows Ai to sometimes randomly do it as it normally does.
int currentPhase = g->getCurrentGamePhase();
if (suggestion == BAKA_EFFECT_GOOD && target->controller() == p)
if ((currentPhase == MTG_PHASE_COMBATBLOCKERS) || (currentPhase == MTG_PHASE_COMBATATTACKERS))
{
if ((currentPhase == MTG_PHASE_COMBATBLOCKERS) || (currentPhase == MTG_PHASE_COMBATATTACKERS))
if (suggestion == BAKA_EFFECT_GOOD && target->controller() == p)
{
if(coreAbilityCardTarget->defenser || coreAbilityCardTarget->blockers.size())
{
@@ -316,14 +317,10 @@ int OrderedAIAction::getEfficiency()
{
//this means im heading directly for the player, pump this creature as much as possible.
efficiency = 100;
if(coreAbilityCardTarget->power > 50)
if(coreAbilityCardTarget->power > 20) // to be realistic
efficiency -= coreAbilityCardTarget->power;//we don't need to go overboard. better to not put all your eggs in a single basket.
}
}
if (currentPhase == MTG_PHASE_FIRSTMAIN)
{
efficiency = 10;
}
}
if (suggestion == BAKA_EFFECT_BAD && target->controller() != p && target->toughness > 0)
{
@@ -672,7 +669,7 @@ int OrderedAIAction::getEfficiency()
{
AIPlayer * chk = (AIPlayer*)p;
if(may->ability && may->ability->getActionTc() && chk->chooseTarget(may->ability->getActionTc(),NULL,NULL,true))
efficiency = 80 + (owner->getRandomGenerator()->random() % 50);
efficiency = 50 + (owner->getRandomGenerator()->random() % 50);
}
if (p->game->hand->nb_cards == 0)
efficiency = (int) ((float) efficiency * 1.3); //increase chance of using ability if hand is empty
@@ -685,8 +682,11 @@ int OrderedAIAction::getEfficiency()
for(unsigned int i = 0; i < ec->costs.size();i++)
{
ExtraCost * tapper = dynamic_cast<TapCost*>(ec->costs[i]);
ExtraCost * sacrifice = dynamic_cast<SacrificeCost*>(ec->costs[i]);
if(tapper)
continue;
continue;
else if(sacrifice)
efficiency = efficiency / 3;
else
efficiency = efficiency / 2;
}
@@ -699,7 +699,7 @@ int OrderedAIAction::getEfficiency()
}
else if (dynamic_cast<MTGAlternativeCostRule *>(a))
{
efficiency += 65;
efficiency += 55;
}
else if (dynamic_cast<MTGSuspendRule *>(a))
{
@@ -707,15 +707,10 @@ int OrderedAIAction::getEfficiency()
}
if (ability->source)
{
if(ability->source->hasType(Subtypes::TYPE_PLANESWALKER))
efficiency += 40;
else if(ability->source->hasType(Subtypes::TYPE_LAND))
{ // probably a shockland, don't pay life if hand is empty
if (p->game->hand->nb_cards == 0 || p->life<=2)
// check that's not a manland(like Celestial Colonnade)
if(efficiency < 50)
efficiency = 0;
}
}
SAFE_DELETE(transAbility);
return efficiency;
+1 -1
View File
@@ -772,7 +772,7 @@ void GameStateDuel::Update(float dt)
= "ai_baka_music_random.mp3";
else if (mParent->gameType == GAME_TYPE_RANDOM3 || mParent->gameType == GAME_TYPE_RANDOM5) musictrack
= "ai_baka_music_random.mp3";
else if (mParent->gameType == GAME_TYPE_HORDE) musictrack
else if (mParent->gameType == GAME_TYPE_HORDE || mParent->gameType == GAME_TYPE_SET_LIMITED) musictrack
= "ai_baka_music_momir.mp3";
if (!MusicExist(musictrack))
musictrack = "ai_baka_music.mp3";
+2 -2
View File
@@ -4572,12 +4572,12 @@ int AbilityFactory::abilityEfficiency(MTGAbility * a, Player * p, int mode, Targ
if (AAMover * aam = dynamic_cast<AAMover *>(a))
{
MTGGameZone * z = aam->destinationZone(target);
if (tc && tc->targetsZone(p->game->library)||tc && tc->targetsZone(p->game->graveyard))
if (tc && tc->targetsZone(p->game->library) || tc && tc->targetsZone(p->game->graveyard) || tc && tc->targetsZone(p->game->hand))
{
if (z == p->game->hand || z == p->game->inPlay)
return BAKA_EFFECT_GOOD;
}
return BAKA_EFFECT_DONTKNOW; //TODO
return BAKA_EFFECT_BAD; //TODO
}
if (dynamic_cast<AACopier *> (a))
+4 -4
View File
@@ -1355,16 +1355,16 @@ int MTGCardInstance::DangerRanking()
}
// Even at 60(danger=3) the AI is hasty to play removal on a simple creature
// a vanilla 2 mana, 2/2 used to be eff = 60
if (result > 2)
danger += 1;
if (result > 4)
danger += 1;
if (result > 6)
danger += 1;
if (result > 8)
danger += 1;
if (result > 10)
danger += 1;
if (result > 12)
danger += 1;
if (result > 14)
danger += 1;
return danger;
}
+59 -30
View File
@@ -170,7 +170,7 @@ void Rules::addExtraRules(GameObserver* g)
difficultyRating = 0;
else if(g->mRules->gamemode == GAME_TYPE_RANDOM3 || g->mRules->gamemode == GAME_TYPE_RANDOM5)
difficultyRating = 0;
else if(g->mRules->gamemode == GAME_TYPE_HORDE)
else if(g->mRules->gamemode == GAME_TYPE_HORDE || g->mRules->gamemode == GAME_TYPE_SET_LIMITED)
difficultyRating = 0;
else if (g->mRules->gamemode == GAME_TYPE_STORY)
difficultyRating = 0;
@@ -311,6 +311,50 @@ Player * Rules::loadPlayerRandom(GameObserver* observer, int isAI, int mode)
return player;
}
Player * Rules::loadRandomSetLimited(GameObserver* observer, int isAI)
{
//Random sets
int setId[] = { observer->getRandomGenerator()->random() % setlist.size(), observer->getRandomGenerator()->random() % setlist.size() };
int nbSet = sizeof(setId)/sizeof(setId[0]);
int color1 = 1 + observer->getRandomGenerator()->random() % 5;
int color2 = 1 + observer->getRandomGenerator()->random() % 5;
int colors[] = { color1, color2 };
int nbcolors = 2;
string lands[] = { "", "forest", "island", "mountain", "swamp", "plains" };
MTGDeck * tempDeck = NEW MTGDeck(MTGCollection());
// Try to add basic lands from that set
tempDeck->addRandomCards(8, setId, nbSet, -1, lands[color1].c_str());
tempDeck->addRandomCards(8, setId, nbSet, -1, lands[color2].c_str());
tempDeck->addRandomCards(2, setId, nbSet, -1, "land");
// If lands < 18 add from any set
int missingLands = 18 - tempDeck->totalCards();
if (missingLands > 0)
{
tempDeck->addRandomCards(missingLands/2, 0, 0, -1, lands[color1].c_str());
tempDeck->addRandomCards(missingLands/2, 0, 0, -1, lands[color2].c_str());
}
// Lone artifact and creatures.
tempDeck->addRandomCards(1, setId, nbSet, -1, "artifact");
tempDeck->addRandomCards(12, setId, nbSet, -1, "creature", colors, nbcolors);
// Want the deck to be 40 cards, take any card from the set in the colors
int missingCards = 40 - tempDeck->totalCards();
if (missingCards > 0)
tempDeck->addRandomCards(missingCards, setId, nbSet, -1, "", colors, nbcolors);
string deckFile = "random";
string deckFileSmall = "random";
Player *player = NULL;
if (!isAI) // Human Player
player = NEW HumanPlayer(observer, deckFile, deckFileSmall, false, tempDeck);
else
player = NEW AIPlayerBaka(observer, deckFile, deckFileSmall, "", tempDeck);
return player;
}
Player * Rules::loadPlayerRandomThree(GameObserver* observer, int isAI)
{
int color1 = 1 + observer->getRandomGenerator()->random() % 5;
@@ -357,27 +401,10 @@ Player * Rules::loadPlayerRandomThree(GameObserver* observer, int isAI)
Player * Rules::loadPlayerRandomFive(GameObserver* observer, int isAI)
{
MTGDeck * tempDeck = NEW MTGDeck(MTGCollection());
tempDeck->addRandomCards(1, 0, 0, -1, "plains");
tempDeck->addRandomCards(1, 0, 0, -1, "island");
tempDeck->addRandomCards(1, 0, 0, -1, "swamp");
tempDeck->addRandomCards(1, 0, 0, -1, "mountain");
tempDeck->addRandomCards(1, 0, 0, -1, "forest");
tempDeck->addRandomCards(3, 0, 0, 'R', "plains");
tempDeck->addRandomCards(3, 0, 0, 'R', "island");
tempDeck->addRandomCards(3, 0, 0, 'R', "swamp");
tempDeck->addRandomCards(3, 0, 0, 'R', "mountain");
tempDeck->addRandomCards(3, 0, 0, 'R', "forest");
tempDeck->addRandomCards(4, 0, 0, -1, "land");
tempDeck->addRandomCards(1, 0, 0, 'U', "land");
tempDeck->addRandomCards(1, 0, 0, 'R', "land");
tempDeck->addRandomCards(18, 0, 0, -1, "creature");
tempDeck->addRandomCards(1, 0, 0, 'R', "creature");
tempDeck->addRandomCards(1, 0, 0, 'M', "creature");
tempDeck->addRandomCards(3, 0, 0, -1, "sorcery");
tempDeck->addRandomCards(3, 0, 0, -1, "enchantment");
tempDeck->addRandomCards(3, 0, 0, -1, "instant");
tempDeck->addRandomCards(4, 0, 0, -1, "artifact");
tempDeck->addRandomCards(1, 0, 0, -1, "planeswalker");
tempDeck->addRandomCards(20, 0, 0, -1, "land");
tempDeck->addRandomCards(20, 0, 0, -1, "creature");
tempDeck->addRandomCards(20, 0, 0, -1, "");
string deckFile = "random";
string deckFileSmall = "random";
@@ -399,14 +426,13 @@ Player * Rules::loadPlayerHorde(GameObserver* observer, int isAI)
string lands[] = { "land", "forest", "island", "mountain", "swamp", "plains" };
const char* const multicolorTribes[] = { "Ally", "Atog", "Eldrazi", "Elemental", "Human", "Knight",
"Myr", "Samurai", "Shaman", "Shapeshifter", "Sliver", "Soldier", "Spellshaper" };
const char* const whiteTribes[] = { "Angel","Cat", "Griffin", "Kithkin", "Knight", "Pegasus", "Soldier" };
const char* const blueTribes[] = { "Artificer", "Merfolk", "Drake", "Faerie", "Illusion", "Vedalken" };
const char* const blackTribes[] = { "Demon", "Faerie", "Horror", "Pirate", "Rat", "Shade", "Skeleton", "Vampire", "Zombie" };
const char* const redTribes[] = { "Barbarian", "Berserker","Cat", "Devil", "Goblin", "Minotaur", "Werewolf" };
const char* const greenTribes[] = { "Beast", "Cat", "Centaur", "Dinosaur", "Druid", "Elf", "Fungus",
"Saproling", "Spider", "Treefolk", "Werewolf" };
const char* const multicolorTribes[] = { "Ally", "Atog", "Eldrazi", "Elemental", "Golem", "Hound", "Human", "Knight",
"Myr", "Samurai", "Shaman", "Shapeshifter", "Sliver", "Soldier", "Spellshaper", "Spirit", "Warrior" };
const char* const whiteTribes[] = { "Angel", "Bird", "Cat", "cleric", "Griffin", "Kithkin", "Knight", "Soldier", "Spirit" };
const char* const blueTribes[] = { "Artificer", "Bird", "Drake", "Faerie", "Illusion", "Merfolk", "Spirit", "Vedalken", "Zombie" };
const char* const blackTribes[] = { "Cleric", "Demon", "Faerie", "Horror", "Pirate", "Rat", "Rogue", "Shade", "Skeleton", "Vampire", "Zombie" };
const char* const redTribes[] = { "Barbarian", "Berserker"," Cat", "Devil", "Goblin", "Minotaur", "Ogre", "Werewolf" };
const char* const greenTribes[] = { "Beast", "Cat", "Centaur", "Dinosaur", "Druid", "Elf", "Fungus", "Snake", "Spider", "Treefolk", "Werewolf" };
int multicolorTribesSize = sizeof(multicolorTribes)/sizeof(multicolorTribes[0]);
int whiteTribesSize = sizeof(whiteTribes)/sizeof(whiteTribes[0]);
@@ -482,6 +508,8 @@ Player * Rules::initPlayer(GameObserver *g, int playerId)
return loadPlayerRandomFive(g, isAI);
case GAME_TYPE_HORDE:
return loadPlayerHorde(g, isAI);
case GAME_TYPE_SET_LIMITED:
return loadRandomSetLimited(g, isAI);
default:
return NULL;
}
@@ -790,6 +818,7 @@ GameType Rules::strToGameMode(string s)
if (s.compare("random3") == 0) return GAME_TYPE_RANDOM3;
if (s.compare("random5") == 0) return GAME_TYPE_RANDOM5;
if (s.compare("horde") == 0) return GAME_TYPE_HORDE;
if (s.compare("set_limited") == 0) return GAME_TYPE_SET_LIMITED;
if (s.compare("story") == 0) return GAME_TYPE_STORY;
if (s.compare("stonehewer") == 0) return GAME_TYPE_STONEHEWER;
if (s.compare("hermit") == 0) return GAME_TYPE_HERMIT;