From a9437221bf8ae259e7169943fd5be77d01f5516d Mon Sep 17 00:00:00 2001 From: Maxmtg Date: Tue, 30 Oct 2012 05:21:07 +0000 Subject: [PATCH] AF:ManaDrain (other mana Abs use some special classes =( --- .gitattributes | 2 + src/main/java/forge/CardUtil.java | 141 +++++ .../card/abilityfactory/AbilityFactory.java | 9 +- .../abilityfactory/AbilityFactoryMana.java | 544 +----------------- .../card/abilityfactory/ai/DrainManaAi.java | 143 +++++ .../effects/DrainManaEffect.java | 91 +++ .../control/input/InputPayManaCostUtil.java | 6 +- 7 files changed, 409 insertions(+), 527 deletions(-) create mode 100644 src/main/java/forge/card/abilityfactory/ai/DrainManaAi.java create mode 100644 src/main/java/forge/card/abilityfactory/effects/DrainManaEffect.java diff --git a/.gitattributes b/.gitattributes index df9a911a856..c567c57964a 100644 --- a/.gitattributes +++ b/.gitattributes @@ -12500,6 +12500,7 @@ src/main/java/forge/card/abilityfactory/ai/AnimateAi.java -text src/main/java/forge/card/abilityfactory/ai/AnimateAllAi.java -text src/main/java/forge/card/abilityfactory/ai/BondAi.java -text src/main/java/forge/card/abilityfactory/ai/DiscardAi.java -text +src/main/java/forge/card/abilityfactory/ai/DrainManaAi.java -text src/main/java/forge/card/abilityfactory/ai/DrawAi.java svneol=native#text/plain src/main/java/forge/card/abilityfactory/ai/EndTurnAi.java -text src/main/java/forge/card/abilityfactory/ai/ExchangeLifeAi.java -text @@ -12515,6 +12516,7 @@ src/main/java/forge/card/abilityfactory/effects/AnimateAllEffect.java -text src/main/java/forge/card/abilityfactory/effects/AnimateEffect.java -text src/main/java/forge/card/abilityfactory/effects/BondEffect.java -text src/main/java/forge/card/abilityfactory/effects/DiscardEffect.java -text +src/main/java/forge/card/abilityfactory/effects/DrainManaEffect.java -text src/main/java/forge/card/abilityfactory/effects/DrawEffect.java -text src/main/java/forge/card/abilityfactory/effects/EndTurnEffect.java -text src/main/java/forge/card/abilityfactory/effects/ExchangeLifeEffect.java -text diff --git a/src/main/java/forge/CardUtil.java b/src/main/java/forge/CardUtil.java index ab4dfaed85b..15be56caa17 100644 --- a/src/main/java/forge/CardUtil.java +++ b/src/main/java/forge/CardUtil.java @@ -36,7 +36,10 @@ import com.google.common.collect.Iterables; import forge.card.CardCharacteristics; import forge.card.CardManaCost; import forge.card.EditionInfo; +import forge.card.abilityfactory.AbilityFactory; +import forge.card.abilityfactory.AbilityFactoryMana; import forge.card.mana.ManaCost; +import forge.card.spellability.AbilityMana; import forge.control.input.InputPayManaCostUtil; import forge.game.player.Player; import forge.game.zone.ZoneType; @@ -887,7 +890,145 @@ public final class CardUtil { ret.setImageName(NewConstants.MORPH_IMAGE_FILE_NAME); return ret; + } + + + private static List getColorsOfCards(final int maxChoices, final List cards, final List colors) { + for (final Card card : cards) { + // For each card, go through all the colors and if the card is that + // color, add + for (final String col : Constant.Color.ONLY_COLORS) { + if (card.isColor(col) && !colors.contains(col)) { + colors.add(col); + if (colors.size() == maxChoices) { + break; + } + } + } + } + return colors; + } + // add Colors and + /** + *

+ * reflectableMana. + *

+ * + * @param abMana + * a {@link forge.card.spellability.AbilityMana} object. + * @param af + * a {@link forge.card.abilityfactory.AbilityFactory} object. + * @param colors + * a {@link java.util.ArrayList} object. + * @param parents + * a {@link java.util.ArrayList} object. + * @return a {@link java.util.ArrayList} object. + */ + public static List getReflectableManaColors(final AbilityMana abMana, final AbilityFactory af, + List colors, final ArrayList parents) { + // Here's the problem with reflectable Mana. If more than one is out, + // they need to Reflect each other, + // so we basically need to have a recursive list that send the parents + // so we don't infinite recurse. + final HashMap params = af.getMapParams(); + final Card card = af.getHostCard(); + + if (!parents.contains(card)) { + parents.add(card); + } + + final String colorOrType = params.get("ColorOrType"); // currently Color + // or + // Type, Type is colors + // + colorless + final String validCard = params.get("Valid"); + final String reflectProperty = params.get("ReflectProperty"); // Produce + // (Reflecting + // Pool) or Is + // (Meteor + // Crater) + + int maxChoices = 5; // Color is the default colorOrType + if (colorOrType.equals("Type")) { + maxChoices++; + } + + List cards = null; + + // Reuse AF_Defined in a slightly different way + if (validCard.startsWith("Defined.")) { + cards = new ArrayList(); + for (final Card c : AbilityFactory.getDefinedCards(card, validCard.replace("Defined.", ""), abMana)) { + cards.add(c); + } + } else { + cards = CardLists.getValidCards(Singletons.getModel().getGame().getCardsIn(ZoneType.Battlefield), validCard, abMana.getActivatingPlayer(), card); + } + + // remove anything cards that is already in parents + for (final Card p : parents) { + if (cards.contains(p)) { + cards.remove(p); + } + } + + if ((cards.size() == 0) && !reflectProperty.equals("Produced")) { + return colors; + } + + if (reflectProperty.equals("Is")) { // Meteor Crater + colors = getColorsOfCards(maxChoices, cards, colors); + } else if (reflectProperty.equals("Produced")) { + final String producedColors = (String) abMana.getTriggeringObject("Produced"); + for (final String col : Constant.Color.ONLY_COLORS) { + final String s = InputPayManaCostUtil.getShortColorString(col); + if (producedColors.contains(s) && !colors.contains(col)) { + colors.add(col); + } + } + if ((maxChoices == 6) && producedColors.contains("1") && !colors.contains(Constant.Color.COLORLESS)) { + colors.add(Constant.Color.COLORLESS); + } + } else if (reflectProperty.equals("Produce")) { + final ArrayList abilities = new ArrayList(); + for (final Card c : cards) { + abilities.addAll(c.getManaAbility()); + } + // currently reflected mana will ignore other reflected mana + // abilities + + final ArrayList reflectAbilities = new ArrayList(); + + for (final AbilityMana ab : abilities) { + if (maxChoices == colors.size()) { + break; + } + + if (ab.isReflectedMana()) { + if (!parents.contains(ab.getSourceCard())) { + // Recursion! + reflectAbilities.add(ab); + parents.add(ab.getSourceCard()); + } + continue; + } + colors = AbilityFactoryMana.canProduce(maxChoices, ab, colors); + if (!parents.contains(ab.getSourceCard())) { + parents.add(ab.getSourceCard()); + } + } + + for (final AbilityMana ab : reflectAbilities) { + if (maxChoices == colors.size()) { + break; + } + + colors = CardUtil.getReflectableManaColors(ab, ab.getAbilityFactory(), colors, parents); + } + } + + return colors; } } // end class CardUtil diff --git a/src/main/java/forge/card/abilityfactory/AbilityFactory.java b/src/main/java/forge/card/abilityfactory/AbilityFactory.java index 9858fca7580..9810f73e685 100644 --- a/src/main/java/forge/card/abilityfactory/AbilityFactory.java +++ b/src/main/java/forge/card/abilityfactory/AbilityFactory.java @@ -699,13 +699,8 @@ public class AbilityFactory { } else if (this.api.equals("DrainMana")) { - if (this.isAb) { - spellAbility = AbilityFactoryMana.createAbilityDrainMana(this); - } else if (this.isSp) { - spellAbility = AbilityFactoryMana.createSpellDrainMana(this); - } else if (this.isDb) { - spellAbility = AbilityFactoryMana.createDrawbackDrainMana(this); - } + ai = new DrainManaAi(); + se = new DrainManaEffect(); } else if (this.api.equals("Draw")) { diff --git a/src/main/java/forge/card/abilityfactory/AbilityFactoryMana.java b/src/main/java/forge/card/abilityfactory/AbilityFactoryMana.java index 187d717306e..50938b27625 100644 --- a/src/main/java/forge/card/abilityfactory/AbilityFactoryMana.java +++ b/src/main/java/forge/card/abilityfactory/AbilityFactoryMana.java @@ -19,16 +19,14 @@ package forge.card.abilityfactory; import java.util.ArrayList; import java.util.HashMap; -import java.util.Iterator; import java.util.List; -import java.util.Random; import com.google.common.collect.Iterables; import forge.Card; -import forge.CardLists; import forge.CardPredicates; +import forge.CardUtil; import forge.Constant; import forge.Counters; import forge.Singletons; @@ -41,11 +39,9 @@ import forge.card.spellability.Spell; import forge.card.spellability.SpellAbility; import forge.card.spellability.Target; import forge.control.input.InputPayManaCostUtil; -import forge.game.player.ComputerUtil; import forge.game.player.Player; import forge.game.zone.ZoneType; import forge.gui.GuiChoose; -import forge.util.MyRandom; /** *

@@ -248,7 +244,7 @@ public class AbilityFactoryMana { * a {@link forge.card.abilityfactory.AbilityFactory} object. * @return a boolean. */ - public static boolean manaCanPlayAI(final AbilityFactory af) { + private static boolean manaCanPlayAI(final AbilityFactory af) { // AI cannot use this properly until he has a ManaPool return false; } @@ -266,7 +262,7 @@ public class AbilityFactoryMana { * a {@link forge.card.spellability.SpellAbility} object. * @return a {@link java.lang.String} object. */ - public static String manaStackDescription(final AbilityMana abMana, final AbilityFactory af, final SpellAbility sa) { + private static String manaStackDescription(final AbilityMana abMana, final AbilityFactory af, final SpellAbility sa) { final StringBuilder sb = new StringBuilder(); if (sa instanceof AbilitySub) { @@ -292,7 +288,7 @@ public class AbilityFactoryMana { * @param sa a {@link forge.card.spellability.SpellAbility} object. * @return a {@link java.lang.String} object. */ - public static String manaGenerated(final AbilityMana abMana, final AbilityFactory af, final SpellAbility sa) { + private static String manaGenerated(final AbilityMana abMana, final AbilityFactory af, final SpellAbility sa) { return generatedMana(abMana, af, sa); } @@ -308,7 +304,7 @@ public class AbilityFactoryMana { * @param sa * a {@link forge.card.spellability.SpellAbility} object. */ - public static void manaResolve(final AbilityMana abMana, final AbilityFactory af, final SpellAbility sa) { + private static void manaResolve(final AbilityMana abMana, final AbilityFactory af, final SpellAbility sa) { final HashMap params = af.getMapParams(); final Card card = af.getHostCard(); @@ -561,6 +557,22 @@ public class AbilityFactoryMana { return sb.toString(); } + /** + *

+ * hasUrzaLands. + *

+ * + * @param p + * a {@link forge.game.player.Player} object. + * @return a boolean. + */ + private static boolean hasUrzaLands(final Player p) { + final List landsControlled = p.getCardsIn(ZoneType.Battlefield); + return Iterables.any(landsControlled, CardPredicates.nameEquals("Urza's Mine")) && + Iterables.any(landsControlled, CardPredicates.nameEquals("Urza's Tower")) && + Iterables.any(landsControlled, CardPredicates.nameEquals("Urza's Power Plant")); + } + // ****************************** MANAREFLECTED ************************ /** *

@@ -693,7 +705,7 @@ public class AbilityFactoryMana { final Card card = af.getHostCard(); - final ArrayList colors = AbilityFactoryMana.reflectableMana(abMana, af, new ArrayList(), + final List colors = CardUtil.getReflectableManaColors(abMana, af, new ArrayList(), new ArrayList()); ArrayList tgtPlayers; @@ -706,6 +718,7 @@ public class AbilityFactoryMana { } for (final Player player : tgtPlayers) { + final String generated = AbilityFactoryMana.generatedReflectedMana(abMana, af, colors, player); if (abMana.getCanceled()) { @@ -720,157 +733,6 @@ public class AbilityFactoryMana { AbilityFactoryMana.doDrawback(af, abMana, card); } - // add Colors and - /** - *

- * reflectableMana. - *

- * - * @param abMana - * a {@link forge.card.spellability.AbilityMana} object. - * @param af - * a {@link forge.card.abilityfactory.AbilityFactory} object. - * @param colors - * a {@link java.util.ArrayList} object. - * @param parents - * a {@link java.util.ArrayList} object. - * @return a {@link java.util.ArrayList} object. - */ - public static ArrayList reflectableMana(final AbilityMana abMana, final AbilityFactory af, - ArrayList colors, final ArrayList parents) { - // Here's the problem with reflectable Mana. If more than one is out, - // they need to Reflect each other, - // so we basically need to have a recursive list that send the parents - // so we don't infinite recurse. - final HashMap params = af.getMapParams(); - final Card card = af.getHostCard(); - - if (!parents.contains(card)) { - parents.add(card); - } - - final String colorOrType = params.get("ColorOrType"); // currently Color - // or - // Type, Type is colors - // + colorless - final String validCard = params.get("Valid"); - final String reflectProperty = params.get("ReflectProperty"); // Produce - // (Reflecting - // Pool) or Is - // (Meteor - // Crater) - - int maxChoices = 5; // Color is the default colorOrType - if (colorOrType.equals("Type")) { - maxChoices++; - } - - List cards = null; - - // Reuse AF_Defined in a slightly different way - if (validCard.startsWith("Defined.")) { - cards = new ArrayList(); - for (final Card c : AbilityFactory.getDefinedCards(card, validCard.replace("Defined.", ""), abMana)) { - cards.add(c); - } - } else { - cards = CardLists.getValidCards(Singletons.getModel().getGame().getCardsIn(ZoneType.Battlefield), validCard, abMana.getActivatingPlayer(), card); - } - - // remove anything cards that is already in parents - for (final Card p : parents) { - if (cards.contains(p)) { - cards.remove(p); - } - } - - if ((cards.size() == 0) && !reflectProperty.equals("Produced")) { - return colors; - } - - if (reflectProperty.equals("Is")) { // Meteor Crater - colors = AbilityFactoryMana.hasProperty(maxChoices, cards, colors); - } else if (reflectProperty.equals("Produced")) { - final String producedColors = (String) abMana.getTriggeringObject("Produced"); - for (final String col : Constant.Color.ONLY_COLORS) { - final String s = InputPayManaCostUtil.getShortColorString(col); - if (producedColors.contains(s) && !colors.contains(col)) { - colors.add(col); - } - } - if ((maxChoices == 6) && producedColors.contains("1") && !colors.contains(Constant.Color.COLORLESS)) { - colors.add(Constant.Color.COLORLESS); - } - } else if (reflectProperty.equals("Produce")) { - final ArrayList abilities = new ArrayList(); - for (final Card c : cards) { - abilities.addAll(c.getManaAbility()); - } - // currently reflected mana will ignore other reflected mana - // abilities - - final ArrayList reflectAbilities = new ArrayList(); - - for (final AbilityMana ab : abilities) { - if (maxChoices == colors.size()) { - break; - } - - if (ab.isReflectedMana()) { - if (!parents.contains(ab.getSourceCard())) { - // Recursion! - reflectAbilities.add(ab); - parents.add(ab.getSourceCard()); - } - continue; - } - colors = AbilityFactoryMana.canProduce(maxChoices, ab, colors); - if (!parents.contains(ab.getSourceCard())) { - parents.add(ab.getSourceCard()); - } - } - - for (final AbilityMana ab : reflectAbilities) { - if (maxChoices == colors.size()) { - break; - } - - colors = AbilityFactoryMana.reflectableMana(ab, ab.getAbilityFactory(), colors, parents); - } - } - - return colors; - } - - /** - *

- * hasProperty. - *

- * - * @param maxChoices - * a int. - * @param cards - * a {@link forge.CardList} object. - * @param colors - * a {@link java.util.ArrayList} object. - * @return a {@link java.util.ArrayList} object. - */ - private static ArrayList hasProperty(final int maxChoices, final List cards, - final ArrayList colors) { - for (final Card c : cards) { - // For each card, go through all the colors and if the card is that - // color, add - for (final String col : Constant.Color.ONLY_COLORS) { - if (c.isColor(col) && !colors.contains(col)) { - colors.add(col); - if (colors.size() == maxChoices) { - break; - } - } - } - } - return colors; - } /** *

@@ -885,8 +747,8 @@ public class AbilityFactoryMana { * a {@link java.util.ArrayList} object. * @return a {@link java.util.ArrayList} object. */ - private static ArrayList canProduce(final int maxChoices, final AbilityMana ab, - final ArrayList colors) { + public static List canProduce(final int maxChoices, final AbilityMana ab, + final List colors) { for (final String col : Constant.Color.ONLY_COLORS) { final String s = InputPayManaCostUtil.getShortColorString(col); if (ab.canProduce(s) && !colors.contains(col)) { @@ -917,7 +779,7 @@ public class AbilityFactoryMana { * @return a {@link java.lang.String} object. */ private static String generatedReflectedMana(final AbilityMana abMana, final AbilityFactory af, - final ArrayList colors, final Player player) { + final List colors, final Player player) { // Calculate generated mana here for stack description and resolving final HashMap params = af.getMapParams(); final int amount = params.containsKey("Amount") ? AbilityFactory.calculateAmount(af.getHostCard(), @@ -990,361 +852,9 @@ public class AbilityFactoryMana { } } - /** - *

- * hasUrzaLands. - *

- * - * @param p - * a {@link forge.game.player.Player} object. - * @return a boolean. - */ - private static boolean hasUrzaLands(final Player p) { - final List landsControlled = p.getCardsIn(ZoneType.Battlefield); - return Iterables.any(landsControlled, CardPredicates.nameEquals("Urza's Mine")) && - Iterables.any(landsControlled, CardPredicates.nameEquals("Urza's Tower")) && - Iterables.any(landsControlled, CardPredicates.nameEquals("Urza's Power Plant")); - } - // **************************************** // ************** DrainMana *************** // **************************************** - /** - *

- * createAbilityDrainMana. - *

- * - * @param af - * a {@link forge.card.abilityfactory.AbilityFactory} object. - * @return a {@link forge.card.spellability.SpellAbility} object. - * @since 1.0.15 - */ - public static SpellAbility createAbilityDrainMana(final AbilityFactory af) { - class AbilityDrainMana extends AbilityActivated { - public AbilityDrainMana(final Card ca, final Cost co, final Target t) { - super(ca, co, t); - } - @Override - public AbilityActivated getCopy() { - AbilityActivated res = new AbilityDrainMana(getSourceCard(), - getPayCosts(), getTarget() == null ? null : new Target(getTarget())); - CardFactoryUtil.copySpellAbility(this, res); - return res; - } - - private static final long serialVersionUID = 5669367387381350104L; - - @Override - public String getStackDescription() { - return AbilityFactoryMana.drainManaStackDescription(af, this); - } - - @Override - public boolean canPlayAI() { - return AbilityFactoryMana.drainManaCanPlayAI(getActivatingPlayer(), af, this); - } - - @Override - public void resolve() { - AbilityFactoryMana.drainManaResolve(af, this); - } - - @Override - public boolean doTrigger(final boolean mandatory) { - return AbilityFactoryMana.drainManaTrigger(getActivatingPlayer(), af, this, mandatory); - } - } - - final SpellAbility abDrainMana = new AbilityDrainMana(af.getHostCard(), af.getAbCost(), af.getAbTgt()); - - return abDrainMana; - } - - /** - *

- * createSpellDrainMana. - *

- * - * @param af - * a {@link forge.card.abilityfactory.AbilityFactory} object. - * @return a {@link forge.card.spellability.SpellAbility} object. - * @since 1.0.15 - */ - public static SpellAbility createSpellDrainMana(final AbilityFactory af) { - final SpellAbility spDrainMana = new Spell(af.getHostCard(), af.getAbCost(), af.getAbTgt()) { - private static final long serialVersionUID = -4294474468024747680L; - - @Override - public String getStackDescription() { - return AbilityFactoryMana.drainManaStackDescription(af, this); - } - - @Override - public boolean canPlayAI() { - return AbilityFactoryMana.drainManaCanPlayAI(getActivatingPlayer(), af, this); - } - - @Override - public void resolve() { - AbilityFactoryMana.drainManaResolve(af, this); - } - - }; - return spDrainMana; - } - - /** - *

- * createDrawbackDrainMana. - *

- * - * @param af - * a {@link forge.card.abilityfactory.AbilityFactory} object. - * @return a {@link forge.card.spellability.SpellAbility} object. - * @since 1.0.15 - */ - public static SpellAbility createDrawbackDrainMana(final AbilityFactory af) { - class DrawbackDrainMana extends AbilitySub { - public DrawbackDrainMana(final Card ca, final Target t) { - super(ca, t); - } - - @Override - public AbilitySub getCopy() { - AbilitySub res = new DrawbackDrainMana(getSourceCard(), - getTarget() == null ? null : new Target(getTarget())); - CardFactoryUtil.copySpellAbility(this, res); - return res; - } - - private static final long serialVersionUID = 1458568386420831420L; - - @Override - public String getStackDescription() { - return AbilityFactoryMana.drainManaStackDescription(af, this); - } - - @Override - public void resolve() { - AbilityFactoryMana.drainManaResolve(af, this); - } - - @Override - public boolean chkAIDrawback() { - return AbilityFactoryMana.drainManaPlayDrawbackAI(getActivatingPlayer(), af, this); - } - - @Override - public boolean doTrigger(final boolean mandatory) { - return AbilityFactoryMana.drainManaTrigger(getActivatingPlayer(), af, this, mandatory); - } - } - final SpellAbility dbDrainMana = new DrawbackDrainMana(af.getHostCard(), af.getAbTgt()); - - return dbDrainMana; - } - - /** - *

- * drainManaStackDescription. - *

- * - * @param af - * a {@link forge.card.abilityfactory.AbilityFactory} object. - * @param sa - * a {@link forge.card.spellability.SpellAbility} object. - * @return a {@link java.lang.String} object. - */ - private static String drainManaStackDescription(final AbilityFactory af, final SpellAbility sa) { - final StringBuilder sb = new StringBuilder(); - - final HashMap params = af.getMapParams(); - - if (sa instanceof AbilitySub) { - sb.append(" "); - } else { - sb.append(sa.getSourceCard()).append(" - "); - } - - ArrayList tgtPlayers; - final Target tgt = sa.getTarget(); - if (tgt != null) { - tgtPlayers = tgt.getTargetPlayers(); - } else { - tgtPlayers = AbilityFactory.getDefinedPlayers(sa.getSourceCard(), params.get("Defined"), sa); - } - - final Iterator it = tgtPlayers.iterator(); - while (it.hasNext()) { - sb.append(it.next()); - if (it.hasNext()) { - sb.append(", "); - } - } - - sb.append(" empties his or her mana pool."); - - final AbilitySub subAb = sa.getSubAbility(); - if (subAb != null) { - sb.append(subAb.getStackDescription()); - } - - return sb.toString(); - } - - /** - *

- * drainManaCanPlayAI. - *

- * - * @param af - * a {@link forge.card.abilityfactory.AbilityFactory} object. - * @param sa - * a {@link forge.card.spellability.SpellAbility} object. - * @return a boolean. - */ - private static boolean drainManaCanPlayAI(final Player ai, final AbilityFactory af, final SpellAbility sa) { - // AI cannot use this properly until he can use SAs during Humans turn - - final HashMap params = af.getMapParams(); - final Target tgt = sa.getTarget(); - final Card source = sa.getSourceCard(); - final Player opp = ai.getOpponent(); - final Random r = MyRandom.getRandom(); - boolean randomReturn = r.nextFloat() <= Math.pow(.6667, sa.getActivationsThisTurn()); - - if (tgt == null) { - // assume we are looking to tap human's stuff - // TODO - check for things with untap abilities, and don't tap - // those. - final ArrayList defined = AbilityFactory.getDefinedPlayers(source, params.get("Defined"), sa); - - if (!defined.contains(opp)) { - return false; - } - } else { - tgt.resetTargets(); - tgt.addTarget(opp); - } - - final AbilitySub subAb = sa.getSubAbility(); - if (subAb != null) { - randomReturn &= subAb.chkAIDrawback(); - } - - return randomReturn; - } - - /** - *

- * drainManaTrigger. - *

- * - * @param af - * a {@link forge.card.abilityfactory.AbilityFactory} object. - * @param sa - * a {@link forge.card.spellability.SpellAbility} object. - * @param mandatory - * a boolean. - * @return a boolean. - */ - private static boolean drainManaTrigger(final Player ai, final AbilityFactory af, final SpellAbility sa, final boolean mandatory) { - if (!ComputerUtil.canPayCost(sa, ai)) { - return false; - } - final Player opp = ai.getOpponent(); - - final HashMap params = af.getMapParams(); - final Target tgt = sa.getTarget(); - final Card source = sa.getSourceCard(); - - if (null == tgt) { - if (mandatory) { - return true; - } else { - final ArrayList defined = AbilityFactory.getDefinedPlayers(source, params.get("Defined"), sa); - - if (!defined.contains(opp)) { - return false; - } - } - - return true; - } else { - tgt.resetTargets(); - tgt.addTarget(opp); - } - - return true; - } - - /** - *

- * drainManaPlayDrawbackAI. - *

- * - * @param af - * a {@link forge.card.abilityfactory.AbilityFactory} object. - * @param sa - * a {@link forge.card.spellability.SpellAbility} object. - * @return a boolean. - */ - private static boolean drainManaPlayDrawbackAI(final Player ai, final AbilityFactory af, final SpellAbility sa) { - // AI cannot use this properly until he can use SAs during Humans turn - final HashMap params = af.getMapParams(); - final Target tgt = sa.getTarget(); - final Card source = sa.getSourceCard(); - - boolean randomReturn = true; - - if (tgt == null) { - final ArrayList defined = AbilityFactory.getDefinedPlayers(source, params.get("Defined"), sa); - - if (defined.contains(ai)) { - return false; - } - } else { - tgt.resetTargets(); - tgt.addTarget(ai.getOpponent()); - } - - final AbilitySub subAb = sa.getSubAbility(); - if (subAb != null) { - randomReturn &= subAb.chkAIDrawback(); - } - - return randomReturn; - } - - /** - *

- * drainManaResolve. - *

- * - * @param af - * a {@link forge.card.abilityfactory.AbilityFactory} object. - * @param sa - * a {@link forge.card.spellability.SpellAbility} object. - */ - private static void drainManaResolve(final AbilityFactory af, final SpellAbility sa) { - final HashMap params = af.getMapParams(); - final Card card = sa.getSourceCard(); - - ArrayList tgtPlayers; - final Target tgt = sa.getTarget(); - if (tgt != null) { - tgtPlayers = tgt.getTargetPlayers(); - } else { - tgtPlayers = AbilityFactory.getDefinedPlayers(card, params.get("Defined"), sa); - } - - for (final Player p : tgtPlayers) { - if ((tgt == null) || p.canBeTargetedBy(sa)) { - p.getManaPool().clearPool(false); - } - } - } - -} // end class AbilityFactory_Mana +} diff --git a/src/main/java/forge/card/abilityfactory/ai/DrainManaAi.java b/src/main/java/forge/card/abilityfactory/ai/DrainManaAi.java new file mode 100644 index 00000000000..3343bee129e --- /dev/null +++ b/src/main/java/forge/card/abilityfactory/ai/DrainManaAi.java @@ -0,0 +1,143 @@ +package forge.card.abilityfactory.ai; + +import java.util.ArrayList; +import java.util.Map; +import java.util.Random; + +import forge.Card; +import forge.card.abilityfactory.AbilityFactory; +import forge.card.abilityfactory.SpellAiLogic; +import forge.card.spellability.AbilitySub; +import forge.card.spellability.SpellAbility; +import forge.card.spellability.Target; +import forge.game.player.ComputerUtil; +import forge.game.player.Player; +import forge.util.MyRandom; + +/** + *

+ * drainManaCanPlayAI. + *

+ * + * @param af + * a {@link forge.card.abilityfactory.AbilityFactory} object. + * @param sa + * a {@link forge.card.spellability.SpellAbility} object. + * @return a boolean. + */ + +public class DrainManaAi extends SpellAiLogic { + + @Override + public boolean canPlayAI(Player ai, java.util.Map params, SpellAbility sa) { + // AI cannot use this properly until he can use SAs during Humans turn + + final Target tgt = sa.getTarget(); + final Card source = sa.getSourceCard(); + final Player opp = ai.getOpponent(); + final Random r = MyRandom.getRandom(); + boolean randomReturn = r.nextFloat() <= Math.pow(.6667, sa.getActivationsThisTurn()); + + if (tgt == null) { + // assume we are looking to tap human's stuff + // TODO - check for things with untap abilities, and don't tap + // those. + final ArrayList defined = AbilityFactory.getDefinedPlayers(source, params.get("Defined"), sa); + + if (!defined.contains(opp)) { + return false; + } + } else { + tgt.resetTargets(); + tgt.addTarget(opp); + } + + final AbilitySub subAb = sa.getSubAbility(); + if (subAb != null) { + randomReturn &= subAb.chkAIDrawback(); + } + + return randomReturn; + } + + /** + *

+ * drainManaTrigger. + *

+ * + * @param af + * a {@link forge.card.abilityfactory.AbilityFactory} object. + * @param sa + * a {@link forge.card.spellability.SpellAbility} object. + * @param mandatory + * a boolean. + * @return a boolean. + */ + @Override + public boolean doTriggerAI(Player ai, java.util.Map params, SpellAbility sa, boolean mandatory) { + if (!ComputerUtil.canPayCost(sa, ai)) { + return false; + } + final Player opp = ai.getOpponent(); + + final Target tgt = sa.getTarget(); + final Card source = sa.getSourceCard(); + + if (null == tgt) { + if (mandatory) { + return true; + } else { + final ArrayList defined = AbilityFactory.getDefinedPlayers(source, params.get("Defined"), sa); + + if (!defined.contains(opp)) { + return false; + } + } + + return true; + } else { + tgt.resetTargets(); + tgt.addTarget(opp); + } + + return true; + } + + /** + *

+ * drainManaPlayDrawbackAI. + *

+ * + * @param af + * a {@link forge.card.abilityfactory.AbilityFactory} object. + * @param sa + * a {@link forge.card.spellability.SpellAbility} object. + * @return a boolean. + */ + @Override + public boolean chkAIDrawback(Map params, SpellAbility sa, Player ai) { + // AI cannot use this properly until he can use SAs during Humans turn + final Target tgt = sa.getTarget(); + final Card source = sa.getSourceCard(); + + boolean randomReturn = true; + + if (tgt == null) { + final ArrayList defined = AbilityFactory.getDefinedPlayers(source, params.get("Defined"), sa); + + if (defined.contains(ai)) { + return false; + } + } else { + tgt.resetTargets(); + tgt.addTarget(ai.getOpponent()); + } + + final AbilitySub subAb = sa.getSubAbility(); + if (subAb != null) { + randomReturn &= subAb.chkAIDrawback(); + } + + return randomReturn; + } +} \ No newline at end of file diff --git a/src/main/java/forge/card/abilityfactory/effects/DrainManaEffect.java b/src/main/java/forge/card/abilityfactory/effects/DrainManaEffect.java new file mode 100644 index 00000000000..fd9df237c6b --- /dev/null +++ b/src/main/java/forge/card/abilityfactory/effects/DrainManaEffect.java @@ -0,0 +1,91 @@ +package forge.card.abilityfactory.effects; + +import java.util.ArrayList; +import java.util.Iterator; + +import forge.Card; +import forge.card.abilityfactory.AbilityFactory; +import forge.card.abilityfactory.SpellEffect; +import forge.card.spellability.AbilitySub; +import forge.card.spellability.SpellAbility; +import forge.card.spellability.Target; +import forge.game.player.Player; + +public class DrainManaEffect extends SpellEffect { + /** + *

+ * drainManaResolve. + *

+ * + * @param af + * a {@link forge.card.abilityfactory.AbilityFactory} object. + * @param sa + * a {@link forge.card.spellability.SpellAbility} object. + */ + @Override + public void resolve(java.util.Map params, SpellAbility sa) { + final Card card = sa.getSourceCard(); + + ArrayList tgtPlayers; + final Target tgt = sa.getTarget(); + if (tgt != null) { + tgtPlayers = tgt.getTargetPlayers(); + } else { + tgtPlayers = AbilityFactory.getDefinedPlayers(card, params.get("Defined"), sa); + } + + for (final Player p : tgtPlayers) { + if ((tgt == null) || p.canBeTargetedBy(sa)) { + p.getManaPool().clearPool(false); + } + } + } + + /** + *

+ * drainManaStackDescription. + *

+ * + * @param af + * a {@link forge.card.abilityfactory.AbilityFactory} object. + * @param sa + * a {@link forge.card.spellability.SpellAbility} object. + * @return a {@link java.lang.String} object. + */ + @Override + public String getStackDescription(java.util.Map params, SpellAbility sa) { + final StringBuilder sb = new StringBuilder(); + + if (sa instanceof AbilitySub) { + sb.append(" "); + } else { + sb.append(sa.getSourceCard()).append(" - "); + } + + ArrayList tgtPlayers; + final Target tgt = sa.getTarget(); + if (tgt != null) { + tgtPlayers = tgt.getTargetPlayers(); + } else { + tgtPlayers = AbilityFactory.getDefinedPlayers(sa.getSourceCard(), params.get("Defined"), sa); + } + + final Iterator it = tgtPlayers.iterator(); + while (it.hasNext()) { + sb.append(it.next()); + if (it.hasNext()) { + sb.append(", "); + } + } + + sb.append(" empties his or her mana pool."); + + final AbilitySub subAb = sa.getSubAbility(); + if (subAb != null) { + sb.append(subAb.getStackDescription()); + } + + return sb.toString(); + } + +} // end class AbilityFactory_Mana \ No newline at end of file diff --git a/src/main/java/forge/control/input/InputPayManaCostUtil.java b/src/main/java/forge/control/input/InputPayManaCostUtil.java index e5fff436efe..76f4c06098b 100644 --- a/src/main/java/forge/control/input/InputPayManaCostUtil.java +++ b/src/main/java/forge/control/input/InputPayManaCostUtil.java @@ -20,6 +20,7 @@ package forge.control.input; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; +import java.util.List; import java.util.Map; import forge.Card; @@ -27,7 +28,6 @@ import forge.CardUtil; import forge.Constant; import forge.Singletons; import forge.card.abilityfactory.AbilityFactory; -import forge.card.abilityfactory.AbilityFactoryMana; import forge.card.cost.CostMana; import forge.card.cost.CostPayment; import forge.card.mana.ManaCost; @@ -153,7 +153,7 @@ public class InputPayManaCostUtil { for (final AbilityMana am : abilities) { if (am.isReflectedMana()) { - final ArrayList reflectableColors = AbilityFactoryMana.reflectableMana(am, + final List reflectableColors = CardUtil.getReflectableManaColors(am, am.getAbilityFactory(), new ArrayList(), new ArrayList()); for (final String color : reflectableColors) { if (manaCost.isColor(color)) { @@ -268,7 +268,7 @@ public class InputPayManaCostUtil { return true; } if (am.isReflectedMana()) { - final ArrayList reflectableColors = AbilityFactoryMana.reflectableMana(am, am.getAbilityFactory(), + final List reflectableColors = CardUtil.getReflectableManaColors(am, am.getAbilityFactory(), new ArrayList(), new ArrayList()); for (final String color : reflectableColors) { if (mana.contains(InputPayManaCostUtil.getShortColorString(color))) {