aicode and revised legendary rule

added aicode for cards that uses reveal. since reveal cancels for ai,
aicode is the alternative code. use basic code only.
aicode=activate dosomething...
aicode - use with caution, its very basic atm and you must test each
card that uses it as it can cause crash.
legendary rule moved to game state based effect so it will not conflict
with cards with copy effects and andability. the legendary check applies
only when  legendrule is found.
This commit is contained in:
Anthony Calosa
2017-01-24 16:10:35 +08:00
parent 94aefa6dba
commit 5c3a064746
10 changed files with 145 additions and 6 deletions
+15
View File
@@ -1484,6 +1484,7 @@ AALibraryBottom::AALibraryBottom(GameObserver* observer, int _id, MTGCardInstanc
ActivatedAbility(observer, _id, _source, _cost, 0)
{
target = _target;
andAbility = NULL;
}
int AALibraryBottom::resolve()
@@ -1503,6 +1504,20 @@ int AALibraryBottom::resolve()
newOrder.push_back(rearranged);
}
library->cards = newOrder;
if(andAbility)
{
MTGAbility * andAbilityClone = andAbility->clone();
andAbilityClone->target = _target;
if(andAbility->oneShot)
{
andAbilityClone->resolve();
SAFE_DELETE(andAbilityClone);
}
else
{
andAbilityClone->addToGame();
}
}
return 1;
}
return 0;
+11
View File
@@ -57,6 +57,7 @@ CardPrimitive::CardPrimitive(CardPrimitive * source)
setName(source->name);
setdoubleFaced(source->doubleFaced);
setAICustomCode(source->AICustomCode);
power = source->power;
toughness = source->toughness;
restrictions = source->restrictions ? source->restrictions->clone() : NULL;
@@ -341,6 +342,16 @@ const string& CardPrimitive::getdoubleFaced() const
return doubleFaced;
}
void CardPrimitive::setAICustomCode(const string& value)
{
std::transform(AICustomCode.begin(), AICustomCode.end(), AICustomCode.begin(), ::tolower);
AICustomCode = value;
}
const string& CardPrimitive::getAICustomCode() const
{
return AICustomCode;
}
void CardPrimitive::setName(const string& value)
{
+47 -1
View File
@@ -110,6 +110,7 @@ GameObserver::GameObserver(WResourceManager *output, JGE* input)
mLayers = NULL;
mTrash = new Trash();
mDeckManager = new DeckManager();
foundlegendrule = false;
}
GamePhase GameObserver::getCurrentGamePhase()
@@ -880,6 +881,7 @@ void GameObserver::gameStateBasedEffects()
if(card->life < 1 && !card->has(Constants::INDESTRUCTIBLE))
card->destroy();//manor gargoyle... recheck
}
checkLegendary(card); //legendary rule as state based effect
}
if(card->childrenCards.size())
@@ -935,7 +937,6 @@ void GameObserver::gameStateBasedEffects()
p->nomaxhandsize = true;
else
p->nomaxhandsize = false;
/////////////////////////////////////////////////
//handle end of turn effects while we're at it.//
/////////////////////////////////////////////////
@@ -1055,6 +1056,51 @@ void GameObserver::gameStateBasedEffects()
}
}
void GameObserver::checkLegendary(MTGCardInstance * card)
{
if(!foundlegendrule)
return;
if(card->has(Constants::NOLEGEND)||card->controller()->opponent()->inPlay()->hasAbility(Constants::NOLEGENDRULE)||card->controller()->inPlay()->hasAbility(Constants::NOLEGENDRULE))
return;
int destroy = 0;
vector<MTGCardInstance*>oldCards;
MTGGameZone * z = card->controller()->game->inPlay;
int nbcards = z->nb_cards-1;
for (int r = 0; r < nbcards; r++)
{
MTGCardInstance * comparison = z->cards[r];
if (comparison != card && comparison->hasType("legendary") && !(comparison->getName().compare(card->getName())))
{
oldCards.push_back(comparison);
destroy = 1;
}
}
if(destroy)
{
vector<MTGAbility*>selection;
MultiAbility * multi = NEW MultiAbility(this, this->mLayers->actionLayer()->getMaxId(), card, card, NULL);
for(unsigned int i = 0;i < oldCards.size();i++)
{
AAMover *a = NEW AAMover(this, this->mLayers->actionLayer()->getMaxId(), card, oldCards[i],"ownergraveyard","Keep New");
a->oneShot = true;
multi->Add(a);
}
multi->oneShot = 1;
MTGAbility * a1 = multi;
selection.push_back(a1);
AAMover *b = NEW AAMover(this, this->mLayers->actionLayer()->getMaxId(), card, card,"ownergraveyard","Keep Old");
b->oneShot = true;
MTGAbility * b1 = b;
selection.push_back(b1);
MTGAbility * menuChoice = NEW MenuAbility(this, this->mLayers->actionLayer()->getMaxId(), card, card,true,selection,card->controller(),"Legendary Rule");
menuChoice->addToGame();
}
return;
}
void GameObserver::enchantmentStatus()
{
for (int i = 0; i < 2; i++)
+23 -2
View File
@@ -1386,7 +1386,13 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
found = s.find("legendrule");
if(found != string::npos)
{
observer->addObserver(NEW MTGLegendRule(observer, -1));
//I replaced this rule since it broke cards with copy effects and with andability and other
//complex cards. So I moved it to gameobserver state based effects, if there are no more
//abilities that needs resolving then trigger this legend check... example bug:
//cast Phantasmal Image, then copy Vendilion Clique in play, after you choose target player
//there will be infinite menu for legendary rule that conflicts with Phantasmal andAbility
//observer->addObserver(NEW MTGLegendRule(observer, -1));
observer->foundlegendrule = true;
return NULL;
}
//this handles the planeswalker named legend rule which is dramatically different from above.
@@ -2733,6 +2739,13 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
{
MTGAbility * a = NEW AALibraryBottom(observer, id, card, target);
a->oneShot = 1;
//andability
if(storedAndAbility.size())
{
string stored = storedAndAbility;
storedAndAbility.clear();
((AALibraryBottom*)a)->andAbility = parseMagicLine(stored, id, spell, card);
}
return a;
}
@@ -3553,7 +3566,15 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
a->oneShot = 1;
a->canBeInterrupted = false;
a->named = newName;
return a;
if(card->getAICustomCode().size() && card->controller()->isAI())
{
MTGAbility * a3 = parseMagicLine(card->getAICustomCode(), id, spell, card);
a3->oneShot = 1;
a3->canBeInterrupted = false;
return a3;
}
else
return a;
}
//scry:x (activate aility)
+1
View File
@@ -130,6 +130,7 @@ void MTGCardInstance::copy(MTGCardInstance * card)
alias = data->alias;
copiedID = card->copiedID;
doubleFaced = data->doubleFaced;
AICustomCode = data->AICustomCode;
origpower = card->origpower;//for flip
origtoughness = card->origtoughness;//for flip
+6 -1
View File
@@ -58,7 +58,12 @@ int MTGAllCards::processConfLine(string &s, MTGCard *card, CardPrimitive * primi
switch (key[0])
{
case 'a':
if (key == "auto")
if (key == "aicode")//replacement code for AI. for reveal:number basic version only
{
if (!primitive) primitive = NEW CardPrimitive();
primitive->setAICustomCode(val);
}
else if (key == "auto")
{
if (!primitive) primitive = NEW CardPrimitive();
primitive->addMagicText(val);