mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-18 03:38:01 +00:00
changed parameters consumed by HumanPlay.payCostDuringAbilityResolve - it does not really need a surrogate ability.
AiController.confirmAction - spread choices made for specific apis among their matching XxxxxAi classes - to avoid a huge switch and keep all related code in a single place.
This commit is contained in:
@@ -1102,22 +1102,20 @@ public class AbilityUtils {
|
||||
}
|
||||
|
||||
final Cost cost = new Cost(unlessCost, true);
|
||||
final Ability ability = new AbilityStatic(source, cost, sa.getTarget()) {
|
||||
@Override
|
||||
public void resolve() { /* nothing to do here */ }
|
||||
};
|
||||
|
||||
|
||||
boolean paid = false;
|
||||
for (Player payer : payers) {
|
||||
final Ability ability = new AbilityStatic(source, cost, sa.getTarget()) { @Override public void resolve() { } };
|
||||
ability.setActivatingPlayer(payer);
|
||||
if (payer.isComputer()) {
|
||||
if (ComputerUtilCost.willPayUnlessCost(sa, payer, ability, paid, payers) && ComputerUtilCost.canPayCost(ability, payer)) {
|
||||
if (ComputerUtilCost.willPayUnlessCost(sa, payer, cost, paid, payers) && ComputerUtilCost.canPayCost(ability, payer)) {
|
||||
ComputerUtil.playNoStack(payer, ability, game); // Unless cost was payed - no resolve
|
||||
paid = true;
|
||||
}
|
||||
} else {
|
||||
// if it's paid by the AI already the human can pay, but it won't change anything
|
||||
paid |= HumanPlay.payCostDuringAbilityResolve(ability, cost, sa);
|
||||
paid |= HumanPlay.payCostDuringAbilityResolve(payer, source, cost, sa);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -242,7 +242,6 @@ public enum ApiType {
|
||||
|
||||
public SpellAbilityEffect getSpellEffect() {
|
||||
return clsEffect == null ? null : ReflectionUtil.makeDefaultInstanceOf(clsEffect);
|
||||
|
||||
}
|
||||
|
||||
public SpellAbilityAi getAi() {
|
||||
|
||||
@@ -7,6 +7,7 @@ import forge.game.ai.ComputerUtilCost;
|
||||
import forge.game.phase.PhaseHandler;
|
||||
import forge.game.phase.PhaseType;
|
||||
import forge.game.player.Player;
|
||||
import forge.game.player.PlayerActionConfirmMode;
|
||||
|
||||
public abstract class SpellAbilityAi {
|
||||
|
||||
@@ -103,4 +104,9 @@ public abstract class SpellAbilityAi {
|
||||
final AbilitySub subAb = ab.getSubAbility();
|
||||
return ab.getAi().chkAIDrawback(ab, aiPlayer) && (subAb == null || chkDrawbackWithSubs(aiPlayer, subAb));
|
||||
}
|
||||
|
||||
public boolean confirmAction(Player player, SpellAbility sa, PlayerActionConfirmMode mode, String message) {
|
||||
System.err.println("Warning: default (ie. inherited from base class) implementation of confirmAction is used for " + this.getClass().getName() + ". Consider declaring an overloaded method");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ import forge.card.spellability.Target;
|
||||
import forge.game.ai.ComputerUtilCard;
|
||||
import forge.game.phase.PhaseType;
|
||||
import forge.game.player.Player;
|
||||
import forge.game.player.PlayerActionConfirmMode;
|
||||
import forge.game.zone.ZoneType;
|
||||
import forge.util.MyRandom;
|
||||
|
||||
@@ -112,4 +113,13 @@ public class CopyPermanentAi extends SpellAbilityAi {
|
||||
return true;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see forge.card.ability.SpellAbilityAi#confirmAction(forge.game.player.Player, forge.card.spellability.SpellAbility, forge.game.player.PlayerActionConfirmMode, java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
public boolean confirmAction(Player player, SpellAbility sa, PlayerActionConfirmMode mode, String message) {
|
||||
//TODO: add logic here
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -2,11 +2,13 @@ package forge.card.ability.ai;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
import forge.Card;
|
||||
import forge.card.ability.SpellAbilityAi;
|
||||
import forge.card.spellability.SpellAbility;
|
||||
import forge.card.spellability.Target;
|
||||
import forge.game.phase.PhaseType;
|
||||
import forge.game.player.Player;
|
||||
import forge.game.player.PlayerActionConfirmMode;
|
||||
import forge.game.zone.ZoneType;
|
||||
import forge.util.MyRandom;
|
||||
|
||||
@@ -65,4 +67,13 @@ public class DigAi extends SpellAbilityAi {
|
||||
return true;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see forge.card.ability.SpellAbilityAi#confirmAction(forge.card.spellability.SpellAbility, forge.game.player.PlayerActionConfirmMode, java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
public boolean confirmAction(Player player, SpellAbility sa, PlayerActionConfirmMode mode, String message) {
|
||||
// looks like perfect code for Delver of Secrets, but what about other cards?
|
||||
Card topc = player.getZone(ZoneType.Library).get(0);
|
||||
return topc.isInstant() || topc.isSorcery();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ import forge.game.ai.ComputerUtilCost;
|
||||
import forge.game.ai.ComputerUtilMana;
|
||||
import forge.game.phase.PhaseType;
|
||||
import forge.game.player.Player;
|
||||
import forge.game.player.PlayerActionConfirmMode;
|
||||
import forge.game.zone.ZoneType;
|
||||
import forge.util.MyRandom;
|
||||
|
||||
@@ -165,4 +166,13 @@ public class DiscardAi extends SpellAbilityAi {
|
||||
// TODO: check for some extra things
|
||||
return true;
|
||||
} // discardCheckDrawbackAI()
|
||||
|
||||
|
||||
public boolean confirmAction(Player player, SpellAbility sa, PlayerActionConfirmMode mode, String message) {
|
||||
if ( mode == PlayerActionConfirmMode.Random ) { //
|
||||
// TODO For now AI will always discard Random used currently with: Balduvian Horde and similar cards
|
||||
return true;
|
||||
}
|
||||
return super.confirmAction(player, sa, mode, message);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,6 +37,7 @@ import forge.game.ai.ComputerUtilCost;
|
||||
import forge.game.ai.ComputerUtilMana;
|
||||
import forge.game.phase.PhaseType;
|
||||
import forge.game.player.Player;
|
||||
import forge.game.player.PlayerActionConfirmMode;
|
||||
import forge.game.zone.ZoneType;
|
||||
import forge.util.MyRandom;
|
||||
|
||||
@@ -267,4 +268,14 @@ public class DrawAi extends SpellAbilityAi {
|
||||
return targetAI(ai, sa, mandatory);
|
||||
}
|
||||
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see forge.card.ability.SpellAbilityAi#confirmAction(forge.game.player.Player, forge.card.spellability.SpellAbility, forge.game.player.PlayerActionConfirmMode, java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
public boolean confirmAction(Player player, SpellAbility sa, PlayerActionConfirmMode mode, String message) {
|
||||
int numCards = sa.hasParam("NumCards") ? AbilityUtils.calculateAmount(sa.getSourceCard(), sa.getParam("NumCards"), sa) : 1;
|
||||
// AI shouldn't mill itself
|
||||
return numCards < player.getZone(ZoneType.Library).size();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ package forge.card.ability.ai;
|
||||
import forge.card.ability.SpellAbilityAi;
|
||||
import forge.card.spellability.SpellAbility;
|
||||
import forge.game.player.Player;
|
||||
import forge.game.player.PlayerActionConfirmMode;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
@@ -51,4 +52,10 @@ public final class EncodeAi extends SpellAbilityAi {
|
||||
public boolean chkAIDrawback(SpellAbility sa, Player ai) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean confirmAction(Player player, SpellAbility sa, PlayerActionConfirmMode mode, String message) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
package forge.card.ability.ai;
|
||||
|
||||
import forge.card.ability.SpellAbilityAi;
|
||||
import forge.card.spellability.AbilitySub;
|
||||
import forge.card.spellability.SpellAbility;
|
||||
import forge.game.player.Player;
|
||||
import forge.game.player.PlayerActionConfirmMode;
|
||||
|
||||
/**
|
||||
* TODO: Write javadoc for this type.
|
||||
@@ -20,4 +22,13 @@ public class PeekAndRevealAi extends SpellAbilityAi {
|
||||
return true;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see forge.card.ability.SpellAbilityAi#confirmAction(forge.game.player.Player, forge.card.spellability.SpellAbility, forge.game.player.PlayerActionConfirmMode, java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
public boolean confirmAction(Player player, SpellAbility sa, PlayerActionConfirmMode mode, String message) {
|
||||
AbilitySub subAb = sa.getSubAbility();
|
||||
return subAb != null && subAb.getAi().chkDrawbackWithSubs(player, subAb);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ import forge.game.ai.ComputerUtilMana;
|
||||
import forge.game.phase.PhaseHandler;
|
||||
import forge.game.phase.PhaseType;
|
||||
import forge.game.player.Player;
|
||||
import forge.game.player.PlayerActionConfirmMode;
|
||||
import forge.game.zone.ZoneType;
|
||||
|
||||
public class PumpAi extends PumpAiBase {
|
||||
@@ -446,4 +447,14 @@ public class PumpAi extends PumpAiBase {
|
||||
|
||||
return true;
|
||||
} // pumpDrawbackAI()
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public boolean confirmAction(Player player, SpellAbility sa, PlayerActionConfirmMode mode, String message) {
|
||||
//TODO Add logic here if necessary but I think the AI won't cast
|
||||
//the spell in the first place if it would curse its own creature
|
||||
//and the pump isn't mandatory
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import forge.card.ability.SpellAbilityAi;
|
||||
import forge.card.spellability.SpellAbility;
|
||||
import forge.card.spellability.Target;
|
||||
import forge.game.player.Player;
|
||||
import forge.game.player.PlayerActionConfirmMode;
|
||||
|
||||
public class RepeatAi extends SpellAbilityAi {
|
||||
|
||||
@@ -21,4 +22,11 @@ public class RepeatAi extends SpellAbilityAi {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean confirmAction(Player player, SpellAbility sa, PlayerActionConfirmMode mode, String message) {
|
||||
//TODO add logic to have computer make better choice (ArsenalNut)
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package forge.card.ability.ai;
|
||||
import forge.card.ability.SpellAbilityAi;
|
||||
import forge.card.spellability.SpellAbility;
|
||||
import forge.game.player.Player;
|
||||
import forge.game.player.PlayerActionConfirmMode;
|
||||
|
||||
public class ShuffleAi extends SpellAbilityAi {
|
||||
@Override
|
||||
@@ -47,4 +48,12 @@ public class ShuffleAi extends SpellAbilityAi {
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public boolean confirmAction(Player player, SpellAbility sa, PlayerActionConfirmMode mode, String message) {
|
||||
// ai could analyze parameter denoting the player to shuffle
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -506,9 +506,7 @@ public class GameAction {
|
||||
private static final long serialVersionUID = 8858061639236920054L;
|
||||
|
||||
@Override
|
||||
public void resolve() {
|
||||
|
||||
}
|
||||
public void resolve() {}
|
||||
|
||||
@Override
|
||||
public String getStackDescription() {
|
||||
@@ -533,7 +531,7 @@ public class GameAction {
|
||||
Player p = recoverable.getController();
|
||||
boolean hasPaid = false;
|
||||
if (p.isHuman()) {
|
||||
hasPaid = HumanPlay.payCostDuringAbilityResolve(abRecover, abRecover.getPayCosts(), null);
|
||||
hasPaid = HumanPlay.payCostDuringAbilityResolve(p, recoverable, cost, null);
|
||||
} else { // computer
|
||||
if (ComputerUtilCost.canPayCost(abRecover, p)) {
|
||||
ComputerUtil.playNoStack(p, abRecover, game);
|
||||
|
||||
@@ -35,12 +35,10 @@ import forge.CardPredicates;
|
||||
import forge.CardPredicates.Presets;
|
||||
import forge.Constant;
|
||||
import forge.GameEntity;
|
||||
import forge.card.ability.AbilityUtils;
|
||||
import forge.card.ability.ApiType;
|
||||
import forge.card.cardfactory.CardFactoryUtil;
|
||||
import forge.card.cost.CostDiscard;
|
||||
import forge.card.cost.CostPart;
|
||||
import forge.card.spellability.AbilitySub;
|
||||
import forge.card.spellability.Spell;
|
||||
import forge.card.spellability.SpellAbility;
|
||||
import forge.card.spellability.SpellPermanent;
|
||||
@@ -711,50 +709,12 @@ public class AiController {
|
||||
if( mode != null ) switch (mode) {
|
||||
case BraidOfFire: return true;
|
||||
}
|
||||
} else switch(api) {
|
||||
case Discard:
|
||||
if ( mode == PlayerActionConfirmMode.Random ) { //
|
||||
// TODO For now AI will always discard Random used currently with: Balduvian Horde and similar cards
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
|
||||
case Encode:
|
||||
return true;
|
||||
|
||||
case Dig:
|
||||
Card topc = player.getZone(ZoneType.Library).get(0);
|
||||
return topc.isInstant() || topc.isSorcery();
|
||||
|
||||
case Repeat:
|
||||
//TODO add logic to have computer make better choice (ArsenalNut)
|
||||
return false;
|
||||
|
||||
case PeekAndReveal:
|
||||
AbilitySub subAb = sa.getSubAbility();
|
||||
return subAb != null && subAb.getAi().chkDrawbackWithSubs(player, subAb);
|
||||
|
||||
case Shuffle: // ai could analyze parameter denoting the player to shuffle
|
||||
return true;
|
||||
|
||||
case Pump: //TODO Add logic here if necessary but I think the AI won't cast
|
||||
//the spell in the first place if it would curse its own creature
|
||||
//and the pump isn't mandatory
|
||||
return true;
|
||||
|
||||
case Draw:
|
||||
int numCards = sa.hasParam("NumCards") ? AbilityUtils.calculateAmount(sa.getSourceCard(), sa.getParam("NumCards"), sa) : 1;
|
||||
// AI shouldn't mill itself
|
||||
return numCards < player.getZone(ZoneType.Library).size();
|
||||
|
||||
case CopyPermanent:
|
||||
//TODO: add logic here
|
||||
return true;
|
||||
|
||||
default:
|
||||
}
|
||||
String exMsg = String.format("AI confirmAction does not know what to decide about %s API with %s mode.", api, mode);
|
||||
String exMsg = String.format("AI confirmAction does not know what to decide about %s mode (api is null).", mode);
|
||||
throw new InvalidParameterException(exMsg);
|
||||
|
||||
} else
|
||||
return api.getAi().confirmAction(player, sa, mode, message);
|
||||
}
|
||||
|
||||
public boolean confirmStaticApplication(Card hostCard, GameEntity affected, String logic, String message) {
|
||||
|
||||
@@ -312,8 +312,7 @@ public class ComputerUtilCost {
|
||||
* a {@link java.lang.String} object.
|
||||
* @return a boolean.
|
||||
*/
|
||||
public static boolean shouldPayCost(final Player ai, final Card hostCard, final String costString) {
|
||||
final Cost cost = new Cost(costString, false);
|
||||
public static boolean shouldPayCost(final Player ai, final Card hostCard, final Cost cost) {
|
||||
|
||||
for (final CostPart part : cost.getCostParts()) {
|
||||
if (part instanceof CostPayLife) {
|
||||
@@ -368,7 +367,7 @@ public class ComputerUtilCost {
|
||||
&& CostPayment.canPayAdditionalCosts(sa.getPayCosts(), sa);
|
||||
} // canPayCost()
|
||||
|
||||
public static boolean willPayUnlessCost(SpellAbility sa, Player payer, SpellAbility ability, boolean alreadyPaid, List<Player> payers) {
|
||||
public static boolean willPayUnlessCost(SpellAbility sa, Player payer, Cost cost, boolean alreadyPaid, List<Player> payers) {
|
||||
final Card source = sa.getSourceCard();
|
||||
boolean payForOwnOnly = "OnlyOwn".equals(sa.getParam("UnlessAI"));
|
||||
boolean payOwner = sa.hasParam("UnlessAI") ? sa.getParam("UnlessAI").startsWith("Defined") : false;
|
||||
@@ -409,9 +408,9 @@ public class ComputerUtilCost {
|
||||
// AI was crashing because the blank ability used to pay costs
|
||||
// Didn't have any of the data on the original SA to pay dependant costs
|
||||
|
||||
return checkLifeCost(payer, ability.getPayCosts(), source, 4, sa)
|
||||
&& checkDamageCost(payer, ability.getPayCosts(), source, 4)
|
||||
&& (isMine || checkDiscardCost(payer, ability.getPayCosts(), source))
|
||||
return checkLifeCost(payer, cost, source, 4, sa)
|
||||
&& checkDamageCost(payer, cost, source, 4)
|
||||
&& (isMine || checkDiscardCost(payer, cost, source))
|
||||
&& (!source.getName().equals("Tyrannize") || payer.getCardsIn(ZoneType.Hand).size() > 2)
|
||||
&& (!source.getName().equals("Perplex") || payer.getCardsIn(ZoneType.Hand).size() < 2)
|
||||
&& (!source.getName().equals("Breaking Point") || payer.getCreaturesInPlay().size() > 1)
|
||||
|
||||
@@ -1005,7 +1005,7 @@ public class CombatUtil {
|
||||
ability.setActivatingPlayer(c.getController());
|
||||
|
||||
if (c.getController().isHuman()) {
|
||||
isPaid = HumanPlay.payCostDuringAbilityResolve(ability, attackCost, null);
|
||||
isPaid = HumanPlay.payCostDuringAbilityResolve(c.getController(), c, attackCost, null);
|
||||
} else { // computer
|
||||
if (ComputerUtilCost.canPayCost(ability, c.getController())) {
|
||||
ComputerUtil.playNoStack(c.getController(), ability, game);
|
||||
|
||||
@@ -181,7 +181,7 @@ public class PhaseUtil {
|
||||
ability.setActivatingPlayer(blocker.getController());
|
||||
|
||||
if (blocker.getController().isHuman()) {
|
||||
hasPaid = HumanPlay.payCostDuringAbilityResolve(ability, blockCost, null);
|
||||
hasPaid = HumanPlay.payCostDuringAbilityResolve(blocker.getController(), blocker, blockCost, null);
|
||||
} else { // computer
|
||||
if (ComputerUtilCost.canPayCost(ability, blocker.getController())) {
|
||||
ComputerUtil.playNoStack(blocker.getController(), ability, game);
|
||||
|
||||
@@ -165,7 +165,8 @@ public class Upkeep extends Phase {
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
final Card c = list.get(i);
|
||||
if (c.hasStartOfKeyword("(Echo unpaid)")) {
|
||||
final Ability blankAbility = Upkeep.getBlankAbility(c, c.getEchoCost());
|
||||
Cost cost = new Cost(c.getEchoCost(), true);
|
||||
final Ability blankAbility = Upkeep.getBlankAbility(c, cost);
|
||||
blankAbility.setActivatingPlayer(c.getController());
|
||||
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
@@ -178,7 +179,7 @@ public class Upkeep extends Phase {
|
||||
Player controller = c.getController();
|
||||
if (controller.isHuman()) {
|
||||
Cost cost = new Cost(c.getEchoCost().trim(), true);
|
||||
hasPaid = HumanPlay.payCostDuringAbilityResolve(blankAbility, cost, null);
|
||||
hasPaid = HumanPlay.payCostDuringAbilityResolve(controller, c, cost, null);
|
||||
} else { // computer
|
||||
if (ComputerUtilCost.canPayCost(blankAbility, controller)) {
|
||||
ComputerUtil.playNoStack(controller, blankAbility, game);
|
||||
@@ -230,7 +231,7 @@ public class Upkeep extends Phase {
|
||||
Singletons.getControl().getInputQueue().setInputAndWait(inp);
|
||||
isUpkeepPaid = inp.isPaid();
|
||||
} else { // computer
|
||||
Ability aiPaid = Upkeep.getBlankAbility(c, upkeepCost.toString());
|
||||
Ability aiPaid = Upkeep.getBlankAbility(c, new Cost(upkeepCost, true));
|
||||
isUpkeepPaid = ComputerUtilCost.canPayCost(aiPaid, controller) && !c.hasKeyword("Indestructible");
|
||||
if (isUpkeepPaid) {
|
||||
ComputerUtil.playNoStack(controller, aiPaid, game);
|
||||
@@ -271,24 +272,27 @@ public class Upkeep extends Phase {
|
||||
sb.append("Cumulative upkeep for ").append(c).append("\n");
|
||||
}
|
||||
|
||||
final String upkeepCost = cost;
|
||||
final Cost upkeepCost = new Cost(cost, true);
|
||||
final Ability blankAbility = Upkeep.getBlankAbility(c, upkeepCost);
|
||||
blankAbility.setActivatingPlayer(controller);
|
||||
|
||||
final Ability upkeepAbility = new Ability(c, ManaCost.ZERO) {
|
||||
@Override
|
||||
public void resolve() {
|
||||
boolean isPaid = false;
|
||||
if (controller.isHuman()) {
|
||||
if ( !HumanPlay.payCostDuringAbilityResolve(blankAbility, blankAbility.getPayCosts(), this))
|
||||
game.getAction().sacrifice(c, null);
|
||||
isPaid = HumanPlay.payCostDuringAbilityResolve(controller, c, upkeepCost, this);
|
||||
|
||||
} else { // computer
|
||||
if (ComputerUtilCost.shouldPayCost(controller, c, upkeepCost) && ComputerUtilCost.canPayCost(blankAbility, controller)) {
|
||||
ComputerUtil.playNoStack(controller, blankAbility, game); // this makes AI pay
|
||||
} else {
|
||||
isPaid = true;
|
||||
}
|
||||
}
|
||||
|
||||
if(!isPaid)
|
||||
game.getAction().sacrifice(c, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
upkeepAbility.setActivatingPlayer(controller);
|
||||
upkeepAbility.setStackDescription(sb.toString());
|
||||
@@ -315,7 +319,7 @@ public class Upkeep extends Phase {
|
||||
Singletons.getControl().getInputQueue().setInputAndWait(inp);
|
||||
isUpkeepPaid = inp.isPaid();
|
||||
} else { // computers
|
||||
final Ability aiPaid = Upkeep.getBlankAbility(c, upkeepCost.toString());
|
||||
final Ability aiPaid = Upkeep.getBlankAbility(c, new Cost(upkeepCost, true));
|
||||
if (ComputerUtilCost.canPayCost(aiPaid, controller) && ComputerUtilCombat.predictDamageTo(controller, upkeepDamage, c, false) > 0) {
|
||||
ComputerUtil.playNoStack(controller, aiPaid, game);
|
||||
isUpkeepPaid = true;
|
||||
@@ -350,8 +354,8 @@ public class Upkeep extends Phase {
|
||||
* a {@link java.lang.String} object.
|
||||
* @return a {@link forge.card.spellability.Ability} object.
|
||||
*/
|
||||
public static Ability getBlankAbility(final Card c, final String costString) {
|
||||
return new AbilityStatic(c, new Cost(costString, true), null) {
|
||||
public static Ability getBlankAbility(final Card c, final Cost cost) {
|
||||
return new AbilityStatic(c, cost, null) {
|
||||
@Override
|
||||
public void resolve() {}
|
||||
};
|
||||
|
||||
@@ -49,6 +49,7 @@ import forge.gui.input.InputPayManaExecuteCommands;
|
||||
import forge.gui.input.InputPayManaSimple;
|
||||
import forge.gui.input.InputSelectCards;
|
||||
import forge.gui.input.InputSelectCardsFromList;
|
||||
import forge.util.Lang;
|
||||
|
||||
/**
|
||||
* TODO: Write javadoc for this type.
|
||||
@@ -280,11 +281,9 @@ public class HumanPlay {
|
||||
* a {@link forge.Command} object.
|
||||
* @param sourceAbility TODO
|
||||
*/
|
||||
public static boolean payCostDuringAbilityResolve(final SpellAbility ability, final Cost cost, SpellAbility sourceAbility) {
|
||||
public static boolean payCostDuringAbilityResolve(final Player p, final Card source, final Cost cost, SpellAbility sourceAbility) {
|
||||
|
||||
// Only human player pays this way
|
||||
final Player p = ability.getActivatingPlayer();
|
||||
final Card source = ability.getSourceCard();
|
||||
Card current = null; // Used in spells with RepeatEach effect to distinguish cards, Cut the Tethers
|
||||
if (!source.getRemembered().isEmpty()) {
|
||||
if (source.getRemembered().get(0) instanceof Card) {
|
||||
@@ -295,6 +294,8 @@ public class HumanPlay {
|
||||
current = source.getImprinted().get(0);
|
||||
}
|
||||
|
||||
String promptCurrent = current == null ? "" : "Current Card: " + current + "\r\n";
|
||||
|
||||
final List<CostPart> parts = cost.getCostParts();
|
||||
ArrayList<CostPart> remainingParts = new ArrayList<CostPart>(cost.getCostParts());
|
||||
CostPart costPart = null;
|
||||
@@ -353,8 +354,7 @@ public class HumanPlay {
|
||||
return false;
|
||||
}
|
||||
|
||||
String plural = amount > 1 ? "s" : "";
|
||||
if (false == GuiDialog.confirm(source, "Do you want to put " + amount + " " + counterType.getName() + " counter" + plural + " on " + source + "?"))
|
||||
if (false == GuiDialog.confirm(source, "Do you want to put " + Lang.nounWithAmount(amount, counterType.getName() + " counter") + " on " + source + "?"))
|
||||
return false;
|
||||
|
||||
source.addCounter(counterType, amount, false);
|
||||
@@ -363,12 +363,11 @@ public class HumanPlay {
|
||||
else if (part instanceof CostRemoveCounter) {
|
||||
CounterType counterType = ((CostRemoveCounter) part).getCounter();
|
||||
int amount = getAmountFromPartX(part, source, sourceAbility);
|
||||
String plural = amount > 1 ? "s" : "";
|
||||
|
||||
if (!part.canPay(sourceAbility))
|
||||
return false;
|
||||
|
||||
if ( false == GuiDialog.confirm(source, "Do you want to remove " + amount + " " + counterType.getName() + " counter" + plural + " from " + source + "?"))
|
||||
if ( false == GuiDialog.confirm(source, "Do you want to remove " + Lang.nounWithAmount(amount, counterType.getName() + " counter") + " from " + source + "?"))
|
||||
return false;
|
||||
|
||||
source.subtractCounter(counterType, amount);
|
||||
@@ -387,7 +386,7 @@ public class HumanPlay {
|
||||
CostExile costExile = (CostExile) part;
|
||||
ZoneType from = costExile.getFrom();
|
||||
List<Card> list = CardLists.getValidCards(p.getCardsIn(from), part.getType().split(";"), p, source);
|
||||
final int nNeeded = AbilityUtils.calculateAmount(source, part.getAmount(), ability);
|
||||
final int nNeeded = getAmountFromPart(costPart, source, sourceAbility);
|
||||
if (list.size() < nNeeded)
|
||||
return false;
|
||||
|
||||
@@ -453,9 +452,8 @@ public class HumanPlay {
|
||||
if (!(costPart instanceof CostPartMana ))
|
||||
throw new RuntimeException("GameActionUtil.payCostDuringAbilityResolve - The remaining payment type is not Mana.");
|
||||
|
||||
InputPayMana toSet = current == null
|
||||
? new InputPayManaExecuteCommands(p, source + "\r\n", cost.getCostMana().getManaToPay())
|
||||
: new InputPayManaExecuteCommands(p, source + "\r\n" + "Current Card: " + current + "\r\n" , cost.getCostMana().getManaToPay());
|
||||
String prompt = source + "\r\n" + promptCurrent;
|
||||
InputPayMana toSet = new InputPayManaExecuteCommands(p, prompt, cost.getCostMana().getManaToPay());
|
||||
Singletons.getControl().getInputQueue().setInputAndWait(toSet);
|
||||
return toSet.isPaid();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user