From cf327ad0f7b22dfe6e3c089420050ae7cb6c2749 Mon Sep 17 00:00:00 2001 From: jendave Date: Sat, 6 Aug 2011 05:45:54 +0000 Subject: [PATCH] Added spCounter keyword, migrated old cards to it. Also modified ReadCard.Run() to output linenumber on exception. --- res/cards.txt | 499 ++++++++++++----- src/forge/CardFactory.java | 668 +++++++++++------------ src/forge/ComputerAI_counterSpells2.java | 30 +- src/forge/ReadCard.java | 7 +- 4 files changed, 685 insertions(+), 519 deletions(-) diff --git a/res/cards.txt b/res/cards.txt index 9da8b93eb8d..79eed830db3 100644 --- a/res/cards.txt +++ b/res/cards.txt @@ -1,3 +1,362 @@ +Absorb +W U U +Instant +Counter target spell. You gain 3 life. +spCounter:Spell:None:Graveyard:My-GainLife(3) +SVar:Rarity:Rare +SVar:Picture:http://resources.wizards.com/magic/cards/in/en-us/card23155.jpg + +Annul +U +Instant +Counter target artifact or enchantment spell. +spCounter:Spell:Type(Artifact,Enchantment):Graveyard:None +SVar:Rarity:Common + +Artifact Blast +R +Instant +Counter target artifact spell. +spCounter:Spell:Type(Artifact):Graveyard:None +SVar:Rarity:Common + +Assert Authority +5 U U +Instant +Counter target spell. If that spell is countered this way, exile it instead of putting it into its owner's graveyard. +spCounter:Spell:None:Exile:None +CostChange:Player:Less:1:Self:All:All:Affinity/Artifact +SVar:Rarity:Uncommon +SVar:Picture:http://www.wizards.com/global/images/magic/general/assert_authority.jpg + +Avoid Fate +G +Instant +Counter target instant or Aura spell that targets a permanent you control. +spCounter:Spell:Type(Instant,Aura) Targets(My-Creature,My-Enchantment,My-Artifact,My-Land,My-Equipment,My-Planeswalker):Graveyard:None +SVar:Rarity:Common + +Bind +1 G +Instant +Counter target activated ability. Draw a card. +spCounter:Ability:None:None:My-Draw(1) +SVar:Rarity:Rare + +Cancel +1 U U +Instant +Counter target spell. +spCounter:Spell::Graveyard:None +SVar:Rarity:Common +SVar:Picture:http://www.wizards.com/global/images/magic/general/cancel.jpg + +Confound +1 U +Instant +Counter target spell that targets one or more creatures. Draw a card. +spCounter:Spell:Targets(Creature):Graveyard:My-Draw(1) +SVar:Rarity:Common + +Counterspell +U U +Instant +Counter target spell. +spCounter:Spell:None:Graveyard:None +SVar:Rarity:Uncommon +SVar:Picture:http://resources.wizards.com/magic/cards/mm/en-us/card19570.jpg + +Countersquall +U B +Instant +Counter target noncreature spell. It's controller loses 2 life. +spCounter:Spell:Type(Non-Creature):Graveyard:Opp-LoseLife(2) +SVar:Rarity:Uncommon + +Dismal Failure +2 U U +Instant +Counter target spell. Its controller discards a card. +spCounter:Spell:None:Graveyard:Opp-Discard(1) +SVar:Rarity:Uncommon + +Dismiss +2 U U +Instant +Counter target spell. Draw a card. +spCounter:Spell:None:Graveyard:My-Draw(1) +SVar:Rarity:Uncommon +SVar:Picture:http://www.wizards.com/global/images/magic/general/dismiss.jpg + +Dispel +U +Instant +Counter target instant spell. +spCounter:Spell:Type(Instant):Graveyard:None +SVar:Rarity:Common + +Dissipate +1 U U +Instant +Counter target spell. If that spell is countered this way, exile it instead of putting it into its owner's graveyard. +spCounter:Spell:None:Exile:None +SVar:Rarity:Uncommon +SVar:Picture:http://www.wizards.com/global/images/magic/general/dissipate.jpg + +Dream Fracture +1 U U +Counter target spell. Its controller draws a card. Draw a card. +spCounter:Spell:None:Graveyard:My-Draw(1) Opp-Draw(1) +SVar:Rarity:Uncommon + +Envelop +U +Instant +Counter target sorcery spell. +spCounter:Spell:Type(Sorcery):Graveyard:None +SVar:Rarity:Common + +Essence Scatter +1 U +Instant +Counter target creature spell. +spCounter:Spell:Type(Creature):Graveyard:None +SVar:Rarity:Common +SVar:Picture:http://www.wizards.com/global/images/magic/general/essence_scatter.jpg + +Exclude +2 U +Instant +Counter target creature spell. Draw a card. +spCounter:Spell:Type(Creature):Graveyard:My-Draw(1) +SVar:Rarity:Common +SVar:Picture:http://www.wizards.com/global/images/magic/general/exclude.jpg + +Extinguish +2 U +Instant +Counter target sorcery spell. +spCounter:Spell:Type(Sorcery):Graveyard:None +SVar:Rarity:Common + +Faerie Trickery +1 U U +Tribal Instant Faerie +Counter target non-Faerie spell. If that spell is countered this way, exile it instead of putting it into its owner's graveyard. +spCounter:Spell:Type(Non-Faerie):Exile:None +SVar:Rarity:Common + +False Summoning +1 U +Instant +Counter target creature spell. +spCounter:Spell:Type(Creature):Graveyard:None +SVar:Rarity:Common +SVar:Picture:http://gatherer.wizards.com/handlers/image.ashx?multiverseid=6533&type=card + +Fervent Denial +3 U U +Instant +Counter target spell. +spCounter:Spell:None:Graveyard:None +Flashback:5 U U +SVar:Rarity:Uncommon + +Flash Counter +1 U +Instant +Counter target instant spell. +spCounter:Spell:Type(Instant):Graveyard:None +SVar:Rarity:Common + +Flashfreeze +1 U +Instant +Counter target red or green spell. +spCounter:Spell:Color(red,green):Graveyard:None +SVar:Rarity:Uncommon + +Frazzle +3 U +Instant +Counter target nonblue spell. +spCounter:Spell:Color(Non-blue):Graveyard:None +SVar:Rarity:Uncommon + +Gainsay +1 U +Instant +Counter target blue spell. +spCounter:Spell:Color(blue):Graveyard:None +SVar:Rarity:Uncommon + +Guttural Response +RG +Instant +Counter target blue instant spell. +spCounter:Spell:Type(Instant) Color(blue):Graveyard:None +SVar:Rarity:Uncommon + +Hisoka's Defiance +1 U +Instant +Counter target Spirit or Arcane spell. +spCounter:Spell:Type(Spirit,Arcane):Graveyard:None +SVar:Rarity:Common + +Intervene +U +Instant +Counter target spell that targets a creature. +spCounter:Spell:Targets(Creature):Graveyard:None +SVar:Rarity:Common + +Lapse of Certainty +2 W +Instant +Counter target spell. If that spell is countered this way, put it on top of its owner's library instead of into that player's graveyard. +spCounter:Spell:None:Topdeck:None +SVar:Rarity:Common + +Last Word +2 U U +Instant +Counter target spell. +spCounter:Spell:None:Graveyard:None +CARDNAME can't be countered. +SVar:Rarity:Rare +SVar:Picture:http://www.wizards.com/global/images/magic/general/last_word.jpg + +Liquify +2 U +Instant +Counter target spell with converted mana cost 3 or less. If that spell is countered this way, exile it instead of putting it into its owner's graveyard. +spCounter:Spell:CMC(<=,3):Exile:None +SVar:Rarity:Common + +Memory Lapse +1 U +Instant +Counter target spell. If that spell is countered this way, put it on top of its owner's library instead of into that player's graveyard. +spCounter:Spell:None:Topdeck:None +SVar:Rarity:Common + +Muddle the Mixture +U U +Instant +Counter target instant or sorcery spell. +spCounter:Spell:Type(Instant,Sorcery):Graveyard:None +Transmute:1 U U +SVar:Rarity:Common +SVar:Picture:http://www.wizards.com/global/images/magic/general/muddle_the_mixture.jpg + +Mystic Denial +1 U U +Instant +Counter target creature or sorcery spell. +spCounter:Spell:Type(Creature,Sorcery):Graveyard:None +SVar:Rarity:Uncommon + +Negate +1 U +Instant +Counter target noncreature spell. +spCounter:Spell:Type(Non-Creature):Graveyard:None +SVar:Rarity:Common + +Preemptive Strike +1 U +Instant +Counter target creature spell. +spCounter:Spell:Type(Creature):Graveyard:None +SVar:Rarity:Common +SVar:Picture:http://gatherer.wizards.com/handlers/image.ashx?multiverseid=10530&type=card + +Punish Ignorance +W U U B +Instant +Counter target spell. It's controller loses 3 life and you gain 3 life. +spCounter:Spell:None:Graveyard:Opp-LoseLife(3) My-GainLife(3) +SVar:Rarity:Rare +SVar:Picture:http://www.wizards.com/global/images/magic/general/punish_ignorance.jpg + +Rebuff the Wicked +W +Instant +Counter target spell that targets a permanent you control. +spCounter:Spell:Targets(My-Creature,My-Land,My-Enchantment,My-Artifact,My-Planeswalker,My-Equipment):Graveyard:None +SVar:Rarity:Uncommon + +Remand +1 U +Instant +Counter target spell.If that spell is countered this way, put it into it's owner's hand instead of into that player's library. Draw a card. +spCounter:Spell:None:Hand:My-Draw(1) +SVar:Rarity:Uncommon +SVar:Picture:http://resources.wizards.com/magic/cards/rav/en-us/card87919.jpg + +Remove Soul +1 U +Instant +Counter target creature spell. +spCounter:Spell:Type(Creature):Graveyard:None +SVar:Rarity:Common +SVar:Picture:http://resources.wizards.com/magic/cards/9ed/en-us/card83228.jpg + +Spell Snare +U +Instant +Counter target spell with converted mana cost 2. +spCounter:Spell:CMC(==,2):Graveyard:None +SVar:Rarity:Uncommon +SVar:Picture:http://www.wizards.com/global/images/magic/general/spell_snare.jpg + +Squelch +1 U +Instant +Counter target activated ability. Draw a card. +spCounter:Ability:None:None:My-Draw(1) +SVar:Rarity:Uncommon + +Stifle +U +Instant +Counter target activated or triggered ability. +spCounter:Ability:None:None:None +SVar:Rarity:Rare +SVar:Picture:http://www.wizards.com/global/images/magic/general/stifle.jpg + +Thoughtbind +2 U +Instant +Counter target spell with converted mana cost 4 or less. +spCounter:Spell:CMC(<=,4):Graveyard:None +SVar:Rarity:Common + +Traumatic Visions +3 U U +Instant +Counter target spell. +spCounter:Spell:None:Graveyard:None +TypeCycling:Basic:1 U +SVar:Rarity:Common +SVar:Picture:http://www.wizards.com/global/images/magic/general/traumatic_visions.jpg + +Undermine +U U B +Instant +Counter target spell. It's controller loses 3 life. +spCounter:Spell:None:Graveyard:Opp-LoseLife(3) +SVar:Rarity:Rare +SVar:Picture:http://resources.wizards.com/magic/cards/in/en-us/card23190.jpg + +Voidslime +G U U +Instant +Counter target spell, activated ability, or triggered ability. +spCounter:SpellOrAbility:None:Graveyard:None +SVar:Rarity:Rare + Surging AEther 3 U Instant @@ -382,13 +741,6 @@ All creatures gain protection from red. SVar:Rarity:Uncommon SVar:Picture:http://www.wizards.com/global/images/magic/general/absolute_law.jpg -Absorb -U U W -Instant -Counter target spell. You gain 3 life. -SVar:Rarity:Rare -SVar:Picture:http://resources.wizards.com/magic/cards/in/en-us/card23155.jpg - Absorb Vis 6 B Sorcery @@ -2096,14 +2448,6 @@ no text SVar:Rarity:Uncommon SVar:Picture:http://www.wizards.com/global/images/magic/general/assembly_worker.jpg -Assert Authority -5 U U -Instant -Affinity for artifacts (This spell costs 1 less to cast for each artifact you control.) Counter target spell. If that spell is countered this way, exile it instead of putting it into its owner's graveyard. -CostChange:Player:Less:1:Self:All:All:Affinity/Artifact -SVar:Rarity:Uncommon -SVar:Picture:http://www.wizards.com/global/images/magic/general/assert_authority.jpg - Astral Steel 2 W Instant @@ -4601,13 +4945,6 @@ If a source would deal 3 or less damage to Callous Giant, prevent that damage. SVar:Rarity:Rare SVar:Picture:http://www.wizards.com/global/images/magic/general/callous_giant.jpg -Cancel -1 U U -Instant -no text -SVar:Rarity:Common -SVar:Picture:http://www.wizards.com/global/images/magic/general/cancel.jpg - Canopy Spider 1 G Creature Spider @@ -6090,13 +6427,6 @@ SVar:RemAIDeck:True SVar:Rarity:Uncommon SVar:Picture:http://www.wizards.com/global/images/magic/general/counterbalance.jpg -Counterspell -U U -Instant -no text -SVar:Rarity:Uncommon -SVar:Picture:http://resources.wizards.com/magic/cards/mm/en-us/card19570.jpg - Courier Hawk 1 W Creature Bird @@ -7652,14 +7982,6 @@ spRaiseDead:1 SVar:Rarity:Common SVar:Picture:http://www.wizards.com/global/images/magic/general/disentomb.jpg -Dismiss -2 U U -Instant -Counter target spell. -Draw a card. -SVar:Rarity:Uncommon -SVar:Picture:http://www.wizards.com/global/images/magic/general/dismiss.jpg - Disorient 3 U Instant @@ -7676,13 +7998,6 @@ spBounceTgt:Permanent.nonLand:Hand SVar:Rarity:Common SVar:Picture:http://www.wizards.com/global/images/magic/general/disperse.jpg -Dissipate -1 U U -Instant -Counter target spell. If that spell is countered this way, exile it instead of putting it into its owner's graveyard. -SVar:Rarity:Uncommon -SVar:Picture:http://www.wizards.com/global/images/magic/general/dissipate.jpg - Distress B B Sorcery @@ -9104,13 +9419,6 @@ As long as you control another multicolored permanent, Esper Stormblade gets +1/ SVar:Rarity:Common SVar:Picture:http://www.wizards.com/global/images/magic/general/esper_stormblade.jpg -Essence Scatter -1 U -Instant -Counter target creature spell. -SVar:Rarity:Common -SVar:Picture:http://www.wizards.com/global/images/magic/general/essence_scatter.jpg - Essence Sliver 3 W Creature Sliver @@ -9281,14 +9589,6 @@ Morph:2 W W SVar:Rarity:Rare SVar:Picture:http://www.wizards.com/global/images/magic/general/exalted_angel.jpg -Exclude -2 U -Instant -Counter target creature spell. -Draw a card. -SVar:Rarity:Common -SVar:Picture:http://www.wizards.com/global/images/magic/general/exclude.jpg - Excommunicate 2 W Instant @@ -9521,13 +9821,6 @@ Return target creature card from your graveyard to the battlefield. SVar:Rarity:Common SVar:Picture:http://gatherer.wizards.com/handlers/image.ashx?multiverseid=10509&type=card -False Summoning -1 U -Instant -Counter target creature spell. -SVar:Rarity:Common -SVar:Picture:http://gatherer.wizards.com/handlers/image.ashx?multiverseid=6533&type=card - Fanatical Fever 2 G G Instant @@ -16594,14 +16887,6 @@ spDamageTgtC:2:Drawback$YouGainLife/2:Last Kiss deals 2 damage to target creatur SVar:Rarity:Common SVar:Picture:http://www.wizards.com/global/images/magic/general/last_kiss.jpg -Last Word -2 U U -Instant -no text -CARDNAME can't be countered. -SVar:Rarity:Rare -SVar:Picture:http://www.wizards.com/global/images/magic/general/last_word.jpg - Launch 1 U Enchantment Aura @@ -19320,14 +19605,6 @@ When Mudbutton Torchrunner is put into a graveyard from play, it deals 3 damage SVar:Rarity:Common SVar:Picture:http://www.wizards.com/global/images/magic/general/mudbutton_torchrunner.jpg -Muddle the Mixture -U U -Instant -no text -Transmute:1 U U -SVar:Rarity:Common -SVar:Picture:http://www.wizards.com/global/images/magic/general/muddle_the_mixture.jpg - Mul Daya Channelers 1 G G Creature Elf Druid Shaman @@ -21887,13 +22164,6 @@ First Strike SVar:Rarity:Rare SVar:Picture:http://www.wizards.com/global/images/magic/general/preeminent_captain.jpg -Preemptive Strike -1 U -Instant -Counter target creature spell. -SVar:Rarity:Common -SVar:Picture:http://gatherer.wizards.com/handlers/image.ashx?multiverseid=10530&type=card - Presence of the Wise 2 W W Sorcery @@ -22217,13 +22487,6 @@ Whenever Pulse Tracker attacks, each opponent loses 1 life. SVar:Rarity:Common SVar:Picture:http://www.wizards.com/global/images/magic/general/pulse_tracker.jpg -Punish Ignorance -W U U B -Instant -Counter target spell. Its controller loses 3 life and you gain 3 life. -SVar:Rarity:Rare -SVar:Picture:http://www.wizards.com/global/images/magic/general/punish_ignorance.jpg - Puppeteer 2 U Creature Human Wizard @@ -23128,14 +23391,6 @@ tap: add 1 SVar:Rarity:Uncommon SVar:Picture:http://www.wizards.com/global/images/magic/general/reliquary_tower.jpg -Remand -1 U -Instant -Counter target spell. If that spell is countered this way, put it into its owner's hand instead of into that player's graveyard. -Draw a card. -SVar:Rarity:Uncommon -SVar:Picture:http://resources.wizards.com/magic/cards/rav/en-us/card87919.jpg - Reminisce 2 U Sorcery @@ -23153,13 +23408,6 @@ Cycling:2 SVar:Rarity:Common SVar:Picture:http://www.wizards.com/global/images/magic/general/remote_isle.jpg -Remove Soul -1 U -Instant -Counter target creature spell. -SVar:Rarity:Common -SVar:Picture:http://resources.wizards.com/magic/cards/9ed/en-us/card83228.jpg - Rend Flesh 2 B Instant Arcane @@ -27138,13 +27386,6 @@ Counter target noncreature spell unless its controller pays 2. SVar:Rarity:Common SVar:Picture:http://www.wizards.com/global/images/magic/general/spell_pierce.jpg -Spell Snare -U -Instant -Counter target spell with converted mana cost 2. -SVar:Rarity:Uncommon -SVar:Picture:http://www.wizards.com/global/images/magic/general/spell_snare.jpg - Spell Snip 2 U Instant @@ -27841,13 +28082,6 @@ Vigilance SVar:Rarity:Common SVar:Picture:http://www.wizards.com/global/images/magic/general/steward_of_valeron.jpg -Stifle -U -Instant -no text -SVar:Rarity:Rare -SVar:Picture:http://www.wizards.com/global/images/magic/general/stifle.jpg - Stillmoon Cavalier 1 WB WB Creature Zombie Knight @@ -30515,14 +30749,6 @@ Persist SVar:Rarity:Common SVar:Picture:http://www.wizards.com/global/images/magic/general/trapjaw_kelpie.jpg -Traumatic Visions -3 U U -Instant -no text -TypeCycling:Basic:1 U -SVar:Rarity:Common -SVar:Picture:http://www.wizards.com/global/images/magic/general/traumatic_visions.jpg - Traumatize 3 U U Sorcery @@ -31037,13 +31263,6 @@ tap: add B SVar:Rarity:Rare SVar:Picture:http://www.wizards.com/global/images/magic/general/underground_sea.jpg -Undermine -U U B -Instant -Counter target spell. Its controller loses 3 life. -SVar:Rarity:Rare -SVar:Picture:http://resources.wizards.com/magic/cards/in/en-us/card23190.jpg - Underworld Dreams B B B Enchantment diff --git a/src/forge/CardFactory.java b/src/forge/CardFactory.java index c05322b4007..17e4aa38d02 100644 --- a/src/forge/CardFactory.java +++ b/src/forge/CardFactory.java @@ -10972,38 +10972,7 @@ public class CardFactory implements NewConstants { card.clearSpellAbility(); card.addSpellAbility(spell); }//*************** END ************ END ************************** - - //*************** START *********** START ************************** - else if(cardName.equals("Remove Soul") || cardName.equals("False Summoning") - || cardName.equals("Essence Scatter") || cardName.equals("Preemptive Strike")) { - SpellAbility spell = new Spell(card) { - private static final long serialVersionUID = 4685055135070191326L; - - @Override - public void resolve() { - SpellAbility sa = AllZone.Stack.pop(); - AllZone.GameAction.moveToGraveyard(sa.getSourceCard()); - } - - @Override - public boolean canPlay() { - if(AllZone.Stack.size() == 0) return false; - - //see if spell is on stack and that opponent played it - String opponent = AllZone.GameAction.getOpponent(card.getController()); - SpellAbility sa = AllZone.Stack.peek(); - - //is spell?, did opponent play it?, is this a creature spell? - return sa.isSpell() && opponent.equals(sa.getSourceCard().getController()) - && sa.getSourceCard().getType().contains("Creature") - && CardFactoryUtil.isCounterable(sa.getSourceCard()); - }//canPlay() - }; - card.clearSpellAbility(); - card.addSpellAbility(spell); - }//*************** END ************ END ************************** - //*************** START *********** START ************************** else if(cardName.equals("Spell Pierce")) { SpellAbility spell = new Spell(card) { @@ -11057,50 +11026,6 @@ public class CardFactory implements NewConstants { card.clearSpellAbility(); card.addSpellAbility(spell); }//*************** END ************ END ************************** - - //*************** START *********** START ************************** - else if(cardName.equals("Counterspell") || cardName.equals("Cancel") || cardName.equals("Last Word") - || cardName.equals("Traumatic Visions") || cardName.equals("Stifle")) { - SpellAbility spell = new Spell(card) { - private static final long serialVersionUID = -2489268054171391552L; - - @Override - public void resolve() { - SpellAbility sa = AllZone.Stack.pop(); - if(!cardName.equals("Stifle")) AllZone.GameAction.moveToGraveyard(sa.getSourceCard()); - } - - @Override - public boolean canPlay() { - if(AllZone.Stack.size() == 0) return false; - - //see if spell is on stack and that opponent played it - String opponent = AllZone.GameAction.getOpponent(card.getController()); - SpellAbility sa = AllZone.Stack.peek(); - - if(cardName.equals("Stifle")) return !sa.isSpell() - && CardFactoryUtil.isCounterable(sa.getSourceCard()); - - - return sa.isSpell() && opponent.equals(sa.getSourceCard().getController()) - && CardFactoryUtil.isCounterable(sa.getSourceCard()); - } - }; - card.clearSpellAbility(); - String desc = ""; - if(cardName.equals("Last Word")) { - desc = "Last Word can't be countered by spells or abilities.\r\n"; - } - if(cardName.equals("Stifle")) { - spell.setDescription(desc + "Counter target triggered or activated ability."); - spell.setStackDescription(card.getName() + " - Counters target triggered or activated ability."); - } else { - spell.setDescription(desc + "Counter target spell."); - spell.setStackDescription(card.getName() + " - Counters target spell."); - } - card.addSpellAbility(spell); - }//*************** END ************ END ************************** - //*************** START *********** START ************************** else if(cardName.equals("Mana Leak") || cardName.equals("Convolute") || cardName.equals("Daze") @@ -11238,39 +11163,6 @@ public class CardFactory implements NewConstants { } }//*************** END ************ END ************************** - - //*************** START *********** START ************************** - else if(cardName.equals("Remand")) { - SpellAbility spell = new Spell(card) { - private static final long serialVersionUID = 7259402997927108504L; - - @Override - public void resolve() { - //counter spell, return it to owner's hand - SpellAbility sa = AllZone.Stack.pop(); - PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, sa.getSourceCard().getOwner()); - AllZone.GameAction.moveTo(hand, sa.getSourceCard()); - - //draw card - // AllZone.GameAction.drawCard(card.getController()); - } - - @Override - public boolean canPlay() { - if(AllZone.Stack.size() == 0) return false; - - //see if spell is on stack and that opponent played it - String opponent = AllZone.GameAction.getOpponent(card.getController()); - SpellAbility sa = AllZone.Stack.peek(); - - return sa.isSpell() && opponent.equals(sa.getSourceCard().getController()) - && CardFactoryUtil.isCounterable(sa.getSourceCard()); - } - }; - card.clearSpellAbility(); - card.addSpellAbility(spell); - }//*************** END ************ END ************************** - /* Converted to keyword //*************** START *********** START ************************** else if(cardName.equals("Regress")) { @@ -13308,134 +13200,7 @@ public class CardFactory implements NewConstants { card.clearSpellAbility(); card.addSpellAbility(spell); }//*************** END ************ END ************************** - - - //*************** START *********** START ************************** - else if(cardName.equals("Absorb")) { - SpellAbility spell = new Spell(card) { - private static final long serialVersionUID = -2007620906017942538L; - - @Override - public void resolve() { - SpellAbility sa = AllZone.Stack.pop(); - AllZone.GameAction.moveToGraveyard(sa.getSourceCard()); - - PlayerLife life = AllZone.GameAction.getPlayerLife(card.getController()); - life.addLife(3); - } - - @Override - public boolean canPlay() { - if(AllZone.Stack.size() == 0) return false; - - //see if spell is on stack and that opponent played it - String opponent = AllZone.GameAction.getOpponent(card.getController()); - SpellAbility sa = AllZone.Stack.peek(); - - return sa.isSpell() && opponent.equals(sa.getSourceCard().getController()) - && CardFactoryUtil.isCounterable(sa.getSourceCard()); - } - }; - card.clearSpellAbility(); - card.addSpellAbility(spell); - }//*************** END ************ END ************************** - - //*************** START *********** START ************************** - else if(cardName.equals("Undermine")) { - SpellAbility spell = new Spell(card) { - private static final long serialVersionUID = -4999966043862729936L; - - @Override - public void resolve() { - SpellAbility sa = AllZone.Stack.pop(); - AllZone.GameAction.moveToGraveyard(sa.getSourceCard()); - - String opponent = AllZone.GameAction.getOpponent(card.getController()); - AllZone.GameAction.getPlayerLife(opponent).subtractLife(3,card); - - } - - @Override - public boolean canPlay() { - if(AllZone.Stack.size() == 0) return false; - - //see if spell is on stack and that opponent played it - String opponent = AllZone.GameAction.getOpponent(card.getController()); - SpellAbility sa = AllZone.Stack.peek(); - - return sa.isSpell() && opponent.equals(sa.getSourceCard().getController()) - && CardFactoryUtil.isCounterable(sa.getSourceCard()); - } - }; - card.clearSpellAbility(); - card.addSpellAbility(spell); - }//*************** END ************ END ************************** - - //*************** START *********** START ************************** - else if(cardName.equals("Punish Ignorance")) { - SpellAbility spell = new Spell(card) { - private static final long serialVersionUID = 6845184687406705133L; - - @Override - public void resolve() { - SpellAbility sa = AllZone.Stack.pop(); - AllZone.GameAction.moveToGraveyard(sa.getSourceCard()); - - String opponent = AllZone.GameAction.getOpponent(card.getController()); - AllZone.GameAction.getPlayerLife(opponent).subtractLife(3,card); - - String player = card.getController(); - AllZone.GameAction.getPlayerLife(player).addLife(3); - - } - - @Override - public boolean canPlay() { - if(AllZone.Stack.size() == 0) return false; - - //see if spell is on stack and that opponent played it - String opponent = AllZone.GameAction.getOpponent(card.getController()); - SpellAbility sa = AllZone.Stack.peek(); - - return sa.isSpell() && opponent.equals(sa.getSourceCard().getController()) - && CardFactoryUtil.isCounterable(sa.getSourceCard()); - } - }; - card.clearSpellAbility(); - card.addSpellAbility(spell); - }//*************** END ************ END ************************** - - //*************** START *********** START ************************** - else if(cardName.equals("Exclude")) { - SpellAbility spell = new Spell(card) { - private static final long serialVersionUID = -5615796501064636046L; - - @Override - public void resolve() { - SpellAbility sa = AllZone.Stack.pop(); - AllZone.GameAction.moveToGraveyard(sa.getSourceCard()); - // AllZone.GameAction.drawCard(card.getController()); - } - - @Override - public boolean canPlay() { - if(AllZone.Stack.size() == 0) return false; - - //see if spell is on stack and that opponent played it - String opponent = AllZone.GameAction.getOpponent(card.getController()); - SpellAbility sa = AllZone.Stack.peek(); - - //is spell?, did opponent play it?, is this a creature spell? - return sa.isSpell() && opponent.equals(sa.getSourceCard().getController()) - && sa.getSourceCard().getType().contains("Creature") - && CardFactoryUtil.isCounterable(sa.getSourceCard()); - }//canPlay() - }; - card.clearSpellAbility(); - card.addSpellAbility(spell); - }//*************** END ************ END ************************** - //*************** START *********** START ************************** else if(cardName.equals("Eladamri's Call")) { final SpellAbility spell = new Spell(card) { @@ -13494,37 +13259,7 @@ public class CardFactory implements NewConstants { card.clearSpellAbility(); card.addSpellAbility(spell); }//*************** END ************ END ************************** - - //*************** START *********** START ************************** - else if(cardName.equals("Dismiss")) { - SpellAbility spell = new Spell(card) { - private static final long serialVersionUID = -7959473218345045760L; - - @Override - public void resolve() { - SpellAbility sa = AllZone.Stack.pop(); - AllZone.GameAction.moveToGraveyard(sa.getSourceCard()); - - // AllZone.GameAction.drawCard(card.getController()); - - } - - @Override - public boolean canPlay() { - if(AllZone.Stack.size() == 0) return false; - - //see if spell is on stack and that opponent played it - String opponent = AllZone.GameAction.getOpponent(card.getController()); - SpellAbility sa = AllZone.Stack.peek(); - - return sa.isSpell() && opponent.equals(sa.getSourceCard().getController()) - && CardFactoryUtil.isCounterable(sa.getSourceCard()); - } - }; - card.clearSpellAbility(); - card.addSpellAbility(spell); - }//*************** END ************ END ************************** - + //*************** START *********** START ************************** else if(cardName.equals("Global Ruin")) { final CardList target = new CardList(); @@ -17788,35 +17523,6 @@ public class CardFactory implements NewConstants { ability.setBeforePayMana(runtime); }//*************** END ************ END ************************** - - //*************** START *********** START ************************** - else if(cardName.equals("Spell Snare")) { - SpellAbility spell = new Spell(card) { - private static final long serialVersionUID = -3254886985412814994L; - - @Override - public void resolve() { - SpellAbility sa = AllZone.Stack.pop(); - AllZone.GameAction.moveToGraveyard(sa.getSourceCard()); - } - - @Override - public boolean canPlay() { - if(AllZone.Stack.size() == 0) return false; - - //see if spell is on stack and that opponent played it - String opponent = AllZone.GameAction.getOpponent(card.getController()); - SpellAbility sa = AllZone.Stack.peek(); - - return sa.isSpell() && opponent.equals(sa.getSourceCard().getController()) - && CardFactoryUtil.isCounterable(sa.getSourceCard()) - && CardUtil.getConvertedManaCost(sa.getSourceCard().getManaCost()) == 2; - } - }; - card.clearSpellAbility(); - card.addSpellAbility(spell); - }//*************** END ************ END ************************** - //*************** START *********** START ************************** else if(cardName.equals("Time Walk") || cardName.equals("Temporal Manipulation") @@ -19118,7 +18824,7 @@ public class CardFactory implements NewConstants { if (getSourceCard().getAttachedCards().length > 0) { Card c = copyCard(getSourceCard().getAttachedCards()[0]); - if (c.getName().equals("Counterspell") || c.getName().equals("Stifle")) + if (ComputerAI_counterSpells2.KeywordedCounterspells.contains(c.getName())) { SpellAbility sa = c.getSpellAbility()[0]; return sa.canPlay(); @@ -21981,35 +21687,6 @@ public class CardFactory implements NewConstants { card.addSpellAbility(spell); }// *************** END ************ END ************************** - //*************** START *********** START ************************** - else if(cardName.equals("Dissipate") || cardName.equals("Assert Authority")) { - SpellAbility spell = new Spell(card) { - private static final long serialVersionUID = 4165714000804564686L; - - @Override - public void resolve() { - //counter spell, remove it from the game - SpellAbility sa = AllZone.Stack.pop(); - PlayerZone rfg = AllZone.getZone(Constant.Zone.Removed_From_Play, sa.getSourceCard().getOwner()); - AllZone.GameAction.moveTo(rfg, sa.getSourceCard()); - } - - @Override - public boolean canPlay() { - if(AllZone.Stack.size() == 0) return false; - - //see if spell is on stack and that opponent played it - String opponent = AllZone.GameAction.getOpponent(card.getController()); - SpellAbility sa = AllZone.Stack.peek(); - - return sa.isSpell() && opponent.equals(sa.getSourceCard().getController()) - && CardFactoryUtil.isCounterable(sa.getSourceCard()); - } - }; - card.clearSpellAbility(); - card.addSpellAbility(spell); - }//*************** END ************ END ************************** - //*************** START *********** START ************************** else if(cardName.equals("Acidic Soil")) { /* @@ -23518,41 +23195,7 @@ public class CardFactory implements NewConstants { }//canPlayAI });//addSpellAbility }//*************** END ************ END ************************** - - //*************** START *********** START ************************** - else if(cardName.equals("Muddle the Mixture")) { - /* - * This card can not be used by the computer at this time. - */ - SpellAbility spell = new Spell(card) { - private static final long serialVersionUID = -2489268054171391552L; - @Override - public void resolve() { - SpellAbility sa = AllZone.Stack.pop(); - AllZone.GameAction.moveToGraveyard(sa.getSourceCard()); - }//resolve() - - @Override - public boolean canPlay() { - if(AllZone.Stack.size() == 0) return false; - - //see if spell is on stack and that opponent played it - String opponent = AllZone.GameAction.getOpponent(card.getController()); - SpellAbility sa = AllZone.Stack.peek(); - - return sa.isSpell() - && opponent.equals(sa.getSourceCard().getController()) - && CardFactoryUtil.isCounterable(sa.getSourceCard()) - && (sa.getSourceCard().isInstant() || sa.getSourceCard().isSorcery()); - }//canPlay() - };//SpellAbility - card.clearSpellAbility(); - spell.setDescription("Counter target instant or sorcery spell."); - spell.setStackDescription("Muddle The Mixture - Counters target instant or sorcery."); - card.addSpellAbility(spell); - }//*************** END ************ END ************************** - //*************** START ********** START ************************* if (cardName.equals("Destructive Force") || cardName.equals("Wildfire")) { @@ -23867,6 +23510,313 @@ public class CardFactory implements NewConstants { card.addChangeControllerCommand(controllerChanges); } //HandSize + if(hasKeyword(card,"spCounter") != -1) { + System.out.println("Processing spCounter for card " + card.getName()); + ComputerAI_counterSpells2.KeywordedCounterspells.add(card.getName()); + String keyword = card.getKeyword().get(hasKeyword(card,"spCounter")); + if(keyword.contains("X")) + { + keyword = keyword.replace("X", card.getSVar("X")); + } + card.removeIntrinsicKeyword(keyword); + + String[] splitkeyword = keyword.split(":"); + + final String TargetType = splitkeyword[1]; + final String TargetingRestrictions = splitkeyword[2]; + final String Destination = splitkeyword[3]; + final String ExtraActions = splitkeyword[4]; + + final String[] SplitTargetingRestrictions = TargetingRestrictions.split(" "); + final String[] SplitExtraActions = ExtraActions.split(" "); + + SpellAbility spCounterAbility = new Spell(card) + { + private static final long serialVersionUID = 9763720166553L; + + @Override + public boolean canPlayAI() + { + System.out.println("AI is pondering us..."); + return canPlay(); + } + + @Override + public boolean canPlay() + { + if(AllZone.Stack.size() == 0) + { + return false; + } + + boolean fullResult = true; + SpellAbility sa = AllZone.Stack.peek(); + Card tgtCard = sa.getSourceCard(); + + if(TargetType.equals("Spell")) + { + if(sa.isAbility()) + { + System.out.println(card.getName() + " can only counter spells, not abilities."); + return false; + + } + } + else if(TargetType.equals("Ability")) + { + if(sa.isSpell()) + { + System.out.println(card.getName() + " can only counter abilities, not spells."); + return false; + } + } + else if(TargetType.equals("SpellOrAbility")) + { + //Do nothing. This block is only for clarity and enforcing parameters. + } + else + { + throw new IllegalArgumentException("Invalid target type for card " + card.getName()); + } + + for(int i=0;i")) + { + subResult |= (CardUtil.getConvertedManaCost(tgtCard) > value); + } + else if(mode.equals("==")) + { + subResult |= (CardUtil.getConvertedManaCost(tgtCard) == value); + } + else if(mode.equals("!=")) + { + subResult |= (CardUtil.getConvertedManaCost(tgtCard) != value); + } + else if(mode.equals("<=")) + { + subResult |= (CardUtil.getConvertedManaCost(tgtCard) <= value); + } + else if(mode.equals(">=")) + { + subResult |= (CardUtil.getConvertedManaCost(tgtCard) >= value); + } + else + { + throw new IllegalArgumentException("spCounter: Invalid mode parameter to CMC restriction in card " + card.getName()); + } + } + else if(RestrictionID.equals("Targets")) + { + for(int p=0;p permanent + { + if(sa.getTargetCard().getController() != card.getController()) + { + return false; + } + if(SplitParameters[p].contains("Non-")) + { + subResult |= !sa.getTargetCard().getType().contains(SplitParameters[p].substring(7)); + } + else + { + subResult |= (sa.getTargetCard().getType().contains(SplitParameters[p].substring(3))); + } + } + else if(SplitParameters[p].startsWith("Opp-")) //Targets opponent's permanent + { + if(sa.getTargetCard().getController() == card.getController()) + { + return false; + } + + if(SplitParameters[p].contains("Non-")) + { + subResult |= !(sa.getTargetCard().getType().contains(SplitParameters[p].substring(8))); + } + else + { + subResult |= (sa.getTargetCard().getType().contains(SplitParameters[p].substring(4))); + } + } + else + { + if(SplitParameters[p].contains("Non-")) + { + subResult |= !(sa.getTargetCard().getType().contains(SplitParameters[p].substring(4))); + } + else + { + subResult |= (sa.getTargetCard().getType().contains(SplitParameters[p])); + } + } + } + } + System.out.println("Sub: " + Boolean.toString(subResult)); + fullResult &= subResult; + } //End Targeting parsing + System.out.println("Success: " + Boolean.toString(fullResult)); + return fullResult; + } + + @Override + public void resolve() + { + System.out.println("Resolving " + card.getName()); + SpellAbility sa = AllZone.Stack.pop(); + + System.out.println("Send countered spell to " + Destination); + + if(Destination.equals("None") || TargetType.contains("Ability")) //For Ability-targeting counterspells + { + + } + else if(Destination.equals("Graveyard")) + { + AllZone.GameAction.moveToGraveyard(sa.getSourceCard()); + } + else if(Destination.equals("Exile")) + { + AllZone.GameAction.exile(sa.getSourceCard()); + } + else if(Destination.equals("Topdeck")) + { + AllZone.GameAction.moveToTopOfLibrary(sa.getSourceCard()); + } + else if(Destination.equals("Hand")) + { + AllZone.GameAction.moveToHand(sa.getSourceCard()); + } + else if(Destination.equals("BottomDeck")) + { + AllZone.GameAction.moveToBottomOfLibrary(sa.getSourceCard()); + } + else if(Destination.equals("Shuffle")) + { + AllZone.GameAction.moveToBottomOfLibrary(sa.getSourceCard()); + AllZone.GameAction.shuffle(sa.getSourceCard().getController()); + } + else + { + throw new IllegalArgumentException("spCounter: Invalid Destination argument for card " + card.getName()); + } + + for(int ea = 0;ea KeywordedCounterspells = new ArrayList(); + public static void counter_Spell(SpellAbility sa) { CardList counterSpells = getPlayableCounterSpells(sa); @@ -24,16 +28,11 @@ public class ComputerAI_counterSpells2 { public static CardList getPlayableCounterSpells(final SpellAbility sa){ final String[] basic = { - "Counterspell", "Remand", "Cancel", "Mystic Snake", "Absorb", "Undermine", "Punish Ignorance", - "Dismiss", "Last Word", "Dissipate", "Assert Authority" /*, "Force of Will", "Thwart" */ + "Mystic Snake"/*, "Force of Will", "Thwart" */ }; final String[] creature = { - "Exclude", "Overwhelming Intellect", "Preemptive Strike", "Remove Soul", "Essence Scatter", "False Summoning" - }; - - final String[] nonCreature = { - "" + "Overwhelming Intellect" }; final String[] nonCreatureUnlessPay2 = { @@ -51,7 +50,7 @@ public class ComputerAI_counterSpells2 { final String[] unlessPay4 = { "Convolute" }; - + final int usableManaSources = CardFactoryUtil.getUsableManaSources(Constant.Player.Human); PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, Constant.Player.Computer); @@ -60,13 +59,11 @@ public class ComputerAI_counterSpells2 { { public boolean addCard(Card c) { - if(sa.getSourceCard().getType().contains("Sorcery") || sa.getSourceCard().getType().contains("Instant")) { - if(c.getName().equals("Muddle the Mixture")) - return true; + if(KeywordedCounterspells.contains(c.getName())) + { + System.out.println("Counterspell is keyworded, casting is a-go."); + return c.getSpells().get(0).canPlayAI(); } - if (CardUtil.getConvertedManaCost(sa.getSourceCard().getManaCost()) == 2) - if (c.getName().equals("Spell Snare")) - return true; if (usableManaSources == 0) { if (checkArray(c, unlessPay1)) @@ -87,11 +84,6 @@ public class ComputerAI_counterSpells2 { if (checkArray(c, creature)) return true; } - - else if (!sa.getSourceCard().isCreature()) { - if (checkArray(c, nonCreature)) - return true; - } else if (!sa.getSourceCard().isCreature() && usableManaSources < 2) { if (checkArray(c, nonCreatureUnlessPay2)) diff --git a/src/forge/ReadCard.java b/src/forge/ReadCard.java index 1c2dcd8b6fd..c4745c7d5ba 100644 --- a/src/forge/ReadCard.java +++ b/src/forge/ReadCard.java @@ -64,10 +64,12 @@ public class ReadCard implements Runnable, NewConstants { Card c; String s = readLine(); ArrayList cardNames = new ArrayList(); + int linenum = 1; while(!s.equals("End")) { c = new Card(); - if(s.equals("")) throw new RuntimeException("ReadCard : run() reading error, cardname is blank"); + if(s.equals("")) throw new RuntimeException("ReadCard : run() reading error, cardname is blank! Line: " + Integer.toString(linenum)); + linenum += 4; c.setName(s); //for debugging @@ -93,13 +95,16 @@ public class ReadCard implements Runnable, NewConstants { c.setBaseAttack(att); c.setBaseDefense(def); s = readLine(); + linenum++; } while(!s.equals("")) { c.addIntrinsicKeyword(s); s = readLine(); + linenum++; } s = readLine(); + linenum++; if(cardNames.contains(c.getName())) { System.out.println("ReadCard:run() error - duplicate card name: " + c.getName());