Erwan
- Adding new icons from J - fixed a bug with Zombie Master (for real this time, I swear !) - The AI should play Wrath of god in a more "clever" way
This commit is contained in:
BIN
projects/mtg/bin/Res/graphics/menuicons.png
Normal file
BIN
projects/mtg/bin/Res/graphics/menuicons.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 26 KiB |
@@ -50,4 +50,5 @@ stasis.txt
|
|||||||
terror.txt
|
terror.txt
|
||||||
volcanic_island.txt
|
volcanic_island.txt
|
||||||
white_knight1.txt
|
white_knight1.txt
|
||||||
wrath_of_god.txt
|
wrath_of_god.txt
|
||||||
|
zombie_master.txt
|
||||||
24
projects/mtg/bin/Res/test/zombie_master.txt
Normal file
24
projects/mtg/bin/Res/test/zombie_master.txt
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
#Testing Zombie Master crash ?
|
||||||
|
[INIT]
|
||||||
|
COMBATATTACKERS
|
||||||
|
[PLAYER1]
|
||||||
|
inplay:1188,129693,135216
|
||||||
|
[PLAYER2]
|
||||||
|
inplay:1299
|
||||||
|
[DO]
|
||||||
|
129693
|
||||||
|
1188
|
||||||
|
next
|
||||||
|
1299
|
||||||
|
next
|
||||||
|
next
|
||||||
|
129693
|
||||||
|
[ASSERT]
|
||||||
|
COMBATEND
|
||||||
|
[PLAYER1]
|
||||||
|
inplay:135216,129693
|
||||||
|
graveyard:1188
|
||||||
|
[PLAYER2]
|
||||||
|
life:18
|
||||||
|
inplay:1299
|
||||||
|
[END]
|
||||||
@@ -882,7 +882,8 @@ class ALord:public ListMaintainerAbility{
|
|||||||
card->addToToughness(toughness);
|
card->addToToughness(toughness);
|
||||||
if (ability != -1) card->basicAbilities[ability] +=1;
|
if (ability != -1) card->basicAbilities[ability] +=1;
|
||||||
if (regenCost){
|
if (regenCost){
|
||||||
AStandardRegenerate * regen = NEW AStandardRegenerate(0, card, card, regenCost);
|
ManaCost * _regenCost = NEW ManaCost(regenCost);
|
||||||
|
AStandardRegenerate * regen = NEW AStandardRegenerate(0, card, card, _regenCost);
|
||||||
regenerations[card] = regen;
|
regenerations[card] = regen;
|
||||||
game->addObserver(regen);
|
game->addObserver(regen);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,10 +22,11 @@ using std::map;
|
|||||||
|
|
||||||
//Two stupid variables used to give a hint to the AI:
|
//Two stupid variables used to give a hint to the AI:
|
||||||
// Should I cast a spell on an enemy or friendly unit ?
|
// Should I cast a spell on an enemy or friendly unit ?
|
||||||
#define BAKA_EFFECT_GOOD 10
|
#define BAKA_EFFECT_GOOD 1
|
||||||
#define BAKA_EFFECT_BAD 11
|
#define BAKA_EFFECT_BAD -1
|
||||||
|
#define BAKA_EFFECT_DONTKNOW 0
|
||||||
|
|
||||||
|
#define COUNT_POWER 1
|
||||||
|
|
||||||
class MTGAbility: public ActionElement{
|
class MTGAbility: public ActionElement{
|
||||||
protected:
|
protected:
|
||||||
@@ -183,6 +184,7 @@ class GenericTriggeredAbility:public TriggeredAbility{
|
|||||||
/* Ability Factory */
|
/* Ability Factory */
|
||||||
class AbilityFactory{
|
class AbilityFactory{
|
||||||
private:
|
private:
|
||||||
|
int countCards(TargetChooser * tc, Player * player = NULL, int option = 0);
|
||||||
int destroyAllInPlay(TargetChooser * tc, int bury = 0);
|
int destroyAllInPlay(TargetChooser * tc, int bury = 0);
|
||||||
int putInPlayFromZone(MTGCardInstance * card, MTGGameZone * zone, Player * p);
|
int putInPlayFromZone(MTGCardInstance * card, MTGGameZone * zone, Player * p);
|
||||||
Trigger * parseTrigger(string magicText);
|
Trigger * parseTrigger(string magicText);
|
||||||
@@ -195,3 +197,4 @@ class AbilityFactory{
|
|||||||
#include "MTGCardInstance.h"
|
#include "MTGCardInstance.h"
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -76,31 +76,7 @@ void AIPlayer::tapLandsForMana(ManaCost * potentialMana, ManaCost * cost){
|
|||||||
|
|
||||||
delete(diff);
|
delete(diff);
|
||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
for (int i=MTG_NB_COLORS-1; i>= 0; i--){
|
|
||||||
#if defined (WIN32) || defined (LINUX)
|
|
||||||
char buf[4096];
|
|
||||||
sprintf(buf,"Testing %s \n" ,MTG_LAND_TEXTS[i]);
|
|
||||||
OutputDebugString(buf);
|
|
||||||
#endif
|
|
||||||
currentCost = cost->getCost(i);
|
|
||||||
while(currentCost){
|
|
||||||
#if defined (WIN32) || defined (LINUX)
|
|
||||||
sprintf(buf,"Cost for %s is %i \n" ,MTG_LAND_TEXTS[i], currentCost);
|
|
||||||
OutputDebugString(buf);
|
|
||||||
#endif
|
|
||||||
MTGCardInstance * card = NULL;
|
|
||||||
while(currentCost && (card = cd.nextmatch(game->inPlay, card))){
|
|
||||||
if (i==MTG_COLOR_ARTIFACT || card->hasSubtype(MTG_LAND_TEXTS[i]) ){
|
|
||||||
currentCost--;
|
|
||||||
gameObs->cardClick(card);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
*/
|
|
||||||
#if defined (WIN32) || defined (LINUX)
|
#if defined (WIN32) || defined (LINUX)
|
||||||
OutputDebugString("ok land tapped");
|
OutputDebugString("ok land tapped");
|
||||||
#endif
|
#endif
|
||||||
@@ -167,7 +143,7 @@ int AIPlayer::effectBadOrGood(MTGCardInstance * card){
|
|||||||
int autoGuess = af->magicText(id,NULL,card);
|
int autoGuess = af->magicText(id,NULL,card);
|
||||||
delete af;
|
delete af;
|
||||||
if (autoGuess) return autoGuess;
|
if (autoGuess) return autoGuess;
|
||||||
return BAKA_EFFECT_BAD;
|
return BAKA_EFFECT_DONTKNOW;
|
||||||
}
|
}
|
||||||
|
|
||||||
int AIPlayer::chooseTarget(TargetChooser * tc){
|
int AIPlayer::chooseTarget(TargetChooser * tc){
|
||||||
@@ -184,7 +160,7 @@ int AIPlayer::chooseTarget(TargetChooser * tc){
|
|||||||
if (!(gameObs->currentlyActing() == this)) return 0;
|
if (!(gameObs->currentlyActing() == this)) return 0;
|
||||||
Player * target = this;
|
Player * target = this;
|
||||||
int cardEffect = effectBadOrGood(tc->source);
|
int cardEffect = effectBadOrGood(tc->source);
|
||||||
if (cardEffect == BAKA_EFFECT_BAD){
|
if (cardEffect != BAKA_EFFECT_GOOD){
|
||||||
target = this->opponent();
|
target = this->opponent();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -464,9 +440,18 @@ MTGCardInstance * AIPlayerBaka::FindCardToPlay(ManaCost * potentialMana, const c
|
|||||||
TargetChooser * tc = tcf->createTargetChooser(card);
|
TargetChooser * tc = tcf->createTargetChooser(card);
|
||||||
delete tcf;
|
delete tcf;
|
||||||
if (tc){
|
if (tc){
|
||||||
int hasTarget = (chooseTarget(tc));
|
int hasTarget = (chooseTarget(tc));
|
||||||
delete tc;
|
delete tc;
|
||||||
if (!hasTarget)continue;
|
if (!hasTarget)continue;
|
||||||
|
}else{
|
||||||
|
int shouldPlayPercentage = 10;
|
||||||
|
int shouldPlay = effectBadOrGood(card);
|
||||||
|
if (shouldPlay == BAKA_EFFECT_GOOD){
|
||||||
|
shouldPlayPercentage = 90;
|
||||||
|
}else if(BAKA_EFFECT_DONTKNOW == shouldPlay){
|
||||||
|
shouldPlayPercentage = 70;
|
||||||
|
}
|
||||||
|
if (rand() % 100 > shouldPlayPercentage) continue;
|
||||||
}
|
}
|
||||||
nextCardToPlay = card;
|
nextCardToPlay = card;
|
||||||
maxCost = currentCost;
|
maxCost = currentCost;
|
||||||
|
|||||||
@@ -9,243 +9,288 @@
|
|||||||
#include "../include/MTGDeck.h"
|
#include "../include/MTGDeck.h"
|
||||||
|
|
||||||
|
|
||||||
int AbilityFactory::destroyAllInPlay(TargetChooser * tc, int bury){
|
int AbilityFactory::countCards(TargetChooser * tc, Player * player, int option){
|
||||||
tc->source = NULL; // This is to prevent protection from... as objects that destroy all do not actually target
|
int result = 0;
|
||||||
GameObserver * game = GameObserver::GetInstance();
|
GameObserver * game = GameObserver::GetInstance();
|
||||||
for (int i = 0; i < 2 ; i++){
|
for (int i = 0; i < 2 ; i++){
|
||||||
for (int j = 0; j < game->players[i]->game->inPlay->nb_cards; j++){
|
if (player && player!= game->players[i]) continue;
|
||||||
MTGCardInstance * current = game->players[i]->game->inPlay->cards[j];
|
for (int j = game->players[i]->game->inPlay->nb_cards-1; j >=0 ; j--){
|
||||||
if (tc->canTarget(current)){
|
MTGCardInstance * current = game->players[i]->game->inPlay->cards[j];
|
||||||
if (bury){
|
if (tc->canTarget(current)){
|
||||||
game->players[i]->game->putInGraveyard(current);
|
switch (option){
|
||||||
}else{
|
case COUNT_POWER:
|
||||||
game->mLayers->stackLayer()->addPutInGraveyard(current);
|
result+= current->power;
|
||||||
}
|
break;
|
||||||
}
|
default:
|
||||||
}
|
result++;
|
||||||
}
|
break;
|
||||||
return 1;
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
int AbilityFactory::putInPlayFromZone(MTGCardInstance * card, MTGGameZone * zone, Player * p){
|
return result;
|
||||||
Spell * spell = NEW Spell(card);
|
}
|
||||||
p->game->putInZone(card, zone, p->game->stack);
|
|
||||||
spell->resolve();
|
int AbilityFactory::destroyAllInPlay(TargetChooser * tc, int bury){
|
||||||
delete spell;
|
tc->source = NULL; // This is to prevent protection from... as objects that destroy all do not actually target
|
||||||
return 1;
|
GameObserver * game = GameObserver::GetInstance();
|
||||||
}
|
for (int i = 0; i < 2 ; i++){
|
||||||
|
for (int j = game->players[i]->game->inPlay->nb_cards-1; j >=0 ; j--){
|
||||||
|
MTGCardInstance * current = game->players[i]->game->inPlay->cards[j];
|
||||||
Trigger * AbilityFactory::parseTrigger(string magicText){
|
if (tc->canTarget(current)){
|
||||||
size_t found = magicText.find("@");
|
if (bury){
|
||||||
if (found == string::npos) return NULL;
|
game->players[i]->game->putInGraveyard(current);
|
||||||
|
}else{
|
||||||
//Next Time...
|
game->mLayers->stackLayer()->addPutInGraveyard(current);
|
||||||
found = magicText.find("next");
|
}
|
||||||
if (found != string::npos){
|
}
|
||||||
for (int i = 0; i < NB_MTG_PHASES; i++){
|
}
|
||||||
found = magicText.find(MTGPhaseCodeNames[i]);
|
}
|
||||||
if (found != string::npos){
|
return 1;
|
||||||
return NEW TriggerNextPhase(i);
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
int AbilityFactory::putInPlayFromZone(MTGCardInstance * card, MTGGameZone * zone, Player * p){
|
||||||
|
Spell * spell = NEW Spell(card);
|
||||||
return NULL;
|
p->game->putInZone(card, zone, p->game->stack);
|
||||||
}
|
spell->resolve();
|
||||||
|
delete spell;
|
||||||
//Some basic functionalities that can be added automatically in the text file
|
return 1;
|
||||||
/*
|
}
|
||||||
* Several objects are computed from the text string, and have a direct influence on what action we should take
|
|
||||||
* (direct impact on the game such as draw a card immediately, or create a new GameObserver and add it to the Abilities,etc..)
|
|
||||||
* These objects are:
|
Trigger * AbilityFactory::parseTrigger(string magicText){
|
||||||
* - trigger (if there is an "@" in the string, this is a triggered ability)
|
int found = magicText.find("@");
|
||||||
* - target (if there ie a "target(" in the string, then this is a TargetAbility)
|
if (found == string::npos) return NULL;
|
||||||
* - doTap (a dirty way to know if tapping is included in the cost...
|
|
||||||
*/
|
//Next Time...
|
||||||
int AbilityFactory::magicText(int id, Spell * spell, MTGCardInstance * card){
|
found = magicText.find("next");
|
||||||
int dryMode = 0;
|
if (found != string::npos){
|
||||||
if (!spell) dryMode = 1;
|
for (int i = 0; i < NB_MTG_PHASES; i++){
|
||||||
GameObserver * game = GameObserver::GetInstance();
|
found = magicText.find(MTGPhaseCodeNames[i]);
|
||||||
if (!card) card = spell->source;
|
if (found != string::npos){
|
||||||
MTGCardInstance * target = card->target;
|
return NEW TriggerNextPhase(i);
|
||||||
if (!target) target = card;
|
}
|
||||||
string magicText = card->magicText;
|
}
|
||||||
if (card->alias && magicText.size() == 0){
|
}
|
||||||
//An awful way to get access to the aliasedcard
|
|
||||||
magicText = GameObserver::GetInstance()->players[0]->game->collection->getCardById(card->alias)->magicText;
|
return NULL;
|
||||||
}
|
}
|
||||||
string s;
|
|
||||||
int size = magicText.size();
|
//Some basic functionalities that can be added automatically in the text file
|
||||||
if (size == 0) return 0;
|
/*
|
||||||
unsigned int found;
|
* Several objects are computed from the text string, and have a direct influence on what action we should take
|
||||||
int result = id;
|
* (direct impact on the game such as draw a card immediately, or create a new GameObserver and add it to the Abilities,etc..)
|
||||||
|
* These objects are:
|
||||||
|
* - trigger (if there is an "@" in the string, this is a triggered ability)
|
||||||
while (magicText.size()){
|
* - target (if there ie a "target(" in the string, then this is a TargetAbility)
|
||||||
found = magicText.find("\n");
|
* - doTap (a dirty way to know if tapping is included in the cost...
|
||||||
if (found != string::npos){
|
*/
|
||||||
s = magicText.substr(0,found);
|
int AbilityFactory::magicText(int id, Spell * spell, MTGCardInstance * card){
|
||||||
magicText = magicText.substr(found+1);
|
int dryMode = 0;
|
||||||
}else{
|
if (!spell) dryMode = 1;
|
||||||
s = magicText;
|
GameObserver * game = GameObserver::GetInstance();
|
||||||
magicText = "";
|
if (!card) card = spell->source;
|
||||||
}
|
MTGCardInstance * target = card->target;
|
||||||
#if defined (WIN32) || defined (LINUX)
|
if (!target) target = card;
|
||||||
char buf[4096];
|
string magicText = card->magicText;
|
||||||
sprintf(buf, "AUTO ACTION: %s\n", s.c_str());
|
if (card->alias && magicText.size() == 0){
|
||||||
OutputDebugString(buf);
|
//An awful way to get access to the aliasedcard
|
||||||
#endif
|
magicText = GameObserver::GetInstance()->players[0]->game->collection->getCardById(card->alias)->magicText;
|
||||||
|
}
|
||||||
TargetChooser * tc = NULL;
|
string s;
|
||||||
int doTap = 0;
|
int size = magicText.size();
|
||||||
string lordType = "";
|
if (size == 0) return 0;
|
||||||
|
unsigned int found;
|
||||||
Trigger * trigger = parseTrigger(s);
|
int result = id;
|
||||||
//Dirty way to remove the trigger text (could get in the way)
|
|
||||||
if (trigger){
|
|
||||||
found = s.find(":");
|
while (magicText.size()){
|
||||||
s = s.substr(found+1);
|
found = magicText.find("\n");
|
||||||
}
|
if (found != string::npos){
|
||||||
|
s = magicText.substr(0,found);
|
||||||
//Tap in the cost ?
|
magicText = magicText.substr(found+1);
|
||||||
if (s.find("{t}") != string::npos) doTap = 1;
|
}else{
|
||||||
|
s = magicText;
|
||||||
//Target Abilities
|
magicText = "";
|
||||||
found = s.find("target(");
|
}
|
||||||
if (found != string::npos){
|
#if defined (WIN32) || defined (LINUX)
|
||||||
int end = s.find(")");
|
char buf[4096];
|
||||||
string starget = s.substr(found + 7,end - found - 7);
|
sprintf(buf, "AUTO ACTION: %s\n", s.c_str());
|
||||||
TargetChooserFactory tcf;
|
OutputDebugString(buf);
|
||||||
tc = tcf.createTargetChooser(starget, card);
|
#endif
|
||||||
|
|
||||||
}
|
TargetChooser * tc = NULL;
|
||||||
|
int doTap = 0;
|
||||||
//Lord
|
string lordType = "";
|
||||||
found = s.find("lord(");
|
|
||||||
if (found != string::npos){
|
Trigger * trigger = parseTrigger(s);
|
||||||
if (dryMode) return BAKA_EFFECT_GOOD;
|
//Dirty way to remove the trigger text (could get in the way)
|
||||||
unsigned int end = s.find(")", found+5);
|
if (trigger){
|
||||||
if (end != string::npos){
|
found = s.find(":");
|
||||||
lordType = s.substr(found+5,end-found-5).c_str();
|
s = s.substr(found+1);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
//Tap in the cost ?
|
||||||
//Champion. Very basic, needs to be improved !
|
if (s.find("{t}") != string::npos) doTap = 1;
|
||||||
found = s.find("champion(name:");
|
|
||||||
if (found != string::npos){
|
//Target Abilities
|
||||||
if (dryMode) return BAKA_EFFECT_GOOD;
|
found = s.find("target(");
|
||||||
unsigned int end = s.find(")", found+14);
|
if (found != string::npos){
|
||||||
if (end != string::npos){
|
int end = s.find(")");
|
||||||
string type = s.substr(found+14,end-found-14).c_str();
|
string starget = s.substr(found + 7,end - found - 7);
|
||||||
game->addObserver(NEW APlagueRats(id,card,type.c_str()));
|
TargetChooserFactory tcf;
|
||||||
result++;
|
tc = tcf.createTargetChooser(starget, card);
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
//Lord
|
||||||
//Untapper (Ley Druid...)
|
found = s.find("lord(");
|
||||||
found = s.find("untap");
|
if (found != string::npos){
|
||||||
if (found != string::npos){
|
if (dryMode) return BAKA_EFFECT_GOOD;
|
||||||
if (dryMode) return BAKA_EFFECT_GOOD;
|
unsigned int end = s.find(")", found+5);
|
||||||
ManaCost * cost = ManaCost::parseManaCost(s);
|
if (end != string::npos){
|
||||||
if (tc){
|
lordType = s.substr(found+5,end-found-5).c_str();
|
||||||
game->addObserver(NEW AUntaper(id, card, cost, tc));
|
}
|
||||||
}else{
|
}
|
||||||
target->tapped = 0;
|
|
||||||
}
|
//Champion. Very basic, needs to be improved !
|
||||||
|
found = s.find("champion(name:");
|
||||||
result++;
|
if (found != string::npos){
|
||||||
continue;
|
if (dryMode) return BAKA_EFFECT_GOOD;
|
||||||
}
|
unsigned int end = s.find(")", found+14);
|
||||||
|
if (end != string::npos){
|
||||||
//Tapper (icy manipulator)
|
string type = s.substr(found+14,end-found-14).c_str();
|
||||||
found = s.find("tap");
|
game->addObserver(NEW APlagueRats(id,card,type.c_str()));
|
||||||
if (found != string::npos){
|
result++;
|
||||||
if (dryMode) return BAKA_EFFECT_GOOD;
|
continue;
|
||||||
ManaCost * cost = ManaCost::parseManaCost(s);
|
}
|
||||||
if (tc){
|
}
|
||||||
game->addObserver(NEW ATapper(id, card, cost, tc));
|
|
||||||
}else{
|
//Untapper (Ley Druid...)
|
||||||
target->tapped = 1;
|
found = s.find("untap");
|
||||||
}
|
if (found != string::npos){
|
||||||
|
if (dryMode) return BAKA_EFFECT_GOOD;
|
||||||
result++;
|
ManaCost * cost = ManaCost::parseManaCost(s);
|
||||||
continue;
|
if (tc){
|
||||||
}
|
game->addObserver(NEW AUntaper(id, card, cost, tc));
|
||||||
|
}else{
|
||||||
//Regeneration
|
target->tapped = 0;
|
||||||
found = s.find("}:regenerate");
|
}
|
||||||
if (found != string::npos){
|
|
||||||
if (dryMode) return BAKA_EFFECT_GOOD;
|
result++;
|
||||||
ManaCost * cost = ManaCost::parseManaCost(s);
|
continue;
|
||||||
|
}
|
||||||
if (lordType.size() > 0){
|
|
||||||
game->addObserver(NEW ALord(id,card,lordType.c_str(),0,0,-1,cost));
|
//Tapper (icy manipulator)
|
||||||
}else{
|
found = s.find("tap");
|
||||||
|
if (found != string::npos){
|
||||||
if (tc){
|
if (dryMode) return BAKA_EFFECT_GOOD;
|
||||||
//TODO
|
ManaCost * cost = ManaCost::parseManaCost(s);
|
||||||
}else{
|
if (tc){
|
||||||
game->addObserver(NEW AStandardRegenerate(id, card, target, cost));
|
game->addObserver(NEW ATapper(id, card, cost, tc));
|
||||||
//TODO death ward !
|
}else{
|
||||||
}
|
target->tapped = 1;
|
||||||
}
|
}
|
||||||
result++;
|
|
||||||
continue;
|
result++;
|
||||||
}
|
continue;
|
||||||
|
}
|
||||||
//Bury
|
|
||||||
found = s.find("bury");
|
//Regeneration
|
||||||
if (found != string::npos){
|
found = s.find("}:regenerate");
|
||||||
if (dryMode) return BAKA_EFFECT_BAD;
|
if (found != string::npos){
|
||||||
if (trigger){
|
if (dryMode) return BAKA_EFFECT_GOOD;
|
||||||
BuryEvent * action = NEW BuryEvent();
|
ManaCost * cost = ManaCost::parseManaCost(s);
|
||||||
game->addObserver(NEW GenericTriggeredAbility(id, card,trigger,action));
|
|
||||||
}else{
|
if (lordType.size() > 0){
|
||||||
found = s.find("all(");
|
game->addObserver(NEW ALord(id,card,lordType.c_str(),0,0,-1,cost));
|
||||||
if (found != string::npos){
|
}else{
|
||||||
int end = s.find(")");
|
|
||||||
string starget = s.substr(found + 4,end - found - 4);
|
if (tc){
|
||||||
TargetChooserFactory tcf;
|
//TODO
|
||||||
TargetChooser * targetAll = tcf.createTargetChooser(starget, card);
|
}else{
|
||||||
this->destroyAllInPlay(targetAll,1);
|
game->addObserver(NEW AStandardRegenerate(id, card, target, cost));
|
||||||
delete targetAll;
|
//TODO death ward !
|
||||||
}else{
|
}
|
||||||
if (tc){
|
}
|
||||||
game->addObserver(NEW ABurier(id, card,tc));
|
result++;
|
||||||
}else{
|
continue;
|
||||||
target->controller()->game->putInGraveyard(target);
|
}
|
||||||
}
|
|
||||||
}
|
//Bury
|
||||||
}
|
found = s.find("bury");
|
||||||
result++;
|
if (found != string::npos){
|
||||||
continue;
|
if (trigger){
|
||||||
}
|
if (dryMode) return BAKA_EFFECT_BAD;
|
||||||
|
BuryEvent * action = NEW BuryEvent();
|
||||||
//Destroy
|
game->addObserver(NEW GenericTriggeredAbility(id, card,trigger,action));
|
||||||
found = s.find("destroy");
|
}else{
|
||||||
if (found != string::npos){
|
found = s.find("all(");
|
||||||
if (dryMode) return BAKA_EFFECT_BAD; //TODO compute according to nb in case of destroy all
|
if (found != string::npos){
|
||||||
found = s.find("all(");
|
int end = s.find(")");
|
||||||
if (found != string::npos){
|
string starget = s.substr(found + 4,end - found - 4);
|
||||||
int end = s.find(")");
|
TargetChooserFactory tcf;
|
||||||
string starget = s.substr(found + 4,end - found - 4);
|
TargetChooser * targetAll = tcf.createTargetChooser(starget, card);
|
||||||
TargetChooserFactory tcf;
|
if (dryMode){
|
||||||
TargetChooser * targetAll = tcf.createTargetChooser(starget, card);
|
int myNbCards = countCards(targetAll,card->controller());
|
||||||
this->destroyAllInPlay(targetAll);
|
int opponentNbCards = countCards(targetAll, card->controller()->opponent());
|
||||||
delete targetAll;
|
int myCardsPower = countCards(targetAll,card->controller(),COUNT_POWER);
|
||||||
}else{
|
int opponentCardsPower = countCards(targetAll, card->controller()->opponent(),COUNT_POWER);
|
||||||
if (tc){
|
delete targetAll;
|
||||||
game->addObserver(NEW ADestroyer(id, card,tc));
|
if (myNbCards < opponentNbCards || myCardsPower < opponentCardsPower) return BAKA_EFFECT_GOOD;
|
||||||
}else{
|
return BAKA_EFFECT_BAD;
|
||||||
game->mLayers->stackLayer()->addPutInGraveyard(target);
|
}else{
|
||||||
}
|
this->destroyAllInPlay(targetAll,1);
|
||||||
}
|
delete targetAll;
|
||||||
result++;
|
}
|
||||||
continue;
|
|
||||||
}
|
}else{
|
||||||
|
if (dryMode) return BAKA_EFFECT_BAD;
|
||||||
|
if (tc){
|
||||||
|
game->addObserver(NEW ABurier(id, card,tc));
|
||||||
|
}else{
|
||||||
|
target->controller()->game->putInGraveyard(target);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Destroy
|
||||||
|
found = s.find("destroy");
|
||||||
|
if (found != string::npos){
|
||||||
|
|
||||||
|
found = s.find("all(");
|
||||||
|
if (found != string::npos){
|
||||||
|
int end = s.find(")");
|
||||||
|
string starget = s.substr(found + 4,end - found - 4);
|
||||||
|
TargetChooserFactory tcf;
|
||||||
|
TargetChooser * targetAll = tcf.createTargetChooser(starget, card);
|
||||||
|
if (dryMode){
|
||||||
|
int myNbCards = countCards(targetAll,card->controller());
|
||||||
|
int opponentNbCards = countCards(targetAll, card->controller()->opponent());
|
||||||
|
int myCardsPower = countCards(targetAll,card->controller(),COUNT_POWER);
|
||||||
|
int opponentCardsPower = countCards(targetAll, card->controller()->opponent(),COUNT_POWER);
|
||||||
|
delete targetAll;
|
||||||
|
if (myNbCards < opponentNbCards || myCardsPower < opponentCardsPower) return BAKA_EFFECT_GOOD;
|
||||||
|
return BAKA_EFFECT_BAD;
|
||||||
|
}else{
|
||||||
|
this->destroyAllInPlay(targetAll);
|
||||||
|
delete targetAll;
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
if (dryMode) return BAKA_EFFECT_BAD;
|
||||||
|
if (tc){
|
||||||
|
game->addObserver(NEW ADestroyer(id, card,tc));
|
||||||
|
}else{
|
||||||
|
game->mLayers->stackLayer()->addPutInGraveyard(target);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
//Damage
|
//Damage
|
||||||
found = s.find("damage");
|
found = s.find("damage");
|
||||||
@@ -1804,4 +1849,4 @@ GenericTriggeredAbility::~GenericTriggeredAbility(){
|
|||||||
delete t;
|
delete t;
|
||||||
delete te;
|
delete te;
|
||||||
SAFE_DELETE(dc);
|
SAFE_DELETE(dc);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -294,9 +294,9 @@ int TestSuite::assertGame(){
|
|||||||
}
|
}
|
||||||
for (int k = 0; k < endState.playerData[i].zones[j].nbitems; k++){
|
for (int k = 0; k < endState.playerData[i].zones[j].nbitems; k++){
|
||||||
int cardid = endState.playerData[i].zones[j].cards[k];
|
int cardid = endState.playerData[i].zones[j].cards[k];
|
||||||
int realcardid = zone->cards[k]->getMTGId();
|
MTGCardInstance * card = getCardByMTGId(cardid);
|
||||||
if ( realcardid!= cardid){
|
if (!card || !zone->hasCard(card)){
|
||||||
sprintf(result, "<span class=\"error\">==Card ID not the same. Expected %i, got %i==</span><br />", cardid, realcardid);
|
sprintf(result, "<span class=\"error\">==Card ID not the same. Didn't find %i</span><br />", cardid);
|
||||||
Log(result);
|
Log(result);
|
||||||
error++;
|
error++;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user