* Costs: removed isUndoable, isReusable backing fields, appropiate values are returned by method overloads in classes

* Costs: joined all CostGainLife implementations. Syntax is: GainLife<LifeAmount/Player.Selector/[cntPlayers|*]> asterisk in last parameter means "all players".
* Changed a lot of methods to pass GameState as a parameter rather than get it from Singletons.*
This commit is contained in:
Maxmtg
2013-01-22 06:58:11 +00:00
parent 4ca6d8cbdf
commit ab95f36861
47 changed files with 537 additions and 785 deletions

1
.gitattributes vendored
View File

@@ -13447,7 +13447,6 @@ src/main/java/forge/card/cost/CostDamage.java -text
src/main/java/forge/card/cost/CostDiscard.java -text
src/main/java/forge/card/cost/CostExile.java -text
src/main/java/forge/card/cost/CostGainLife.java -text
src/main/java/forge/card/cost/CostGainLifeEachOther.java -text
src/main/java/forge/card/cost/CostMana.java -text
src/main/java/forge/card/cost/CostMill.java -text
src/main/java/forge/card/cost/CostPart.java -text

View File

@@ -55,6 +55,7 @@ import forge.card.staticability.StaticAbility;
import forge.card.trigger.Trigger;
import forge.card.trigger.TriggerType;
import forge.card.trigger.ZCTrigger;
import forge.game.GameState;
import forge.game.GlobalRuleChange;
import forge.game.event.CounterAddedEvent;
import forge.game.event.CardEquippedEvent;
@@ -1338,17 +1339,18 @@ public class Card extends GameEntity implements Comparable<Card> {
private void playFromSuspend() {
final Card c = this;
final GameState game = Singletons.getModel().getGame();
c.setSuspendCast(true);
// set activating player for base spell ability
c.getSpellAbility()[0].setActivatingPlayer(c.getOwner());
// Any trigger should cause the phase not to skip
for (Player p : Singletons.getModel().getGame().getPlayers()) {
for (Player p : game.getPlayers()) {
p.getController().autoPassCancel();
}
if (c.getOwner().isHuman()) {
Singletons.getModel().getGame().getAction().playCardWithoutManaCost(c, c.getOwner());
game.getAction().playCardWithoutManaCost(c, c.getOwner());
} else {
final List<SpellAbility> choices = this.getBasicSpells();
@@ -1364,7 +1366,7 @@ public class Card extends GameEntity implements Comparable<Card> {
continue;
}
}
ComputerUtil.playSpellAbilityWithoutPayingManaCost(c.getOwner(), sa);
ComputerUtil.playSpellAbilityWithoutPayingManaCost(c.getOwner(), sa, game);
break;
}
}

View File

@@ -555,10 +555,10 @@ public class GameAction {
Player p = recoverable.getController();
if (p.isHuman()) {
GameActionUtil.payCostDuringAbilityResolve(abRecover, abRecover.getPayCosts(),
paidCommand, unpaidCommand, null);
paidCommand, unpaidCommand, null, game);
} else { // computer
if (ComputerUtil.canPayCost(abRecover, p)) {
ComputerUtil.playNoStack(p, abRecover);
ComputerUtil.playNoStack(p, abRecover, game);
} else {
Singletons.getModel().getGame().getAction().exile(recoverable);
}
@@ -820,7 +820,7 @@ public class GameAction {
Spell spell = (Spell) miracle;
spell.setActivatingPlayer(card.getOwner());
if (spell.canPlayFromEffectAI(false, false)) {
ComputerUtil.playStack(miracle, card.getOwner());
ComputerUtil.playStack(miracle, card.getOwner(), game);
}
}
}
@@ -870,7 +870,7 @@ public class GameAction {
} else {
Spell spell = (Spell) madness;
if (spell.canPlayFromEffectAI(false, false)) {
ComputerUtil.playStack(madness, card.getOwner());
ComputerUtil.playStack(madness, card.getOwner(), game);
}
}
}
@@ -1585,7 +1585,7 @@ public class GameAction {
public final void playSpellAbilityForFree(final SpellAbility sa) {
if (sa.getPayCosts() != null) {
final TargetSelection ts = new TargetSelection(sa.getTarget(), sa);
final CostPayment payment = new CostPayment(sa.getPayCosts(), sa);
final CostPayment payment = new CostPayment(sa.getPayCosts(), sa, game);
final SpellAbilityRequirements req = new SpellAbilityRequirements(sa, ts, payment);
req.setFree(true);
@@ -1891,9 +1891,9 @@ public class GameAction {
final TargetSelection ts = new TargetSelection(sa.getTarget(), sa);
CostPayment payment = null;
if (sa.getPayCosts() == null) {
payment = new CostPayment(new Cost(sa.getSourceCard(), "0", sa.isAbility()), sa);
payment = new CostPayment(new Cost(sa.getSourceCard(), "0", sa.isAbility()), sa, game);
} else {
payment = new CostPayment(sa.getPayCosts(), sa);
payment = new CostPayment(sa.getPayCosts(), sa, game);
}
final SpellAbilityRequirements req = new SpellAbilityRequirements(sa, ts, payment);
@@ -1940,7 +1940,7 @@ public class GameAction {
if (sa.getPayCosts() != null) {
final TargetSelection ts = new TargetSelection(sa.getTarget(), sa);
final CostPayment payment = new CostPayment(sa.getPayCosts(), sa);
final CostPayment payment = new CostPayment(sa.getPayCosts(), sa, game);
if (!sa.isTrigger()) {
payment.changeCost();

View File

@@ -53,6 +53,7 @@ import forge.control.input.Input;
import forge.control.input.InputPayDiscardCost;
import forge.control.input.InputPayManaCostAbility;
import forge.control.input.InputPayReturnCost;
import forge.game.GameState;
import forge.game.event.CardDamagedEvent;
import forge.game.event.FlipCoinEvent;
import forge.game.event.LifeLossEvent;
@@ -135,6 +136,7 @@ public final class GameActionUtil {
final Ability ability = new Ability(c, SpellManaCost.ZERO) {
@Override
public void resolve() {
final GameState game = Singletons.getModel().getGame();
final List<Card> topOfLibrary = controller.getCardsIn(ZoneType.Library);
final List<Card> revealed = new ArrayList<Card>();
@@ -173,7 +175,7 @@ public final class GameActionUtil {
title.toString(), JOptionPane.YES_NO_OPTION);
if (answer == JOptionPane.YES_OPTION) {
Singletons.getModel().getGame().getAction().playCardWithoutManaCost(cascadedCard, p);
game.getAction().playCardWithoutManaCost(cascadedCard, p);
revealed.remove(cascadedCard);
}
} else {
@@ -192,7 +194,7 @@ public final class GameActionUtil {
continue;
}
}
ComputerUtil.playSpellAbilityWithoutPayingManaCost(p, sa);
ComputerUtil.playSpellAbilityWithoutPayingManaCost(p, sa, game);
revealed.remove(cascadedCard);
break;
}
@@ -200,7 +202,7 @@ public final class GameActionUtil {
}
CardLists.shuffle(revealed);
for (final Card bottom : revealed) {
Singletons.getModel().getGame().getAction().moveToBottomOfLibrary(bottom);
game.getAction().moveToBottomOfLibrary(bottom);
}
}
};
@@ -258,6 +260,7 @@ public final class GameActionUtil {
final Ability ability = new Ability(c, SpellManaCost.ZERO) {
@Override
public void resolve() {
final GameState game = Singletons.getModel().getGame();
final List<Card> topOfLibrary = controller.getCardsIn(ZoneType.Library);
final List<Card> revealed = new ArrayList<Card>();
int rippleNumber = rippleCount;
@@ -293,7 +296,7 @@ public final class GameActionUtil {
JOptionPane.DEFAULT_OPTION, JOptionPane.INFORMATION_MESSAGE, null,
possibleValues, possibleValues[0]);
if (q.equals(0)) {
Singletons.getModel().getGame().getAction().playCardWithoutManaCost(rippledCards[i], p);
game.getAction().playCardWithoutManaCost(rippledCards[i], p);
revealed.remove(rippledCards[i]);
}
} else {
@@ -311,7 +314,7 @@ public final class GameActionUtil {
continue;
}
}
ComputerUtil.playSpellAbilityWithoutPayingManaCost(p, sa);
ComputerUtil.playSpellAbilityWithoutPayingManaCost(p, sa, game);
revealed.remove(rippledCards[i]);
break;
}
@@ -378,7 +381,7 @@ public final class GameActionUtil {
* @param sourceAbility TODO
*/
public static void payCostDuringAbilityResolve(final SpellAbility ability, final Cost cost, final Command paid,
final Command unpaid, SpellAbility sourceAbility) {
final Command unpaid, SpellAbility sourceAbility, final GameState game) {
final Card source = ability.getSourceCard();
final List<CostPart> parts = cost.getCostParts();
Player p = Singletons.getControl().getPlayer();
@@ -458,7 +461,7 @@ public final class GameActionUtil {
int amount = amountString.matches("[0-9][0-9]?") ? Integer.parseInt(amountString)
: CardFactoryUtil.xCount(source, source.getSVar(amountString));
String plural = amount > 1 ? "s" : "";
if (part.canPay(sourceAbility, source, p, cost)
if (part.canPay(sourceAbility, source, p, cost, game)
&& showYesNoDialog(source, "Do you want to remove " + amount + " " + counterType.getName()
+ " counter" + plural + " from " + source + "?")) {
source.subtractCounter(counterType, amount);

View File

@@ -1584,18 +1584,18 @@ public class AbilityFactory {
* @param usedStack
* a boolean.
*/
public static void passUnlessCost(final SpellAbility sa, final boolean usedStack) {
public static void passUnlessCost(final SpellAbility sa, final boolean usedStack, final GameState game) {
final Card source = sa.getSourceCard();
final ApiType api = sa.getApi();
if (api == null) {
sa.resolve();
AbilityFactory.resolveSubAbilities(sa, usedStack);
AbilityFactory.resolveSubAbilities(sa, usedStack, game);
return;
}
// Nothing to do
if (sa.getParam("UnlessCost") == null) {
sa.resolve();
AbilityFactory.resolveSubAbilities(sa, usedStack);
AbilityFactory.resolveSubAbilities(sa, usedStack, game);
return;
}
@@ -1632,7 +1632,7 @@ public class AbilityFactory {
@Override
public void execute() {
AbilityFactory.resolveSubAbilities(sa, usedStack);
AbilityFactory.resolveSubAbilities(sa, usedStack, game);
}
};
@@ -1645,7 +1645,7 @@ public class AbilityFactory {
if (sa.hasParam("PowerSink")) {
GameActionUtil.doPowerSink(sa.getActivatingPlayer());
}
AbilityFactory.resolveSubAbilities(sa, usedStack);
AbilityFactory.resolveSubAbilities(sa, usedStack, game);
}
};
@@ -1682,7 +1682,7 @@ public class AbilityFactory {
// Didn't have any of the data on the original SA to pay dependant costs
ability.setActivatingPlayer(payer);
ability.setTarget(sa.getTarget());
ComputerUtil.playNoStack(payer, ability); // Unless cost was payed - no resolve
ComputerUtil.playNoStack(payer, ability, game); // Unless cost was payed - no resolve
paid = true;
}
}
@@ -1694,20 +1694,20 @@ public class AbilityFactory {
if (paid) {
unpaidCommand = paidCommand;
}
GameActionUtil.payCostDuringAbilityResolve(ability, cost, paidCommand, unpaidCommand, sa);
GameActionUtil.payCostDuringAbilityResolve(ability, cost, paidCommand, unpaidCommand, sa, game);
waitForInput = true; // wait for the human input
break; // multiple human players are not supported
}
}
if (!waitForInput) {
if (paid) {
AbilityFactory.resolveSubAbilities(sa, usedStack);
AbilityFactory.resolveSubAbilities(sa, usedStack, game);
} else {
sa.resolve();
if (sa.hasParam("PowerSink")) {
GameActionUtil.doPowerSink(payers.get(0));
}
AbilityFactory.resolveSubAbilities(sa, usedStack);
AbilityFactory.resolveSubAbilities(sa, usedStack, game);
}
}
@@ -1735,17 +1735,18 @@ public class AbilityFactory {
}
return;
}
final GameState game = Singletons.getModel().getGame();
// check conditions
if (AbilityFactory.checkConditional(sa)) {
if (sa.isWrapper()) {
sa.resolve();
AbilityFactory.resolveSubAbilities(sa, usedStack);
AbilityFactory.resolveSubAbilities(sa, usedStack, game);
} else {
AbilityFactory.passUnlessCost(sa, usedStack);
AbilityFactory.passUnlessCost(sa, usedStack, game);
}
} else {
AbilityFactory.resolveSubAbilities(sa, usedStack);
AbilityFactory.resolveSubAbilities(sa, usedStack, game);
}
}
@@ -1758,7 +1759,7 @@ public class AbilityFactory {
* a {@link forge.card.spellability.SpellAbility} object.
* @since 1.0.15
*/
public static void resolveSubAbilities(final SpellAbility sa, boolean usedStack) {
public static void resolveSubAbilities(final SpellAbility sa, boolean usedStack, final GameState game) {
final AbilitySub abSub = sa.getSubAbility();
if (abSub == null || sa.isWrapper()) {
// every resolving spellAbility will end here
@@ -1770,9 +1771,9 @@ public class AbilityFactory {
}
// check conditions
if (AbilityFactory.checkConditional(abSub)) {
AbilityFactory.passUnlessCost(abSub, usedStack);
AbilityFactory.passUnlessCost(abSub, usedStack, game);
} else {
AbilityFactory.resolveSubAbilities(abSub, usedStack);
AbilityFactory.resolveSubAbilities(abSub, usedStack, game);
}
}

View File

@@ -187,7 +187,7 @@ public class ChangeZoneAi extends SpellAiLogic {
if (part instanceof CostDiscard) {
CostDiscard cd = (CostDiscard) part;
// this is mainly for typecycling
if (!cd.getThis() || !ComputerUtil.isWorseThanDraw(ai, source)) {
if (!cd.isTargetingThis() || !ComputerUtil.isWorseThanDraw(ai, source)) {
return false;
}
}

View File

@@ -86,7 +86,7 @@ public class DestroyAi extends SpellAiLogic {
continue;
}
CostSacrifice sacCost = (CostSacrifice) part;
if (sacCost.getThis() && ComputerUtil.canPayCost(ability, c.getController())) {
if (sacCost.isTargetingThis() && ComputerUtil.canPayCost(ability, c.getController())) {
return false;
}
}

View File

@@ -22,6 +22,7 @@ import forge.card.cost.CostPart;
import forge.card.spellability.Spell;
import forge.card.spellability.SpellAbility;
import forge.card.spellability.SpellAbilityRestriction;
import forge.game.GameState;
import forge.game.player.ComputerUtil;
import forge.game.player.Player;
import forge.game.zone.ZoneType;
@@ -50,6 +51,7 @@ public class PlayEffect extends SpellEffect {
@Override
public void resolve(SpellAbility sa) {
final GameState game = Singletons.getModel().getGame();
final Card source = sa.getSourceCard();
Player activator = sa.getActivatingPlayer();
boolean optional = sa.hasParam("Optional");
@@ -73,7 +75,7 @@ public class PlayEffect extends SpellEffect {
if (sa.hasParam("ValidZone")) {
zone = ZoneType.smartValueOf(sa.getParam("ValidZone"));
}
tgtCards = Singletons.getModel().getGame().getCardsIn(zone);
tgtCards = game.getCardsIn(zone);
tgtCards = AbilityFactory.filterListByType(tgtCards, sa.getParam("Valid"), sa);
}
else if (sa.hasParam("Encoded")) {
@@ -217,7 +219,7 @@ public class PlayEffect extends SpellEffect {
newSA.setPayCosts(cost);
newSA.setManaCost(SpellManaCost.NO_COST);
newSA.setDescription(newSA.getDescription() + " (without paying its mana cost)");
Singletons.getModel().getGame().getAction().playSpellAbility(newSA, activator);
game.getAction().playSpellAbility(newSA, activator);
if (remember) {
source.addRemembered(tgtSA.getSourceCard());
}
@@ -225,7 +227,7 @@ public class PlayEffect extends SpellEffect {
if (tgtSA instanceof Spell) {
Spell spell = (Spell) tgtSA;
if (spell.canPlayFromEffectAI(!optional, true) || !optional) {
ComputerUtil.playSpellAbilityWithoutPayingManaCost(controller, tgtSA);
ComputerUtil.playSpellAbilityWithoutPayingManaCost(controller, tgtSA, game);
if (remember) {
source.addRemembered(tgtSA.getSourceCard());
}
@@ -234,7 +236,7 @@ public class PlayEffect extends SpellEffect {
}
} else {
if (controller.isHuman()) {
Singletons.getModel().getGame().getAction().playSpellAbility(tgtSA, activator);
game.getAction().playSpellAbility(tgtSA, activator);
if (remember) {
source.addRemembered(tgtSA.getSourceCard());
}
@@ -242,7 +244,7 @@ public class PlayEffect extends SpellEffect {
if (tgtSA instanceof Spell) {
Spell spell = (Spell) tgtSA;
if (spell.canPlayFromEffectAI(!optional, false) || !optional) {
ComputerUtil.playStack(tgtSA, controller);
ComputerUtil.playStack(tgtSA, controller, game);
if (remember) {
source.addRemembered(tgtSA.getSourceCard());
}

View File

@@ -69,6 +69,7 @@ import forge.card.trigger.TriggerHandler;
import forge.card.trigger.TriggerType;
import forge.control.input.Input;
import forge.control.input.InputPayManaCostUtil;
import forge.game.GameState;
import forge.game.event.TokenCreatedEvent;
import forge.game.phase.PhaseHandler;
import forge.game.phase.PhaseType;
@@ -4168,6 +4169,7 @@ public class CardFactoryUtil {
@Override
public void resolve() {
final GameState game = Singletons.getModel().getGame();
String name = card.toString() + " Epic";
if (card.getController().getCardsIn(ZoneType.Battlefield, name).isEmpty()) {
@@ -4196,15 +4198,15 @@ public class CardFactoryUtil {
eff.addTrigger(copyTrigger);
Singletons.getModel().getGame().getTriggerHandler().suppressMode(TriggerType.ChangesZone);
Singletons.getModel().getGame().getAction().moveToPlay(eff);
Singletons.getModel().getGame().getTriggerHandler().clearSuppression(TriggerType.ChangesZone);
game.getTriggerHandler().suppressMode(TriggerType.ChangesZone);
game.getAction().moveToPlay(eff);
game.getTriggerHandler().clearSuppression(TriggerType.ChangesZone);
}
if (card.getController().isHuman()) {
Singletons.getModel().getGame().getAction().playSpellAbilityNoStack(origSA, false);
game.getAction().playSpellAbilityNoStack(origSA, false);
} else {
ComputerUtil.playNoStack(card.getController(), origSA);
ComputerUtil.playNoStack(card.getController(), origSA, game);
}
}
};

View File

@@ -212,9 +212,9 @@ public class Cost {
if(parse.startsWith("AddCounter<")) {
// AddCounter<NumCounters/CounterType>
final String[] splitStr = abCostParse(parse, 4);
final String type = splitStr.length > 2 ? splitStr[2] : "CARDNAME";
final String target = splitStr.length > 2 ? splitStr[2] : "CARDNAME";
final String description = splitStr.length > 3 ? splitStr[3] : null;
return new CostPutCounter(splitStr[0], CounterType.valueOf(splitStr[1]), type, description);
return new CostPutCounter(splitStr[0], CounterType.valueOf(splitStr[1]), target, description);
}
// While no card has "PayLife<2> PayLife<3> there might be a card that
@@ -225,16 +225,11 @@ public class Cost {
return new CostPayLife(splitStr[0]);
}
if(parse.startsWith("OppGainLife<")) {
if(parse.startsWith("GainLife<")) {
// PayLife<LifeCost>
final String[] splitStr = abCostParse(parse, 1);
return new CostGainLife(splitStr[0]);
}
if(parse.startsWith("OthersEachGainLife<")) {
// PayLife<LifeCost>
final String[] splitStr = abCostParse(parse, 1);
return new CostGainLifeEachOther(splitStr[0]);
final String[] splitStr = abCostParse(parse, 3);
int cnt = splitStr.length > 2 ? "*".equals(splitStr[2]) ? Integer.MAX_VALUE : Integer.parseInt(splitStr[2]) : 1;
return new CostGainLife(splitStr[0], splitStr[1], cnt);
}
if(parse.startsWith("DamageYou<")) {

View File

@@ -21,6 +21,7 @@ import forge.Card;
import forge.GameActionUtil;
import forge.card.abilityfactory.AbilityFactory;
import forge.card.spellability.SpellAbility;
import forge.game.GameState;
import forge.game.player.Player;
/**
@@ -70,16 +71,6 @@ public class CostDamage extends CostPart {
return sb.toString();
}
/*
* (non-Javadoc)
*
* @see forge.card.cost.CostPart#refund(forge.Card)
*/
@Override
public final void refund(final Card source) {
}
/*
* (non-Javadoc)
*
@@ -88,7 +79,7 @@ public class CostDamage extends CostPart {
* forge.Card, forge.Player, forge.card.cost.Cost)
*/
@Override
public final boolean canPay(final SpellAbility ability, final Card source, final Player activator, final Cost cost) {
public final boolean canPay(final SpellAbility ability, final Card source, final Player activator, final Cost cost, final GameState game) {
return true;
}
@@ -99,7 +90,7 @@ public class CostDamage extends CostPart {
* forge.Card, forge.card.cost.Cost_Payment)
*/
@Override
public final void payAI(final Player ai, final SpellAbility ability, final Card source, final CostPayment payment) {
public final void payAI(final Player ai, final SpellAbility ability, final Card source, final CostPayment payment, final GameState game) {
ability.getActivatingPlayer().addDamage(this.getLastPaidAmount(), source);
}
@@ -111,7 +102,7 @@ public class CostDamage extends CostPart {
* forge.Card, forge.card.cost.Cost_Payment)
*/
@Override
public final boolean payHuman(final SpellAbility ability, final Card source, final CostPayment payment) {
public final boolean payHuman(final SpellAbility ability, final Card source, final CostPayment payment, final GameState game) {
final String amount = this.getAmount();
final Player activator = ability.getActivatingPlayer();
final int life = activator.getLife();

View File

@@ -30,6 +30,7 @@ import forge.CardLists;
import forge.card.abilityfactory.AbilityFactory;
import forge.card.spellability.SpellAbility;
import forge.control.input.Input;
import forge.game.GameState;
import forge.game.player.ComputerUtil;
import forge.game.player.Player;
import forge.game.zone.Zone;
@@ -69,7 +70,7 @@ public class CostDiscard extends CostPartWithList {
final Integer i = this.convertAmount();
if (this.getThis()) {
if (this.isTargetingThis()) {
sb.append(this.getType());
} else if (this.getType().equals("Hand")) {
sb.append("your hand");
@@ -95,17 +96,6 @@ public class CostDiscard extends CostPartWithList {
}
/*
* (non-Javadoc)
*
* @see forge.card.cost.CostPart#refund(forge.Card)
*/
@Override
public void refund(final Card source) {
// TODO Auto-generated method stub
}
/*
* (non-Javadoc)
*
@@ -114,12 +104,12 @@ public class CostDiscard extends CostPartWithList {
* forge.Card, forge.Player, forge.card.cost.Cost)
*/
@Override
public final boolean canPay(final SpellAbility ability, final Card source, final Player activator, final Cost cost) {
public final boolean canPay(final SpellAbility ability, final Card source, final Player activator, final Cost cost, final GameState game) {
List<Card> handList = new ArrayList<Card>(activator.getCardsIn(ZoneType.Hand));
String type = this.getType();
final Integer amount = this.convertAmount();
if (this.getThis()) {
if (this.isTargetingThis()) {
if (!source.isInZone(ZoneType.Hand)) {
return false;
}
@@ -164,7 +154,7 @@ public class CostDiscard extends CostPartWithList {
* forge.Card, forge.card.cost.Cost_Payment)
*/
@Override
public final void payAI(final Player ai, final SpellAbility ability, final Card source, final CostPayment payment) {
public final void payAI(final Player ai, final SpellAbility ability, final Card source, final CostPayment payment, final GameState game) {
for (final Card c : this.getList()) {
ai.discard(c, ability);
}
@@ -178,14 +168,14 @@ public class CostDiscard extends CostPartWithList {
* forge.Card, forge.card.cost.Cost_Payment)
*/
@Override
public final boolean payHuman(final SpellAbility ability, final Card source, final CostPayment payment) {
public final boolean payHuman(final SpellAbility ability, final Card source, final CostPayment payment, final GameState game) {
final Player activator = ability.getActivatingPlayer();
List<Card> handList = new ArrayList<Card>(activator.getCardsIn(ZoneType.Hand));
String discType = this.getType();
final String amount = this.getAmount();
this.resetList();
if (this.getThis()) {
if (this.isTargetingThis()) {
if (!handList.contains(source)) {
return false;
}
@@ -283,7 +273,7 @@ public class CostDiscard extends CostPartWithList {
this.addToList(ai.getLastDrawnCard());
}
else if (this.getThis()) {
else if (this.isTargetingThis()) {
if (!hand.contains(source)) {
return false;
}

View File

@@ -98,7 +98,7 @@ public class CostExile extends CostPartWithList {
final Integer i = this.convertAmount();
sb.append("Exile ");
if (this.getThis()) {
if (this.isTargetingThis()) {
sb.append(this.getType());
if (!this.from.equals(ZoneType.Battlefield)) {
sb.append(" from your ").append(this.from);
@@ -113,7 +113,7 @@ public class CostExile extends CostPartWithList {
final String desc = this.getTypeDescription() == null ? this.getType() : this.getTypeDescription();
sb.append(Cost.convertAmountTypeToWords(i, this.getAmount(), desc));
if (!this.getThis()) {
if (!this.isTargetingThis()) {
sb.append(" you control");
}
return sb.toString();
@@ -143,17 +143,6 @@ public class CostExile extends CostPartWithList {
return sb.toString();
}
/*
* (non-Javadoc)
*
* @see forge.card.cost.CostPart#refund(forge.Card)
*/
@Override
public void refund(final Card source) {
// TODO Currently there's no way to refund an exiled cost
}
/*
* (non-Javadoc)
*
@@ -162,9 +151,8 @@ public class CostExile extends CostPartWithList {
* forge.Card, forge.Player, forge.card.cost.Cost)
*/
@Override
public final boolean canPay(final SpellAbility ability, final Card source, final Player activator, final Cost cost) {
public final boolean canPay(final SpellAbility ability, final Card source, final Player activator, final Cost cost, final GameState game) {
List<Card> typeList = new ArrayList<Card>();
final GameState game = Singletons.getModel().getGame();
if (this.getType().equals("All")) {
return true; // this will always work
}
@@ -179,7 +167,7 @@ public class CostExile extends CostPartWithList {
typeList = new ArrayList<Card>(activator.getCardsIn(this.getFrom()));
}
}
if (!this.getThis()) {
if (!this.isTargetingThis()) {
typeList = CardLists.getValidCards(typeList, this.getType().split(";"), activator, source);
final Integer amount = this.convertAmount();
@@ -214,7 +202,7 @@ public class CostExile extends CostPartWithList {
* forge.Card, forge.card.cost.Cost_Payment)
*/
@Override
public final void payAI(final Player ai, final SpellAbility ability, final Card source, final CostPayment payment) {
public final void payAI(final Player ai, final SpellAbility ability, final Card source, final CostPayment payment, final GameState game) {
for (final Card c : this.getList()) {
Singletons.getModel().getGame().getAction().exile(c);
if (this.from.equals(ZoneType.Stack)) {
@@ -237,10 +225,9 @@ public class CostExile extends CostPartWithList {
* forge.Card, forge.card.cost.Cost_Payment)
*/
@Override
public final boolean payHuman(final SpellAbility ability, final Card source, final CostPayment payment) {
public final boolean payHuman(final SpellAbility ability, final Card source, final CostPayment payment, final GameState game) {
final String amount = this.getAmount();
Integer c = this.convertAmount();
final GameState game = Singletons.getModel().getGame();
final Player activator = ability.getActivatingPlayer();
List<Card> list;
@@ -269,7 +256,7 @@ public class CostExile extends CostPartWithList {
c = AbilityFactory.calculateAmount(source, amount, ability);
}
}
if (this.getThis()) {
if (this.isTargetingThis()) {
final Input inp = CostExile.exileThis(ability, payment, this);
Singletons.getModel().getMatch().getInput().setInputInterrupt(inp);
} else if (this.from.equals(ZoneType.Battlefield) || this.from.equals(ZoneType.Hand)) {
@@ -311,7 +298,7 @@ public class CostExile extends CostPartWithList {
@Override
public final boolean decideAIPayment(final Player ai, final SpellAbility ability, final Card source, final CostPayment payment) {
this.resetList();
if (this.getThis()) {
if (this.isTargetingThis()) {
this.getList().add(source);
} else if (this.getType().equals("All")) {
this.setList(new ArrayList<Card>(ability.getActivatingPlayer().getCardsIn(this.getFrom())));

View File

@@ -23,6 +23,7 @@ import java.util.List;
import forge.Card;
import forge.card.abilityfactory.AbilityFactory;
import forge.card.spellability.SpellAbility;
import forge.game.GameState;
import forge.game.player.Player;
import forge.gui.GuiChoose;
@@ -30,6 +31,7 @@ import forge.gui.GuiChoose;
* The Class CostGainLife.
*/
public class CostGainLife extends CostPart {
private final int cntPlayers; // MAX_VALUE means ALL/EACH PLAYERS
private int lastPaidAmount = 0;
/**
@@ -57,8 +59,9 @@ public class CostGainLife extends CostPart {
* @param amount
* the amount
*/
public CostGainLife(final String amount) {
this.setAmount(amount);
public CostGainLife(final String amount, String playerSelector, int qty) {
super(amount, playerSelector, null);
cntPlayers = qty;
}
/*
@@ -72,15 +75,16 @@ public class CostGainLife extends CostPart {
sb.append("Have an opponent gain ").append(this.getAmount()).append(" life");
return sb.toString();
}
/*
* (non-Javadoc)
*
* @see forge.card.cost.CostPart#refund(forge.Card)
*/
@Override
public void refund(final Card source) {
private List<Player> getPotentialTargets(final GameState game, final Player payer, final Card source)
{
List<Player> res = new ArrayList<Player>();
for(Player p : game.getPlayers())
{
if(p.isValid(getType(), payer, source))
res.add(p);
}
return res;
}
/*
@@ -91,19 +95,20 @@ public class CostGainLife extends CostPart {
* forge.Card, forge.Player, forge.card.cost.Cost)
*/
@Override
public final boolean canPay(final SpellAbility ability, final Card source, final Player activator, final Cost cost) {
public final boolean canPay(final SpellAbility ability, final Card source, final Player activator, final Cost cost, final GameState game) {
final Integer amount = this.convertAmount();
boolean oppCanGainLife = false;
if (amount != null) {
for (final Player opp : activator.getOpponents()) {
if (opp.canGainLife()) {
oppCanGainLife = true;
break;
}
if ( amount == null ) return false;
int cntAbleToGainLife = 0;
List<Player> possibleTargets = getPotentialTargets(game, activator, source);
for (final Player opp : possibleTargets) {
if (opp.canGainLife()) {
cntAbleToGainLife++;
}
}
return oppCanGainLife;
return cntPlayers < Integer.MAX_VALUE ? cntAbleToGainLife >= cntPlayers : cntAbleToGainLife == possibleTargets.size();
}
/*
@@ -113,14 +118,14 @@ public class CostGainLife extends CostPart {
* forge.Card, forge.card.cost.Cost_Payment)
*/
@Override
public final void payAI(final Player ai, final SpellAbility ability, final Card source, final CostPayment payment) {
final List<Player> oppsThatCanGainLife = new ArrayList<Player>();
for (final Player opp : ai.getOpponents()) {
if (opp.canGainLife()) {
oppsThatCanGainLife.add(opp);
public final void payAI(final Player ai, final SpellAbility ability, final Card source, final CostPayment payment, final GameState game) {
int playersLeft = cntPlayers;
for (final Player opp : getPotentialTargets(game, ai, source)) {
if (opp.canGainLife() && playersLeft > 0) {
playersLeft--;
opp.gainLife(this.getLastPaidAmount(), null);
}
}
oppsThatCanGainLife.get(0).gainLife(this.getLastPaidAmount(), null);
}
/*
@@ -131,7 +136,7 @@ public class CostGainLife extends CostPart {
* forge.Card, forge.card.cost.Cost_Payment)
*/
@Override
public final boolean payHuman(final SpellAbility ability, final Card source, final CostPayment payment) {
public final boolean payHuman(final SpellAbility ability, final Card source, final CostPayment payment, final GameState game) {
final String amount = this.getAmount();
final Player activator = ability.getActivatingPlayer();
final int life = activator.getLife();
@@ -148,26 +153,36 @@ public class CostGainLife extends CostPart {
}
final List<Player> oppsThatCanGainLife = new ArrayList<Player>();
for (final Player opp : activator.getOpponents()) {
for (final Player opp : getPotentialTargets(game, activator, source)) {
if (opp.canGainLife()) {
oppsThatCanGainLife.add(opp);
}
}
if(cntPlayers == Integer.MAX_VALUE) { // applied to all players who can gain
for(Player opp: oppsThatCanGainLife)
opp.gainLife(c, null);
payment.setPaidManaPart(this);
return true;
}
final StringBuilder sb = new StringBuilder();
sb.append(source.getName()).append(" - Choose an opponent to gain ").append(c).append(" life:");
final Player chosenToGain = GuiChoose.oneOrNone(sb.toString(), oppsThatCanGainLife);
if (null == chosenToGain) {
payment.setCancel(true);
payment.getRequirements().finishPaying();
return false;
} else {
final Player chosen = chosenToGain;
chosen.gainLife(c, null);
this.setLastPaidAmount(c);
payment.setPaidManaPart(this);
for(int playersLeft = cntPlayers; playersLeft > 0; playersLeft--) {
final Player chosenToGain = GuiChoose.oneOrNone(sb.toString(), oppsThatCanGainLife);
if (null == chosenToGain) {
payment.setCancel(true);
payment.getRequirements().finishPaying();
return false;
} else {
final Player chosen = chosenToGain;
chosen.gainLife(c, null);
}
}
payment.setPaidManaPart(this);
return true;
}

View File

@@ -1,197 +0,0 @@
/*
* Forge: Play Magic: the Gathering.
* Copyright (C) 2011 Forge Team
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package forge.card.cost;
import forge.Card;
import forge.GameActionUtil;
import forge.card.abilityfactory.AbilityFactory;
import forge.card.spellability.SpellAbility;
import forge.game.player.Player;
/**
* The Class CostGainLife.
*/
public class CostGainLifeEachOther extends CostPart {
private int lastPaidAmount = 0;
/**
* Gets the last paid amount.
*
* @return the last paid amount
*/
public final int getLastPaidAmount() {
return this.lastPaidAmount;
}
/**
* Sets the last paid amount.
*
* @param paidAmount
* the new last paid amount
*/
public final void setLastPaidAmount(final int paidAmount) {
this.lastPaidAmount = paidAmount;
}
/**
* Instantiates a new cost gain life.
*
* @param amount
* the amount
*/
public CostGainLifeEachOther(final String amount) {
this.setAmount(amount);
}
/*
* (non-Javadoc)
*
* @see forge.card.cost.CostPart#toString()
*/
@Override
public final String toString() {
final StringBuilder sb = new StringBuilder();
sb.append("Have each other player gain ").append(this.getAmount()).append(" life");
return sb.toString();
}
/*
* (non-Javadoc)
*
* @see forge.card.cost.CostPart#refund(forge.Card)
*/
@Override
public void refund(final Card source) {
}
/*
* (non-Javadoc)
*
* @see
* forge.card.cost.CostPart#canPay(forge.card.spellability.SpellAbility,
* forge.Card, forge.Player, forge.card.cost.Cost)
*/
@Override
public final boolean canPay(final SpellAbility ability, final Card source, final Player activator, final Cost cost) {
final Integer amount = this.convertAmount();
if (amount != null) {
for (final Player otherP : activator.getAllOtherPlayers()) {
if (!otherP.canGainLife()) {
return false;
}
}
}
return true;
}
/*
* (non-Javadoc)
*
* @see forge.card.cost.CostPart#payAI(forge.card.spellability.SpellAbility,
* forge.Card, forge.card.cost.Cost_Payment)
*/
@Override
public final void payAI(final Player ai, final SpellAbility ability, final Card source, final CostPayment payment) {
for (final Player otherP : ai.getAllOtherPlayers()) {
otherP.gainLife(this.getLastPaidAmount(), null);
}
}
/*
* (non-Javadoc)
*
* @see
* forge.card.cost.CostPart#payHuman(forge.card.spellability.SpellAbility,
* forge.Card, forge.card.cost.Cost_Payment)
*/
@Override
public final boolean payHuman(final SpellAbility ability, final Card source, final CostPayment payment) {
final String amount = this.getAmount();
final Player activator = ability.getActivatingPlayer();
final int life = activator.getLife();
Integer c = this.convertAmount();
if (c == null) {
final String sVar = ability.getSVar(amount);
// Generalize this
if (sVar.equals("XChoice")) {
c = CostUtil.chooseXValue(source, ability, life);
} else {
c = AbilityFactory.calculateAmount(source, amount, ability);
}
}
for (final Player other : activator.getAllOtherPlayers()) {
// each other player MUST be able to gain life
if (!other.canGainLife()) {
payment.setCancel(true);
payment.getRequirements().finishPaying();
return false;
}
}
final StringBuilder sb = new StringBuilder();
sb.append(source.getName()).append(" - Have each other player gain ").append(c).append(" life?");
if (GameActionUtil.showYesNoDialog(source, sb.toString())) {
for (final Player playerToGain : activator.getAllOtherPlayers()) {
playerToGain.gainLife(c, null);
this.setLastPaidAmount(c);
payment.setPaidManaPart(this);
}
} else {
payment.setCancel(true);
payment.getRequirements().finishPaying();
return false;
}
return true;
}
/*
* (non-Javadoc)
*
* @see
* forge.card.cost.CostPart#decideAIPayment(forge.card.spellability.SpellAbility
* , forge.Card, forge.card.cost.Cost_Payment)
*/
@Override
public final boolean decideAIPayment(final Player ai, final SpellAbility ability, final Card source, final CostPayment payment) {
Integer c = this.convertAmount();
if (c == null) {
final String sVar = ability.getSVar(this.getAmount());
// Generalize this
if (sVar.equals("XChoice")) {
return false;
} else {
c = AbilityFactory.calculateAmount(source, this.getAmount(), ability);
}
}
for (final Player otherP : ai.getAllOtherPlayers()) {
if (!otherP.canGainLife()) {
return false;
}
}
this.setLastPaidAmount(c);
return true;
}
}

View File

@@ -26,6 +26,7 @@ import forge.card.spellability.SpellAbility;
import forge.control.input.Input;
import forge.control.input.InputPayManaCost2;
import forge.control.input.InputPayManaX;
import forge.game.GameState;
import forge.game.player.ComputerUtil;
import forge.game.player.Player;
@@ -133,7 +134,13 @@ public class CostMana extends CostPart {
return this.mana;
}
@Override
public boolean isReusable() { return true; }
@Override
public boolean isUndoable() { return true; }
/**
* Instantiates a new cost mana.
*
@@ -146,8 +153,6 @@ public class CostMana extends CostPart {
public CostMana(final String mana, final int amount, boolean xCantBe0) {
this.mana = mana.trim();
this.amountX = amount;
this.setUndoable(true);
this.setReusable(true);
this.setxCantBe0(xCantBe0);
}
@@ -167,17 +172,6 @@ public class CostMana extends CostPart {
return sb.toString().trim();
}
/*
* (non-Javadoc)
*
* @see forge.card.cost.CostPart#refund(forge.Card)
*/
@Override
public void refund(final Card source) {
// TODO Auto-generated method stub
}
/*
* (non-Javadoc)
*
@@ -186,7 +180,7 @@ public class CostMana extends CostPart {
* forge.Card, forge.Player, forge.card.cost.Cost)
*/
@Override
public final boolean canPay(final SpellAbility ability, final Card source, final Player activator, final Cost cost) {
public final boolean canPay(final SpellAbility ability, final Card source, final Player activator, final Cost cost, final GameState game) {
// For now, this will always return true. But this should probably be
// checked at some point
return true;
@@ -199,7 +193,7 @@ public class CostMana extends CostPart {
* forge.Card, forge.card.cost.Cost_Payment)
*/
@Override
public final void payAI(final Player ai, final SpellAbility ability, final Card source, final CostPayment payment) {
public final void payAI(final Player ai, final SpellAbility ability, final Card source, final CostPayment payment, final GameState game) {
ComputerUtil.payManaCost(ai, ability);
}
@@ -211,7 +205,7 @@ public class CostMana extends CostPart {
* forge.Card, forge.card.cost.Cost_Payment)
*/
@Override
public final boolean payHuman(final SpellAbility ability, final Card source, final CostPayment payment) {
public final boolean payHuman(final SpellAbility ability, final Card source, final CostPayment payment, final GameState game) {
int manaToAdd = 0;
if (!this.hasNoXManaCost()) {
// if X cost is a defined value, other than xPaid

View File

@@ -27,6 +27,7 @@ import forge.GameActionUtil;
import forge.Singletons;
import forge.card.abilityfactory.AbilityFactory;
import forge.card.spellability.SpellAbility;
import forge.game.GameState;
import forge.game.player.Player;
import forge.game.zone.PlayerZone;
import forge.game.zone.ZoneType;
@@ -56,7 +57,7 @@ public class CostMill extends CostPartWithList {
* forge.Card, forge.Player, forge.card.cost.Cost)
*/
@Override
public final boolean canPay(final SpellAbility ability, final Card source, final Player activator, final Cost cost) {
public final boolean canPay(final SpellAbility ability, final Card source, final Player activator, final Cost cost, final GameState game) {
final PlayerZone zone = activator.getZone(ZoneType.Library);
Integer i = this.convertAmount();
@@ -111,7 +112,7 @@ public class CostMill extends CostPartWithList {
* forge.Card, forge.card.cost.Cost_Payment)
*/
@Override
public final void payAI(final Player ai, final SpellAbility ability, final Card source, final CostPayment payment) {
public final void payAI(final Player ai, final SpellAbility ability, final Card source, final CostPayment payment, final GameState game) {
for (final Card c : this.getList()) {
Singletons.getModel().getGame().getAction().moveToGraveyard(c);
}
@@ -125,7 +126,7 @@ public class CostMill extends CostPartWithList {
* forge.Card, forge.card.cost.Cost_Payment)
*/
@Override
public final boolean payHuman(final SpellAbility ability, final Card source, final CostPayment payment) {
public final boolean payHuman(final SpellAbility ability, final Card source, final CostPayment payment, final GameState game) {
final String amount = this.getAmount();
Integer c = this.convertAmount();
final Player activator = ability.getActivatingPlayer();
@@ -194,12 +195,4 @@ public class CostMill extends CostPartWithList {
return sb.toString();
}
/*
* (non-Javadoc)
*
* @see forge.card.cost.CostPart#refund(forge.Card)
*/
@Override
public void refund(final Card source) {
}
}

View File

@@ -19,6 +19,7 @@ package forge.card.cost;
import forge.Card;
import forge.card.spellability.SpellAbility;
import forge.game.GameState;
import forge.game.player.Player;
/**
@@ -26,31 +27,24 @@ import forge.game.player.Player;
*/
public abstract class CostPart {
/** The is reusable. */
private boolean isReusable = false;
/** The is undoable. */
private boolean isUndoable = false;
/** The optional. */
// private boolean optional = false;
/** The optional type. */
private String optionalType = null;
/** The amount. */
private String amount = "1";
/** The type. */
private String type = "Card";
private final String type;
/** The type description. */
private String typeDescription = null;
private final String typeDescription;
/**
* Instantiates a new cost part.
*/
public CostPart() {
type = "Card";
typeDescription = null;
}
/**
@@ -65,8 +59,8 @@ public abstract class CostPart {
*/
public CostPart(final String amount, final String type, final String description) {
this.setAmount(amount);
this.setType(type);
this.setTypeDescription(description);
this.type = type;
this.typeDescription = description;
}
/**
@@ -92,7 +86,7 @@ public abstract class CostPart {
*
* @return the this
*/
public final boolean getThis() {
public final boolean isTargetingThis() {
return this.getType().equals("CARDNAME");
}
@@ -119,8 +113,8 @@ public abstract class CostPart {
*
* @return true, if is reusable
*/
public final boolean isReusable() {
return this.isReusable;
public boolean isReusable() {
return false;
}
/**
@@ -128,27 +122,8 @@ public abstract class CostPart {
*
* @return true, if is undoable
*/
public final boolean isUndoable() {
return this.isUndoable;
}
/**
* Gets the optional type.
*
* @return the optional type
*/
public final String getOptionalType() {
return this.optionalType;
}
/**
* Sets the optional type.
*
* @param optionalType
* the new optional type
*/
public final void setOptionalType(final String optionalType) {
this.optionalType = optionalType;
public boolean isUndoable() {
return false;
}
/**
@@ -176,9 +151,10 @@ public abstract class CostPart {
* the activator
* @param cost
* the cost
* @param game
* @return true, if successful
*/
public abstract boolean canPay(SpellAbility ability, Card source, Player activator, Cost cost);
public abstract boolean canPay(SpellAbility ability, Card source, Player activator, Cost cost, GameState game);
/**
* Decide ai payment.
@@ -198,8 +174,9 @@ public abstract class CostPart {
* @param ability {@link forge.card.spellability.SpellAbility}
* @param source {@link forge.Card}
* @param payment {@link forge.card.cost.CostPayment}
* @param game
*/
public abstract void payAI(final Player ai, SpellAbility ability, Card source, CostPayment payment);
public abstract void payAI(final Player ai, SpellAbility ability, Card source, CostPayment payment, GameState game);
/**
* Pay human.
@@ -207,9 +184,10 @@ public abstract class CostPart {
* @param ability {@link forge.card.spellability.SpellAbility}
* @param source {@link forge.Card}
* @param payment {@link forge.card.cost.CostPayment}
* @param game
* @return true, if successful
*/
public abstract boolean payHuman(SpellAbility ability, Card source, CostPayment payment);
public abstract boolean payHuman(SpellAbility ability, Card source, CostPayment payment, GameState game);
/*
* (non-Javadoc)
@@ -220,22 +198,13 @@ public abstract class CostPart {
public abstract String toString();
/**
* Refund.
* Refund. Overridden in classes which know how to refund.
*
* @param source
* the source
*/
public abstract void refund(Card source);
public void refund(Card source) {}
/**
* Sets the reusable.
*
* @param isReusableIn
* the isReusable to set
*/
public void setReusable(final boolean isReusableIn) {
this.isReusable = isReusableIn;
}
/**
* Sets the amount.
@@ -246,34 +215,4 @@ public abstract class CostPart {
public void setAmount(final String amountIn) {
this.amount = amountIn;
}
/**
* Sets the type.
*
* @param typeIn
* the type to set
*/
public void setType(final String typeIn) {
this.type = typeIn;
}
/**
* Sets the type description.
*
* @param typeDescriptionIn
* the typeDescription to set
*/
public void setTypeDescription(final String typeDescriptionIn) {
this.typeDescription = typeDescriptionIn;
}
/**
* Sets the undoable.
*
* @param isUndoableIn
* the isUndoable to set
*/
public void setUndoable(final boolean isUndoableIn) {
this.isUndoable = isUndoableIn;
}
}

View File

@@ -21,6 +21,7 @@ import forge.Card;
import forge.GameActionUtil;
import forge.card.abilityfactory.AbilityFactory;
import forge.card.spellability.SpellAbility;
import forge.game.GameState;
import forge.game.player.Player;
/**
@@ -89,7 +90,7 @@ public class CostPayLife extends CostPart {
* forge.Card, forge.Player, forge.card.cost.Cost)
*/
@Override
public final boolean canPay(final SpellAbility ability, final Card source, final Player activator, final Cost cost) {
public final boolean canPay(final SpellAbility ability, final Card source, final Player activator, final Cost cost, final GameState game) {
final Integer amount = this.convertAmount();
if ((amount != null) && !activator.canPayLife(amount)) {
return false;
@@ -109,7 +110,7 @@ public class CostPayLife extends CostPart {
* forge.Card, forge.card.cost.Cost_Payment)
*/
@Override
public final void payAI(final Player ai, final SpellAbility ability, final Card source, final CostPayment payment) {
public final void payAI(final Player ai, final SpellAbility ability, final Card source, final CostPayment payment, final GameState game) {
ai.payLife(this.getLastPaidAmount(), null);
}
@@ -121,7 +122,7 @@ public class CostPayLife extends CostPart {
* forge.Card, forge.card.cost.Cost_Payment)
*/
@Override
public final boolean payHuman(final SpellAbility ability, final Card source, final CostPayment payment) {
public final boolean payHuman(final SpellAbility ability, final Card source, final CostPayment payment, final GameState game) {
final String amount = this.getAmount();
final Player activator = ability.getActivatingPlayer();
final int life = activator.getLife();

View File

@@ -23,6 +23,7 @@ import java.util.List;
import forge.Card;
import forge.card.spellability.SpellAbility;
import forge.card.spellability.SpellAbilityRequirements;
import forge.game.GameState;
import forge.game.player.Player;
/**
@@ -40,6 +41,7 @@ public class CostPayment {
private SpellAbilityRequirements req = null;
private boolean bCancel = false;
private final ArrayList<CostPart> paidCostParts = new ArrayList<CostPart>();
private final GameState game;
/**
* <p>
@@ -129,10 +131,11 @@ public class CostPayment {
* @param abil
* a {@link forge.card.spellability.SpellAbility} object.
*/
public CostPayment(final Cost cost, final SpellAbility abil) {
public CostPayment(final Cost cost, final SpellAbility abil, final GameState game) {
this.cost = cost;
this.ability = abil;
this.card = abil.getSourceCard();
this.game = game;
}
/**
@@ -146,7 +149,7 @@ public class CostPayment {
* a {@link forge.card.spellability.SpellAbility} object.
* @return a boolean.
*/
public static boolean canPayAdditionalCosts(final Cost cost, final SpellAbility ability) {
public static boolean canPayAdditionalCosts(final GameState game, final Cost cost, final SpellAbility ability) {
if (cost == null) {
return true;
}
@@ -159,7 +162,7 @@ public class CostPayment {
}
for (final CostPart part : cost.getCostParts()) {
if (!part.canPay(ability, card, activator, cost)) {
if (!part.canPay(ability, card, activator, cost, game)) {
return false;
}
}
@@ -218,7 +221,7 @@ public class CostPayment {
continue;
}
if (!part.payHuman(this.ability, this.card, this)) {
if (!part.payHuman(this.ability, this.card, this, game)) {
return false;
}
}
@@ -281,7 +284,7 @@ public class CostPayment {
*
* @return a boolean.
*/
public final boolean payComputerCosts(final Player ai) {
public final boolean payComputerCosts(final Player ai, final GameState game) {
// canPayAdditionalCosts now Player Agnostic
// Just in case it wasn't set, but honestly it shouldn't have gotten
@@ -303,7 +306,7 @@ public class CostPayment {
}
for (final CostPart part : parts) {
part.payAI(ai, this.ability, this.ability.getSourceCard(), this);
part.payAI(ai, this.ability, this.ability.getSourceCard(), this, game);
}
return true;
}

View File

@@ -28,6 +28,7 @@ import forge.card.abilityfactory.AbilityFactory;
import forge.card.cardfactory.CardFactoryUtil;
import forge.card.spellability.SpellAbility;
import forge.control.input.Input;
import forge.game.GameState;
import forge.game.player.Player;
import forge.game.zone.ZoneType;
import forge.gui.match.CMatchUI;
@@ -73,14 +74,14 @@ public class CostPutCounter extends CostPartWithList {
* the description
*/
public CostPutCounter(final String amount, final CounterType cntr, final String type, final String description) {
this.setReusable(true);
this.setAmount(amount);
super(amount, type, description);
this.counter = cntr;
this.setType(type);
this.setTypeDescription(description);
}
@Override
public boolean isReusable() { return true; }
/*
* (non-Javadoc)
*
@@ -89,7 +90,7 @@ public class CostPutCounter extends CostPartWithList {
@Override
public final String toString() {
final StringBuilder sb = new StringBuilder();
if (this.counter.getName().equals("Loyalty")) {
if (this.counter == CounterType.LOYALTY) {
sb.append("+").append(this.getAmount());
} else {
sb.append("Put ");
@@ -97,7 +98,7 @@ public class CostPutCounter extends CostPartWithList {
sb.append(Cost.convertAmountTypeToWords(i, this.getAmount(), this.counter.getName() + " counter"));
sb.append(" on ");
if (this.getThis()) {
if (this.isTargetingThis()) {
sb.append(this.getType());
} else {
final String desc = this.getTypeDescription() == null ? this.getType() : this.getTypeDescription();
@@ -127,8 +128,8 @@ public class CostPutCounter extends CostPartWithList {
* forge.Card, forge.Player, forge.card.cost.Cost)
*/
@Override
public final boolean canPay(final SpellAbility ability, final Card source, final Player activator, final Cost cost) {
if (this.getThis()) {
public final boolean canPay(final SpellAbility ability, final Card source, final Player activator, final Cost cost, final GameState game) {
if (this.isTargetingThis()) {
if (source.hasKeyword("CARDNAME can't have counters placed on it.")) {
return false;
}
@@ -155,13 +156,13 @@ public class CostPutCounter extends CostPartWithList {
* forge.Card, forge.card.cost.Cost_Payment)
*/
@Override
public final void payAI(final Player ai, final SpellAbility ability, final Card source, final CostPayment payment) {
public final void payAI(final Player ai, final SpellAbility ability, final Card source, final CostPayment payment, final GameState game) {
Integer c = this.convertAmount();
if (c == null) {
c = AbilityFactory.calculateAmount(source, this.getAmount(), ability);
}
if (this.getThis()) {
if (this.isTargetingThis()) {
source.addCounter(this.getCounter(), c, false);
} else {
// Put counter on chosen card
@@ -179,13 +180,13 @@ public class CostPutCounter extends CostPartWithList {
* forge.Card, forge.card.cost.Cost_Payment)
*/
@Override
public final boolean payHuman(final SpellAbility ability, final Card source, final CostPayment payment) {
public final boolean payHuman(final SpellAbility ability, final Card source, final CostPayment payment, final GameState game) {
Integer c = this.convertAmount();
if (c == null) {
c = AbilityFactory.calculateAmount(source, this.getAmount(), ability);
}
if (this.getThis()) {
if (this.isTargetingThis()) {
source.addCounter(this.getCounter(), c, false);
payment.setPaidManaPart(this);
this.addToList(source);
@@ -207,7 +208,7 @@ public class CostPutCounter extends CostPartWithList {
@Override
public final boolean decideAIPayment(final Player ai, final SpellAbility ability, final Card source, final CostPayment payment) {
this.resetList();
if (this.getThis()) {
if (this.isTargetingThis()) {
this.addToList(source);
return true;
} else {

View File

@@ -28,6 +28,7 @@ import forge.Singletons;
import forge.card.abilityfactory.AbilityFactory;
import forge.card.spellability.SpellAbility;
import forge.control.input.Input;
import forge.game.GameState;
import forge.game.player.Player;
import forge.game.zone.ZoneType;
import forge.gui.GuiChoose;
@@ -97,14 +98,15 @@ public class CostRemoveCounter extends CostPartWithList {
*/
public CostRemoveCounter(final String amount, final CounterType counter, final String type, final String description, ZoneType zone) {
super(amount, type, description);
this.setReusable(true);
this.counter = counter;
this.setType(type);
this.setTypeDescription(description);
this.setZone(zone);
}
@Override
public boolean isReusable() { return true; }
/*
* (non-Javadoc)
*
@@ -126,7 +128,7 @@ public class CostRemoveCounter extends CostPartWithList {
sb.append(" from ");
if (this.getThis()) {
if (this.isTargetingThis()) {
sb.append(this.getType());
} else {
final String desc = this.getTypeDescription() == null ? this.getType() : this.getTypeDescription();
@@ -156,11 +158,11 @@ public class CostRemoveCounter extends CostPartWithList {
* forge.Card, forge.Player, forge.card.cost.Cost)
*/
@Override
public final boolean canPay(final SpellAbility ability, final Card source, final Player activator, final Cost cost) {
public final boolean canPay(final SpellAbility ability, final Card source, final Player activator, final Cost cost, final GameState game) {
final CounterType cntrs = this.getCounter();
final Integer amount = this.convertAmount();
if (this.getThis()) {
if (this.isTargetingThis()) {
if ((amount != null) && ((source.getCounters(cntrs) - amount) < 0)) {
return false;
}
@@ -187,7 +189,7 @@ public class CostRemoveCounter extends CostPartWithList {
* forge.Card, forge.card.cost.Cost_Payment)
*/
@Override
public final void payAI(final Player ai, final SpellAbility ability, final Card source, final CostPayment payment) {
public final void payAI(final Player ai, final SpellAbility ability, final Card source, final CostPayment payment, final GameState game) {
final String amount = this.getAmount();
Integer c = this.convertAmount();
if (c == null) {
@@ -198,7 +200,7 @@ public class CostRemoveCounter extends CostPartWithList {
}
}
if (this.getThis()) {
if (this.isTargetingThis()) {
source.subtractCounter(this.counter, c);
} else {
for (final Card card : this.getList()) {
@@ -216,12 +218,12 @@ public class CostRemoveCounter extends CostPartWithList {
* forge.Card, forge.card.cost.Cost_Payment)
*/
@Override
public final boolean payHuman(final SpellAbility ability, final Card source, final CostPayment payment) {
public final boolean payHuman(final SpellAbility ability, final Card source, final CostPayment payment, final GameState game) {
final String amount = this.getAmount();
Integer c = this.convertAmount();
int maxCounters = 0;
if (!this.getThis()) {
if (!this.isTargetingThis()) {
if (this.getZone().equals(ZoneType.Battlefield)) {
final Input inp = CostRemoveCounter.removeCounterType(ability, this.getType(), payment, this, c);
Singletons.getModel().getMatch().getInput().setInputInterrupt(inp);
@@ -287,7 +289,7 @@ public class CostRemoveCounter extends CostPartWithList {
}
}
if (!this.getThis()) {
if (!this.isTargetingThis()) {
this.getList().clear();
final List<Card> typeList =
CardLists.getValidCards(ai.getCardsIn(this.getZone()), this.getType().split(";"), ai, source);

View File

@@ -29,6 +29,7 @@ import forge.Singletons;
import forge.card.abilityfactory.AbilityFactory;
import forge.card.spellability.SpellAbility;
import forge.control.input.Input;
import forge.game.GameState;
import forge.game.player.ComputerUtil;
import forge.game.player.Player;
import forge.game.zone.ZoneType;
@@ -68,7 +69,7 @@ public class CostReturn extends CostPartWithList {
final Integer i = this.convertAmount();
String pronoun = "its";
if (this.getThis()) {
if (this.isTargetingThis()) {
sb.append(this.getType());
} else {
final String desc = this.getTypeDescription() == null ? this.getType() : this.getTypeDescription();
@@ -87,17 +88,6 @@ public class CostReturn extends CostPartWithList {
return sb.toString();
}
/*
* (non-Javadoc)
*
* @see forge.card.cost.CostPart#refund(forge.Card)
*/
@Override
public void refund(final Card source) {
// TODO Auto-generated method stub
}
/*
* (non-Javadoc)
*
@@ -106,8 +96,8 @@ public class CostReturn extends CostPartWithList {
* forge.Card, forge.Player, forge.card.cost.Cost)
*/
@Override
public final boolean canPay(final SpellAbility ability, final Card source, final Player activator, final Cost cost) {
if (!this.getThis()) {
public final boolean canPay(final SpellAbility ability, final Card source, final Player activator, final Cost cost, final GameState game) {
if (!this.isTargetingThis()) {
List<Card> typeList = new ArrayList<Card>(activator.getCardsIn(ZoneType.Battlefield));
typeList = CardLists.getValidCards(typeList, this.getType().split(";"), activator, source);
@@ -129,7 +119,7 @@ public class CostReturn extends CostPartWithList {
* forge.Card, forge.card.cost.Cost_Payment)
*/
@Override
public final void payAI(final Player ai, final SpellAbility ability, final Card source, final CostPayment payment) {
public final void payAI(final Player ai, final SpellAbility ability, final Card source, final CostPayment payment, final GameState game) {
for (final Card c : this.getList()) {
Singletons.getModel().getGame().getAction().moveToHand(c);
}
@@ -143,7 +133,7 @@ public class CostReturn extends CostPartWithList {
* forge.Card, forge.card.cost.Cost_Payment)
*/
@Override
public final boolean payHuman(final SpellAbility ability, final Card source, final CostPayment payment) {
public final boolean payHuman(final SpellAbility ability, final Card source, final CostPayment payment, final GameState game) {
final String amount = this.getAmount();
Integer c = this.convertAmount();
final Player activator = ability.getActivatingPlayer();
@@ -157,7 +147,7 @@ public class CostReturn extends CostPartWithList {
c = AbilityFactory.calculateAmount(source, amount, ability);
}
}
if (this.getThis()) {
if (this.isTargetingThis()) {
final Input inp = CostReturn.returnThis(ability, payment, this);
Singletons.getModel().getMatch().getInput().setInputInterrupt(inp);
} else {
@@ -177,7 +167,7 @@ public class CostReturn extends CostPartWithList {
@Override
public final boolean decideAIPayment(final Player ai, final SpellAbility ability, final Card source, final CostPayment payment) {
this.resetList();
if (this.getThis()) {
if (this.isTargetingThis()) {
this.getList().add(source);
} else {
Integer c = this.convertAmount();

View File

@@ -27,6 +27,7 @@ import forge.CardLists;
import forge.card.abilityfactory.AbilityFactory;
import forge.card.spellability.SpellAbility;
import forge.control.input.Input;
import forge.game.GameState;
import forge.game.player.ComputerUtil;
import forge.game.player.Player;
import forge.game.zone.Zone;
@@ -63,12 +64,12 @@ public class CostReveal extends CostPartWithList {
* forge.Card, forge.Player, forge.card.cost.Cost)
*/
@Override
public final boolean canPay(final SpellAbility ability, final Card source, final Player activator, final Cost cost) {
public final boolean canPay(final SpellAbility ability, final Card source, final Player activator, final Cost cost, final GameState game) {
List<Card> handList = new ArrayList<Card>(activator.getCardsIn(ZoneType.Hand));
final String type = this.getType();
final Integer amount = this.convertAmount();
if (this.getThis()) {
if (this.isTargetingThis()) {
if (!source.isInZone(ZoneType.Hand)) {
return false;
}
@@ -102,7 +103,7 @@ public class CostReveal extends CostPartWithList {
List<Card> hand = new ArrayList<Card>(ai.getCardsIn(ZoneType.Hand));
this.resetList();
if (this.getThis()) {
if (this.isTargetingThis()) {
if (!hand.contains(source)) {
return false;
}
@@ -135,7 +136,7 @@ public class CostReveal extends CostPartWithList {
* forge.Card, forge.card.cost.Cost_Payment)
*/
@Override
public final void payAI(final Player ai, final SpellAbility ability, final Card source, final CostPayment payment) {
public final void payAI(final Player ai, final SpellAbility ability, final Card source, final CostPayment payment, final GameState game) {
GuiChoose.oneOrNone("Revealed cards:", this.getList());
}
@@ -147,12 +148,12 @@ public class CostReveal extends CostPartWithList {
* forge.Card, forge.card.cost.Cost_Payment)
*/
@Override
public final boolean payHuman(final SpellAbility ability, final Card source, final CostPayment payment) {
public final boolean payHuman(final SpellAbility ability, final Card source, final CostPayment payment, final GameState game) {
final Player activator = ability.getActivatingPlayer();
final String amount = this.getAmount();
this.resetList();
if (this.getThis()) {
if (this.isTargetingThis()) {
this.addToList(source);
payment.setPaidManaPart(this);
} else if (this.getType().equals("Hand")) {
@@ -196,7 +197,7 @@ public class CostReveal extends CostPartWithList {
final Integer i = this.convertAmount();
if (this.getThis()) {
if (this.isTargetingThis()) {
sb.append(this.getType());
} else if (this.getType().equals("Hand")) {
return ("Reveal you hand");
@@ -217,16 +218,6 @@ public class CostReveal extends CostPartWithList {
return sb.toString();
}
/*
* (non-Javadoc)
*
* @see forge.card.cost.CostPart#refund(forge.Card)
*/
@Override
public void refund(final Card source) {
}
// Inputs
/**

View File

@@ -29,6 +29,7 @@ import forge.Singletons;
import forge.card.abilityfactory.AbilityFactory;
import forge.card.spellability.SpellAbility;
import forge.control.input.Input;
import forge.game.GameState;
import forge.game.player.ComputerUtil;
import forge.game.player.Player;
import forge.game.zone.ZoneType;
@@ -66,7 +67,7 @@ public class CostSacrifice extends CostPartWithList {
final Integer i = this.convertAmount();
if (this.getThis()) {
if (this.isTargetingThis()) {
sb.append(this.getType());
} else {
final String desc = this.getTypeDescription() == null ? this.getType() : this.getTypeDescription();
@@ -79,17 +80,6 @@ public class CostSacrifice extends CostPartWithList {
return sb.toString();
}
/*
* (non-Javadoc)
*
* @see forge.card.cost.CostPart#refund(forge.Card)
*/
@Override
public void refund(final Card source) {
// TODO Auto-generated method stub
}
/*
* (non-Javadoc)
*
@@ -98,9 +88,9 @@ public class CostSacrifice extends CostPartWithList {
* forge.Card, forge.Player, forge.card.cost.Cost)
*/
@Override
public final boolean canPay(final SpellAbility ability, final Card source, final Player activator, final Cost cost) {
public final boolean canPay(final SpellAbility ability, final Card source, final Player activator, final Cost cost, final GameState game) {
// You can always sac all
if (!this.getThis()) {
if (!this.isTargetingThis()) {
List<Card> typeList = new ArrayList<Card>(activator.getCardsIn(ZoneType.Battlefield));
typeList = CardLists.getValidCards(typeList, this.getType().split(";"), activator, source);
@@ -137,7 +127,7 @@ public class CostSacrifice extends CostPartWithList {
* forge.Card, forge.card.cost.Cost_Payment)
*/
@Override
public final void payAI(final Player ai, final SpellAbility ability, final Card source, final CostPayment payment) {
public final void payAI(final Player ai, final SpellAbility ability, final Card source, final CostPayment payment, final GameState game) {
this.addListToHash(ability, "Sacrificed");
for (final Card c : this.getList()) {
Singletons.getModel().getGame().getAction().sacrifice(c, ability);
@@ -152,7 +142,7 @@ public class CostSacrifice extends CostPartWithList {
* forge.Card, forge.card.cost.Cost_Payment)
*/
@Override
public final boolean payHuman(final SpellAbility ability, final Card source, final CostPayment payment) {
public final boolean payHuman(final SpellAbility ability, final Card source, final CostPayment payment, final GameState game) {
final String amount = this.getAmount();
final String type = this.getType();
final Player activator = ability.getActivatingPlayer();
@@ -162,7 +152,7 @@ public class CostSacrifice extends CostPartWithList {
list = CardLists.getNotType(list, "Creature");
}
if (this.getThis()) {
if (this.isTargetingThis()) {
final Input inp = CostSacrifice.sacrificeThis(ability, payment, this);
Singletons.getModel().getMatch().getInput().setInputInterrupt(inp);
} else if (amount.equals("All")) {
@@ -203,7 +193,7 @@ public class CostSacrifice extends CostPartWithList {
public final boolean decideAIPayment(final Player ai, final SpellAbility ability, final Card source, final CostPayment payment) {
this.resetList();
final Player activator = ability.getActivatingPlayer();
if (this.getThis()) {
if (this.isTargetingThis()) {
this.getList().add(source);
} else if (this.getAmount().equals("All")) {
List<Card> typeList = new ArrayList<Card>(activator.getCardsIn(ZoneType.Battlefield));

View File

@@ -19,6 +19,7 @@ package forge.card.cost;
import forge.Card;
import forge.card.spellability.SpellAbility;
import forge.game.GameState;
import forge.game.player.Player;
/**
@@ -30,10 +31,16 @@ public class CostTap extends CostPart {
* Instantiates a new cost tap.
*/
public CostTap() {
this.setReusable(true);
this.setUndoable(true);
}
@Override
public boolean isUndoable() { return true; }
@Override
public boolean isReusable() { return true; }
/*
* (non-Javadoc)
*
@@ -62,7 +69,7 @@ public class CostTap extends CostPart {
* forge.Card, forge.Player, forge.card.cost.Cost)
*/
@Override
public final boolean canPay(final SpellAbility ability, final Card source, final Player activator, final Cost cost) {
public final boolean canPay(final SpellAbility ability, final Card source, final Player activator, final Cost cost, final GameState game) {
return source.isUntapped() && (!source.isSick() || source.hasKeyword("CARDNAME may activate abilities as though it has haste."));
}
@@ -73,7 +80,7 @@ public class CostTap extends CostPart {
* forge.Card, forge.card.cost.Cost_Payment)
*/
@Override
public final void payAI(final Player ai, final SpellAbility ability, final Card source, final CostPayment payment) {
public final void payAI(final Player ai, final SpellAbility ability, final Card source, final CostPayment payment, final GameState game) {
source.tap();
}
@@ -85,7 +92,7 @@ public class CostTap extends CostPart {
* forge.Card, forge.card.cost.Cost_Payment)
*/
@Override
public final boolean payHuman(final SpellAbility ability, final Card source, final CostPayment payment) {
public final boolean payHuman(final SpellAbility ability, final Card source, final CostPayment payment, final GameState game) {
// if (!canPay(ability, source, ability.getActivatingPlayer(),
// payment.getCost()))
// return false;

View File

@@ -28,6 +28,7 @@ import forge.Singletons;
import forge.card.abilityfactory.AbilityFactory;
import forge.card.spellability.SpellAbility;
import forge.control.input.Input;
import forge.game.GameState;
import forge.game.player.ComputerUtil;
import forge.game.player.Player;
import forge.game.zone.Zone;
@@ -52,9 +53,12 @@ public class CostTapType extends CostPartWithList {
*/
public CostTapType(final String amount, final String type, final String description) {
super(amount, type, description);
this.setReusable(true);
}
@Override
public boolean isReusable() { return true; }
/**
* Gets the description.
*
@@ -84,16 +88,6 @@ public class CostTapType extends CostPartWithList {
return sb.toString();
}
/**
* Adds the to tapped list.
*
* @param c
* the c
*/
public final void addToTappedList(final Card c) {
this.getList().add(c);
}
/*
* (non-Javadoc)
*
@@ -116,7 +110,7 @@ public class CostTapType extends CostPartWithList {
* forge.Card, forge.Player, forge.card.cost.Cost)
*/
@Override
public final boolean canPay(final SpellAbility ability, final Card source, final Player activator, final Cost cost) {
public final boolean canPay(final SpellAbility ability, final Card source, final Player activator, final Cost cost, final GameState game) {
List<Card> typeList = new ArrayList<Card>(activator.getCardsIn(ZoneType.Battlefield));
typeList = CardLists.getValidCards(typeList, this.getType().split(";"), activator, source);
@@ -141,7 +135,7 @@ public class CostTapType extends CostPartWithList {
* forge.Card, forge.card.cost.Cost_Payment)
*/
@Override
public final void payAI(final Player ai, final SpellAbility ability, final Card source, final CostPayment payment) {
public final void payAI(final Player ai, final SpellAbility ability, final Card source, final CostPayment payment, final GameState game) {
for (final Card c : this.getList()) {
c.tap();
}
@@ -155,7 +149,7 @@ public class CostTapType extends CostPartWithList {
* forge.Card, forge.card.cost.Cost_Payment)
*/
@Override
public final boolean payHuman(final SpellAbility ability, final Card source, final CostPayment payment) {
public final boolean payHuman(final SpellAbility ability, final Card source, final CostPayment payment, final GameState game) {
List<Card> typeList = new ArrayList<Card>(ability.getActivatingPlayer().getCardsIn(ZoneType.Battlefield));
typeList = CardLists.getValidCards(typeList, this.getType().split(";"), ability.getActivatingPlayer(), ability.getSourceCard());
typeList = CardLists.filter(typeList, Presets.UNTAPPED);

View File

@@ -19,6 +19,7 @@ package forge.card.cost;
import forge.Card;
import forge.card.spellability.SpellAbility;
import forge.game.GameState;
import forge.game.player.Player;
/**
@@ -30,10 +31,15 @@ public class CostUntap extends CostPart {
* Instantiates a new cost untap.
*/
public CostUntap() {
this.setReusable(true);
this.setUndoable(true);
}
@Override
public boolean isReusable() { return true; }
@Override
public boolean isUndoable() { return true; }
/*
* (non-Javadoc)
*
@@ -62,7 +68,7 @@ public class CostUntap extends CostPart {
* forge.Card, forge.Player, forge.card.cost.Cost)
*/
@Override
public final boolean canPay(final SpellAbility ability, final Card source, final Player activator, final Cost cost) {
public final boolean canPay(final SpellAbility ability, final Card source, final Player activator, final Cost cost, final GameState game) {
return source.isTapped() && (!source.isSick() || source.hasKeyword("CARDNAME may activate abilities as though it has haste."));
}
@@ -73,7 +79,7 @@ public class CostUntap extends CostPart {
* forge.Card, forge.card.cost.Cost_Payment)
*/
@Override
public final void payAI(final Player ai, final SpellAbility ability, final Card source, final CostPayment payment) {
public final void payAI(final Player ai, final SpellAbility ability, final Card source, final CostPayment payment, final GameState game) {
source.untap();
}
@@ -85,7 +91,7 @@ public class CostUntap extends CostPart {
* forge.Card, forge.card.cost.Cost_Payment)
*/
@Override
public final boolean payHuman(final SpellAbility ability, final Card source, final CostPayment payment) {
public final boolean payHuman(final SpellAbility ability, final Card source, final CostPayment payment, final GameState game) {
// if (!canPay(ability, source, ability.getActivatingPlayer(),
// payment.getCost()))
// return false;

View File

@@ -27,6 +27,7 @@ import forge.Singletons;
import forge.card.abilityfactory.AbilityFactory;
import forge.card.spellability.SpellAbility;
import forge.control.input.Input;
import forge.game.GameState;
import forge.game.player.ComputerUtil;
import forge.game.player.Player;
import forge.game.zone.Zone;
@@ -51,9 +52,12 @@ public class CostUntapType extends CostPartWithList {
*/
public CostUntapType(final String amount, final String type, final String description) {
super(amount, type, description);
this.setReusable(true);
}
@Override
public boolean isReusable() { return true; }
/**
* Gets the description.
*
@@ -119,7 +123,7 @@ public class CostUntapType extends CostPartWithList {
* forge.Card, forge.Player, forge.card.cost.Cost)
*/
@Override
public final boolean canPay(final SpellAbility ability, final Card source, final Player activator, final Cost cost) {
public final boolean canPay(final SpellAbility ability, final Card source, final Player activator, final Cost cost, final GameState game) {
List<Card> typeList = Singletons.getModel().getGame().getCardsIn(ZoneType.Battlefield);
typeList = CardLists.getValidCards(typeList, this.getType().split(";"), activator, source);
@@ -144,7 +148,7 @@ public class CostUntapType extends CostPartWithList {
* forge.Card, forge.card.cost.Cost_Payment)
*/
@Override
public final void payAI(final Player ai, final SpellAbility ability, final Card source, final CostPayment payment) {
public final void payAI(final Player ai, final SpellAbility ability, final Card source, final CostPayment payment, final GameState game) {
for (final Card c : this.getList()) {
c.untap();
}
@@ -158,7 +162,7 @@ public class CostUntapType extends CostPartWithList {
* forge.Card, forge.card.cost.Cost_Payment)
*/
@Override
public final boolean payHuman(final SpellAbility ability, final Card source, final CostPayment payment) {
public final boolean payHuman(final SpellAbility ability, final Card source, final CostPayment payment, final GameState game) {
final boolean untap = payment.getCost().hasUntapCost();
List<Card> typeList = Singletons.getModel().getGame().getCardsIn(ZoneType.Battlefield);
typeList = CardLists.getValidCards(typeList, this.getType().split(";"), ability.getActivatingPlayer(), ability.getSourceCard());

View File

@@ -109,7 +109,7 @@ public class CostUtil {
for (final CostPart part : cost.getCostParts()) {
if (part instanceof CostSacrifice) {
final CostSacrifice sac = (CostSacrifice) part;
if (sac.getThis() && source.isCreature()) {
if (sac.isTargetingThis() && source.isCreature()) {
return false;
}
final String type = sac.getType();
@@ -257,7 +257,7 @@ public class CostUtil {
final CounterType type = remCounter.getCounter();
final double percent = type.name().equals("P1P1") ? p1p1Percent : otherPercent;
final int currentNum = source.getCounters(type);
if (!part.getThis()) {
if (!part.isTargetingThis()) {
if (type.name().equals("P1P1")) {
return false;
}

View File

@@ -27,6 +27,7 @@ import forge.GameActionUtil;
import forge.Singletons;
import forge.card.abilityfactory.AbilityFactory;
import forge.card.spellability.SpellAbility;
import forge.game.GameState;
import forge.game.player.ComputerUtil;
import forge.game.player.Player;
import forge.game.zone.ZoneType;
@@ -42,6 +43,7 @@ public class ReplacementHandler {
public ReplacementResult run(final HashMap<String, Object> runParams) {
final Object affected = runParams.get("Affected");
final GameState game = Singletons.getModel().getGame();
Player decider = null;
// Figure out who decides which of multiple replacements to apply
@@ -53,25 +55,25 @@ public class ReplacementHandler {
}
if (runParams.get("Event").equals("Moved")) {
ReplacementResult res = run(runParams, ReplacementLayer.Control, decider);
ReplacementResult res = run(runParams, ReplacementLayer.Control, decider, game);
if (res != ReplacementResult.NotReplaced) {
return res;
}
res = run(runParams, ReplacementLayer.Copy, decider);
res = run(runParams, ReplacementLayer.Copy, decider, game);
if (res != ReplacementResult.NotReplaced) {
return res;
}
res = run(runParams, ReplacementLayer.Other, decider);
res = run(runParams, ReplacementLayer.Other, decider, game);
if (res != ReplacementResult.NotReplaced) {
return res;
}
res = run(runParams, ReplacementLayer.None, decider);
res = run(runParams, ReplacementLayer.None, decider, game);
if (res != ReplacementResult.NotReplaced) {
return res;
}
}
else {
ReplacementResult res = run(runParams, ReplacementLayer.None, decider);
ReplacementResult res = run(runParams, ReplacementLayer.None, decider, game);
if (res != ReplacementResult.NotReplaced) {
return res;
}
@@ -89,7 +91,7 @@ public class ReplacementHandler {
* the run params,same as for triggers.
* @return true if the event was replaced.
*/
public ReplacementResult run(final HashMap<String, Object> runParams, final ReplacementLayer layer, final Player decider) {
public ReplacementResult run(final HashMap<String, Object> runParams, final ReplacementLayer layer, final Player decider, final GameState game) {
final List<ReplacementEffect> possibleReplacers = new ArrayList<ReplacementEffect>();
// Round up Non-static replacement effects ("Until EOT," or
@@ -101,7 +103,7 @@ public class ReplacementHandler {
}*/
// Round up Static replacement effects
for (final Player p : Singletons.getModel().getGame().getPlayers()) {
for (final Player p : game.getPlayers()) {
for (final Card crd : p.getAllCards()) {
for (final ReplacementEffect replacementEffect : crd.getReplacementEffects()) {
if (!replacementEffect.hasRun()
@@ -109,7 +111,7 @@ public class ReplacementHandler {
&& replacementEffect.requirementsCheck()
&& replacementEffect.canReplace(runParams)
&& !possibleReplacers.contains(replacementEffect)
&& replacementEffect.zonesCheck(Singletons.getModel().getGame().getZoneOf(crd))) {
&& replacementEffect.zonesCheck(game.getZoneOf(crd))) {
possibleReplacers.add(replacementEffect);
}
}
@@ -141,7 +143,7 @@ public class ReplacementHandler {
if (chosenRE != null) {
chosenRE.setHasRun(true);
ReplacementResult res = this.executeReplacement(runParams, chosenRE, decider);
ReplacementResult res = this.executeReplacement(runParams, chosenRE, decider, game);
if (res != ReplacementResult.NotReplaced) {
chosenRE.setHasRun(false);
Singletons.getModel().getGame().getGameLog().add("ReplacementEffect", chosenRE.toString(), 2);
@@ -171,7 +173,7 @@ public class ReplacementHandler {
* the replacement effect to run
*/
private ReplacementResult executeReplacement(final HashMap<String, Object> runParams,
final ReplacementEffect replacementEffect, final Player decider) {
final ReplacementEffect replacementEffect, final Player decider, final GameState game) {
final HashMap<String, String> mapParams = replacementEffect.getMapParams();
SpellAbility effectSA = null;
@@ -234,9 +236,9 @@ public class ReplacementHandler {
Player player = replacementEffect.getHostCard().getController();
if (player.isHuman()) {
Singletons.getModel().getGame().getAction().playSpellAbilityNoStack(effectSA, false);
game.getAction().playSpellAbilityNoStack(effectSA, false);
} else {
ComputerUtil.playNoStack(player, effectSA);
ComputerUtil.playNoStack(player, effectSA, game);
}
return ReplacementResult.Replaced;

View File

@@ -25,6 +25,7 @@ import forge.Singletons;
import forge.card.cost.Cost;
import forge.card.cost.CostPayment;
import forge.card.staticability.StaticAbility;
import forge.game.GameState;
import forge.game.GlobalRuleChange;
import forge.game.zone.ZoneType;
@@ -82,7 +83,8 @@ public abstract class AbilityActivated extends SpellAbility implements java.io.S
/** {@inheritDoc} */
@Override
public boolean canPlay() {
if (Singletons.getModel().getGame().getStack().isSplitSecondOnStack() && !this.isManaAbility()) {
final GameState game = Singletons.getModel().getGame();
if (game.getStack().isSplitSecondOnStack() && !this.isManaAbility()) {
return false;
}
@@ -115,7 +117,7 @@ public abstract class AbilityActivated extends SpellAbility implements java.io.S
return false;
}
return CostPayment.canPayAdditionalCosts(this.getPayCosts(), this);
return CostPayment.canPayAdditionalCosts(game, this.getPayCosts(), this);
}
/* (non-Javadoc)

View File

@@ -29,6 +29,7 @@ import forge.card.cost.Cost;
import forge.card.cost.CostPayment;
import forge.card.staticability.StaticAbility;
import forge.error.ErrorViewer;
import forge.game.GameState;
import forge.game.player.Player;
import forge.game.zone.ZoneType;
import forge.util.Expressions;
@@ -86,7 +87,8 @@ public abstract class Spell extends SpellAbility implements java.io.Serializable
/** {@inheritDoc} */
@Override
public boolean canPlay() {
if (Singletons.getModel().getGame().getStack().isSplitSecondOnStack()) {
final GameState game = Singletons.getModel().getGame();
if (game.getStack().isSplitSecondOnStack()) {
return false;
}
@@ -113,13 +115,13 @@ public abstract class Spell extends SpellAbility implements java.io.Serializable
}
if (this.getPayCosts() != null) {
if (!CostPayment.canPayAdditionalCosts(this.getPayCosts(), this)) {
if (!CostPayment.canPayAdditionalCosts(game, this.getPayCosts(), this)) {
return false;
}
}
// CantBeCast static abilities
final List<Card> allp = new ArrayList<Card>(Singletons.getModel().getGame().getCardsIn(ZoneType.listValueOf("Battlefield,Command")));
final List<Card> allp = new ArrayList<Card>(game.getCardsIn(ZoneType.listValueOf("Battlefield,Command")));
allp.add(card);
for (final Card ca : allp) {
final ArrayList<StaticAbility> staticAbilities = ca.getStaticAbilities();

View File

@@ -546,7 +546,7 @@ public class TriggerHandler {
game.getAction().playSpellAbilityNoStack(wrapperAbility, false);
} else {
wrapperAbility.doTrigger(isMandatory);
ComputerUtil.playNoStack(wrapperAbility.getActivatingPlayer(), wrapperAbility);
ComputerUtil.playNoStack(wrapperAbility.getActivatingPlayer(), wrapperAbility, game);
}
} else {
game.getStack().addSimultaneousStackEntry(wrapperAbility);

View File

@@ -19,6 +19,7 @@ import forge.card.spellability.SpellAbility;
import forge.card.spellability.SpellAbilityRestriction;
import forge.card.spellability.Target;
import forge.control.input.Input;
import forge.game.GameState;
import forge.game.player.ComputerUtil;
import forge.game.player.Player;
@@ -454,6 +455,7 @@ public class WrappedAbility extends Ability implements ISpellAbility {
// //////////////////////////////////////
@Override
public void resolve() {
final GameState game = Singletons.getModel().getGame();
if (!(regtrig instanceof TriggerAlways)) {
// State triggers
// don't do the whole
@@ -463,7 +465,7 @@ public class WrappedAbility extends Ability implements ISpellAbility {
return;
}
}
TriggerHandler th = Singletons.getModel().getGame().getTriggerHandler();
TriggerHandler th = game.getTriggerHandler();
Map<String, String> triggerParams = regtrig.getMapParams();
if (decider != null) {
@@ -508,12 +510,12 @@ public class WrappedAbility extends Ability implements ISpellAbility {
}
if (getActivatingPlayer().isHuman()) {
Singletons.getModel().getGame().getAction().playSpellAbilityNoStack(sa, true);
game.getAction().playSpellAbilityNoStack(sa, true);
} else {
// commented out because i don't think this should be called
// again here
// sa.doTrigger(isMandatory);
ComputerUtil.playNoStack(getActivatingPlayer(), sa);
ComputerUtil.playNoStack(getActivatingPlayer(), sa, game);
}
// Add eventual delayed trigger.

View File

@@ -160,7 +160,7 @@ public class InputMulligan extends Input {
// Is there a better way for the AI to decide this?
if (effect.doTrigger(false)) {
GameActionUtil.showInfoDialg("Computer reveals " + c.getName() + "(" + c.getUniqueNumber() + ").");
ComputerUtil.playNoStack(p, effect);
ComputerUtil.playNoStack(p, effect, game);
}
}
}

View File

@@ -69,13 +69,13 @@ public class GameState {
private final List<Card> communalPlanarDeck = new ArrayList<Card>();
private Card activePlane = null;
private final Cleanup cleanup = new Cleanup();
private final EndOfTurn endOfTurn = new EndOfTurn();
private final EndOfCombat endOfCombat = new EndOfCombat();
private final Untap untap = new Untap();
private final Upkeep upkeep = new Upkeep();
public final Cleanup cleanup;
public final EndOfTurn endOfTurn;
public final EndOfCombat endOfCombat;
public final Untap untap;
public final Upkeep upkeep;
private final PhaseHandler phaseHandler;
private final MagicStack stack;
public final MagicStack stack;
private final StaticEffects staticEffects = new StaticEffects();
private final TriggerHandler triggerHandler = new TriggerHandler();
private final ReplacementHandler replacementHandler = new ReplacementHandler();
@@ -89,7 +89,7 @@ public class GameState {
private final Zone stackZone = new Zone(ZoneType.Stack);
private long timestamp = 0;
private final GameAction action;
public final GameAction action;
/**
* Constructor.
@@ -108,6 +108,12 @@ public class GameState {
action = new GameAction(this);
stack = new MagicStack(this);
phaseHandler = new PhaseHandler(this);
untap = new Untap(this);
upkeep = new Upkeep(this);
cleanup = new Cleanup(this);
endOfTurn = new EndOfTurn(this);
endOfCombat = new EndOfCombat(this);
events.register(Singletons.getControl().getSoundSystem());
events.register(gameLog);

View File

@@ -17,6 +17,8 @@
*/
package forge.game.phase;
import forge.game.GameState;
/**
* <p>
* Handles "until your next turn" effects and Cleanup hardcoded triggers.
@@ -26,7 +28,10 @@ package forge.game.phase;
*/
public class Cleanup extends Phase {
/** Constant <code>serialVersionUID=-6993476643509826990L</code>. */
private static final long serialVersionUID = -6993476643509826990L;
public Cleanup(final GameState game) { super(game); }
} // end class Cleanup

View File

@@ -55,6 +55,7 @@ import forge.card.staticability.StaticAbility;
import forge.card.trigger.Trigger;
import forge.card.trigger.TriggerHandler;
import forge.card.trigger.TriggerType;
import forge.game.GameState;
import forge.game.GlobalRuleChange;
import forge.game.player.ComputerUtil;
import forge.game.player.ComputerUtilBlock;
@@ -2706,11 +2707,12 @@ public class CombatUtil {
*/
public static void checkPropagandaEffects(final Card c, final boolean bLast) {
Cost attackCost = new Cost(c, "0", true);
final GameState game = Singletons.getModel().getGame();
// Sort abilities to apply them in proper order
for (Card card : Singletons.getModel().getGame().getCardsIn(ZoneType.Battlefield)) {
final ArrayList<StaticAbility> staticAbilities = card.getStaticAbilities();
for (final StaticAbility stAb : staticAbilities) {
Cost additionalCost = stAb.getCostAbility("CantAttackUnless", c, Singletons.getModel().getGame().getCombat().getDefenderByAttacker(c));
Cost additionalCost = stAb.getCostAbility("CantAttackUnless", c, game.getCombat().getDefenderByAttacker(c));
attackCost = CostUtil.combineCosts(attackCost, additionalCost);
}
}
@@ -2727,7 +2729,8 @@ public class CombatUtil {
final Card crd = c;
final PhaseType phase = Singletons.getModel().getGame().getPhaseHandler().getPhase();
final PhaseType phase = game.getPhaseHandler().getPhase();
if (phase == PhaseType.COMBAT_DECLARE_ATTACKERS || phase == PhaseType.COMBAT_DECLARE_ATTACKERS_INSTANT_ABILITY) {
final Ability ability = new AbilityStatic(c, attackCost, null) {
@@ -2743,7 +2746,7 @@ public class CombatUtil {
@Override
public void execute() {
Singletons.getModel().getGame().getCombat().removeFromCombat(crd);
game.getCombat().removeFromCombat(crd);
if (bLast) {
PhaseUtil.handleAttackingTriggers();
@@ -2768,17 +2771,17 @@ public class CombatUtil {
};
if (c.getController().isHuman()) {
GameActionUtil.payCostDuringAbilityResolve(ability, attackCost, paidCommand, unpaidCommand, null);
GameActionUtil.payCostDuringAbilityResolve(ability, attackCost, paidCommand, unpaidCommand, null, game);
} else { // computer
if (ComputerUtil.canPayCost(ability, c.getController())) {
ComputerUtil.playNoStack(c.getController(), ability);
ComputerUtil.playNoStack(c.getController(), ability, game);
if (!crd.hasKeyword("Vigilance")) {
crd.tap();
}
} else {
// TODO remove the below line after Propaganda occurs
// during Declare_Attackers
Singletons.getModel().getGame().getCombat().removeFromCombat(crd);
game.getCombat().removeFromCombat(crd);
}
if (bLast) {
PhaseUtil.handleAttackingTriggers();

View File

@@ -17,6 +17,8 @@
*/
package forge.game.phase;
import forge.game.GameState;
/**
* <p>
* Handles "until end of combat" effects and "at end of combat" hardcoded triggers.
@@ -30,4 +32,6 @@ public class EndOfCombat extends Phase {
/** Constant <code>serialVersionUID=3035250030566186842L</code>. */
private static final long serialVersionUID = 3035250030566186842L;
public EndOfCombat(final GameState game) { super(game); }
} // end class EndOfCombat

View File

@@ -24,6 +24,7 @@ import forge.card.SpellManaCost;
import forge.card.spellability.Ability;
import forge.card.spellability.SpellAbility;
import forge.game.GameLossReason;
import forge.game.GameState;
import forge.game.player.Player;
import forge.game.zone.ZoneType;
@@ -40,6 +41,7 @@ public class EndOfTurn extends Phase {
/** Constant <code>serialVersionUID=-3656715295379727275L</code>. */
private static final long serialVersionUID = -3656715295379727275L;
public EndOfTurn(final GameState game) { super(game); }
/**
* <p>
* Handles all the hardcoded events that happen "at end of turn".
@@ -48,11 +50,11 @@ public class EndOfTurn extends Phase {
@Override
public final void executeAt() {
// reset mustAttackEntity for me
Singletons.getModel().getGame().getPhaseHandler().getPlayerTurn().setMustAttackEntity(null);
game.getPhaseHandler().getPlayerTurn().setMustAttackEntity(null);
Singletons.getModel().getGame().getStaticEffects().rePopulateStateBasedList();
game.getStaticEffects().rePopulateStateBasedList();
for (final Card c : Singletons.getModel().getGame().getCardsIn(ZoneType.Battlefield)) {
for (final Card c : game.getCardsIn(ZoneType.Battlefield)) {
if (!c.isFaceDown() && c.hasKeyword("At the beginning of the end step, sacrifice CARDNAME.")) {
final Card card = c;
final SpellAbility sac = new Ability(card, SpellManaCost.ZERO) {
@@ -68,7 +70,7 @@ public class EndOfTurn extends Phase {
sac.setStackDescription(sb.toString());
sac.setDescription(sb.toString());
Singletons.getModel().getGame().getStack().addSimultaneousStackEntry(sac);
game.getStack().addSimultaneousStackEntry(sac);
}
if (!c.isFaceDown() && c.hasKeyword("At the beginning of the end step, exile CARDNAME.")) {
@@ -86,7 +88,7 @@ public class EndOfTurn extends Phase {
exile.setStackDescription(sb.toString());
exile.setDescription(sb.toString());
Singletons.getModel().getGame().getStack().addSimultaneousStackEntry(exile);
game.getStack().addSimultaneousStackEntry(exile);
}
if (!c.isFaceDown() && c.hasKeyword("At the beginning of the end step, destroy CARDNAME.")) {
@@ -95,7 +97,7 @@ public class EndOfTurn extends Phase {
@Override
public void resolve() {
if (card.isInPlay()) {
Singletons.getModel().getGame().getAction().destroy(card);
game.getAction().destroy(card);
}
}
};
@@ -104,7 +106,7 @@ public class EndOfTurn extends Phase {
destroy.setStackDescription(sb.toString());
destroy.setDescription(sb.toString());
Singletons.getModel().getGame().getStack().addSimultaneousStackEntry(destroy);
game.getStack().addSimultaneousStackEntry(destroy);
}
// Berserk is using this, so don't check isFaceDown()
@@ -115,7 +117,7 @@ public class EndOfTurn extends Phase {
@Override
public void resolve() {
if (card.isInPlay()) {
Singletons.getModel().getGame().getAction().destroy(card);
game.getAction().destroy(card);
}
}
};
@@ -124,7 +126,7 @@ public class EndOfTurn extends Phase {
sac.setStackDescription(sb.toString());
sac.setDescription(sb.toString());
Singletons.getModel().getGame().getStack().addSimultaneousStackEntry(sac);
game.getStack().addSimultaneousStackEntry(sac);
} else {
c.removeAllExtrinsicKeyword("At the beginning of the next end step, "
@@ -133,13 +135,13 @@ public class EndOfTurn extends Phase {
}
if (c.hasKeyword("At the beginning of your end step, return CARDNAME to its owner's hand.")
&& Singletons.getModel().getGame().getPhaseHandler().isPlayerTurn(c.getController())) {
&& game.getPhaseHandler().isPlayerTurn(c.getController())) {
final Card source = c;
final SpellAbility change = new Ability(source, SpellManaCost.ZERO) {
@Override
public void resolve() {
if (source.isInPlay()) {
Singletons.getModel().getGame().getAction().moveToHand(source);
game.getAction().moveToHand(source);
}
}
};
@@ -148,12 +150,12 @@ public class EndOfTurn extends Phase {
change.setStackDescription(sb.toString());
change.setDescription(sb.toString());
Singletons.getModel().getGame().getStack().addSimultaneousStackEntry(change);
game.getStack().addSimultaneousStackEntry(change);
}
}
Player activePlayer = Singletons.getModel().getGame().getPhaseHandler().getPlayerTurn();
Player activePlayer = game.getPhaseHandler().getPlayerTurn();
if (activePlayer.hasKeyword("At the beginning of this turn's end step, you lose the game.")) {
final Card source = new Card();
final SpellAbility change = new Ability(source, SpellManaCost.ZERO) {
@@ -166,7 +168,7 @@ public class EndOfTurn extends Phase {
change.setDescription("At the beginning of this turn's end step, you lose the game.");
change.setActivatingPlayer(activePlayer);
Singletons.getModel().getGame().getStack().addSimultaneousStackEntry(change);
game.getStack().addSimultaneousStackEntry(change);
}
this.execute(this.getAt());

View File

@@ -22,6 +22,7 @@ import java.util.HashMap;
import forge.Command;
import forge.CommandList;
import forge.Singletons;
import forge.game.GameState;
import forge.game.player.Player;
@@ -39,7 +40,12 @@ public abstract class Phase implements java.io.Serializable {
/** The at. */
private final CommandList at = new CommandList();
protected final GameState game;
public Phase(final GameState game0) {
game = game0;
}
/**
* Gets the at.
*

View File

@@ -33,6 +33,7 @@ import forge.GameEntity;
import forge.Singletons;
import forge.card.cardfactory.CardFactoryUtil;
import forge.control.input.Input;
import forge.game.GameState;
import forge.game.player.Player;
import forge.game.zone.Zone;
import forge.game.zone.ZoneType;
@@ -51,9 +52,12 @@ import forge.view.ButtonUtil;
* @version $Id: Untap 12482 2011-12-06 11:14:11Z Sloth $
*/
public class Untap extends Phase {
private static final long serialVersionUID = 4515266331266259123L;
public Untap(final GameState game0) {
super(game0);
}
/**
* <p>
* Executes any hardcoded triggers that happen "at end of combat".
@@ -63,7 +67,7 @@ public class Untap extends Phase {
public void executeAt() {
this.execute(this.getAt());
final Player turn = Singletons.getModel().getGame().getPhaseHandler().getPlayerTurn();
final Player turn = game.getPhaseHandler().getPlayerTurn();
Untap.doPhasing(turn);
Untap.doUntap();

View File

@@ -69,6 +69,8 @@ import forge.view.ButtonUtil;
public class Upkeep extends Phase {
private static final long serialVersionUID = 6906459482978819354L;
public Upkeep(final GameState game) { super(game); }
/**
* <p>
* Handles all the hardcoded events that happen at the beginning of each
@@ -80,29 +82,30 @@ public class Upkeep extends Phase {
*/
@Override
public final void executeAt() {
Singletons.getModel().getGame().getStack().freezeStack();
Upkeep.upkeepBraidOfFire();
game.getStack().freezeStack();
Upkeep.upkeepBraidOfFire(game);
Upkeep.upkeepSlowtrips(); // for "Draw a card at the beginning of the next turn's upkeep."
Upkeep.upkeepUpkeepCost(); // sacrifice unless upkeep cost is paid
Upkeep.upkeepEcho();
Upkeep.upkeepSlowtrips(game); // for "Draw a card at the beginning of the next turn's upkeep."
Upkeep.upkeepUpkeepCost(game); // sacrifice unless upkeep cost is paid
Upkeep.upkeepEcho(game);
Upkeep.upkeepTheAbyss();
Upkeep.upkeepDropOfHoney();
Upkeep.upkeepDemonicHordes();
Upkeep.upkeepTangleWire();
Upkeep.upkeepTheAbyss(game);
Upkeep.upkeepDropOfHoney(game);
Upkeep.upkeepDemonicHordes(game);
Upkeep.upkeepTangleWire(game);
Upkeep.upkeepKarma();
Upkeep.upkeepOathOfDruids();
Upkeep.upkeepOathOfGhouls();
Upkeep.upkeepSuspend();
Upkeep.upkeepVanishing();
Upkeep.upkeepFading();
Upkeep.upkeepBlazeCounters();
Upkeep.upkeepCurseOfMisfortunes();
Upkeep.upkeepPowerSurge();
Upkeep.upkeepKarma(game);
Upkeep.upkeepOathOfDruids(game);
Upkeep.upkeepOathOfGhouls(game);
Upkeep.upkeepSuspend(game);
Upkeep.upkeepVanishing(game);
Upkeep.upkeepFading(game);
Upkeep.upkeepBlazeCounters(game);
Upkeep.upkeepCurseOfMisfortunes(game);
Upkeep.upkeepPowerSurge(game);
Singletons.getModel().getGame().getStack().unfreezeStack();
game.getStack().unfreezeStack();
}
// UPKEEP CARDS:
@@ -112,8 +115,8 @@ public class Upkeep extends Phase {
* upkeepBraidOfFire.
* </p>
*/
private static void upkeepBraidOfFire() {
final Player player = Singletons.getModel().getGame().getPhaseHandler().getPlayerTurn();
private static void upkeepBraidOfFire(final GameState game) {
final Player player = game.getPhaseHandler().getPlayerTurn();
final List<Card> braids = player.getCardsIn(ZoneType.Battlefield, "Braid of Fire");
@@ -138,14 +141,14 @@ public class Upkeep extends Phase {
} else if (GameActionUtil.showYesNoDialog(c, sb.toString())) {
abMana.produceMana(this);
} else {
Singletons.getModel().getGame().getAction().sacrifice(c, null);
game.getAction().sacrifice(c, null);
}
}
};
upkeepAbility.setStackDescription(sb.toString());
Singletons.getModel().getGame().getStack().addSimultaneousStackEntry(upkeepAbility);
game.getStack().addSimultaneousStackEntry(upkeepAbility);
}
} // upkeepBraidOfFire
@@ -155,8 +158,8 @@ public class Upkeep extends Phase {
* upkeepEcho.
* </p>
*/
private static void upkeepEcho() {
List<Card> list = Singletons.getModel().getGame().getPhaseHandler().getPlayerTurn().getCardsIn(ZoneType.Battlefield);
private static void upkeepEcho(final GameState game) {
List<Card> list = game.getPhaseHandler().getPlayerTurn().getCardsIn(ZoneType.Battlefield);
list = CardLists.filter(list, new Predicate<Card>() {
@Override
public boolean apply(final Card c) {
@@ -175,7 +178,7 @@ public class Upkeep extends Phase {
@Override
public void execute() {
Singletons.getModel().getGame().getAction().sacrifice(c, null);
game.getAction().sacrifice(c, null);
}
};
@@ -187,15 +190,16 @@ public class Upkeep extends Phase {
final Ability sacAbility = new Ability(c, SpellManaCost.ZERO) {
@Override
public void resolve() {
Player controller = c.getController();
if (controller.isHuman()) {
Cost cost = new Cost(c, c.getEchoCost().trim(), true);
GameActionUtil.payCostDuringAbilityResolve(blankAbility, cost, paidCommand, unpaidCommand, null);
GameActionUtil.payCostDuringAbilityResolve(blankAbility, cost, paidCommand, unpaidCommand, null, game);
} else { // computer
if (ComputerUtil.canPayCost(blankAbility, controller)) {
ComputerUtil.playNoStack(controller, blankAbility);
ComputerUtil.playNoStack(controller, blankAbility, game);
} else {
Singletons.getModel().getGame().getAction().sacrifice(c, null);
game.getAction().sacrifice(c, null);
}
}
}
@@ -203,7 +207,7 @@ public class Upkeep extends Phase {
sacAbility.setStackDescription(sb.toString());
sacAbility.setDescription(sb.toString());
Singletons.getModel().getGame().getStack().addSimultaneousStackEntry(sacAbility);
game.getStack().addSimultaneousStackEntry(sacAbility);
c.removeAllExtrinsicKeyword("(Echo unpaid)");
}
@@ -215,20 +219,20 @@ public class Upkeep extends Phase {
* upkeepSlowtrips. Draw a card at the beginning of the next turn's upkeep.
* </p>
*/
private static void upkeepSlowtrips() {
Player turnOwner = Singletons.getModel().getGame().getPhaseHandler().getPlayerTurn();
private static void upkeepSlowtrips(final GameState game) {
Player turnOwner = game.getPhaseHandler().getPlayerTurn();
// does order matter here?
drawForSlowtrips(turnOwner);
for (Player p : Singletons.getModel().getGame().getPlayers()) {
drawForSlowtrips(turnOwner, game);
for (Player p : game.getPlayers()) {
if (p == turnOwner) {
continue;
}
drawForSlowtrips(p);
drawForSlowtrips(p, game);
}
}
public static void drawForSlowtrips(final Player player) {
public static void drawForSlowtrips(final Player player, final GameState game) {
List<Card> list = player.getSlowtripList();
for (Card card : list) {
@@ -244,7 +248,7 @@ public class Upkeep extends Phase {
slowtrip.setStackDescription(card + " - Draw a card.");
slowtrip.setDescription(card + " - Draw a card.");
Singletons.getModel().getGame().getStack().addSimultaneousStackEntry(slowtrip);
game.getStack().addSimultaneousStackEntry(slowtrip);
}
player.clearSlowtripList();
@@ -255,8 +259,9 @@ public class Upkeep extends Phase {
* upkeepUpkeepCost.
* </p>
*/
private static void upkeepUpkeepCost() {
final List<Card> list = Singletons.getModel().getGame().getPhaseHandler().getPlayerTurn().getCardsIn(ZoneType.Battlefield);
private static void upkeepUpkeepCost(final GameState game) {
final List<Card> list = game.getPhaseHandler().getPlayerTurn().getCardsIn(ZoneType.Battlefield);
for (int i = 0; i < list.size(); i++) {
final Card c = list.get(i);
@@ -278,7 +283,7 @@ public class Upkeep extends Phase {
if (c.getName().equals("Cosmic Horror")) {
controller.addDamage(7, c);
}
Singletons.getModel().getGame().getAction().destroy(c);
game.getAction().destroy(c);
}
};
@@ -295,12 +300,12 @@ public class Upkeep extends Phase {
GameActionUtil.payManaDuringAbilityResolve(sb.toString(), upkeepCost, paidCommand, unpaidCommand);
} else { // computer
if (ComputerUtil.canPayCost(aiPaid, controller) && !c.hasKeyword("Indestructible")) {
ComputerUtil.playNoStack(controller, aiPaid);
ComputerUtil.playNoStack(controller, aiPaid, game);
} else {
if (c.getName().equals("Cosmic Horror")) {
controller.addDamage(7, c);
}
Singletons.getModel().getGame().getAction().destroy(c);
game.getAction().destroy(c);
}
}
}
@@ -308,7 +313,7 @@ public class Upkeep extends Phase {
upkeepAbility.setStackDescription(sb.toString());
upkeepAbility.setDescription(sb.toString());
Singletons.getModel().getGame().getStack().addSimultaneousStackEntry(upkeepAbility);
game.getStack().addSimultaneousStackEntry(upkeepAbility);
} // destroy
// sacrifice
@@ -337,7 +342,7 @@ public class Upkeep extends Phase {
@Override
public void execute() {
Singletons.getModel().getGame().getAction().sacrifice(c, null);
game.getAction().sacrifice(c, null);
}
};
@@ -350,12 +355,12 @@ public class Upkeep extends Phase {
public void resolve() {
if (controller.isHuman()) {
GameActionUtil.payCostDuringAbilityResolve(blankAbility, blankAbility.getPayCosts(),
paidCommand, unpaidCommand, null);
paidCommand, unpaidCommand, null, game);
} else { // computer
if (ComputerUtil.shouldPayCost(controller, c, upkeepCost) && ComputerUtil.canPayCost(blankAbility, controller)) {
ComputerUtil.playNoStack(controller, blankAbility);
ComputerUtil.playNoStack(controller, blankAbility, game);
} else {
Singletons.getModel().getGame().getAction().sacrifice(c, null);
game.getAction().sacrifice(c, null);
}
}
}
@@ -363,7 +368,7 @@ public class Upkeep extends Phase {
upkeepAbility.setStackDescription(sb.toString());
upkeepAbility.setDescription(sb.toString());
Singletons.getModel().getGame().getStack().addSimultaneousStackEntry(upkeepAbility);
game.getStack().addSimultaneousStackEntry(upkeepAbility);
} // sacrifice
// destroy
@@ -397,7 +402,7 @@ public class Upkeep extends Phase {
} else { // computers
if (ComputerUtil.canPayCost(aiPaid, controller)
&& (controller.predictDamage(upkeepDamage, c, false) > 0)) {
ComputerUtil.playNoStack(controller, aiPaid);
ComputerUtil.playNoStack(controller, aiPaid, game);
} else {
controller.addDamage(upkeepDamage, c);
}
@@ -407,7 +412,7 @@ public class Upkeep extends Phase {
upkeepAbility.setStackDescription(sb.toString());
upkeepAbility.setDescription(sb.toString());
Singletons.getModel().getGame().getStack().addSimultaneousStackEntry(upkeepAbility);
game.getStack().addSimultaneousStackEntry(upkeepAbility);
} // destroy
}
@@ -442,15 +447,15 @@ public class Upkeep extends Phase {
* upkeepTheAbyss.
* </p>
*/
private static void upkeepTheAbyss() {
private static void upkeepTheAbyss(final GameState game) {
/*
* At the beginning of each player's upkeep, destroy target nonartifact
* creature that player controls of his or her choice. It can't be
* regenerated.
*/
final Player player = Singletons.getModel().getGame().getPhaseHandler().getPlayerTurn();
final List<Card> the = CardLists.filter(Singletons.getModel().getGame().getCardsIn(ZoneType.Battlefield), CardPredicates.nameEquals("The Abyss"));
final List<Card> magus = CardLists.filter(Singletons.getModel().getGame().getCardsIn(ZoneType.Battlefield), CardPredicates.nameEquals("Magus of the Abyss"));
final Player player = game.getPhaseHandler().getPlayerTurn();
final List<Card> the = CardLists.filter(game.getCardsIn(ZoneType.Battlefield), CardPredicates.nameEquals("The Abyss"));
final List<Card> magus = CardLists.filter(game.getCardsIn(ZoneType.Battlefield), CardPredicates.nameEquals("Magus of the Abyss"));
final List<Card> cards = new ArrayList<Card>();
cards.addAll(the);
@@ -480,7 +485,7 @@ public class Upkeep extends Phase {
@Override
protected Input onDone() {
Singletons.getModel().getGame().getAction().destroyNoRegeneration(selected.get(0));
game.getAction().destroyNoRegeneration(selected.get(0));
return null;
}
};
@@ -490,13 +495,13 @@ public class Upkeep extends Phase {
final List<Card> indestruct = CardLists.getKeyword(targets, "Indestructible");
if (indestruct.size() > 0) {
Singletons.getModel().getGame().getAction().destroyNoRegeneration(indestruct.get(0));
game.getAction().destroyNoRegeneration(indestruct.get(0));
} else if (targets.size() > 0) {
final Card target = CardFactoryUtil.getWorstCreatureAI(targets);
if (null == target) {
// must be nothing valid to destroy
} else {
Singletons.getModel().getGame().getAction().destroyNoRegeneration(target);
game.getAction().destroyNoRegeneration(target);
}
}
}
@@ -506,7 +511,7 @@ public class Upkeep extends Phase {
final StringBuilder sb = new StringBuilder();
sb.append(abyss.getName()).append(" - destroy a nonartifact creature of your choice.");
sacrificeCreature.setStackDescription(sb.toString());
Singletons.getModel().getGame().getStack().addAndUnfreeze(sacrificeCreature);
game.getStack().addAndUnfreeze(sacrificeCreature);
} // end for
} // The Abyss
@@ -515,13 +520,13 @@ public class Upkeep extends Phase {
* upkeepDropOfHoney.
* </p>
*/
private static void upkeepDropOfHoney() {
private static void upkeepDropOfHoney(final GameState game) {
/*
* At the beginning of your upkeep, destroy the creature with the least
* power. It can't be regenerated. If two or more creatures are tied for
* least power, you choose one of them.
*/
final Player player = Singletons.getModel().getGame().getPhaseHandler().getPlayerTurn();
final Player player = game.getPhaseHandler().getPlayerTurn();
final List<Card> drops = player.getCardsIn(ZoneType.Battlefield, "Drop of Honey");
drops.addAll(player.getCardsIn(ZoneType.Battlefield, "Porphyry Nodes"));
final List<Card> cards = drops;
@@ -532,7 +537,7 @@ public class Upkeep extends Phase {
final Ability ability = new Ability(c, SpellManaCost.NO_COST) {
@Override
public void resolve() {
final List<Card> creatures = CardLists.filter(Singletons.getModel().getGame().getCardsIn(ZoneType.Battlefield), Presets.CREATURES);
final List<Card> creatures = CardLists.filter(game.getCardsIn(ZoneType.Battlefield), Presets.CREATURES);
if (creatures.size() > 0) {
CardLists.sortAttackLowFirst(creatures);
final int power = creatures.get(0).getNetAttack();
@@ -542,7 +547,7 @@ public class Upkeep extends Phase {
"Select creature with power: " + power + " to sacrifice."));
} else { // computer
final Card compyTarget = this.getCompyCardToDestroy(creatures);
Singletons.getModel().getGame().getAction().destroyNoRegeneration(compyTarget);
game.getAction().destroyNoRegeneration(compyTarget);
}
}
} // resolve
@@ -580,7 +585,7 @@ public class Upkeep extends Phase {
sb.append(c.getName()).append(" - destroy 1 creature with lowest power.");
ability.setStackDescription(sb.toString());
Singletons.getModel().getGame().getStack().addSimultaneousStackEntry(ability);
game.getStack().addSimultaneousStackEntry(ability);
} // end for
} // upkeepDropOfHoney()
@@ -590,14 +595,14 @@ public class Upkeep extends Phase {
* upkeepDemonicHordes.
* </p>
*/
private static void upkeepDemonicHordes() {
private static void upkeepDemonicHordes(final GameState game) {
/*
* At the beginning of your upkeep, unless you pay BBB, tap Demonic
* Hordes and sacrifice a land of an opponent's choice.
*/
final Player player = Singletons.getModel().getGame().getPhaseHandler().getPlayerTurn();
final Player player = game.getPhaseHandler().getPlayerTurn();
final List<Card> cards = player.getCardsIn(ZoneType.Battlefield, "Demonic Hordes");
for (int i = 0; i < cards.size(); i++) {
@@ -625,7 +630,7 @@ public class Upkeep extends Phase {
} else {
target = CardFactoryUtil.getBestLandAI(playerLand);
}
Singletons.getModel().getGame().getAction().sacrifice(target, null);
game.getAction().sacrifice(target, null);
} // end resolve()
}; // end noPay ability
@@ -636,7 +641,7 @@ public class Upkeep extends Phase {
final Ability pay = new Ability(c, SpellManaCost.ZERO) {
@Override
public void resolve() {
if (Singletons.getModel().getGame().getZoneOf(c).is(ZoneType.Battlefield)) {
if (game.getZoneOf(c).is(ZoneType.Battlefield)) {
final StringBuilder coststring = new StringBuilder();
coststring.append("Pay cost for ").append(c).append("\r\n");
GameActionUtil.payManaDuringAbilityResolve(coststring.toString(), cost.getManaCost(),
@@ -647,7 +652,7 @@ public class Upkeep extends Phase {
pay.setStackDescription("Demonic Hordes - Upkeep Cost");
pay.setDescription("Demonic Hordes - Upkeep Cost");
Singletons.getModel().getGame().getStack().addSimultaneousStackEntry(pay);
game.getStack().addSimultaneousStackEntry(pay);
} // end choice
else {
@@ -655,7 +660,7 @@ public class Upkeep extends Phase {
sb.append(c.getName()).append(" - is tapped and you must sacrifice a land of opponent's choice");
noPay.setStackDescription(sb.toString());
Singletons.getModel().getGame().getStack().addSimultaneousStackEntry(noPay);
game.getStack().addSimultaneousStackEntry(noPay);
}
} // end human
@@ -670,10 +675,10 @@ public class Upkeep extends Phase {
};
computerPay.setStackDescription("Computer pays Demonic Hordes upkeep cost");
Singletons.getModel().getGame().getStack().addSimultaneousStackEntry(computerPay);
game.getStack().addSimultaneousStackEntry(computerPay);
} else {
noPay.setStackDescription("Demonic Hordes - Upkeep Cost");
Singletons.getModel().getGame().getStack().addSimultaneousStackEntry(noPay);
game.getStack().addSimultaneousStackEntry(noPay);
}
} // end computer
@@ -687,8 +692,8 @@ public class Upkeep extends Phase {
* upkeepSuspend.
* </p>
*/
private static void upkeepSuspend() {
final Player player = Singletons.getModel().getGame().getPhaseHandler().getPlayerTurn();
private static void upkeepSuspend(final GameState game) {
final Player player = game.getPhaseHandler().getPlayerTurn();
List<Card> list = player.getCardsIn(ZoneType.Exile);
@@ -716,9 +721,9 @@ public class Upkeep extends Phase {
* upkeepVanishing.
* </p>
*/
private static void upkeepVanishing() {
private static void upkeepVanishing(final GameState game) {
final Player player = Singletons.getModel().getGame().getPhaseHandler().getPlayerTurn();
final Player player = game.getPhaseHandler().getPlayerTurn();
List<Card> list = player.getCardsIn(ZoneType.Battlefield);
list = CardLists.filter(list, new Predicate<Card>() {
@Override
@@ -743,7 +748,7 @@ public class Upkeep extends Phase {
ability.setDescription(sb.toString());
ability.setActivatingPlayer(card.getController());
Singletons.getModel().getGame().getStack().addSimultaneousStackEntry(ability);
game.getStack().addSimultaneousStackEntry(ability);
}
}
@@ -754,9 +759,9 @@ public class Upkeep extends Phase {
* upkeepFading.
* </p>
*/
private static void upkeepFading() {
private static void upkeepFading(final GameState game) {
final Player player = Singletons.getModel().getGame().getPhaseHandler().getPlayerTurn();
final Player player = game.getPhaseHandler().getPlayerTurn();
List<Card> list = player.getCardsIn(ZoneType.Battlefield);
list = CardLists.filter(list, new Predicate<Card>() {
@Override
@@ -772,7 +777,7 @@ public class Upkeep extends Phase {
public void resolve() {
final int fadeCounters = card.getCounters(CounterType.FADE);
if (fadeCounters <= 0) {
Singletons.getModel().getGame().getAction().sacrifice(card, null);
game.getAction().sacrifice(card, null);
} else {
card.subtractCounter(CounterType.FADE, 1);
}
@@ -786,7 +791,7 @@ public class Upkeep extends Phase {
ability.setDescription(sb.toString());
ability.setActivatingPlayer(card.getController());
Singletons.getModel().getGame().getStack().addSimultaneousStackEntry(ability);
game.getStack().addSimultaneousStackEntry(ability);
}
}
@@ -797,14 +802,14 @@ public class Upkeep extends Phase {
* upkeepOathOfDruids.
* </p>
*/
private static void upkeepOathOfDruids() {
final List<Card> oathList = CardLists.filter(Singletons.getModel().getGame()
private static void upkeepOathOfDruids(final GameState game) {
final List<Card> oathList = CardLists.filter(game
.getCardsIn(ZoneType.Battlefield), CardPredicates.nameEquals("Oath of Druids"));
if (oathList.isEmpty()) {
return;
}
final Player player = Singletons.getModel().getGame().getPhaseHandler().getPlayerTurn();
final Player player = game.getPhaseHandler().getPlayerTurn();
if (GameState.compareTypeAmountInPlay(player, "Creature") < 0) {
for (int i = 0; i < oathList.size(); i++) {
@@ -845,10 +850,10 @@ public class Upkeep extends Phase {
for (final Card c : libraryList) {
cardsToReveal.add(c);
if (c.isCreature()) {
Singletons.getModel().getGame().getAction().moveTo(battlefield, c);
game.getAction().moveTo(battlefield, c);
break;
} else {
Singletons.getModel().getGame().getAction().moveToGraveyard(c);
game.getAction().moveToGraveyard(c);
}
} // for loop
if (cardsToReveal.size() > 0) {
@@ -869,7 +874,7 @@ public class Upkeep extends Phase {
ability.setDescription(sb.toString());
ability.setActivatingPlayer(oath.getController());
Singletons.getModel().getGame().getStack().addSimultaneousStackEntry(ability);
game.getStack().addSimultaneousStackEntry(ability);
}
}
} // upkeepOathOfDruids()
@@ -879,13 +884,13 @@ public class Upkeep extends Phase {
* upkeepOathOfGhouls.
* </p>
*/
private static void upkeepOathOfGhouls() {
final List<Card> oathList = CardLists.filter(Singletons.getModel().getGame().getCardsIn(ZoneType.Battlefield), CardPredicates.nameEquals("Oath of Ghouls"));
private static void upkeepOathOfGhouls(final GameState game) {
final List<Card> oathList = CardLists.filter(game.getCardsIn(ZoneType.Battlefield), CardPredicates.nameEquals("Oath of Ghouls"));
if (oathList.isEmpty()) {
return;
}
final Player player = Singletons.getModel().getGame().getPhaseHandler().getPlayerTurn();
final Player player = game.getPhaseHandler().getPlayerTurn();
if (GameState.compareTypeAmountInGraveyard(player, "Creature") > 0) {
for (int i = 0; i < oathList.size(); i++) {
@@ -901,12 +906,12 @@ public class Upkeep extends Phase {
if (o != null) {
final Card card = o;
Singletons.getModel().getGame().getAction().moveToHand(card);
game.getAction().moveToHand(card);
}
} else if (player.isComputer()) {
final Card card = graveyardCreatures.get(0);
Singletons.getModel().getGame().getAction().moveToHand(card);
game.getAction().moveToHand(card);
}
}
}
@@ -919,7 +924,7 @@ public class Upkeep extends Phase {
ability.setDescription(sb.toString());
ability.setActivatingPlayer(oathList.get(0).getController());
Singletons.getModel().getGame().getStack().addSimultaneousStackEntry(ability);
game.getStack().addSimultaneousStackEntry(ability);
}
}
@@ -930,10 +935,10 @@ public class Upkeep extends Phase {
* upkeepKarma.
* </p>
*/
private static void upkeepKarma() {
final Player player = Singletons.getModel().getGame().getPhaseHandler().getPlayerTurn();
private static void upkeepKarma(final GameState game) {
final Player player = game.getPhaseHandler().getPlayerTurn();
final List<Card> karmas =
CardLists.filter(Singletons.getModel().getGame().getCardsIn(ZoneType.Battlefield), CardPredicates.nameEquals("Karma"));
CardLists.filter(game.getCardsIn(ZoneType.Battlefield), CardPredicates.nameEquals("Karma"));
final List<Card> swamps = CardLists.getType(player.getCardsIn(ZoneType.Battlefield), "Swamp");
// determine how much damage to deal the current player
@@ -959,7 +964,7 @@ public class Upkeep extends Phase {
ability.setDescription(sb.toString());
ability.setActivatingPlayer(karma.getController());
Singletons.getModel().getGame().getStack().addSimultaneousStackEntry(ability);
game.getStack().addSimultaneousStackEntry(ability);
}
}
} // if
@@ -970,14 +975,14 @@ public class Upkeep extends Phase {
* upkeepPowerSurge.
* </p>
*/
private static void upkeepPowerSurge() {
private static void upkeepPowerSurge(final GameState game) {
/*
* At the beginning of each player's upkeep, Power Surge deals X damage
* to that player, where X is the number of untapped lands he or she
* controlled at the beginning of this turn.
*/
final Player player = Singletons.getModel().getGame().getPhaseHandler().getPlayerTurn();
final List<Card> list = CardLists.filter(Singletons.getModel().getGame().getCardsIn(ZoneType.Battlefield), CardPredicates.nameEquals("Power Surge"));
final Player player = game.getPhaseHandler().getPlayerTurn();
final List<Card> list = CardLists.filter(game.getCardsIn(ZoneType.Battlefield), CardPredicates.nameEquals("Power Surge"));
final int damage = player.getNumPowerSurgeLands();
for (final Card surge : list) {
@@ -995,7 +1000,7 @@ public class Upkeep extends Phase {
ability.setDescription(sb.toString());
if (damage > 0) {
Singletons.getModel().getGame().getStack().addSimultaneousStackEntry(ability);
game.getStack().addSimultaneousStackEntry(ability);
}
} // for
} // upkeepPowerSurge()
@@ -1005,9 +1010,9 @@ public class Upkeep extends Phase {
* upkeepTangleWire.
* </p>
*/
private static void upkeepTangleWire() {
final Player player = Singletons.getModel().getGame().getPhaseHandler().getPlayerTurn();
final List<Card> wires = CardLists.filter(Singletons.getModel().getGame().getCardsIn(ZoneType.Battlefield), CardPredicates.nameEquals("Tangle Wire"));
private static void upkeepTangleWire(final GameState game) {
final Player player = game.getPhaseHandler().getPlayerTurn();
final List<Card> wires = CardLists.filter(game.getCardsIn(ZoneType.Battlefield), CardPredicates.nameEquals("Tangle Wire"));
for (final Card source : wires) {
final SpellAbility ability = new Ability(source, SpellManaCost.ZERO) {
@@ -1064,7 +1069,7 @@ public class Upkeep extends Phase {
@Override
public void selectCard(final Card card) {
Zone zone = Singletons.getModel().getGame().getZoneOf(card);
Zone zone = game.getZoneOf(card);
if (zone.is(ZoneType.Battlefield, player) && list.contains(card)) {
card.tap();
list.remove(card);
@@ -1081,7 +1086,7 @@ public class Upkeep extends Phase {
ability.setDescription(source.getName() + " - " + player
+ " taps X artifacts, creatures or lands he or she controls.");
Singletons.getModel().getGame().getStack().addSimultaneousStackEntry(ability);
game.getStack().addSimultaneousStackEntry(ability);
} // foreach(wire)
} // upkeepTangleWire()
@@ -1091,8 +1096,8 @@ public class Upkeep extends Phase {
* upkeepBlazeCounters.
* </p>
*/
private static void upkeepBlazeCounters() {
final Player player = Singletons.getModel().getGame().getPhaseHandler().getPlayerTurn();
private static void upkeepBlazeCounters(final GameState game) {
final Player player = game.getPhaseHandler().getPlayerTurn();
List<Card> blaze = player.getCardsIn(ZoneType.Battlefield);
blaze = CardLists.filter(blaze, new Predicate<Card>() {
@@ -1116,7 +1121,7 @@ public class Upkeep extends Phase {
sb.append(player).append(".");
ability.setStackDescription(sb.toString());
Singletons.getModel().getGame().getStack().addSimultaneousStackEntry(ability);
game.getStack().addSimultaneousStackEntry(ability);
}
}
@@ -1126,8 +1131,8 @@ public class Upkeep extends Phase {
* upkeepCurseOfMisfortunes.
* </p>
*/
private static void upkeepCurseOfMisfortunes() {
final Player player = Singletons.getModel().getGame().getPhaseHandler().getPlayerTurn();
private static void upkeepCurseOfMisfortunes(final GameState game) {
final Player player = game.getPhaseHandler().getPlayerTurn();
final List<Card> misfortunes = player.getCardsIn(ZoneType.Battlefield, "Curse of Misfortunes");
@@ -1163,8 +1168,8 @@ public class Upkeep extends Phase {
enchantment = CardFactoryUtil.getBestEnchantmentAI(enchantmentsInLibrary, this, false);
}
if (enchantment != null) {
Singletons.getModel().getGame().getAction().changeZone(
Singletons.getModel().getGame().getZoneOf(enchantment),
game.getAction().changeZone(
game.getZoneOf(enchantment),
enchantment.getOwner().getZone(ZoneType.Battlefield), enchantment, null);
enchantment.enchantEntity(source.getEnchantingPlayer());
}
@@ -1178,7 +1183,7 @@ public class Upkeep extends Phase {
+ " the same name as a Curse attached to enchanted player, "
+ "put it onto the battlefield attached to that player, then shuffle you library.");
ability.setStackDescription(sb.toString());
Singletons.getModel().getGame().getStack().addSimultaneousStackEntry(ability);
game.getStack().addSimultaneousStackEntry(ability);
}
} // upkeepCurseOfMisfortunes

View File

@@ -81,7 +81,7 @@ public class ComputerAIGeneral implements Computer {
private void playSpellAbilitiesStackEmpty() {
final List<Card> list = getAvailableCards();
final boolean nextPhase = ComputerUtil.playSpellAbilities(player, getSpellAbilities(list));
final boolean nextPhase = ComputerUtil.playSpellAbilities(player, getSpellAbilities(list), game);
if (nextPhase) {
game.getPhaseHandler().passPriority();
@@ -360,7 +360,7 @@ public class ComputerAIGeneral implements Computer {
possibleCounters.clear();
possibleCounters = this.getPossibleETBCounters();
if ((possibleCounters.size() > 0) && !ComputerUtil.playSpellAbilities(player, possibleCounters)) {
if ((possibleCounters.size() > 0) && !ComputerUtil.playSpellAbilities(player, possibleCounters, game)) {
// Responding Permanent w/ ETB Counter is on the Stack
// If playSpellAbilities returns false, a Spell is hitting the Stack
return;
@@ -368,7 +368,7 @@ public class ComputerAIGeneral implements Computer {
final ArrayList<SpellAbility> sas = this.getSpellAbilities(cards);
if (sas.size() > 0) {
// Spell not Countered
if (!ComputerUtil.playSpellAbilities(player, sas)) {
if (!ComputerUtil.playSpellAbilities(player, sas, game)) {
return;
}
}

View File

@@ -59,6 +59,7 @@ import forge.card.spellability.SpellAbility;
import forge.card.spellability.Target;
import forge.control.input.InputPayManaCostUtil;
import forge.error.ErrorViewer;
import forge.game.GameState;
import forge.game.phase.Combat;
import forge.game.phase.CombatUtil;
import forge.game.phase.PhaseHandler;
@@ -90,7 +91,7 @@ public class ComputerUtil {
* objects.
* @return a boolean.
*/
public static boolean playSpellAbilities(final Player ai, final List<SpellAbility> all) {
public static boolean playSpellAbilities(final Player ai, final List<SpellAbility> all, final GameState game) {
// not sure "playing biggest spell" matters?
ComputerUtil.sortSpellAbilityByCost(all);
ArrayList<SpellAbility> abilities = new ArrayList<SpellAbility>();
@@ -113,7 +114,7 @@ public class ComputerUtil {
}
sa.setActivatingPlayer(ai);
if (ComputerUtil.canBePlayedAndPayedByAI(ai, sa) && ComputerUtil.handlePlayingSpellAbility(ai, sa)) {
if (ComputerUtil.canBePlayedAndPayedByAI(ai, sa) && ComputerUtil.handlePlayingSpellAbility(ai, sa, game)) {
return false;
}
}
@@ -129,26 +130,26 @@ public class ComputerUtil {
* a {@link forge.card.spellability.SpellAbility} object.
* @return a boolean.
*/
public static boolean handlePlayingSpellAbility(final Player ai, final SpellAbility sa) {
public static boolean handlePlayingSpellAbility(final Player ai, final SpellAbility sa, final GameState game) {
if (sa instanceof AbilityStatic) {
final Cost cost = sa.getPayCosts();
if (cost == null && ComputerUtil.payManaCost(sa, ai, false, 0, true)) {
sa.resolve();
} else {
final CostPayment pay = new CostPayment(cost, sa);
if (pay.payComputerCosts(ai)) {
final CostPayment pay = new CostPayment(cost, sa, game);
if (pay.payComputerCosts(ai, game)) {
sa.resolve();
}
}
return false;
}
Singletons.getModel().getGame().getStack().freezeStack();
game.getStack().freezeStack();
final Card source = sa.getSourceCard();
if (sa.isSpell() && !source.isCopiedSpell()) {
sa.setSourceCard(Singletons.getModel().getGame().getAction().moveToStack(source));
sa.setSourceCard(game.getAction().moveToStack(source));
}
if (sa.getApi() == ApiType.Charm && !sa.isWrapper()) {
@@ -160,12 +161,12 @@ public class ComputerUtil {
if (cost == null) {
ComputerUtil.payManaCost(ai, sa);
sa.getBeforePayManaAI().execute();
Singletons.getModel().getGame().getStack().addAndUnfreeze(sa);
game.getStack().addAndUnfreeze(sa);
return true;
} else {
final CostPayment pay = new CostPayment(cost, sa);
if (pay.payComputerCosts(ai)) {
Singletons.getModel().getGame().getStack().addAndUnfreeze(sa);
final CostPayment pay = new CostPayment(cost, sa, game);
if (pay.payComputerCosts(ai, game)) {
game.getStack().addAndUnfreeze(sa);
if (sa.getSplicedCards() != null && !sa.getSplicedCards().isEmpty()) {
GuiChoose.oneOrNone("Computer reveals spliced cards:", sa.getSplicedCards());
}
@@ -259,6 +260,7 @@ public class ComputerUtil {
* @return a boolean.
*/
public static boolean playCounterSpell(final Player ai, final ArrayList<SpellAbility> possibleCounters) {
final GameState game = Singletons.getModel().getGame();
SpellAbility bestSA = null;
int bestRestriction = Integer.MIN_VALUE;
final ArrayList<SpellAbility> newAbilities = new ArrayList<SpellAbility>();
@@ -301,11 +303,11 @@ public class ComputerUtil {
// TODO - "Look" at Targeted SA and "calculate" the threshold
// if (bestRestriction < targetedThreshold) return false;
Singletons.getModel().getGame().getStack().freezeStack();
game.getStack().freezeStack();
final Card source = bestSA.getSourceCard();
if (bestSA.isSpell() && !source.isCopiedSpell()) {
bestSA.setSourceCard(Singletons.getModel().getGame().getAction().moveToStack(source));
bestSA.setSourceCard(game.getAction().moveToStack(source));
}
final Cost cost = bestSA.getPayCosts();
@@ -314,11 +316,11 @@ public class ComputerUtil {
// Honestly Counterspells shouldn't use this branch
ComputerUtil.payManaCost(ai, bestSA);
bestSA.getBeforePayManaAI().execute();
Singletons.getModel().getGame().getStack().addAndUnfreeze(bestSA);
game.getStack().addAndUnfreeze(bestSA);
} else {
final CostPayment pay = new CostPayment(cost, bestSA);
if (pay.payComputerCosts(ai)) {
Singletons.getModel().getGame().getStack().addAndUnfreeze(bestSA);
final CostPayment pay = new CostPayment(cost, bestSA, game);
if (pay.payComputerCosts(ai, game)) {
game.getStack().addAndUnfreeze(bestSA);
}
}
@@ -334,21 +336,21 @@ public class ComputerUtil {
* @param sa
* a {@link forge.card.spellability.SpellAbility} object.
*/
public static final void playStack(final SpellAbility sa, final Player ai) {
public static final void playStack(final SpellAbility sa, final Player ai, final GameState game) {
sa.setActivatingPlayer(ai);
if (ComputerUtil.canPayCost(sa, ai)) {
final Card source = sa.getSourceCard();
if (sa.isSpell() && !source.isCopiedSpell()) {
sa.setSourceCard(Singletons.getModel().getGame().getAction().moveToStack(source));
sa.setSourceCard(game.getAction().moveToStack(source));
}
final Cost cost = sa.getPayCosts();
if (cost == null) {
ComputerUtil.payManaCost(ai, sa);
Singletons.getModel().getGame().getStack().add(sa);
game.getStack().add(sa);
} else {
final CostPayment pay = new CostPayment(cost, sa);
if (pay.payComputerCosts(ai)) {
Singletons.getModel().getGame().getStack().add(sa);
final CostPayment pay = new CostPayment(cost, sa, game);
if (pay.payComputerCosts(ai, game)) {
game.getStack().add(sa);
}
}
}
@@ -381,7 +383,7 @@ public class ComputerUtil {
* @param sa
* a {@link forge.card.spellability.SpellAbility} object.
*/
public static final void playSpellAbilityWithoutPayingManaCost(final Player ai, final SpellAbility sa) {
public static final void playSpellAbilityWithoutPayingManaCost(final Player ai, final SpellAbility sa, final GameState game) {
final SpellAbility newSA = sa.copy();
final Cost cost = new Cost(sa.getSourceCard(), "", false);
if (newSA.getPayCosts() != null) {
@@ -398,19 +400,19 @@ public class ComputerUtil {
newSA.setDescription(sb.toString());
newSA.setActivatingPlayer(ai);
if (!ComputerUtil.canPayAdditionalCosts(newSA, ai)) {
if (!ComputerUtil.canPayAdditionalCosts(newSA, ai, game)) {
return;
}
final Card source = newSA.getSourceCard();
if (newSA.isSpell() && !source.isCopiedSpell()) {
newSA.setSourceCard(Singletons.getModel().getGame().getAction().moveToStack(source));
newSA.setSourceCard(game.getAction().moveToStack(source));
}
final CostPayment pay = new CostPayment(cost, newSA);
pay.payComputerCosts(ai);
final CostPayment pay = new CostPayment(cost, newSA, game);
pay.payComputerCosts(ai, game);
Singletons.getModel().getGame().getStack().add(newSA);
game.getStack().add(newSA);
}
/**
@@ -421,13 +423,12 @@ public class ComputerUtil {
* @param sa
* a {@link forge.card.spellability.SpellAbility} object.
*/
public static final void playNoStack(final Player ai, final SpellAbility sa) {
public static final void playNoStack(final Player ai, final SpellAbility sa, final GameState game) {
// TODO: We should really restrict what doesn't use the Stack
if (ComputerUtil.canPayCost(sa, ai)) {
final Card source = sa.getSourceCard();
if (sa.isSpell() && !source.isCopiedSpell()) {
sa.setSourceCard(Singletons.getModel().getGame().getAction().moveToStack(source));
sa.setSourceCard(game.getAction().moveToStack(source));
}
sa.setActivatingPlayer(ai);
@@ -436,14 +437,14 @@ public class ComputerUtil {
if (cost == null) {
ComputerUtil.payManaCost(ai, sa);
} else {
final CostPayment pay = new CostPayment(cost, sa);
pay.payComputerCosts(ai);
final CostPayment pay = new CostPayment(cost, sa, game);
pay.payComputerCosts(ai, game);
}
AbilityFactory.resolve(sa, false);
// destroys creatures if they have lethal damage, etc..
Singletons.getModel().getGame().getAction().checkStateEffects();
game.getAction().checkStateEffects();
}
} // play()
@@ -504,6 +505,7 @@ public class ComputerUtil {
*/
public static boolean canPayCost(final SpellAbility sa, final Player player) {
final GameState game = Singletons.getModel().getGame();
// Check for stuff like Nether Void
int extraManaNeeded = 0;
if (sa instanceof Spell && player.isComputer()) {
@@ -525,7 +527,7 @@ public class ComputerUtil {
return false;
}
return ComputerUtil.canPayAdditionalCosts(sa, player);
return ComputerUtil.canPayAdditionalCosts(sa, player, game);
} // canPayCost()
/**
@@ -565,7 +567,7 @@ public class ComputerUtil {
* a {@link forge.game.player.Player} object.
* @return a boolean.
*/
public static boolean canPayAdditionalCosts(final SpellAbility sa, final Player player) {
public static boolean canPayAdditionalCosts(final SpellAbility sa, final Player player, final GameState game) {
if (sa.getActivatingPlayer() == null) {
final StringBuilder sb = new StringBuilder();
sb.append(sa.getSourceCard());
@@ -573,7 +575,7 @@ public class ComputerUtil {
System.out.println(sb.toString());
sa.setActivatingPlayer(player);
}
return CostPayment.canPayAdditionalCosts(sa.getPayCosts(), sa);
return CostPayment.canPayAdditionalCosts(game, sa.getPayCosts(), sa);
}
/**
@@ -610,6 +612,7 @@ public class ComputerUtil {
final int extraMana, boolean checkPlayable) {
ManaCostBeingPaid cost = calculateManaCost(sa, test, extraMana);
final GameState game = Singletons.getModel().getGame();
final ManaPool manapool = ai.getManaPool();
cost = manapool.payManaFromPool(sa, cost);
@@ -659,7 +662,7 @@ public class ComputerUtil {
ma.setActivatingPlayer(ai);
// if the AI can't pay the additional costs skip the mana ability
if (ma.getPayCosts() != null && checkPlayable) {
if (!ComputerUtil.canPayAdditionalCosts(ma, ai)) {
if (!ComputerUtil.canPayAdditionalCosts(ma, ai, game)) {
continue;
}
} else if (sourceCard.isTapped() && checkPlayable) {
@@ -729,8 +732,8 @@ public class ComputerUtil {
if (!test) {
// Pay additional costs
if (ma.getPayCosts() != null) {
final CostPayment pay = new CostPayment(ma.getPayCosts(), ma);
if (!pay.payComputerCosts(ai)) {
final CostPayment pay = new CostPayment(ma.getPayCosts(), ma, game);
if (!pay.payComputerCosts(ai, game)) {
continue;
}
} else {
@@ -991,6 +994,7 @@ public class ComputerUtil {
* @return a {@link forge.CardList} object.
*/
public static List<Card> getAvailableMana(final Player ai, final boolean checkPlayable) {
final GameState game = Singletons.getModel().getGame();
final List<Card> list = ai.getCardsIn(ZoneType.Battlefield);
final List<Card> manaSources = CardLists.filter(list, new Predicate<Card>() {
@Override
@@ -1054,7 +1058,7 @@ public class ComputerUtil {
// ability
m.setActivatingPlayer(ai);
if (cost != null) {
if (!ComputerUtil.canPayAdditionalCosts(m, ai)) {
if (!ComputerUtil.canPayAdditionalCosts(m, ai, game)) {
continue;
}
}

View File

@@ -519,7 +519,7 @@ public class MagicStack extends MyObservable {
final int neededDamage = CardFactoryUtil.getNeededXDamage(sa);
while (ComputerUtil.canPayCost(ability, player) && (neededDamage != sa.getSourceCard().getXManaCostPaid())) {
ComputerUtil.playNoStack(player, ability);
ComputerUtil.playNoStack(player, ability, game);
}
this.push(sa);
}
@@ -620,7 +620,7 @@ public class MagicStack extends MyObservable {
// computer
while (ComputerUtil.canPayCost(ability, activating)) {
ComputerUtil.playNoStack(activating, ability);
ComputerUtil.playNoStack(activating, ability, game);
}
this.push(sa);
@@ -684,7 +684,7 @@ public class MagicStack extends MyObservable {
} else {
// computer
while (ComputerUtil.canPayCost(ability, controller)) {
ComputerUtil.playNoStack(controller, ability);
ComputerUtil.playNoStack(controller, ability, game);
}
this.push(sa);
@@ -1340,7 +1340,7 @@ public class MagicStack extends MyObservable {
if (activePlayer.isComputer()) {
for (final SpellAbility sa : activePlayerSAs) {
sa.doTrigger(sa.isMandatory());
ComputerUtil.playStack(sa, activePlayer);
ComputerUtil.playStack(sa, activePlayer, game);
}
} else {
// If only one, just add as necessary