diff --git a/src/main/java/forge/card/abilityfactory/AbilityFactory.java b/src/main/java/forge/card/abilityfactory/AbilityFactory.java index 91e7949ef8a..32ad51bb798 100644 --- a/src/main/java/forge/card/abilityfactory/AbilityFactory.java +++ b/src/main/java/forge/card/abilityfactory/AbilityFactory.java @@ -808,6 +808,16 @@ public class AbilityFactory { } } + else if (api.equals("TwoPiles")) { + if (isAb) { + spellAbility = AbilityFactoryClash.createAbilityTwoPiles(this); + } else if (isSp) { + spellAbility = AbilityFactoryClash.createSpellTwoPiles(this); + } else if (isDb) { + spellAbility = AbilityFactoryClash.createDrawbackTwoPiles(this); + } + } + else if (this.api.equals("Animate")) { if (this.isAb) { spellAbility = AbilityFactoryAnimate.createAbilityAnimate(this); diff --git a/src/main/java/forge/card/abilityfactory/AbilityFactoryClash.java b/src/main/java/forge/card/abilityfactory/AbilityFactoryClash.java index fbc0d9e5f75..aa1aedf2068 100644 --- a/src/main/java/forge/card/abilityfactory/AbilityFactoryClash.java +++ b/src/main/java/forge/card/abilityfactory/AbilityFactoryClash.java @@ -2,15 +2,23 @@ package forge.card.abilityfactory; import java.util.ArrayList; import java.util.HashMap; +import java.util.List; + +import javax.swing.JOptionPane; import forge.AllZone; import forge.Card; +import forge.CardList; +import forge.CardUtil; +import forge.Constant.Zone; import forge.GameActionUtil; import forge.Player; import forge.card.spellability.AbilityActivated; import forge.card.spellability.AbilitySub; import forge.card.spellability.Spell; import forge.card.spellability.SpellAbility; +import forge.card.spellability.Target; +import forge.gui.GuiUtils; /** *

@@ -430,4 +438,291 @@ public final class AbilityFactoryClash { // AllZone.getTriggerHandler().runTrigger("FlipsACoin",runParams); } + // ************************************************************************* + // ***************************** TwoPiles ********************************** + // ************************************************************************* + + /** + *

+ * createAbilityTwoPiles. + *

+ * + * @param af + * a {@link forge.card.abilityFactory.AbilityFactory} object. + * @return a {@link forge.card.spellability.SpellAbility} object. + * @since 1.1.7 + */ + public static SpellAbility createAbilityTwoPiles(final AbilityFactory af) { + final SpellAbility abTwoPiles = new AbilityActivated(af.getHostCard(), af.getAbCost(), af.getAbTgt()) { + private static final long serialVersionUID = -2700390539969188516L; + + @Override + public String getStackDescription() { + return twoPilesStackDescription(af, this); + } + + @Override + public boolean canPlayAI() { + return twoPilesCanPlayAI(af, this); + } + + @Override + public void resolve() { + twoPilesResolve(af, this); + } + + @Override + public boolean doTrigger(final boolean mandatory) { + return twoPilesTriggerAI(af, this, mandatory); + } + + }; + return abTwoPiles; + } + + /** + *

+ * createSpellTwoPiles. + *

+ * + * @param af + * a {@link forge.card.abilityFactory.AbilityFactory} object. + * @return a {@link forge.card.spellability.SpellAbility} object. + * @since 1.1.7 + */ + public static SpellAbility createSpellTwoPiles(final AbilityFactory af) { + final SpellAbility spTwoPiles = new Spell(af.getHostCard(), af.getAbCost(), af.getAbTgt()) { + private static final long serialVersionUID = 6521684078773178349L; + + @Override + public String getStackDescription() { + return twoPilesStackDescription(af, this); + } + + @Override + public boolean canPlayAI() { + return twoPilesCanPlayAI(af, this); + } + + @Override + public void resolve() { + twoPilesResolve(af, this); + } + + }; + return spTwoPiles; + } + + /** + *

+ * createDrawbackTwoPiles. + *

+ * + * @param af + * a {@link forge.card.abilityFactory.AbilityFactory} object. + * @return a {@link forge.card.spellability.SpellAbility} object. + * @since 1.1.7 + */ + public static SpellAbility createDrawbackTwoPiles(final AbilityFactory af) { + final SpellAbility dbTwoPiles = new AbilitySub(af.getHostCard(), af.getAbTgt()) { + private static final long serialVersionUID = 7486255949274716808L; + + @Override + public String getStackDescription() { + return twoPilesStackDescription(af, this); + } + + @Override + public void resolve() { + twoPilesResolve(af, this); + } + + @Override + public boolean chkAIDrawback() { + return true; + } + + @Override + public boolean doTrigger(final boolean mandatory) { + return twoPilesTriggerAI(af, this, mandatory); + } + + }; + return dbTwoPiles; + } + + private static String twoPilesStackDescription(final AbilityFactory af, final SpellAbility sa) { + HashMap params = af.getMapParams(); + StringBuilder sb = new StringBuilder(); + + if (sa instanceof AbilitySub) { + sb.append(" "); + } else { + sb.append(sa.getSourceCard()).append(" - "); + } + + ArrayList tgtPlayers; + + Target tgt = af.getAbTgt(); + if (tgt != null) { + tgtPlayers = tgt.getTargetPlayers(); + } else { + tgtPlayers = AbilityFactory.getDefinedPlayers(sa.getSourceCard(), af.getMapParams().get("Defined"), sa); + } + + String valid = ""; + if (params.containsKey("ValidCards")) { + valid = params.get("ValidCards"); + } + + sb.append("Separate all ").append(valid).append(" cards "); + + for (Player p : tgtPlayers) { + sb.append(p).append(" "); + } + sb.append("controls into two piles."); + + AbilitySub abSub = sa.getSubAbility(); + if (abSub != null) { + sb.append(abSub.getStackDescription()); + } + + return sb.toString(); + } + + private static boolean twoPilesCanPlayAI(final AbilityFactory af, final SpellAbility sa) { + return twoPilesTriggerAI(af, sa, false); + } + + private static boolean twoPilesTriggerAI(final AbilityFactory af, final SpellAbility sa, final boolean mandatory) { + return false; + } + + private static void twoPilesResolve(final AbilityFactory af, final SpellAbility sa) { + HashMap params = af.getMapParams(); + Card card = af.getHostCard(); + + String valid = ""; + if (params.containsKey("ValidCards")) { + valid = params.get("ValidCards"); + } + + ArrayList tgtPlayers; + + Target tgt = af.getAbTgt(); + if (tgt != null) { + tgtPlayers = tgt.getTargetPlayers(); + } else { + tgtPlayers = AbilityFactory.getDefinedPlayers(sa.getSourceCard(), params.get("Defined"), sa); + } + + Player separator = card.getController(); + if (params.containsKey("Separator")) { + separator = AbilityFactory.getDefinedPlayers(sa.getSourceCard(), params.get("Separator"), sa).get(0); + } + + Player chooser = tgtPlayers.get(0); + if (params.containsKey("Chooser")) { + chooser = AbilityFactory.getDefinedPlayers(sa.getSourceCard(), params.get("Chooser"), sa).get(0); + } + + for (Player p : tgtPlayers) { + if (tgt == null || p.canTarget(sa)) { + ArrayList pile1 = new ArrayList(); + ArrayList pile2 = new ArrayList(); + CardList pool = p.getCardsIn(Zone.Battlefield); + pool = pool.getValidCards(valid, card.getController(), card); + + //first, separate the cards into piles + if (separator.isHuman()) { + List l = GuiUtils.getChoicesOptional("Put into pile 1 (multi-select)", pool.toArray()); + for (Card c : l) { + pile1.add(c); + pool.remove(c); + } + for (Card c : pool) { + pile2.add(c); + } + } else { + // TODO - not implemented + } + + System.out.println("Pile 1:" + pile1); + System.out.println("Pile 2:" + pile2); + + //then, the chooser picks a pile + if (chooser.isHuman()) { + Card[] disp = new Card[pile1.size() + pile2.size() + 2]; + disp[0] = new Card(); + disp[0].setName("Pile 1"); + for (int i = 0; i < pile1.size(); i++) { + disp[1 + i] = pile1.get(i); + } + disp[pile1.size() + 1] = new Card(); + disp[pile1.size() + 1].setName("Pile 2"); + for (int i = 0; i < pile2.size(); i++) { + disp[pile1.size() + i + 2] = pile2.get(i); + } + + //make sure Pile 1 or Pile 2 is clicked on + boolean chosen = false; + while (!chosen) { + Object o = GuiUtils.getChoice("Choose a pile", disp); + Card c = (Card) o; + if (c.getName().equals("Pile 1")) { + chosen = true; + for (Card z : pile1) { + card.addRemembered(z); + } + } + else if (c.getName().equals("Pile 2")) { + chosen = true; + for (Card z : pile2) { + card.addRemembered(z); + } + } + + } + } else { + int cmc1 = 0; + int cmc2 = 0; + + for (Card c : pile1) { + cmc1 += CardUtil.getConvertedManaCost(c); + } + for (Card c : pile2) { + cmc2 += CardUtil.getConvertedManaCost(c); + } + + //for now, this assumes that the outcome will be bad + //TODO: This should really have a ChooseLogic param to figure this out + if (cmc2 > cmc1) { + JOptionPane.showMessageDialog(null, "Computer chooses the Pile 1", "", + JOptionPane.INFORMATION_MESSAGE); + for (Card c : pile1) { + card.addRemembered(c); + } + } + else { + JOptionPane.showMessageDialog(null, "Computer chooses the Pile 2", "", + JOptionPane.INFORMATION_MESSAGE); + for (Card c : pile2) { + card.addRemembered(c); + } + } + } + + //take action on the chosen pile + if (params.containsKey("ChosenPile")) { + final AbilityFactory afPile = new AbilityFactory(); + final SpellAbility action = afPile.getAbility(card.getSVar(params.get("ChosenPile")), card); + action.setActivatingPlayer(sa.getActivatingPlayer()); + ((AbilitySub) action).setParent(sa); + + AbilityFactory.resolve(action, false); + } + } + } + } //end twoPiles resolve + } // end class AbilityFactory_Clash diff --git a/src/main/java/forge/card/abilityfactory/AbilityFactorySacrifice.java b/src/main/java/forge/card/abilityfactory/AbilityFactorySacrifice.java index 54300c9ad32..dad60293009 100644 --- a/src/main/java/forge/card/abilityfactory/AbilityFactorySacrifice.java +++ b/src/main/java/forge/card/abilityfactory/AbilityFactorySacrifice.java @@ -801,7 +801,13 @@ public class AbilityFactorySacrifice { valid = valid.replace("X", Integer.toString(AbilityFactory.calculateAmount(card, "X", sa))); } - CardList list = AllZoneUtil.getCardsIn(Zone.Battlefield); + CardList list; + if (params.containsKey("Defined")) { + list = new CardList(AbilityFactory.getDefinedCards(af.getHostCard(), params.get("Defined"), sa)); + } + else { + list = AllZoneUtil.getCardsIn(Zone.Battlefield); + } final boolean remSacrificed = params.containsKey("RememberSacrificed"); if (remSacrificed) {