moved a gui reference out from costs

This commit is contained in:
Maxmtg
2014-01-17 08:32:39 +00:00
parent 156bc84c73
commit 19cec963d2
11 changed files with 149 additions and 137 deletions

1
.gitattributes vendored
View File

@@ -15013,6 +15013,7 @@ forge-gui/src/main/java/forge/game/cost/Cost.java svneol=native#text/plain
forge-gui/src/main/java/forge/game/cost/CostAddMana.java -text forge-gui/src/main/java/forge/game/cost/CostAddMana.java -text
forge-gui/src/main/java/forge/game/cost/CostChooseCreatureType.java -text forge-gui/src/main/java/forge/game/cost/CostChooseCreatureType.java -text
forge-gui/src/main/java/forge/game/cost/CostDamage.java -text forge-gui/src/main/java/forge/game/cost/CostDamage.java -text
forge-gui/src/main/java/forge/game/cost/CostDecisionMakerBase.java -text
forge-gui/src/main/java/forge/game/cost/CostDiscard.java -text forge-gui/src/main/java/forge/game/cost/CostDiscard.java -text
forge-gui/src/main/java/forge/game/cost/CostDraw.java -text forge-gui/src/main/java/forge/game/cost/CostDraw.java -text
forge-gui/src/main/java/forge/game/cost/CostExile.java -text forge-gui/src/main/java/forge/game/cost/CostExile.java -text

View File

