diff --git a/projects/mtg/bin/Res/sets/10E/_cards.dat b/projects/mtg/bin/Res/sets/10E/_cards.dat index 3443a6073..55faafecf 100644 --- a/projects/mtg/bin/Res/sets/10E/_cards.dat +++ b/projects/mtg/bin/Res/sets/10E/_cards.dat @@ -1216,6 +1216,19 @@ type=Artifact mana={4} [/card] [card] +text=Juggernaut attacks each turn if able. Juggernaut can't be blocked by Walls. +auto=cantbeblockedby(wall) +abilities=mustattack +id=135240 +name=Juggernaut +rarity=U +type=Artifact Creature +mana={4} +power=5 +subtype=Juggernaut +toughness=3 +[/card] +[card] text=Haste (This creature can attack and {T} as soon as it comes under your control.) {T}: Kamahl, Pit Fighter deals 3 damage to target creature or player. abilities=haste,legendary auto={T}:Damage:3 target(creature,player) diff --git a/projects/mtg/bin/Res/sets/10E/todo.dat b/projects/mtg/bin/Res/sets/10E/todo.dat index 0da577c1a..d99156776 100644 --- a/projects/mtg/bin/Res/sets/10E/todo.dat +++ b/projects/mtg/bin/Res/sets/10E/todo.dat @@ -486,20 +486,6 @@ type=Instant mana={1}{R} [/card] [card] -text=Juggernaut attacks each turn if able. Juggernaut can't be blocked by Walls. -id=135240 -name=Juggernaut -rarity=U -color=Artifact -type=Artifact Creature -mana={4} -power=5 -abilities=mustattack -auto=cantbeblockedby(wall) -subtype=Juggernaut -toughness=3 -[/card] -[card] text=Karplusan Strider can't be the target of blue or black spells. id=129911 name=Karplusan Strider diff --git a/projects/mtg/bin/Res/sets/DIS/_cards.dat b/projects/mtg/bin/Res/sets/DIS/_cards.dat index c08ee321d..c950ce685 100644 --- a/projects/mtg/bin/Res/sets/DIS/_cards.dat +++ b/projects/mtg/bin/Res/sets/DIS/_cards.dat @@ -110,6 +110,18 @@ toughness=9 abilities=trample [/card] [card] +id=107526 +name=Gnat Alley Creeper +mana={2}{R} +type=Creature +subtype=Human Rogue +power=3 +toughness=1 +text=Gnat Alley Creeper can't be blocked by creatures with flying. +auto=cantbeblockedby(creature[flying]) +rarity=U +[/card] +[card] text={T}, Sacrifice Haazda Exonerator: Destroy target Aura. id=107467 name=Haazda Exonerator diff --git a/projects/mtg/bin/Res/sets/DIS/todo.dat b/projects/mtg/bin/Res/sets/DIS/todo.dat index 434641527..1587c6efa 100644 --- a/projects/mtg/bin/Res/sets/DIS/todo.dat +++ b/projects/mtg/bin/Res/sets/DIS/todo.dat @@ -1,6 +1,6 @@ [card] id=111192 -name=ÁEhermage's Touch +name=AEthermage's Touch mana={2}{W}{U} type=Instant text=Reveal the top four cards of your library. You may put a creature card from among them onto the battlefield. It has "At the beginning of your end step, return this creature to its owner's hand." Then put the rest of the cards revealed this way on the bottom of your library in any order. @@ -468,17 +468,6 @@ text={T}: Add {1} to your mana pool. {T}, Sacrifice Ghost Quarter: Destroy targe rarity=U [/card] [card] -id=107526 -name=Gnat Alley Creeper -mana={2}{R} -type=Creature -subtype=Human Rogue -power=3 -toughness=1 -text=Gnat Alley Creeper can't be blocked by creatures with flying. -rarity=U -[/card] -[card] id=107542 name=Gobhobbler Rats mana={B}{R} diff --git a/projects/mtg/bin/Res/sets/DRK/_cards.dat b/projects/mtg/bin/Res/sets/DRK/_cards.dat index f3eec2243..7b657f3b6 100644 --- a/projects/mtg/bin/Res/sets/DRK/_cards.dat +++ b/projects/mtg/bin/Res/sets/DRK/_cards.dat @@ -522,6 +522,15 @@ mana={0} type=Artifact [/card] [card] +id=1725 +name=Tower of Coireall +mana={2} +type=Artifact +text={T}: Target creature can't be blocked by Walls this turn. +auto={T}:cantbeblockedby(wall) target(creature) +rarity=U +[/card] +[card] text=Water Wurm gets +0/+1 as long as an opponent controls an Island. id=1764 name=Water Wurm diff --git a/projects/mtg/bin/Res/sets/DRK/todo.dat b/projects/mtg/bin/Res/sets/DRK/todo.dat index cc5174065..063240478 100644 --- a/projects/mtg/bin/Res/sets/DRK/todo.dat +++ b/projects/mtg/bin/Res/sets/DRK/todo.dat @@ -553,14 +553,6 @@ text=At the beginning of your upkeep, The Fallen deals 1 damage to each opponent rarity=U [/card] [card] -id=1725 -name=Tower of Coireall -mana={2} -type=Artifact -text={T}: Target creature can't be blocked by Walls this turn. -rarity=U -[/card] -[card] id=1779 name=Tracker mana={2}{G} diff --git a/projects/mtg/bin/Res/sets/DST/_cards.dat b/projects/mtg/bin/Res/sets/DST/_cards.dat index 40b99755f..34e2ea0df 100644 --- a/projects/mtg/bin/Res/sets/DST/_cards.dat +++ b/projects/mtg/bin/Res/sets/DST/_cards.dat @@ -231,10 +231,7 @@ subtype=Juggernaut power=5 toughness=3 text=Juggernaut attacks each turn if able. Juggernaut can't be blocked by Walls. -# Following line is not entirely correct: Walls cannot target -# Juggernaut although they should be able to. But it's hard to -# find a case where this difference actually matters. -auto=protection from(wall) +auto=cantbeblockedby(wall) abilities=mustattack rarity=U [/card] diff --git a/projects/mtg/bin/Res/sets/PLC/_cards.dat b/projects/mtg/bin/Res/sets/PLC/_cards.dat index 158c8f0ae..e22b89bc3 100644 --- a/projects/mtg/bin/Res/sets/PLC/_cards.dat +++ b/projects/mtg/bin/Res/sets/PLC/_cards.dat @@ -133,6 +133,18 @@ power=2 toughness=2 [/card] [card] +id=110501 +name=Dust Corona +mana={R} +type=Enchantment +subtype=Aura +text=Enchant creature -- Enchanted creature gets +2/+0 and can't be blocked by creatures with flying. +target=creature +auto=2/0 +auto=cantbeblockedby(creatures[flying]) +rarity=C +[/card] +[card] text=Enchant creature You control enchanted creature. At the beginning of your upkeep, enchanted creature deals 1 damage to its owner. target=creature auto=@each my upkeep:life:-1 opponent diff --git a/projects/mtg/bin/Res/sets/PLC/todo.dat b/projects/mtg/bin/Res/sets/PLC/todo.dat index b7f81adda..0a0efae65 100644 --- a/projects/mtg/bin/Res/sets/PLC/todo.dat +++ b/projects/mtg/bin/Res/sets/PLC/todo.dat @@ -11,7 +11,7 @@ rarity=R [/card] [card] id=124504 -name=ÁEher Membrane +name=AEther Membrane mana={1}{R}{R} type=Creature subtype=Wall @@ -278,15 +278,6 @@ text=Protection from green At the beginning of the end step, if Dunerider Outlaw rarity=U [/card] [card] -id=110501 -name=Dust Corona -mana={R} -type=Enchantment -subtype=Aura -text=Enchant creature Enchanted creature gets +2/+0 and can't be blocked by creatures with flying. -rarity=C -[/card] -[card] id=124343 name=Dust Elemental mana={2}{W}{W} diff --git a/projects/mtg/bin/Res/sets/RV/_cards.dat b/projects/mtg/bin/Res/sets/RV/_cards.dat index 36a702c5a..6310c9e7f 100644 --- a/projects/mtg/bin/Res/sets/RV/_cards.dat +++ b/projects/mtg/bin/Res/sets/RV/_cards.dat @@ -1189,6 +1189,19 @@ mana={4} type=Artifact [/card] [card] +text=Juggernaut attacks each turn if able. Juggernaut can't be blocked by Walls. +auto=cantbeblockedby(wall) +abilities=mustattack +id=1120 +name=Juggernaut +rarity=U +type=Artifact Creature +mana={4} +power=5 +subtype=Juggernaut +toughness=3 +[/card] +[card] text=Target creature gains flying until end of turn. target=creature auto=flying diff --git a/projects/mtg/bin/Res/sets/RV/todo.dat b/projects/mtg/bin/Res/sets/RV/todo.dat index 173102a02..75f5e37c0 100644 --- a/projects/mtg/bin/Res/sets/RV/todo.dat +++ b/projects/mtg/bin/Res/sets/RV/todo.dat @@ -195,18 +195,6 @@ type=Artifact mana={4} [/card] [card] -text=Juggernaut attacks each turn if able. Juggernaut can't be blocked by Walls. -id=1120 -name=Juggernaut -rarity=U -color=Artifact -type=Artifact Creature -mana={4} -power=5 -subtype=Juggernaut -toughness=3 -[/card] -[card] text=You have no maximum hand size. If an effect causes you to discard a card, discard it, but you may put it on top of your library instead of into your graveyard. id=1122 name=Library of Leng diff --git a/projects/mtg/bin/Res/test/_tests.txt b/projects/mtg/bin/Res/test/_tests.txt index caebbcc33..3b49ea58e 100644 --- a/projects/mtg/bin/Res/test/_tests.txt +++ b/projects/mtg/bin/Res/test/_tests.txt @@ -178,6 +178,7 @@ drift_of_the_dead.txt dromad_purebred.txt dross_harvester.txt duskwalker.txt +dust_corona.txt dwarven_warriors.txt ebony_horse.txt ekundu_cyclops1_i218.txt @@ -219,6 +220,8 @@ giant_growth.txt giant_growth2.txt glimpse_the_unthinkable.txt gnarled_effigy.txt +gnat_alley_creeper1.txt +gnat_alley_creeper2.txt goblin_balloon_brigade.txt goblin_balloon_brigade2.txt goblin_king.txt @@ -246,6 +249,7 @@ imaginary_pet.txt immaculate_magistrate.txt instill_energy_i166.txt jodahs_avenger.txt +juggernaut.txt jump.txt karns_touch_i233.txt keldon_warlord.txt diff --git a/projects/mtg/bin/Res/test/dust_corona.txt b/projects/mtg/bin/Res/test/dust_corona.txt new file mode 100644 index 000000000..4a85ffd49 --- /dev/null +++ b/projects/mtg/bin/Res/test/dust_corona.txt @@ -0,0 +1,29 @@ +#NAME: Dust Corona +#DESC: checks an aura which grants +#DESC: a "can't be blocked by" ability +[INIT] +firstmain +[PLAYER1] +inplay:Raging Goblin +hand:Dust Corona +manapool:{R} +[PLAYER2] +inplay:Suntail Hawk +[DO] +Dust Corona +Raging Goblin +next +next +Raging Goblin +next +Suntail Hawk +next +next +[ASSERT] +combatend +[PLAYER1] +inplay:Raging Goblin,Dust Corona +[PLAYER2] +inplay:Suntail Hawk +life:17 +[END] diff --git a/projects/mtg/bin/Res/test/gnat_alley_creeper1.txt b/projects/mtg/bin/Res/test/gnat_alley_creeper1.txt new file mode 100644 index 000000000..c849d266d --- /dev/null +++ b/projects/mtg/bin/Res/test/gnat_alley_creeper1.txt @@ -0,0 +1,23 @@ +#NAME: Gnat Alley Creeper +#DESC: checks the ability "can't be +#DESC: blocked by creatures with flying" +[INIT] +combatattackers +[PLAYER1] +inplay:Gnat Alley Creeper +[PLAYER2] +inplay:Suntail Hawk +[DO] +Gnat Alley Creeper +next +Suntail Hawk +next +next +[ASSERT] +combatend +[PLAYER1] +inplay:Gnat Alley Creeper +[PLAYER2] +inplay:Suntail Hawk +life:17 +[END] diff --git a/projects/mtg/bin/Res/test/gnat_alley_creeper2.txt b/projects/mtg/bin/Res/test/gnat_alley_creeper2.txt new file mode 100644 index 000000000..a2e20c45e --- /dev/null +++ b/projects/mtg/bin/Res/test/gnat_alley_creeper2.txt @@ -0,0 +1,23 @@ +#NAME: Gnat Alley Creeper 2 +#DESC: checks the ability "can't be +#DESC: blocked by creatures with flying" +#DESC: Pass 2: Does normal blocking work? +[INIT] +combatattackers +[PLAYER1] +inplay:Gnat Alley Creeper +[PLAYER2] +inplay:Raging Goblin +[DO] +Gnat Alley Creeper +next +Raging Goblin +next +next +[ASSERT] +combatend +[PLAYER1] +graveyard:Gnat Alley Creeper +[PLAYER2] +graveyard:Raging Goblin +[END] diff --git a/projects/mtg/bin/Res/test/juggernaut.txt b/projects/mtg/bin/Res/test/juggernaut.txt new file mode 100644 index 000000000..dcd3d58b4 --- /dev/null +++ b/projects/mtg/bin/Res/test/juggernaut.txt @@ -0,0 +1,23 @@ +#NAME: Juggernaut +#DESC: checks Juggernaut's ability +#DESC: "can't be blocked by walls" +[INIT] +combatattackers +[PLAYER1] +inplay:Juggernaut +[PLAYER2] +inplay:Wall of Stone +[DO] +Juggernaut +next +Wall of Stone +next +next +[ASSERT] +combatend +[PLAYER1] +inplay:Juggernaut +[PLAYER2] +inplay:Wall of Stone +life:15 +[END] diff --git a/projects/mtg/include/AllAbilities.h b/projects/mtg/include/AllAbilities.h index 45e2c4edd..629343e2b 100644 --- a/projects/mtg/include/AllAbilities.h +++ b/projects/mtg/include/AllAbilities.h @@ -1190,6 +1190,38 @@ class AProtectionFrom: public MTGAbility{ }; +//Can't be blocked by... +class ACantBeBlockedBy: public MTGAbility{ + public: + TargetChooser * fromTc; + ACantBeBlockedBy(int id, MTGCardInstance * _source, MTGCardInstance * _target, TargetChooser *fromTc):MTGAbility(id,_source,_target),fromTc(fromTc){ + + } + + int addToGame(){ + MTGCardInstance * _target = (MTGCardInstance *)target; + _target->addCantBeBlockedBy(fromTc); + return MTGAbility::addToGame(); + } + + int destroy(){ + ((MTGCardInstance *)target)->removeCantBeBlockedBy(fromTc); + return 1; + } + + ACantBeBlockedBy * clone() const{ + ACantBeBlockedBy * a = NEW ACantBeBlockedBy(*this); + a->isClone = 1; + return a; + } + + ~ACantBeBlockedBy(){ + SAFE_DELETE(fromTc); + } + +}; + + //Alteration of Power and Toughness (enchantments) class APowerToughnessModifier: public MTGAbility{ public: diff --git a/projects/mtg/include/MTGCardInstance.h b/projects/mtg/include/MTGCardInstance.h index 7668e944f..413ba8df6 100644 --- a/projects/mtg/include/MTGCardInstance.h +++ b/projects/mtg/include/MTGCardInstance.h @@ -123,6 +123,11 @@ class MTGCardInstance: public CardPrimitive, public MTGCard, public Damageable { int removeProtection(TargetChooser *tc, int erase = 0); int protectedAgainst(MTGCardInstance * card); + vectorcantBeBlockedBys; + int addCantBeBlockedBy(TargetChooser * tc); + int removeCantBeBlockedBy(TargetChooser *tc, int erase = 0); + int cantBeBlockedBy(MTGCardInstance * card); + void copy(MTGCardInstance * card); void setUntapping(); diff --git a/projects/mtg/src/MTGAbility.cpp b/projects/mtg/src/MTGAbility.cpp index f7dfee979..0a4252a05 100644 --- a/projects/mtg/src/MTGAbility.cpp +++ b/projects/mtg/src/MTGAbility.cpp @@ -737,22 +737,6 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG return a; } - //Gain/loose Ability - for (int j = 0; j < Constants::NB_BASIC_ABILITIES; j++){ - found = s.find(Constants::MTGBasicAbilities[j]); - if (found == 0 || found == 1){ - int modifier = 1; - if (found > 0 && s[found-1] == '-') modifier = 0; - if (!activated){ - if(card->hasType("instant") || card->hasType("sorcery") || forceUEOT){ - return NEW AInstantBasicAbilityModifierUntilEOT(id, card,target, j,modifier); - } - return NEW ABasicAbilityModifier(id, card,target, j,modifier); - } - return NEW ABasicAbilityAuraModifierUntilEOT(id, card,target, NULL,j,modifier); - } - } - //Protection from... found = s.find("protection from("); if (found == 0){ @@ -771,6 +755,40 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG return NULL; //TODO } + //Can't be blocked by... + found = s.find("cantbeblockedby("); + if (found == 0){ + size_t end = s.find (")", found); + string targets = s.substr(found+16,end - found - 16); + TargetChooserFactory tcf; + TargetChooser * fromTc = tcf.createTargetChooser(targets, card); + if (!fromTc) return NULL; + //default target zone to opponentbattlefield here? + if (!activated){ + if(card->hasType("instant") || card->hasType("sorcery") || forceUEOT){ + return NULL; //TODO + } + return NEW ACantBeBlockedBy(id, card,target,fromTc); + } + return NULL; //TODO + } + + //Gain/loose simple Ability + for (int j = 0; j < Constants::NB_BASIC_ABILITIES; j++){ + found = s.find(Constants::MTGBasicAbilities[j]); + if (found == 0 || found == 1){ + int modifier = 1; + if (found > 0 && s[found-1] == '-') modifier = 0; + if (!activated){ + if(card->hasType("instant") || card->hasType("sorcery") || forceUEOT){ + return NEW AInstantBasicAbilityModifierUntilEOT(id, card,target, j,modifier); + } + return NEW ABasicAbilityModifier(id, card,target, j,modifier); + } + return NEW ABasicAbilityAuraModifierUntilEOT(id, card,target, NULL,j,modifier); + } + } + //Untapper (Ley Druid...) found = s.find("untap"); if (found != string::npos){ @@ -845,6 +863,9 @@ int AbilityFactory::abilityEfficiency(MTGAbility * a, Player * p, int mode, Targ if (APowerToughnessModifier * abi = dynamic_cast(a)) return (abi->wppt->power.getValue()>=0 && abi->wppt->toughness.getValue()>=0) ? BAKA_EFFECT_GOOD : BAKA_EFFECT_BAD; if (APowerToughnessModifierUntilEndOfTurn * abi = dynamic_cast(a)) return abilityEfficiency(abi->ability, p, mode,tc); + if (dynamic_cast(a)) return BAKA_EFFECT_GOOD; + if (dynamic_cast(a)) return BAKA_EFFECT_GOOD; + map badAbilities; badAbilities[Constants::CANTATTACK] = true; badAbilities[Constants::CANTBLOCK] = true; diff --git a/projects/mtg/src/MTGCardInstance.cpp b/projects/mtg/src/MTGCardInstance.cpp index 87c2a9b8b..30f8792fe 100644 --- a/projects/mtg/src/MTGCardInstance.cpp +++ b/projects/mtg/src/MTGCardInstance.cpp @@ -353,6 +353,7 @@ int MTGCardInstance::canBlock(MTGCardInstance * opponent){ if (!opponent->isAttacker()) return 0; // Comprehensive rule 502.7f : If a creature with protection attacks, it can't be blocked by creatures that have the stated quality. if (opponent->protectedAgainst(this)) return 0; + if (opponent->cantBeBlockedBy(this)) return 0; if (opponent->basicAbilities[Constants::UNBLOCKABLE]) return 0; if (opponent->basicAbilities[Constants::FEAR] && !(hasColor(Constants::MTG_COLOR_ARTIFACT) || hasColor(Constants::MTG_COLOR_BLACK))) return 0; @@ -569,6 +570,33 @@ int MTGCardInstance::protectedAgainst(MTGCardInstance * card){ return 0; } + +int MTGCardInstance::addCantBeBlockedBy(TargetChooser * tc){ + cantBeBlockedBys.push_back(tc); + return cantBeBlockedBys.size(); +} + +int MTGCardInstance::removeCantBeBlockedBy(TargetChooser * tc, int erase){ + for (size_t i = 0; i < cantBeBlockedBys.size() ; i++){ + if (cantBeBlockedBys[i] == tc){ + if (erase) delete (cantBeBlockedBys[i]); + cantBeBlockedBys.erase(cantBeBlockedBys.begin()+i); + return 1; + } + } + return 0; +} + +int MTGCardInstance::cantBeBlockedBy(MTGCardInstance * card){ + for (size_t i = 0; i < cantBeBlockedBys.size() ; i++){ + if (cantBeBlockedBys[i]->canTarget(card)) + return 1; + } + return 0; +} + + + /* Choose a sound sample to associate to that card */ JSample * MTGCardInstance::getSample(){ JSample * js;