From dc515bdf495ff0992318ee80b45192ce181fac8c Mon Sep 17 00:00:00 2001 From: jendave Date: Sat, 6 Aug 2011 10:36:06 +0000 Subject: [PATCH] - Added AbilityFactory_Destroy. - Added Abolish. --- .gitattributes | 2 + res/cardsfolder/abolish.txt | 9 + src/forge/AbilityFactory.java | 8 + src/forge/AbilityFactory_Destroy.java | 231 ++++++++++++++++++++++++++ 4 files changed, 250 insertions(+) create mode 100644 res/cardsfolder/abolish.txt create mode 100644 src/forge/AbilityFactory_Destroy.java diff --git a/.gitattributes b/.gitattributes index 0fcb54a2923..716c4960b22 100644 --- a/.gitattributes +++ b/.gitattributes @@ -18,6 +18,7 @@ res/cards.txt -text svneol=native#text/plain res/cardsScript.py -text svneol=native#text/x-python res/cardsfolder/abandoned_outpost.txt -text svneol=native#text/plain res/cardsfolder/abbey_gargoyles.txt -text svneol=native#text/plain +res/cardsfolder/abolish.txt -text svneol=native#text/plain res/cardsfolder/abomination.txt -text svneol=native#text/plain res/cardsfolder/aboshan_cephalid_emperor.txt -text svneol=native#text/plain res/cardsfolder/aboshans_desire.txt -text svneol=native#text/plain @@ -5618,6 +5619,7 @@ src/forge/AbilityFactory_Bounce.java -text svneol=native#text/plain src/forge/AbilityFactory_Combat.java -text svneol=native#text/plain src/forge/AbilityFactory_Counters.java -text svneol=native#text/plain src/forge/AbilityFactory_DealDamage.java -text svneol=native#text/plain +src/forge/AbilityFactory_Destroy.java -text svneol=native#text/plain src/forge/AbilityFactory_Fetch.java -text svneol=native#text/plain src/forge/AbilityFactory_PermanentState.java -text svneol=native#text/plain src/forge/AbilityFactory_Pump.java -text svneol=native#text/plain diff --git a/res/cardsfolder/abolish.txt b/res/cardsfolder/abolish.txt new file mode 100644 index 00000000000..32b083c1b58 --- /dev/null +++ b/res/cardsfolder/abolish.txt @@ -0,0 +1,9 @@ +Name:Abolish +ManaCost:1 W W +Types:Instant +Text:no text +A:SP$Destroy|Cost$1 W W|ValidTgts$Artifact,Enchantment|TgtPrompt$Select target artifact or enchantment|SpellDescription$Destroy target artifact or enchantment. +SVar:AltCost:Discard<1/Plains> +SVar:Rarity:Uncommon +SVar:Picture:http://www.wizards.com/global/images/magic/general/abolish.jpg +End diff --git a/src/forge/AbilityFactory.java b/src/forge/AbilityFactory.java index f4b36250f88..650e073d8b5 100644 --- a/src/forge/AbilityFactory.java +++ b/src/forge/AbilityFactory.java @@ -288,6 +288,14 @@ public class AbilityFactory { } } + if (API.equals("Destroy")){ + if (isAb) + SA = AbilityFactory_Destroy.createAbilityDestroy(this); + if (isSp){ + SA = AbilityFactory_Destroy.createSpellDestroy(this); + } + } + // ********************************************* // set universal properties of the SpellAbility if (hasSpDesc) diff --git a/src/forge/AbilityFactory_Destroy.java b/src/forge/AbilityFactory_Destroy.java new file mode 100644 index 00000000000..f5ca7daa715 --- /dev/null +++ b/src/forge/AbilityFactory_Destroy.java @@ -0,0 +1,231 @@ +package forge; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Random; + +public class AbilityFactory_Destroy { + // An AbilityFactory subclass for destroying permanents + + public static SpellAbility createAbilityDestroy(final AbilityFactory AF){ + + final SpellAbility abDestroy = new Ability_Activated(AF.getHostCard(), AF.getAbCost(), AF.getAbTgt()){ + private static final long serialVersionUID = -4153613567150919283L; + + final AbilityFactory af = AF; + final HashMap params = af.getMapParams(); + + final boolean noRegen = params.containsKey("NoRegen"); + + @Override + public String getStackDescription(){ + // when getStackDesc is called, just build exactly what is happening + + StringBuilder sb = new StringBuilder(); + String name = af.getHostCard().getName(); + String targetname = ""; + + Card tgt = getTargetCard(); + if (tgt != null) + targetname = tgt.getName(); + else + targetname = name; + + sb.append(name).append(" - Destroy ").append(targetname); + + if(noRegen) + sb.append(". It can't be regenerated"); + + return sb.toString(); + } + + public boolean canPlay(){ + // super takes care of AdditionalCosts + return super.canPlay(); + } + + public boolean canPlayAI() + { + return destroyCanPlayAI(af, this, noRegen); + } + + @Override + public void resolve() { + destroyResolve(af, this, noRegen); + } + + }; + return abDestroy; + } + + public static SpellAbility createSpellDestroy(final AbilityFactory AF){ + final SpellAbility spDestroy = new Spell(AF.getHostCard(), AF.getAbCost(), AF.getAbTgt()){ + private static final long serialVersionUID = -317810567632846523L; + + final AbilityFactory af = AF; + final HashMap params = af.getMapParams(); + + final boolean noRegen = params.containsKey("NoRegen"); + + @Override + public String getStackDescription(){ + // when getStackDesc is called, just build exactly what is happening + + StringBuilder sb = new StringBuilder(); + String name = af.getHostCard().getName(); + String targetname = ""; + + Card tgt = getTargetCard(); + if (tgt != null) + targetname = tgt.getName(); + else + targetname = name; + + sb.append(name).append(" - Destroy ").append(targetname); + + if(noRegen) + sb.append(". It can't be regenerated"); + + return sb.toString(); + } + + public boolean canPlay(){ + // super takes care of AdditionalCosts + return super.canPlay(); + } + + public boolean canPlayAI() + { + return destroyCanPlayAI(af, this, noRegen); + } + + @Override + public void resolve() { + destroyResolve(af, this, noRegen); + } + + }; + return spDestroy; + } + + public static boolean destroyCanPlayAI(final AbilityFactory af, final SpellAbility sa, final boolean noRegen){ + // AI needs to be expanded, since this function can be pretty complex based on what the expected targets could be + Random r = new Random(); + Ability_Cost abCost = sa.getPayCosts(); + Target abTgt = sa.getTarget(); + final Card source = sa.getSourceCard(); + CardList list; + + list = new CardList(AllZone.getZone(Constant.Zone.Play, AllZone.HumanPlayer).getCards()); + list = list.filter(new CardListFilter() { + public boolean addCard(Card c) { + return CardFactoryUtil.canTarget(source, c); + } + }); + + if (abTgt != null){ + list = list.getValidCards(abTgt.getValidTgts(), source.getController(), source); + list = list.getNotKeyword("Indestructible"); + + //TODO: Check for Regeneration + + if (list.size() == 0) + return false; + } + + if (abCost != null){ + // AI currently disabled for some costs + if (abCost.getSacCost()){ + return false; + } + if (abCost.getLifeCost()){ + if (AllZone.ComputerPlayer.getLife() - abCost.getLifeAmount() < 4) + return false; + } + if (abCost.getDiscardCost()) return false; + + if (abCost.getSubCounter()){ + // OK + } + } + + if (!ComputerUtil.canPayCost(sa)) + return false; + + // prevent run-away activations - first time will always return true + boolean chance = r.nextFloat() <= Math.pow(.6667, source.getAbilityUsed()); + + // Targeting + if (abTgt != null){ + abTgt.resetTargets(); + // target loop + while(abTgt.getNumTargeted() < abTgt.getMaxTargets()){ + if (list.size() == 0){ + if (abTgt.getNumTargeted() < abTgt.getMinTargets() || abTgt.getNumTargeted() == 0){ + abTgt.resetTargets(); + return false; + } + else{ + // todo is this good enough? for up to amounts? + break; + } + } + + Card choice = null; + if (list.getNotType("Creature").size() == 0) + choice = CardFactoryUtil.AI_getBestCreature(list); //if the targets are only creatures, take the best + else + choice = CardFactoryUtil.AI_getMostExpensivePermanent(list, af.getHostCard(), true); + + if (choice == null){ // can't find anything left + if (abTgt.getNumTargeted() < abTgt.getMinTargets() || abTgt.getNumTargeted() == 0){ + abTgt.resetTargets(); + return false; + } + else{ + // todo is this good enough? for up to amounts? + break; + } + } + list.remove(choice); + abTgt.addTarget(choice); + } + + } + else{ + return false; + } + + return ((r.nextFloat() < .6667) && chance); + } + + public static void destroyResolve(final AbilityFactory af, final SpellAbility sa, final boolean noRegen){ + HashMap params = af.getMapParams(); + String DrawBack = params.get("SubAbility"); + Card card = sa.getSourceCard(); + + ArrayList tgtCards; + + Target tgt = af.getAbTgt(); + if (tgt != null) + tgtCards = tgt.getTargetCards(); + else{ + tgtCards = new ArrayList(); + tgtCards.add(card); + } + + Card firstTarget = tgtCards.get(0); + + for(Card tgtC : tgtCards){ + if(AllZone.GameAction.isCardInPlay(tgtC) && (tgt == null || CardFactoryUtil.canTarget(card, tgtC))) { + if(noRegen) + AllZone.GameAction.destroyNoRegeneration(tgtC); + else + AllZone.GameAction.destroy(tgtC); + } + } + + if (af.hasSubAbility()) + CardFactoryUtil.doDrawBack(DrawBack, 0, card.getController(), card.getController().getOpponent(), card.getController(), card, firstTarget, sa); + } +}