@@ -18,6 +18,7 @@ import forge.game.card.CardPredicates.Presets;
import forge.game.cost.CostAddMana; import forge.game.cost.CostAddMana;
import forge.game.cost.CostChooseCreatureType; import forge.game.cost.CostChooseCreatureType;
import forge.game.cost.CostDamage; import forge.game.cost.CostDamage;
import forge.game.cost.CostDecisionMakerBase;
import forge.game.cost.CostDiscard; import forge.game.cost.CostDiscard;
import forge.game.cost.CostDraw; import forge.game.cost.CostDraw;
import forge.game.cost.CostExile; import forge.game.cost.CostExile;
@@ -47,19 +48,18 @@ import forge.game.player.PlayerControllerAi;
import forge.game.spellability.SpellAbility; import forge.game.spellability.SpellAbility;
import forge.game.zone.ZoneType; import forge.game.zone.ZoneType;
public class AiCostDecision implements ICostVisitor<PaymentDecision> { public class AiCostDecision extends CostDecisionMakerBase implements ICostVisitor<PaymentDecision> {
private final Player ai;
private final SpellAbility ability; private final SpellAbility ability;
private final Card source; private final Card source;
public AiCostDecision(Player ai0, SpellAbility sa, Card source0) { public AiCostDecision(Player ai0, SpellAbility sa) {
ai = ai0; super(ai0);
ability = sa; ability = sa;
source = source0; source = ability.getSourceCard();
} }
@Override @Override
public PaymentDecision visit(CostAddMana cost) { public PaymentDecision visit(CostAddMana cost) {
Integer c = cost.convertAmount(); Integer c = cost.convertAmount();
@@ -74,7 +74,7 @@ public class AiCostDecision implements ICostVisitor<PaymentDecision> {
@Override @Override
public PaymentDecision visit(CostChooseCreatureType cost) { public PaymentDecision visit(CostChooseCreatureType cost) {
String choice = ai.getController().chooseSomeType("Creature", ability, new ArrayList<String>(CardType.getCreatureTypes()), new ArrayList<String>()); String choice = player.getController().chooseSomeType("Creature", ability, new ArrayList<String>(CardType.getCreatureTypes()), new ArrayList<String>());
return PaymentDecision.type(choice); return PaymentDecision.type(choice);
} }
@@ -82,12 +82,12 @@ public class AiCostDecision implements ICostVisitor<PaymentDecision> {
public PaymentDecision visit(CostDiscard cost) { public PaymentDecision visit(CostDiscard cost) {
final String type = cost.getType(); final String type = cost.getType();
final List<Card> hand = ai.getCardsIn(ZoneType.Hand); final List<Card> hand = player.getCardsIn(ZoneType.Hand);
if (type.equals("LastDrawn")) { if (type.equals("LastDrawn")) {
if (!hand.contains(ai.getLastDrawnCard())) { if (!hand.contains(player.getLastDrawnCard())) {
return null; return null;
} }
return PaymentDecision.card(ai.getLastDrawnCard()); return PaymentDecision.card(player.getLastDrawnCard());
} }
else if (cost.payCostFromSource()) { else if (cost.payCostFromSource()) {
if (!hand.contains(source)) { if (!hand.contains(source)) {
@@ -116,7 +116,7 @@ public class AiCostDecision implements ICostVisitor<PaymentDecision> {
return PaymentDecision.card(CardLists.getRandomSubList(hand, c)); return PaymentDecision.card(CardLists.getRandomSubList(hand, c));
} }
else { else {
final AiController aic = ((PlayerControllerAi)ai.getController()).getAi(); final AiController aic = ((PlayerControllerAi)player.getController()).getAi();
return PaymentDecision.card(aic.getCardsToDiscard(c, type.split(";"), ability)); return PaymentDecision.card(aic.getCardsToDiscard(c, type.split(";"), ability));
} }
} }
@@ -156,7 +156,7 @@ public class AiCostDecision implements ICostVisitor<PaymentDecision> {
} }
if (cost.getType().equals("All")) { if (cost.getType().equals("All")) {
return PaymentDecision.card(ai.getCardsIn(cost.getFrom())); return PaymentDecision.card(player.getCardsIn(cost.getFrom()));
} }
else if (cost.getType().contains("FromTopGrave")) { else if (cost.getType().contains("FromTopGrave")) {
return null; return null;
@@ -173,14 +173,14 @@ public class AiCostDecision implements ICostVisitor<PaymentDecision> {
} }
if (cost.getFrom().equals(ZoneType.Library)) { if (cost.getFrom().equals(ZoneType.Library)) {
return PaymentDecision.card(ai.getCardsIn(ZoneType.Library, c)); return PaymentDecision.card(player.getCardsIn(ZoneType.Library, c));
} }
else if (cost.sameZone) { else if (cost.sameZone) {
// TODO Determine exile from same zone for AI // TODO Determine exile from same zone for AI
return null; return null;
} }
else { else {
List<Card> chosen = ComputerUtil.chooseExileFrom(ai, cost.getFrom(), cost.getType(), source, ability.getTargetCard(), c); List<Card> chosen = ComputerUtil.chooseExileFrom(player, cost.getFrom(), cost.getType(), source, ability.getTargetCard(), c);
return null == chosen ? null : PaymentDecision.card(chosen); return null == chosen ? null : PaymentDecision.card(chosen);
} }
} }
@@ -195,9 +195,9 @@ public class AiCostDecision implements ICostVisitor<PaymentDecision> {
c = AbilityUtils.calculateAmount(source, cost.getAmount(), ability); c = AbilityUtils.calculateAmount(source, cost.getAmount(), ability);
} }
List<Card> typeList = ai.getGame().getCardsIn(ZoneType.Exile); List<Card> typeList = player.getGame().getCardsIn(ZoneType.Exile);
typeList = CardLists.getValidCards(typeList, cost.getType().split(";"), ai, source); typeList = CardLists.getValidCards(typeList, cost.getType().split(";"), player, source);
if (typeList.size() < c) { if (typeList.size() < c) {
return null; return null;
@@ -237,7 +237,7 @@ public class AiCostDecision implements ICostVisitor<PaymentDecision> {
c = AbilityUtils.calculateAmount(source, cost.getAmount(), ability); c = AbilityUtils.calculateAmount(source, cost.getAmount(), ability);
} }
final List<Card> typeList = CardLists.getValidCards(ai.getGame().getCardsIn(ZoneType.Battlefield), cost.getType().split(";"), ai, source); final List<Card> typeList = CardLists.getValidCards(player.getGame().getCardsIn(ZoneType.Battlefield), cost.getType().split(";"), player, source);
if (typeList.size() < c) { if (typeList.size() < c) {
@@ -258,7 +258,7 @@ public class AiCostDecision implements ICostVisitor<PaymentDecision> {
public PaymentDecision visit(CostGainLife cost) { public PaymentDecision visit(CostGainLife cost) {
final List<Player> oppsThatCanGainLife = new ArrayList<Player>(); final List<Player> oppsThatCanGainLife = new ArrayList<Player>();
for (final Player opp : cost.getPotentialTargets(ai, source)) { for (final Player opp : cost.getPotentialTargets(player, source)) {
if (opp.canGainLife()) { if (opp.canGainLife()) {
oppsThatCanGainLife.add(opp); oppsThatCanGainLife.add(opp);
} }
@@ -285,7 +285,7 @@ public class AiCostDecision implements ICostVisitor<PaymentDecision> {
c = AbilityUtils.calculateAmount(source, cost.getAmount(), ability); c = AbilityUtils.calculateAmount(source, cost.getAmount(), ability);
} }
List<Card> topLib = ai.getCardsIn(ZoneType.Library, c); List<Card> topLib = player.getCardsIn(ZoneType.Library, c);
return topLib.size() < c ? null : PaymentDecision.card(topLib); return topLib.size() < c ? null : PaymentDecision.card(topLib);
} }
@@ -306,7 +306,7 @@ public class AiCostDecision implements ICostVisitor<PaymentDecision> {
c = AbilityUtils.calculateAmount(source, cost.getAmount(), ability); c = AbilityUtils.calculateAmount(source, cost.getAmount(), ability);
} }
} }
if (!ai.canPayLife(c)) { if (!player.canPayLife(c)) {
return null; return null;
} }
// activator.payLife(c, null); // activator.payLife(c, null);
@@ -317,14 +317,14 @@ public class AiCostDecision implements ICostVisitor<PaymentDecision> {
@Override @Override
public PaymentDecision visit(CostPutCardToLib cost) { public PaymentDecision visit(CostPutCardToLib cost) {
Integer c = cost.convertAmount(); Integer c = cost.convertAmount();
final Game game = ai.getGame(); final Game game = player.getGame();
List<Card> chosen = new ArrayList<Card>(); List<Card> chosen = new ArrayList<Card>();
List<Card> list; List<Card> list;
if (cost.isSameZone()) { if (cost.isSameZone()) {
list = new ArrayList<Card>(game.getCardsIn(cost.getFrom())); list = new ArrayList<Card>(game.getCardsIn(cost.getFrom()));
} else { } else {
list = new ArrayList<Card>(ai.getCardsIn(cost.getFrom())); list = new ArrayList<Card>(player.getCardsIn(cost.getFrom()));
} }
if (c == null) { if (c == null) {
@@ -337,7 +337,7 @@ public class AiCostDecision implements ICostVisitor<PaymentDecision> {
c = AbilityUtils.calculateAmount(source, cost.getAmount(), ability); c = AbilityUtils.calculateAmount(source, cost.getAmount(), ability);
} }
list = CardLists.getValidCards(list, cost.getType().split(";"), ai, source); list = CardLists.getValidCards(list, cost.getType().split(";"), player, source);
if (cost.isSameZone()) { if (cost.isSameZone()) {
// Jotun Grunt // Jotun Grunt
@@ -352,7 +352,7 @@ public class AiCostDecision implements ICostVisitor<PaymentDecision> {
} }
chosen = chosen.subList(0, c); chosen = chosen.subList(0, c);
} else { } else {
chosen = ComputerUtil.choosePutToLibraryFrom(ai, cost.getFrom(), cost.getType(), source, ability.getTargetCard(), c); chosen = ComputerUtil.choosePutToLibraryFrom(player, cost.getFrom(), cost.getType(), source, ability.getTargetCard(), c);
} }
return chosen.isEmpty() ? null : PaymentDecision.card(chosen); return chosen.isEmpty() ? null : PaymentDecision.card(chosen);
} }
@@ -365,7 +365,7 @@ public class AiCostDecision implements ICostVisitor<PaymentDecision> {
} }
final List<Card> typeList = CardLists.getValidCards(ai.getGame().getCardsIn(ZoneType.Battlefield), cost.getType().split(";"), ai, source); final List<Card> typeList = CardLists.getValidCards(player.getGame().getCardsIn(ZoneType.Battlefield), cost.getType().split(";"), player, source);
Card card = null; Card card = null;
if (cost.getType().equals("Creature.YouCtrl")) { if (cost.getType().equals("Creature.YouCtrl")) {
@@ -390,7 +390,7 @@ public class AiCostDecision implements ICostVisitor<PaymentDecision> {
final String sVar = ability.getSVar(amount); final String sVar = ability.getSVar(amount);
if (sVar.equals("XChoice")) { if (sVar.equals("XChoice")) {
List<Card> typeList = List<Card> typeList =
CardLists.getValidCards(ai.getCardsIn(ZoneType.Battlefield), cost.getType().split(";"), ability.getActivatingPlayer(), ability.getSourceCard()); CardLists.getValidCards(player.getCardsIn(ZoneType.Battlefield), cost.getType().split(";"), ability.getActivatingPlayer(), ability.getSourceCard());
typeList = CardLists.filter(typeList, Presets.UNTAPPED); typeList = CardLists.filter(typeList, Presets.UNTAPPED);
c = typeList.size(); c = typeList.size();
source.setSVar("ChosenX", "Number$" + Integer.toString(c)); source.setSVar("ChosenX", "Number$" + Integer.toString(c));
@@ -402,7 +402,7 @@ public class AiCostDecision implements ICostVisitor<PaymentDecision> {
return null; return null;
} }
List<Card> totap = ComputerUtil.chooseTapType(ai, cost.getType(), source, !cost.canTapSource, c); List<Card> totap = ComputerUtil.chooseTapType(player, cost.getType(), source, !cost.canTapSource, c);
if (totap == null) { if (totap == null) {
@@ -437,7 +437,7 @@ public class AiCostDecision implements ICostVisitor<PaymentDecision> {
c = AbilityUtils.calculateAmount(source, cost.getAmount(), ability); c = AbilityUtils.calculateAmount(source, cost.getAmount(), ability);
} }
List<Card> list = ComputerUtil.chooseSacrificeType(ai, cost.getType(), source, ability.getTargetCard(), c); List<Card> list = ComputerUtil.chooseSacrificeType(player, cost.getType(), source, ability.getTargetCard(), c);
return PaymentDecision.card(list); return PaymentDecision.card(list);
} }
@@ -451,7 +451,7 @@ public class AiCostDecision implements ICostVisitor<PaymentDecision> {
c = AbilityUtils.calculateAmount(source, cost.getAmount(), ability); c = AbilityUtils.calculateAmount(source, cost.getAmount(), ability);
} }
List<Card> res = ComputerUtil.chooseReturnType(ai, cost.getType(), source, ability.getTargetCard(), c); List<Card> res = ComputerUtil.chooseReturnType(player, cost.getType(), source, ability.getTargetCard(), c);
return res.isEmpty() ? null : PaymentDecision.card(res); return res.isEmpty() ? null : PaymentDecision.card(res);
} }
@@ -459,7 +459,7 @@ public class AiCostDecision implements ICostVisitor<PaymentDecision> {
public PaymentDecision visit(CostReveal cost) { public PaymentDecision visit(CostReveal cost) {
final String type = cost.getType(); final String type = cost.getType();
List<Card> hand = new ArrayList<Card>(ai.getCardsIn(ZoneType.Hand)); List<Card> hand = new ArrayList<Card>(player.getCardsIn(ZoneType.Hand));
if (cost.payCostFromSource()) { if (cost.payCostFromSource()) {
if (!hand.contains(source)) { if (!hand.contains(source)) {
@@ -469,13 +469,13 @@ public class AiCostDecision implements ICostVisitor<PaymentDecision> {
} }
if (cost.getType().equals("Hand")) if (cost.getType().equals("Hand"))
return PaymentDecision.card(ai.getCardsIn(ZoneType.Hand)); return PaymentDecision.card(player.getCardsIn(ZoneType.Hand));
if (cost.getType().equals("SameColor")) { if (cost.getType().equals("SameColor")) {
return null; return null;
} }
hand = CardLists.getValidCards(hand, type.split(";"), ai, source); hand = CardLists.getValidCards(hand, type.split(";"), player, source);
Integer c = cost.convertAmount(); Integer c = cost.convertAmount();
if (c == null) { if (c == null) {
final String sVar = ability.getSVar(cost.getAmount()); final String sVar = ability.getSVar(cost.getAmount());
@@ -486,7 +486,7 @@ public class AiCostDecision implements ICostVisitor<PaymentDecision> {
} }
} }
final AiController aic = ((PlayerControllerAi)ai.getController()).getAi(); final AiController aic = ((PlayerControllerAi)player.getController()).getAi();
return PaymentDecision.card(aic.getCardsToDiscard(c, type.split(";"), ability)); return PaymentDecision.card(aic.getCardsToDiscard(c, type.split(";"), ability));
} }
@@ -496,7 +496,7 @@ public class AiCostDecision implements ICostVisitor<PaymentDecision> {
final int c = AbilityUtils.calculateAmount(source, amount, ability); final int c = AbilityUtils.calculateAmount(source, amount, ability);
final String type = cost.getType(); final String type = cost.getType();
List<Card> typeList = CardLists.getValidCards(ai.getCardsIn(ZoneType.Battlefield), type.split(";"), ai, source); List<Card> typeList = CardLists.getValidCards(player.getCardsIn(ZoneType.Battlefield), type.split(";"), player, source);
List<Card> hperms = CardLists.filter(typeList, new Predicate<Card>() { List<Card> hperms = CardLists.filter(typeList, new Predicate<Card>() {
@Override @Override
public boolean apply(final Card crd) { public boolean apply(final Card crd) {
@@ -536,7 +536,7 @@ public class AiCostDecision implements ICostVisitor<PaymentDecision> {
if (type.equals("OriginalHost")) { if (type.equals("OriginalHost")) {
typeList = Lists.newArrayList(ability.getOriginalHost()); typeList = Lists.newArrayList(ability.getOriginalHost());
} else { } else {
typeList = CardLists.getValidCards(ai.getCardsIn(cost.zone), type.split(";"), ai, source); typeList = CardLists.getValidCards(player.getCardsIn(cost.zone), type.split(";"), player, source);
} }
for (Card card : typeList) { for (Card card : typeList) {
if (card.getCounters(cost.counter) >= c) { if (card.getCounters(cost.counter) >= c) {
@@ -563,8 +563,8 @@ public class AiCostDecision implements ICostVisitor<PaymentDecision> {
if (c == null) { if (c == null) {
final String sVar = ability.getSVar(amount); final String sVar = ability.getSVar(amount);
if (sVar.equals("XChoice")) { if (sVar.equals("XChoice")) {
List<Card> typeList = ai.getGame().getCardsIn(ZoneType.Battlefield); List<Card> typeList = player.getGame().getCardsIn(ZoneType.Battlefield);
typeList = CardLists.getValidCards(typeList, cost.getType().split(";"), ai, ability.getSourceCard()); typeList = CardLists.getValidCards(typeList, cost.getType().split(";"), player, ability.getSourceCard());
if (!cost.canUntapSource) { if (!cost.canUntapSource) {
typeList.remove(source); typeList.remove(source);
} }
@@ -576,7 +576,7 @@ public class AiCostDecision implements ICostVisitor<PaymentDecision> {
} }
} }
List<Card> list = ComputerUtil.chooseUntapType(ai, cost.getType(), source, cost.canUntapSource, c); List<Card> list = ComputerUtil.chooseUntapType(player, cost.getType(), source, cost.canUntapSource, c);
if (list == null) { if (list == null) {
System.out.println("Couldn't find a valid card to untap for: " + source.getName()); System.out.println("Couldn't find a valid card to untap for: " + source.getName());
@@ -593,12 +593,17 @@ public class AiCostDecision implements ICostVisitor<PaymentDecision> {
@Override @Override
public PaymentDecision visit(CostUnattach cost) { public PaymentDecision visit(CostUnattach cost) {
Card cardToUnattach = cost.findCardToUnattach(source, (Player) ai, ability); Card cardToUnattach = cost.findCardToUnattach(source, (Player) player, ability);
if (cardToUnattach == null) { if (cardToUnattach == null) {
// We really shouldn't be able to get here if there's nothing to unattach // We really shouldn't be able to get here if there's nothing to unattach
return null; return null;
} }
return PaymentDecision.card(cardToUnattach); return PaymentDecision.card(cardToUnattach);
} }
@Override
public boolean paysRightAfterDecision() {
return false;
}
} }

View File

@@ -116,7 +116,7 @@ public class ComputerUtil {
} }
} else { } else {
final CostPayment pay = new CostPayment(cost, sa); final CostPayment pay = new CostPayment(cost, sa);
if (pay.payComputerCosts(ai, game)) { if (pay.payComputerCosts(new AiCostDecision(ai, sa))) {
game.getStack().addAndUnfreeze(sa); game.getStack().addAndUnfreeze(sa);
if (sa.getSplicedCards() != null && !sa.getSplicedCards().isEmpty()) { if (sa.getSplicedCards() != null && !sa.getSplicedCards().isEmpty()) {
game.getAction().reveal(sa.getSplicedCards(), ai, true, "Computer reveals spliced cards from "); game.getAction().reveal(sa.getSplicedCards(), ai, true, "Computer reveals spliced cards from ");
@@ -240,7 +240,7 @@ public class ComputerUtil {
game.getStack().add(sa); game.getStack().add(sa);
} else { } else {
final CostPayment pay = new CostPayment(cost, sa); final CostPayment pay = new CostPayment(cost, sa);
if (pay.payComputerCosts(ai, game)) { if (pay.payComputerCosts(new AiCostDecision(ai, sa))) {
game.getStack().add(sa); game.getStack().add(sa);
} }
} }
@@ -287,7 +287,7 @@ public class ComputerUtil {
} }
final CostPayment pay = new CostPayment(newSA.getPayCosts(), newSA); final CostPayment pay = new CostPayment(newSA.getPayCosts(), newSA);
pay.payComputerCosts(ai, game); pay.payComputerCosts(new AiCostDecision(ai, sa));
game.getStack().add(newSA); game.getStack().add(newSA);
} }
@@ -314,7 +314,7 @@ public class ComputerUtil {
ComputerUtilMana.payManaCost(ai, sa); ComputerUtilMana.payManaCost(ai, sa);
} else { } else {
final CostPayment pay = new CostPayment(cost, sa); final CostPayment pay = new CostPayment(cost, sa);
pay.payComputerCosts(ai, game); pay.payComputerCosts(new AiCostDecision(ai, sa));
} }
AbilityUtils.resolve(sa); AbilityUtils.resolve(sa);

View File

@@ -209,7 +209,7 @@ public class ComputerUtilMana {
else { else {
if (saPayment.getPayCosts() != null) { if (saPayment.getPayCosts() != null) {
final CostPayment pay = new CostPayment(saPayment.getPayCosts(), saPayment); final CostPayment pay = new CostPayment(saPayment.getPayCosts(), saPayment);
if (!pay.payComputerCosts(ai, ai.getGame())) { if (!pay.payComputerCosts(new AiCostDecision(ai, sa))) {
continue; continue;
} }
} }

View File

@@ -66,7 +66,7 @@ public class DrawAi extends SpellAbilityAi {
} }
if (!ComputerUtilCost.checkDiscardCost(ai, abCost, source)) { if (!ComputerUtilCost.checkDiscardCost(ai, abCost, source)) {
AiCostDecision aiDecisions = new AiCostDecision(ai, sa, source); AiCostDecision aiDecisions = new AiCostDecision(ai, sa);
for (final CostPart part : abCost.getCostParts()) { for (final CostPart part : abCost.getCostParts()) {
if (part instanceof CostDiscard) { if (part instanceof CostDiscard) {
PaymentDecision decision = part.accept(aiDecisions); PaymentDecision decision = part.accept(aiDecisions);

View File

@@ -154,7 +154,10 @@ public class Cost {
parsedMana = new CostPartMana(new ManaCost(new ManaCostParser(manaParts.toString())), xCantBe0 ? "XCantBe0" : null); parsedMana = new CostPartMana(new ManaCost(new ManaCostParser(manaParts.toString())), xCantBe0 ? "XCantBe0" : null);
} }
if (parsedMana != null) { if (parsedMana != null) {
this.costParts.add(0, parsedMana); if(parsedMana.shouldPayLast()) // back from the brink pays mana after 'exile' part is paid
this.costParts.add(parsedMana);
else
this.costParts.add(0, parsedMana);
} }
// inspect parts to set Sac, {T} and {Q} flags // inspect parts to set Sac, {T} and {Q} flags

View File

@@ -0,0 +1,13 @@
package forge.game.cost;
import forge.game.player.Player;
public abstract class CostDecisionMakerBase implements ICostVisitor<PaymentDecision> {
protected final Player player;
public CostDecisionMakerBase(Player player0) {
player = player0;
}
public Player getPlayer() { return player; }
public abstract boolean paysRightAfterDecision();
}

View File

@@ -29,8 +29,12 @@ public class CostPartMana extends CostPart {
// "Leftover" // "Leftover"
private final ManaCost cost; private final ManaCost cost;
private boolean xCantBe0 = false; private boolean xCantBe0 = false;
private boolean isRememberedCreatureCost = false;
private final String restriction; private final String restriction;
public boolean shouldPayLast() {
return isRememberedCreatureCost;
}
/** /**
* Instantiates a new cost mana. * Instantiates a new cost mana.
* *
@@ -43,7 +47,8 @@ public class CostPartMana extends CostPart {
public CostPartMana(final ManaCost cost, String restriction) { public CostPartMana(final ManaCost cost, String restriction) {
this.cost = cost; this.cost = cost;
this.xCantBe0 = "XCantBe0".equals(restriction); this.xCantBe0 = "XCantBe0".equals(restriction);
this.restriction = xCantBe0 ? null : restriction; this.isRememberedCreatureCost = "Remembered".equalsIgnoreCase(restriction);
this.restriction = xCantBe0 || isRememberedCreatureCost ? null : restriction;
} }
/** /**

View File

@@ -19,15 +19,12 @@ package forge.game.cost;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
import forge.ai.AiCostDecision;
import forge.game.Game;
import forge.game.card.Card; import forge.game.card.Card;
import forge.game.player.Player; import forge.game.player.Player;
import forge.game.spellability.SpellAbility; import forge.game.spellability.SpellAbility;
import forge.gui.player.HumanCostDecision;
/** /**
* <p> * <p>
@@ -134,20 +131,12 @@ public class CostPayment {
this.ability.getActivatingPlayer().getManaPool().refundManaPaid(this.ability); this.ability.getActivatingPlayer().getManaPool().refundManaPaid(this.ability);
} }
/** public boolean payCost(final CostDecisionMakerBase decisionMaker) {
* <p>
* payCost.
* </p>
*
* @return a boolean.
*/
public boolean payCost(final Player payer) {
HumanCostDecision hcd = new HumanCostDecision(payer, ability, ability.getSourceCard());
for (final CostPart part : this.cost.getCostParts()) { for (final CostPart part : this.cost.getCostParts()) {
PaymentDecision pd = part.accept(hcd); PaymentDecision pd = part.accept(decisionMaker);
if ( null == pd || !part.payAsDecided(payer, pd, ability)) if ( null == pd || !part.payAsDecided(decisionMaker.getPlayer(), pd, ability))
return false; return false;
// abilities care what was used to pay for them // abilities care what was used to pay for them
@@ -166,35 +155,26 @@ public class CostPayment {
return true; return true;
} }
/** public final boolean payComputerCosts(final CostDecisionMakerBase decisionMaker) {
* <p>
* payComputerCosts.
* </p>
*
* @return a boolean.
*/
public final boolean payComputerCosts(final Player ai, final Game game) {
// canPayAdditionalCosts now Player Agnostic
// Just in case it wasn't set, but honestly it shouldn't have gotten // Just in case it wasn't set, but honestly it shouldn't have gotten
// here without being set // here without being set
this.ability.setActivatingPlayer(ai); this.ability.setActivatingPlayer(decisionMaker.getPlayer());
final Card source = this.ability.getSourceCard();
final List<CostPart> parts = this.cost.getCostParts();
Map<Class<? extends CostPart>, PaymentDecision> decisions = new HashMap<Class<? extends CostPart>, PaymentDecision>(); Map<Class<? extends CostPart>, PaymentDecision> decisions = new HashMap<Class<? extends CostPart>, PaymentDecision>();
AiCostDecision aiDecisions = new AiCostDecision(ai, ability, source);
// Set all of the decisions before attempting to pay anything // Set all of the decisions before attempting to pay anything
for (final CostPart part : parts) { for (final CostPart part : this.cost.getCostParts()) {
PaymentDecision decision = part.accept(aiDecisions); PaymentDecision decision = part.accept(decisionMaker);
if ( null == decision ) return false; if (null == decision) return false;
if (decisionMaker.paysRightAfterDecision() && !part.payAsDecided(decisionMaker.getPlayer(), decision, ability))
return false;
decisions.put(part.getClass(), decision); decisions.put(part.getClass(), decision);
} }
for (final CostPart part : parts) { for (final CostPart part : this.cost.getCostParts()) {
if (!part.payAsDecided(ai, decisions.get(part.getClass()), this.ability)) { if (!part.payAsDecided(decisionMaker.getPlayer(), decisions.get(part.getClass()), this.ability)) {
return false; return false;
} }
// abilities care what was used to pay for them // abilities care what was used to pay for them

View File

@@ -33,6 +33,7 @@ import forge.game.cost.CostPayment;
import forge.game.player.Player; import forge.game.player.Player;
import forge.game.player.PlayerController; import forge.game.player.PlayerController;
import forge.game.zone.Zone; import forge.game.zone.Zone;
import forge.gui.player.HumanCostDecision;
/** /**
* <p> * <p>
@@ -74,7 +75,7 @@ public class HumanPlaySpellAbility {
boolean prerequisitesMet = this.announceValuesLikeX() boolean prerequisitesMet = this.announceValuesLikeX()
&& this.announceType() && this.announceType()
&& (!mayChooseTargets || setupTargets()) // if you can choose targets, then do choose them. && (!mayChooseTargets || setupTargets()) // if you can choose targets, then do choose them.
&& (isFree || this.payment.payCost(human)); && (isFree || this.payment.payCost(new HumanCostDecision(human, ability, ability.getSourceCard())));
if (!prerequisitesMet) { if (!prerequisitesMet) {
if (!ability.isTrigger()) { if (!ability.isTrigger()) {

View File

@@ -25,6 +25,7 @@ import forge.game.card.CardPredicates.Presets;
import forge.game.cost.CostAddMana; import forge.game.cost.CostAddMana;
import forge.game.cost.CostChooseCreatureType; import forge.game.cost.CostChooseCreatureType;
import forge.game.cost.CostDamage; import forge.game.cost.CostDamage;
import forge.game.cost.CostDecisionMakerBase;
import forge.game.cost.CostDiscard; import forge.game.cost.CostDiscard;
import forge.game.cost.CostDraw; import forge.game.cost.CostDraw;
import forge.game.cost.CostExile; import forge.game.cost.CostExile;
@@ -47,7 +48,6 @@ import forge.game.cost.CostTapType;
import forge.game.cost.CostUnattach; import forge.game.cost.CostUnattach;
import forge.game.cost.CostUntap; import forge.game.cost.CostUntap;
import forge.game.cost.CostUntapType; import forge.game.cost.CostUntapType;
import forge.game.cost.ICostVisitor;
import forge.game.cost.PaymentDecision; import forge.game.cost.PaymentDecision;
import forge.game.player.Player; import forge.game.player.Player;
import forge.game.spellability.SpellAbility; import forge.game.spellability.SpellAbility;
@@ -59,14 +59,13 @@ import forge.gui.input.InputSelectManyBase;
import forge.util.Aggregates; import forge.util.Aggregates;
import forge.util.Lang; import forge.util.Lang;
public class HumanCostDecision implements ICostVisitor<PaymentDecision> { public class HumanCostDecision extends CostDecisionMakerBase {
private final Player payer;
private final SpellAbility ability; private final SpellAbility ability;
private final Card source; private final Card source;
public HumanCostDecision(Player p, SpellAbility sa, Card source) { public HumanCostDecision(Player p, SpellAbility sa, Card source) {
payer = p; super(p);
ability = sa; ability = sa;
this.source = source; this.source = source;
} }
@@ -77,7 +76,7 @@ public class HumanCostDecision implements ICostVisitor<PaymentDecision> {
return AbilityFactory.calculateAmount(card, "ChosenX", null); return AbilityFactory.calculateAmount(card, "ChosenX", null);
}*/ }*/
int chosenX = payer.getController().chooseNumber(ability, source.toString() + " - Choose a Value for X", 0, maxValue); int chosenX = player.getController().chooseNumber(ability, source.toString() + " - Choose a Value for X", 0, maxValue);
ability.setSVar("ChosenX", Integer.toString(chosenX)); ability.setSVar("ChosenX", Integer.toString(chosenX));
source.setSVar("ChosenX", Integer.toString(chosenX)); source.setSVar("ChosenX", Integer.toString(chosenX));
return chosenX; return chosenX;
@@ -94,7 +93,7 @@ public class HumanCostDecision implements ICostVisitor<PaymentDecision> {
@Override @Override
public PaymentDecision visit(CostChooseCreatureType cost) { public PaymentDecision visit(CostChooseCreatureType cost) {
String choice = payer.getController().chooseSomeType("Creature", ability, new ArrayList<String>(CardType.getCreatureTypes()), new ArrayList<String>(), true); String choice = player.getController().chooseSomeType("Creature", ability, new ArrayList<String>(CardType.getCreatureTypes()), new ArrayList<String>(), true);
if( null == choice ) if( null == choice )
return null; return null;
return PaymentDecision.type(choice); return PaymentDecision.type(choice);
@@ -102,7 +101,7 @@ public class HumanCostDecision implements ICostVisitor<PaymentDecision> {
@Override @Override
public PaymentDecision visit(CostDiscard cost) { public PaymentDecision visit(CostDiscard cost) {
List<Card> handList = new ArrayList<Card>(payer.getCardsIn(ZoneType.Hand)); List<Card> handList = new ArrayList<Card>(player.getCardsIn(ZoneType.Hand));
String discardType = cost.getType(); String discardType = cost.getType();
final String amount = cost.getAmount(); final String amount = cost.getAmount();
@@ -115,7 +114,7 @@ public class HumanCostDecision implements ICostVisitor<PaymentDecision> {
} }
if (discardType.equals("LastDrawn")) { if (discardType.equals("LastDrawn")) {
final Card lastDrawn = payer.getLastDrawnCard(); final Card lastDrawn = player.getLastDrawnCard();
return handList.contains(lastDrawn) ? PaymentDecision.card(lastDrawn) : null; return handList.contains(lastDrawn) ? PaymentDecision.card(lastDrawn) : null;
} }
@@ -137,7 +136,7 @@ public class HumanCostDecision implements ICostVisitor<PaymentDecision> {
} }
if (discardType.contains("+WithSameName")) { if (discardType.contains("+WithSameName")) {
String type = discardType.replace("+WithSameName", ""); String type = discardType.replace("+WithSameName", "");
handList = CardLists.getValidCards(handList, type.split(";"), payer, source); handList = CardLists.getValidCards(handList, type.split(";"), player, source);
final List<Card> landList2 = handList; final List<Card> landList2 = handList;
handList = CardLists.filter(handList, new Predicate<Card>() { handList = CardLists.filter(handList, new Predicate<Card>() {
@Override @Override
@@ -171,7 +170,7 @@ public class HumanCostDecision implements ICostVisitor<PaymentDecision> {
String type = new String(discardType); String type = new String(discardType);
final String[] validType = type.split(";"); final String[] validType = type.split(";");
handList = CardLists.getValidCards(handList, validType, payer, source); handList = CardLists.getValidCards(handList, validType, player, source);
if (c == null) { if (c == null) {
final String sVar = ability.getSVar(amount); final String sVar = ability.getSVar(amount);
@@ -198,7 +197,7 @@ public class HumanCostDecision implements ICostVisitor<PaymentDecision> {
@Override @Override
public PaymentDecision visit(CostDamage cost) { public PaymentDecision visit(CostDamage cost) {
final String amount = cost.getAmount(); final String amount = cost.getAmount();
final int life = payer.getLife(); final int life = player.getLife();
Integer c = cost.convertAmount(); Integer c = cost.convertAmount();
if (c == null) { if (c == null) {
@@ -212,7 +211,7 @@ public class HumanCostDecision implements ICostVisitor<PaymentDecision> {
} }
} }
if (payer.canPayLife(c) && payer.getController().confirmPayment(cost, "Pay " + c + " Life?")) { if (player.canPayLife(c) && player.getController().confirmPayment(cost, "Pay " + c + " Life?")) {
return PaymentDecision.number(c); return PaymentDecision.number(c);
} }
return null; return null;
@@ -227,7 +226,7 @@ public class HumanCostDecision implements ICostVisitor<PaymentDecision> {
c = AbilityUtils.calculateAmount(source, amount, ability); c = AbilityUtils.calculateAmount(source, amount, ability);
} }
if (!payer.getController().confirmPayment(cost, "Draw " + c + " Card" + (c == 1 ? "" : "s"))) { if (!player.getController().confirmPayment(cost, "Draw " + c + " Card" + (c == 1 ? "" : "s"))) {
return null; return null;
} }
@@ -237,7 +236,7 @@ public class HumanCostDecision implements ICostVisitor<PaymentDecision> {
@Override @Override
public PaymentDecision visit(CostExile cost) { public PaymentDecision visit(CostExile cost) {
final String amount = cost.getAmount(); final String amount = cost.getAmount();
final Game game = payer.getGame(); final Game game = player.getGame();
Integer c = cost.convertAmount(); Integer c = cost.convertAmount();
String type = cost.getType(); String type = cost.getType();
@@ -258,18 +257,18 @@ public class HumanCostDecision implements ICostVisitor<PaymentDecision> {
list = new ArrayList<Card>(game.getCardsIn(cost.from)); list = new ArrayList<Card>(game.getCardsIn(cost.from));
} }
else { else {
list = new ArrayList<Card>(payer.getCardsIn(cost.from)); list = new ArrayList<Card>(player.getCardsIn(cost.from));
} }
if (cost.payCostFromSource()) { if (cost.payCostFromSource()) {
return source.getZone() == payer.getZone(cost.from) && payer.getController().confirmPayment(cost, "Exile " + source.getName() + "?") ? PaymentDecision.card(source) : null; return source.getZone() == player.getZone(cost.from) && player.getController().confirmPayment(cost, "Exile " + source.getName() + "?") ? PaymentDecision.card(source) : null;
} }
if (type.equals("All")) { if (type.equals("All")) {
return PaymentDecision.card(list); return PaymentDecision.card(list);
} }
list = CardLists.getValidCards(list, type.split(";"), payer, source); list = CardLists.getValidCards(list, type.split(";"), player, source);
if (c == null) { if (c == null) {
final String sVar = ability.getSVar(amount); final String sVar = ability.getSVar(amount);
// Generalize this // Generalize this
@@ -290,7 +289,7 @@ public class HumanCostDecision implements ICostVisitor<PaymentDecision> {
} }
if (cost.from == ZoneType.Stack) { return exileFromStack(cost, ability, c); } if (cost.from == ZoneType.Stack) { return exileFromStack(cost, ability, c); }
if (cost.from == ZoneType.Library) { return exileFromTop(cost, ability, payer, c); } if (cost.from == ZoneType.Library) { return exileFromTop(cost, ability, player, c); }
if (fromTopGrave) { return exileFromTopGraveType(ability, c, list); } if (fromTopGrave) { return exileFromTopGraveType(ability, c, list); }
if (!cost.sameZone) { return exileFromMiscZone(cost, ability, c, list); } if (!cost.sameZone) { return exileFromMiscZone(cost, ability, c, list); }
@@ -383,12 +382,12 @@ public class HumanCostDecision implements ICostVisitor<PaymentDecision> {
return PaymentDecision.card(exiled); return PaymentDecision.card(exiled);
} }
private PaymentDecision exileFromTop(final CostExile cost, final SpellAbility sa, final Player payer, final int nNeeded) { private PaymentDecision exileFromTop(final CostExile cost, final SpellAbility sa, final Player player, final int nNeeded) {
final StringBuilder sb = new StringBuilder(); final StringBuilder sb = new StringBuilder();
sb.append("Exile ").append(nNeeded).append(" cards from the top of your library?"); sb.append("Exile ").append(nNeeded).append(" cards from the top of your library?");
final List<Card> list = payer.getCardsIn(ZoneType.Library, nNeeded); final List<Card> list = player.getCardsIn(ZoneType.Library, nNeeded);
if (list.size() > nNeeded || !payer.getController().confirmPayment(cost, "Exile " + Lang.nounWithAmount(nNeeded, "card") + " from the top of your library?")) { if (list.size() > nNeeded || !player.getController().confirmPayment(cost, "Exile " + Lang.nounWithAmount(nNeeded, "card") + " from the top of your library?")) {
return null; return null;
} }
@@ -463,8 +462,8 @@ public class HumanCostDecision implements ICostVisitor<PaymentDecision> {
if (c == null) { if (c == null) {
c = AbilityUtils.calculateAmount(source, amount, ability); c = AbilityUtils.calculateAmount(source, amount, ability);
} }
final List<Card> list = payer.getCardsIn(ZoneType.Battlefield); final List<Card> list = player.getCardsIn(ZoneType.Battlefield);
List<Card> validCards = CardLists.getValidCards(list, cost.getType().split(";"), payer, source); List<Card> validCards = CardLists.getValidCards(list, cost.getType().split(";"), player, source);
InputSelectCardsFromList inp = new InputSelectCardsFromList(c, validCards); InputSelectCardsFromList inp = new InputSelectCardsFromList(c, validCards);
final String desc = cost.getTypeDescription() == null ? cost.getType() : cost.getTypeDescription(); final String desc = cost.getTypeDescription() == null ? cost.getType() : cost.getTypeDescription();
@@ -480,7 +479,7 @@ public class HumanCostDecision implements ICostVisitor<PaymentDecision> {
public PaymentDecision visit(CostGainLife cost) { public PaymentDecision visit(CostGainLife cost) {
final String amount = cost.getAmount(); final String amount = cost.getAmount();
final int life = payer.getLife(); final int life = player.getLife();
Integer c = cost.convertAmount(); Integer c = cost.convertAmount();
if (c == null) { if (c == null) {
@@ -494,7 +493,7 @@ public class HumanCostDecision implements ICostVisitor<PaymentDecision> {
} }
final List<Player> oppsThatCanGainLife = new ArrayList<Player>(); final List<Player> oppsThatCanGainLife = new ArrayList<Player>();
for (final Player opp : cost.getPotentialTargets(payer, source)) { for (final Player opp : cost.getPotentialTargets(player, source)) {
if (opp.canGainLife()) { if (opp.canGainLife()) {
oppsThatCanGainLife.add(opp); oppsThatCanGainLife.add(opp);
} }
@@ -528,16 +527,16 @@ public class HumanCostDecision implements ICostVisitor<PaymentDecision> {
} }
} }
if (!payer.getController().confirmPayment(cost, "Mill " + c + " card" + (c == 1 ? "" : "s") + " from your library?")) { if (!player.getController().confirmPayment(cost, "Mill " + c + " card" + (c == 1 ? "" : "s") + " from your library?")) {
return null; return null;
} }
return PaymentDecision.card(payer.getCardsIn(ZoneType.Library, c)); return PaymentDecision.card(player.getCardsIn(ZoneType.Library, c));
} }
@Override @Override
public PaymentDecision visit(CostPayLife cost) { public PaymentDecision visit(CostPayLife cost) {
final String amount = cost.getAmount(); final String amount = cost.getAmount();
final int life = payer.getLife(); final int life = player.getLife();
Integer c = cost.convertAmount(); Integer c = cost.convertAmount();
if (c == null) { if (c == null) {
@@ -555,7 +554,7 @@ public class HumanCostDecision implements ICostVisitor<PaymentDecision> {
} }
} }
if (payer.canPayLife(c) && payer.getController().confirmPayment(cost, "Pay " + c + " Life?")) { if (player.canPayLife(c) && player.getController().confirmPayment(cost, "Pay " + c + " Life?")) {
return PaymentDecision.number(c); return PaymentDecision.number(c);
} }
return null; return null;
@@ -572,7 +571,7 @@ public class HumanCostDecision implements ICostVisitor<PaymentDecision> {
final String amount = cost.getAmount(); final String amount = cost.getAmount();
Integer c = cost.convertAmount(); Integer c = cost.convertAmount();
List<Card> list = cost.sameZone ? payer.getGame().getCardsIn(cost.getFrom()) : payer.getCardsIn(cost.getFrom()); List<Card> list = cost.sameZone ? player.getGame().getCardsIn(cost.getFrom()) : player.getCardsIn(cost.getFrom());
if (c == null) { if (c == null) {
final String sVar = ability.getSVar(amount); final String sVar = ability.getSVar(amount);
@@ -584,7 +583,7 @@ public class HumanCostDecision implements ICostVisitor<PaymentDecision> {
} }
} }
list = CardLists.getValidCards(list, cost.getType().split(";"), payer, source); list = CardLists.getValidCards(list, cost.getType().split(";"), player, source);
if (cost.from == ZoneType.Hand) { if (cost.from == ZoneType.Hand) {
InputSelectCardsFromList inp = new InputSelectCardsFromList(c, c, list); InputSelectCardsFromList inp = new InputSelectCardsFromList(c, c, list);
@@ -595,7 +594,7 @@ public class HumanCostDecision implements ICostVisitor<PaymentDecision> {
} }
if (cost.sameZone){ if (cost.sameZone){
List<Player> players = payer.getGame().getPlayers(); List<Player> players = player.getGame().getPlayers();
List<Player> payableZone = new ArrayList<Player>(); List<Player> payableZone = new ArrayList<Player>();
for (Player p : players) { for (Player p : players) {
List<Card> enoughType = CardLists.filter(list, CardPredicates.isOwner(p)); List<Card> enoughType = CardLists.filter(list, CardPredicates.isOwner(p));
@@ -664,7 +663,7 @@ public class HumanCostDecision implements ICostVisitor<PaymentDecision> {
} }
// Cards to use this branch: Scarscale Ritual, Wandering Mage - each adds only one counter // Cards to use this branch: Scarscale Ritual, Wandering Mage - each adds only one counter
List<Card> typeList = CardLists.getValidCards(payer.getCardsIn(ZoneType.Battlefield), cost.getType().split(";"), payer, ability.getSourceCard()); List<Card> typeList = CardLists.getValidCards(player.getCardsIn(ZoneType.Battlefield), cost.getType().split(";"), player, ability.getSourceCard());
InputSelectCardsFromList inp = new InputSelectCardsFromList(1, 1, typeList); InputSelectCardsFromList inp = new InputSelectCardsFromList(1, 1, typeList);
inp.setMessage("Put " + Lang.nounWithAmount(c, cost.getCounter().getName() + " counter") + " on " +cost.getDescriptiveType()); inp.setMessage("Put " + Lang.nounWithAmount(c, cost.getCounter().getName() + " counter") + " on " +cost.getDescriptiveType());
@@ -682,7 +681,7 @@ public class HumanCostDecision implements ICostVisitor<PaymentDecision> {
final String amount = cost.getAmount(); final String amount = cost.getAmount();
Integer c = cost.convertAmount(); Integer c = cost.convertAmount();
final List<Card> list = payer.getCardsIn(ZoneType.Battlefield); final List<Card> list = player.getCardsIn(ZoneType.Battlefield);
if (c == null) { if (c == null) {
final String sVar = ability.getSVar(amount); final String sVar = ability.getSVar(amount);
// Generalize this // Generalize this
@@ -694,8 +693,8 @@ public class HumanCostDecision implements ICostVisitor<PaymentDecision> {
} }
if (cost.payCostFromSource()) { if (cost.payCostFromSource()) {
final Card card = ability.getSourceCard(); final Card card = ability.getSourceCard();
if (card.getController() == payer && card.isInPlay()) { if (card.getController() == player && card.isInPlay()) {
return payer.getController().confirmPayment(cost, "Return " + card.getName() + " to hand?") ? PaymentDecision.card(card) : null; return player.getController().confirmPayment(cost, "Return " + card.getName() + " to hand?") ? PaymentDecision.card(card) : null;
} }
} }
else { else {
@@ -721,12 +720,12 @@ public class HumanCostDecision implements ICostVisitor<PaymentDecision> {
return PaymentDecision.card(source); return PaymentDecision.card(source);
if (cost.getType().equals("Hand")) if (cost.getType().equals("Hand"))
return PaymentDecision.card(payer.getCardsIn(ZoneType.Hand)); return PaymentDecision.card(player.getCardsIn(ZoneType.Hand));
InputSelectCardsFromList inp = null; InputSelectCardsFromList inp = null;
if (cost.getType().equals("SameColor")) { if (cost.getType().equals("SameColor")) {
Integer num = cost.convertAmount(); Integer num = cost.convertAmount();
List<Card> handList = payer.getCardsIn(ZoneType.Hand); List<Card> handList = player.getCardsIn(ZoneType.Hand);
final List<Card> handList2 = handList; final List<Card> handList2 = handList;
handList = CardLists.filter(handList, new Predicate<Card>() { handList = CardLists.filter(handList, new Predicate<Card>() {
@Override @Override
@@ -758,8 +757,8 @@ public class HumanCostDecision implements ICostVisitor<PaymentDecision> {
} else { } else {
Integer num = cost.convertAmount(); Integer num = cost.convertAmount();
List<Card> handList = payer.getCardsIn(ZoneType.Hand); List<Card> handList = player.getCardsIn(ZoneType.Hand);
handList = CardLists.getValidCards(handList, cost.getType().split(";"), payer, ability.getSourceCard()); handList = CardLists.getValidCards(handList, cost.getType().split(";"), player, ability.getSourceCard());
if (num == null) { if (num == null) {
final String sVar = ability.getSVar(amount); final String sVar = ability.getSVar(amount);
@@ -792,8 +791,8 @@ public class HumanCostDecision implements ICostVisitor<PaymentDecision> {
c = AbilityUtils.calculateAmount(source, cost.getAmount(), ability); c = AbilityUtils.calculateAmount(source, cost.getAmount(), ability);
} }
List<Card> list = new ArrayList<Card>(payer.getCardsIn(ZoneType.Battlefield)); List<Card> list = new ArrayList<Card>(player.getCardsIn(ZoneType.Battlefield));
list = CardLists.getValidCards(list, type.split(";"), payer, source); list = CardLists.getValidCards(list, type.split(";"), player, source);
list = CardLists.filter(list, new Predicate<Card>() { list = CardLists.filter(list, new Predicate<Card>() {
@@ -930,7 +929,7 @@ public class HumanCostDecision implements ICostVisitor<PaymentDecision> {
return res; return res;
} }
List<Card> validCards = CardLists.getValidCards(payer.getCardsIn(cost.zone), type.split(";"), payer, source); List<Card> validCards = CardLists.getValidCards(player.getCardsIn(cost.zone), type.split(";"), player, source);
if (cost.zone.equals(ZoneType.Battlefield)) { if (cost.zone.equals(ZoneType.Battlefield)) {
final InputSelectCardToRemoveCounter inp = new InputSelectCardToRemoveCounter(cntRemoved, cost.counter, validCards); final InputSelectCardToRemoveCounter inp = new InputSelectCardToRemoveCounter(cntRemoved, cost.counter, validCards);
inp.setMessage("Remove %d " + cost.counter.getName() + " counters from " + cost.getDescriptiveType()); inp.setMessage("Remove %d " + cost.counter.getName() + " counters from " + cost.getDescriptiveType());
@@ -969,15 +968,15 @@ public class HumanCostDecision implements ICostVisitor<PaymentDecision> {
final String amount = cost.getAmount(); final String amount = cost.getAmount();
final String type = cost.getType(); final String type = cost.getType();
List<Card> list = new ArrayList<Card>(payer.getCardsIn(ZoneType.Battlefield)); List<Card> list = new ArrayList<Card>(player.getCardsIn(ZoneType.Battlefield));
list = CardLists.getValidCards(list, type.split(";"), payer, source); list = CardLists.getValidCards(list, type.split(";"), player, source);
if (payer.hasKeyword("You can't sacrifice creatures to cast spells or activate abilities.")) { if (player.hasKeyword("You can't sacrifice creatures to cast spells or activate abilities.")) {
list = CardLists.getNotType(list, "Creature"); list = CardLists.getNotType(list, "Creature");
} }
if (cost.payCostFromSource()) { if (cost.payCostFromSource()) {
if (source.getController() == ability.getActivatingPlayer() && source.isInPlay()) { if (source.getController() == ability.getActivatingPlayer() && source.isInPlay()) {
return payer.getController().confirmPayment(cost, "Sacrifice " + source.getName() + "?") ? PaymentDecision.card(source) : null; return player.getController().confirmPayment(cost, "Sacrifice " + source.getName() + "?") ? PaymentDecision.card(source) : null;
} else } else
return null; return null;
} }
@@ -1020,7 +1019,7 @@ public class HumanCostDecision implements ICostVisitor<PaymentDecision> {
@Override @Override
public PaymentDecision visit(CostTapType cost) { public PaymentDecision visit(CostTapType cost) {
List<Card> typeList = new ArrayList<Card>(payer.getCardsIn(ZoneType.Battlefield)); List<Card> typeList = new ArrayList<Card>(player.getCardsIn(ZoneType.Battlefield));
String type = cost.getType(); String type = cost.getType();
final String amount = cost.getAmount(); final String amount = cost.getAmount();
Integer c = cost.convertAmount(); Integer c = cost.convertAmount();
@@ -1039,7 +1038,7 @@ public class HumanCostDecision implements ICostVisitor<PaymentDecision> {
type = type.replace("+withTotalPowerGE" + totalP, ""); type = type.replace("+withTotalPowerGE" + totalP, "");
} }
typeList = CardLists.getValidCards(typeList, type.split(";"), payer, ability.getSourceCard()); typeList = CardLists.getValidCards(typeList, type.split(";"), player, ability.getSourceCard());
typeList = CardLists.filter(typeList, Presets.UNTAPPED); typeList = CardLists.filter(typeList, Presets.UNTAPPED);
if (c == null && !amount.equals("Any")) { if (c == null && !amount.equals("Any")) {
final String sVar = ability.getSVar(amount); final String sVar = ability.getSVar(amount);
@@ -1113,8 +1112,8 @@ public class HumanCostDecision implements ICostVisitor<PaymentDecision> {
@Override @Override
public PaymentDecision visit(CostUntapType cost) { public PaymentDecision visit(CostUntapType cost) {
List<Card> typeList = CardLists.getValidCards(payer.getGame().getCardsIn(ZoneType.Battlefield), cost.getType().split(";"), List<Card> typeList = CardLists.getValidCards(player.getGame().getCardsIn(ZoneType.Battlefield), cost.getType().split(";"),
payer, ability.getSourceCard()); player, ability.getSourceCard());
typeList = CardLists.filter(typeList, Presets.TAPPED); typeList = CardLists.filter(typeList, Presets.TAPPED);
if (!cost.canUntapSource) { if (!cost.canUntapSource) {
typeList.remove(source); typeList.remove(source);
@@ -1147,10 +1146,15 @@ public class HumanCostDecision implements ICostVisitor<PaymentDecision> {
public PaymentDecision visit(CostUnattach cost) { public PaymentDecision visit(CostUnattach cost) {
final Card source = ability.getSourceCard(); final Card source = ability.getSourceCard();
Card cardToUnattach = cost.findCardToUnattach(source, payer, ability); Card cardToUnattach = cost.findCardToUnattach(source, player, ability);
if (cardToUnattach != null && payer.getController().confirmPayment(cost, "Unattach " + cardToUnattach.getName() + "?")) { if (cardToUnattach != null && player.getController().confirmPayment(cost, "Unattach " + cardToUnattach.getName() + "?")) {
return PaymentDecision.card(cardToUnattach); return PaymentDecision.card(cardToUnattach);
} }
return null; return null;
} }
@Override
public boolean paysRightAfterDecision() {
return true;
}
} }