diff --git a/projects/mtg/bin/Res/test/_tests.txt b/projects/mtg/bin/Res/test/_tests.txt index b896e7ab8..54b97ea8d 100644 --- a/projects/mtg/bin/Res/test/_tests.txt +++ b/projects/mtg/bin/Res/test/_tests.txt @@ -307,6 +307,7 @@ evil_presence_i647_2.txt exaltedsourcekilled.txt explore.txt Faceless_Butcher.txt +fading.txt fangren_pathcutter.txt farhaven_elf.txt farmstead.txt @@ -340,6 +341,7 @@ force_of_nature3.txt fountain_of_youth.txt Frogmite.txt fungus_sliver.txt +fury_charm.txt gamble.txt gelatinous_genesis.txt gempalm_avenger.txt @@ -673,6 +675,7 @@ urzas_mine_i287.txt [at]Vampired#1.txt vampire_bats.txt vampiric_link.txt +vanishing.txt vendetta_TOUGHNESSLIFELOSS.txt vesuva_landlimit_i718.txt vine_dryad.txt diff --git a/projects/mtg/bin/Res/test/fading.txt b/projects/mtg/bin/Res/test/fading.txt new file mode 100644 index 000000000..5e6fe1684 --- /dev/null +++ b/projects/mtg/bin/Res/test/fading.txt @@ -0,0 +1,21 @@ +# Testing (keyword:fading) +# Permanent with fading must be sacrificed at the upkeep after last counter is removed + +[INIT] +UNTAP +[PLAYER1] +inplay:Phyrexian Prowler +[PLAYER2] +[DO] +Phyrexian Prowler +Phyrexian Prowler +Phyrexian Prowler +next +next +next +[ASSERT] +FIRSTMAIN +[PLAYER1] +graveyard:Phyrexian Prowler +[PLAYER2] +[END] \ No newline at end of file diff --git a/projects/mtg/bin/Res/test/fury_charm.txt b/projects/mtg/bin/Res/test/fury_charm.txt new file mode 100644 index 000000000..f7b291d64 --- /dev/null +++ b/projects/mtg/bin/Res/test/fury_charm.txt @@ -0,0 +1,21 @@ +# Testing fury charm (keyword:vanishing) +# Permanent with vanishing must be sacrificed immediately when the last counter is removed + +[INIT] +FIRSTMAIN +[PLAYER1] +hand:Fury Charm +inplay:Waning Wurm +manapool:{1}{R} +[PLAYER2] +[DO] +Fury Charm +choice 2 +Waning Wurm +[ASSERT] +FIRSTMAIN +[PLAYER1] +graveyard:Waning Wurm,Fury Charm +manapool:{0} +[PLAYER2] +[END] \ No newline at end of file diff --git a/projects/mtg/bin/Res/test/vanishing.txt b/projects/mtg/bin/Res/test/vanishing.txt new file mode 100644 index 000000000..abede42fd --- /dev/null +++ b/projects/mtg/bin/Res/test/vanishing.txt @@ -0,0 +1,17 @@ +# Testing vanishing 1 (keyword:vanishing) + +[INIT] +UNTAP +[PLAYER1] +inplay:Lavacore elemental +[PLAYER2] +[DO] +next +next +next +[ASSERT] +FIRSTMAIN +[PLAYER1] +graveyard:Lavacore elemental +[PLAYER2] +[END] \ No newline at end of file diff --git a/projects/mtg/src/AllAbilities.cpp b/projects/mtg/src/AllAbilities.cpp index bb25f7f6d..79f6dd7e3 100644 --- a/projects/mtg/src/AllAbilities.cpp +++ b/projects/mtg/src/AllAbilities.cpp @@ -4656,43 +4656,40 @@ APreventDamageTypesUEOT::~APreventDamageTypesUEOT() } //AVanishing creature also fading +// Comprehensive 702.31a: +// Fading is a keyword that represents two abilities. +// “Fading N” means “This permanent comes into play with N fade counters on it” and +// “At the beginning of your upkeep, remove a fade counter from this permanent. +// If you can’t, sacrifice the permanent.” + +// Comprehensive 702.62a: +// Vanishing is a keyword that represents three abilities. +// "Vanishing N" means "This permanent comes into play with N time counters on it," +// "At the beginning of your upkeep, if this permanent has a time counter on it, remove a time counter from it," and +// "When the last time counter is removed from this permanent, sacrifice it." AVanishing::AVanishing(GameObserver* observer, int _id, MTGCardInstance * card, ManaCost *, int, int amount, string counterName) : MTGAbility(observer, _id, source, target),amount(amount),counterName(counterName) { target = card; source = card; - next = 0; - for(int i = 0;i< amount;i++) - source->counters->addCounter(counterName.c_str(),0,0); + for (int i = 0; i < amount; i++) + source->counters->addCounter(counterName.c_str(), 0, 0); } void AVanishing::Update(float dt) { if (newPhase != currentPhase && source->controller() == game->currentPlayer) { - if(newPhase == MTG_PHASE_UPKEEP) + if (newPhase == MTG_PHASE_UPKEEP) { - source->counters->removeCounter(counterName.c_str(),0,0); - Counter * targetCounter = NULL; - timeLeft = 0; - - if (source->counters && source->counters->hasCounter(counterName.c_str(), 0, 0)) + bool hasCounters = (source->counters && source->counters->hasCounter(counterName.c_str(), 0, 0)); + if (hasCounters) { - targetCounter = source->counters->hasCounter(counterName.c_str(), 0, 0); - timeLeft = targetCounter->nb; - } - else + // sacrifice of card with time counter is handled in removeCounter + source->counters->removeCounter(counterName.c_str(), 0, 0); + } else { - timeLeft = 0; - if(counterName.find("fade") != string::npos && next == 0) - { - next = 1; - } - else - { - next = 0; - } - if (newPhase == MTG_PHASE_UPKEEP && timeLeft <= 0 && next == 0) + if (counterName == "fade") { MTGCardInstance * beforeCard = source; source->controller()->game->putInGraveyard(source); diff --git a/projects/mtg/src/Counters.cpp b/projects/mtg/src/Counters.cpp index 4ff5893b3..f61504e27 100644 --- a/projects/mtg/src/Counters.cpp +++ b/projects/mtg/src/Counters.cpp @@ -146,14 +146,24 @@ int Counters::removeCounter(const char * _name, int _power, int _toughness) { if (counters[i]->nb < 1) return 0; + counters[i]->removed(); counters[i]->nb--; GameObserver *g = target->getObserver(); WEvent * e = NEW WEventCounters(this,_name,_power,_toughness,false,true); dynamic_cast(e)->targetCard = this->target; g->receiveEvent(e); - //special case:if a card is suspended and no longer has a time counter when the last is removed, the card is cast. + // special case: when the last time counter is removed from non-suspended card + // sacrifice that card + if (!target->suspended && counters[i]->name == "time" && counters[i]->nb == 0) { + MTGCardInstance * beforeCard = target; + target->controller()->game->putInGraveyard(target); + WEvent * e = NEW WEventCardSacrifice(beforeCard, target); + g->receiveEvent(e); + } + + //special case:if a card is suspended and no longer has a time counter when the last is removed, the card is cast. if (target->suspended && !target->counters->hasCounter("time",0,0)) { GameObserver * game = target->getObserver();