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) {