From df946206bae42884be705c9ff6e897918ba14a44 Mon Sep 17 00:00:00 2001 From: Maxmtg Date: Sat, 20 Oct 2012 00:02:57 +0000 Subject: [PATCH] passes GameState to phaseHandler, moved player related static calls to player/Player.java --- .../card/cardfactory/CardFactoryUtil.java | 6 +- .../java/forge/card/spellability/Spell.java | 3 +- .../spellability/SpellAbilityCondition.java | 3 +- .../spellability/SpellAbilityRestriction.java | 3 +- .../card/spellability/SpellPermanent.java | 3 +- .../StaticAbilityCantBeCast.java | 3 +- .../card/trigger/TriggerSpellAbilityCast.java | 5 +- src/main/java/forge/game/GameState.java | 3 +- .../java/forge/game/phase/PhaseHandler.java | 129 +++++++----------- src/main/java/forge/game/player/Player.java | 48 ++++++- 10 files changed, 104 insertions(+), 102 deletions(-) diff --git a/src/main/java/forge/card/cardfactory/CardFactoryUtil.java b/src/main/java/forge/card/cardfactory/CardFactoryUtil.java index 4ff68ec5b22..c6d6279710b 100644 --- a/src/main/java/forge/card/cardfactory/CardFactoryUtil.java +++ b/src/main/java/forge/card/cardfactory/CardFactoryUtil.java @@ -863,7 +863,7 @@ public class CardFactoryUtil { //Lands do not have SpellPermanents. if (sourceCard.isLand()) { return (Singletons.getModel().getGame().getZoneOf(sourceCard).is(ZoneType.Hand) || sourceCard.hasKeyword("May be played")) - && PhaseHandler.canCastSorcery(sourceCard.getController()); + && Player.canCastSorcery(sourceCard.getController()); } else { return sourceCard.getSpellPermanent().canPlay(); @@ -1035,7 +1035,7 @@ public class CardFactoryUtil { @Override public boolean canPlay() { - return super.canPlay() && PhaseHandler.canCastSorcery(sourceCard.getController()); + return super.canPlay() && Player.canCastSorcery(sourceCard.getController()); } @Override @@ -1110,7 +1110,7 @@ public class CardFactoryUtil { return true; } - return PhaseHandler.canCastSorcery(sourceCard.getOwner()); + return Player.canCastSorcery(sourceCard.getOwner()); } @Override diff --git a/src/main/java/forge/card/spellability/Spell.java b/src/main/java/forge/card/spellability/Spell.java index a7e6a63bcac..9c47209d49d 100644 --- a/src/main/java/forge/card/spellability/Spell.java +++ b/src/main/java/forge/card/spellability/Spell.java @@ -29,7 +29,6 @@ import forge.card.cost.Cost; import forge.card.cost.CostPayment; import forge.card.staticability.StaticAbility; import forge.error.ErrorViewer; -import forge.game.phase.PhaseHandler; import forge.game.player.Player; import forge.game.zone.ZoneType; import forge.util.Expressions; @@ -102,7 +101,7 @@ public abstract class Spell extends SpellAbility implements java.io.Serializable activator = this.getSourceCard().getController(); } - if (!(card.isInstant() || PhaseHandler.canCastSorcery(activator) || card.hasKeyword("Flash") + if (!(card.isInstant() || Player.canCastSorcery(activator) || card.hasKeyword("Flash") || this.getRestrictions().isInstantSpeed() || activator.hasKeyword("You may cast nonland cards as though they had flash.") || card.hasStartOfKeyword("You may cast CARDNAME as though it had flash."))) { diff --git a/src/main/java/forge/card/spellability/SpellAbilityCondition.java b/src/main/java/forge/card/spellability/SpellAbilityCondition.java index 1dcfdcf1c50..6de7a2a3c08 100644 --- a/src/main/java/forge/card/spellability/SpellAbilityCondition.java +++ b/src/main/java/forge/card/spellability/SpellAbilityCondition.java @@ -27,7 +27,6 @@ import forge.CardLists; import forge.Singletons; import forge.card.abilityfactory.AbilityFactory; import forge.card.cardfactory.CardFactoryUtil; -import forge.game.phase.PhaseHandler; import forge.game.phase.PhaseType; import forge.game.player.Player; import forge.game.zone.ZoneType; @@ -194,7 +193,7 @@ public class SpellAbilityCondition extends SpellAbilityVariables { } } - if (this.isSorcerySpeed() && !PhaseHandler.canCastSorcery(activator)) { + if (this.isSorcerySpeed() && !Player.canCastSorcery(activator)) { return false; } diff --git a/src/main/java/forge/card/spellability/SpellAbilityRestriction.java b/src/main/java/forge/card/spellability/SpellAbilityRestriction.java index 9088734936a..3d0e1e8ecb1 100644 --- a/src/main/java/forge/card/spellability/SpellAbilityRestriction.java +++ b/src/main/java/forge/card/spellability/SpellAbilityRestriction.java @@ -27,7 +27,6 @@ import forge.CardLists; import forge.Singletons; import forge.card.abilityfactory.AbilityFactory; import forge.card.cardfactory.CardFactoryUtil; -import forge.game.phase.PhaseHandler; import forge.game.phase.PhaseType; import forge.game.player.Player; import forge.game.zone.Zone; @@ -294,7 +293,7 @@ public class SpellAbilityRestriction extends SpellAbilityVariables { System.out.println(c.getName() + " Did not have activator set in SpellAbilityRestriction.canPlay()"); } - if (this.isSorcerySpeed() && !PhaseHandler.canCastSorcery(activator)) { + if (this.isSorcerySpeed() && !Player.canCastSorcery(activator)) { return false; } diff --git a/src/main/java/forge/card/spellability/SpellPermanent.java b/src/main/java/forge/card/spellability/SpellPermanent.java index 87afc7ce775..7f400a5bdc0 100644 --- a/src/main/java/forge/card/spellability/SpellPermanent.java +++ b/src/main/java/forge/card/spellability/SpellPermanent.java @@ -39,7 +39,6 @@ import forge.card.replacement.ReplacementEffect; import forge.card.trigger.Trigger; import forge.card.trigger.TriggerType; import forge.control.input.Input; -import forge.game.phase.PhaseHandler; import forge.game.phase.PhaseType; import forge.game.player.ComputerAIGeneral; import forge.game.player.ComputerUtil; @@ -311,7 +310,7 @@ public class SpellPermanent extends Spell { // Prevent the computer from summoning Ball Lightning type creatures after attacking if (card.hasStartOfKeyword("You may cast CARDNAME as though it had flash. If") - && !PhaseHandler.couldCastSorcery(card.getController(), this)) { + && !Player.couldCastSorcery(card.getController(), this)) { return false; } diff --git a/src/main/java/forge/card/staticability/StaticAbilityCantBeCast.java b/src/main/java/forge/card/staticability/StaticAbilityCantBeCast.java index c01e4ecd400..d0cf36b7817 100644 --- a/src/main/java/forge/card/staticability/StaticAbilityCantBeCast.java +++ b/src/main/java/forge/card/staticability/StaticAbilityCantBeCast.java @@ -24,7 +24,6 @@ import forge.Card; import forge.Singletons; import forge.card.spellability.AbilityMana; import forge.card.spellability.SpellAbility; -import forge.game.phase.PhaseHandler; import forge.game.player.Player; import forge.game.zone.ZoneType; @@ -58,7 +57,7 @@ public class StaticAbilityCantBeCast { return false; } - if (params.containsKey("OnlySorcerySpeed") && (activator != null) && PhaseHandler.canCastSorcery(activator)) { + if (params.containsKey("OnlySorcerySpeed") && (activator != null) && Player.canCastSorcery(activator)) { return false; } diff --git a/src/main/java/forge/card/trigger/TriggerSpellAbilityCast.java b/src/main/java/forge/card/trigger/TriggerSpellAbilityCast.java index c4208b68f43..e3d9aecc669 100644 --- a/src/main/java/forge/card/trigger/TriggerSpellAbilityCast.java +++ b/src/main/java/forge/card/trigger/TriggerSpellAbilityCast.java @@ -25,7 +25,6 @@ import forge.Card; import forge.card.cost.Cost; import forge.card.spellability.SpellAbility; import forge.card.spellability.SpellAbilityStackInstance; -import forge.game.phase.PhaseHandler; import forge.game.player.Player; /** @@ -168,11 +167,11 @@ public class TriggerSpellAbilityCast extends Trigger { if (this.getMapParams().containsKey("SpellSpeed")) { if (this.getMapParams().get("SpellSpeed").equals("NotSorcerySpeed")) { boolean notSorcerySpeed = true; - if (PhaseHandler.couldCastSorcery(this.getHostCard().getController(), spellAbility)) { + if (Player.couldCastSorcery(this.getHostCard().getController(), spellAbility)) { notSorcerySpeed = false; } else if (this.getHostCard().hasKeyword("You may cast CARDNAME as though it had flash. If you cast it any time a " + "sorcery couldn't have been cast, the controller of the permanent it becomes sacrifices it at the beginning" - + " of the next cleanup step.") && !PhaseHandler.couldCastSorcery(this.getHostCard().getController(), spellAbility)) { + + " of the next cleanup step.") && !Player.couldCastSorcery(this.getHostCard().getController(), spellAbility)) { boolean instantmentCast = true; // for these cards the trigger must only fire if using their own ability to cast at instant speed if (this.getHostCard().hasKeyword("Flash") || this.getHostCard().hasKeyword("HIDDEN Flash") diff --git a/src/main/java/forge/game/GameState.java b/src/main/java/forge/game/GameState.java index 8e5429116a0..53ae02e7d63 100644 --- a/src/main/java/forge/game/GameState.java +++ b/src/main/java/forge/game/GameState.java @@ -56,7 +56,7 @@ public class GameState { private final EndOfCombat endOfCombat = new EndOfCombat(); private final Untap untap = new Untap(); private final Upkeep upkeep = new Upkeep(); - private PhaseHandler phaseHandler = new PhaseHandler(); + private final PhaseHandler phaseHandler; private final MagicStack stack; private final StaticEffects staticEffects = new StaticEffects(); private final TriggerHandler triggerHandler = new TriggerHandler(); @@ -85,6 +85,7 @@ public class GameState { roPlayers = Collections.unmodifiableList(players); action = new GameAction(this); stack = new MagicStack(this); + phaseHandler = new PhaseHandler(this); } /** diff --git a/src/main/java/forge/game/phase/PhaseHandler.java b/src/main/java/forge/game/phase/PhaseHandler.java index 164baf2a5ac..24f3d8ed0dd 100644 --- a/src/main/java/forge/game/phase/PhaseHandler.java +++ b/src/main/java/forge/game/phase/PhaseHandler.java @@ -28,8 +28,8 @@ import forge.CardLists; import forge.CardPredicates; import forge.GameActionUtil; import forge.Singletons; -import forge.card.spellability.SpellAbility; import forge.card.trigger.TriggerType; +import forge.game.GameState; import forge.game.player.Player; import forge.game.player.PlayerType; import forge.game.zone.ZoneType; @@ -83,6 +83,13 @@ public class PhaseHandler extends MyObservable implements java.io.Serializable { /** The need to next phase init. */ private int needToNextPhaseInit = 0; + private final GameState game; + + public PhaseHandler(final GameState game0) + { + game = game0; + } + /** *

* isPlayerTurn. @@ -176,8 +183,8 @@ public class PhaseHandler extends MyObservable implements java.io.Serializable { * a {@link forge.game.player.Player} object. */ public final void setPriority(final Player p) { - if (Singletons.getModel().getGame().getStack() != null) { - Singletons.getModel().getGame().getStack().chooseOrderOfSimultaneousStackEntryAll(); + if (game.getStack() != null) { + game.getStack().chooseOrderOfSimultaneousStackEntryAll(); } this.pFirstPriority = p; @@ -282,7 +289,7 @@ public class PhaseHandler extends MyObservable implements java.io.Serializable { final PhaseType phase = this.getPhase(); final Player turn = this.getPlayerTurn(); this.setSkipPhase(true); - Singletons.getModel().getGame().getAction().checkStateEffects(); + game.getAction().checkStateEffects(); if (this.isAutoPassedPhase(turn, phase)) { this.setAutoPass(false); @@ -344,14 +351,14 @@ public class PhaseHandler extends MyObservable implements java.io.Serializable { if (!this.inCombat()) { this.setNeedToNextPhase(true); } else { - Singletons.getModel().getGame().getCombat().verifyCreaturesInPlay(); + game.getCombat().verifyCreaturesInPlay(); // no first strikers, skip this step - if (!Singletons.getModel().getGame().getCombat().assignCombatDamage(true)) { + if (!game.getCombat().assignCombatDamage(true)) { this.setNeedToNextPhase(true); } else { Combat.dealAssignedDamage(); - Singletons.getModel().getGame().getAction().checkStateEffects(); + game.getAction().checkStateEffects(); CombatUtil.showCombat(); } } @@ -361,13 +368,13 @@ public class PhaseHandler extends MyObservable implements java.io.Serializable { if (!this.inCombat()) { this.setNeedToNextPhase(true); } else { - Singletons.getModel().getGame().getCombat().verifyCreaturesInPlay(); + game.getCombat().verifyCreaturesInPlay(); - if (!Singletons.getModel().getGame().getCombat().assignCombatDamage(false)) { + if (!game.getCombat().assignCombatDamage(false)) { this.setNeedToNextPhase(true); } else { Combat.dealAssignedDamage(); - Singletons.getModel().getGame().getAction().checkStateEffects(); + game.getAction().checkStateEffects(); CombatUtil.showCombat(); } } @@ -375,8 +382,8 @@ public class PhaseHandler extends MyObservable implements java.io.Serializable { case COMBAT_END: // End Combat always happens - Singletons.getModel().getGame().getEndOfCombat().executeUntil(); - Singletons.getModel().getGame().getEndOfCombat().executeAt(); + game.getEndOfCombat().executeUntil(); + game.getEndOfCombat().executeAt(); CombatUtil.showCombat(); //SDisplayUtil.showTab(EDocID.REPORT_STACK.getDoc()); break; @@ -387,12 +394,12 @@ public class PhaseHandler extends MyObservable implements java.io.Serializable { break; case END_OF_TURN: - Singletons.getModel().getGame().getEndOfTurn().executeAt(); + game.getEndOfTurn().executeAt(); break; case CLEANUP: // Reset Damage received map - final List list = Singletons.getModel().getGame().getCardsIn(ZoneType.Battlefield); + final List list = game.getCardsIn(ZoneType.Battlefield); for (final Card c : list) { c.resetPreventNextDamage(); c.resetReceivedDamageFromThisTurn(); @@ -409,9 +416,9 @@ public class PhaseHandler extends MyObservable implements java.io.Serializable { c.clearBlockedThisTurn(); } - Singletons.getModel().getGame().getEndOfTurn().executeUntil(); + game.getEndOfTurn().executeUntil(); - for (Player player : Singletons.getModel().getGame().getPlayers()) { + for (Player player : game.getPlayers()) { for (Card c : player.getCardsIn(ZoneType.Hand)) c.setDrawnThisTurn(false); @@ -423,7 +430,7 @@ public class PhaseHandler extends MyObservable implements java.io.Serializable { player.resetAttackersDeclaredThisTurn(); } this.getPlayerTurn().removeKeyword("Skip all combat phases of this turn."); - Singletons.getModel().getGame().getCleanup().executeUntilTurn(this.getNextTurn()); + game.getCleanup().executeUntilTurn(this.getNextTurn()); break; default: @@ -435,12 +442,12 @@ public class PhaseHandler extends MyObservable implements java.io.Serializable { final HashMap runParams = new HashMap(); runParams.put("Phase", phase.Name); runParams.put("Player", turn); - Singletons.getModel().getGame().getTriggerHandler().runTrigger(TriggerType.Phase, runParams); + game.getTriggerHandler().runTrigger(TriggerType.Phase, runParams); } // This line fixes Combat Damage triggers not going off when they should - Singletons.getModel().getGame().getStack().unfreezeStack(); + game.getStack().unfreezeStack(); // UNTAP if (phase != PhaseType.UNTAP) { @@ -467,13 +474,13 @@ public class PhaseHandler extends MyObservable implements java.io.Serializable { this.needToNextPhase = false; // If the Stack isn't empty why is nextPhase being called? - if (Singletons.getModel().getGame().getStack().size() != 0) { + if (game.getStack().size() != 0) { Log.debug("Phase.nextPhase() is called, but Stack isn't empty."); return; } this.bPhaseEffects = true; - if (!Singletons.getModel().getGame().isCardInPlay("Upwelling")) { - for (Player p : Singletons.getModel().getGame().getPlayers()) { + if (!game.isCardInPlay("Upwelling")) { + for (Player p : game.getPlayers()) { int burn = p.getManaPool().clearPool(); if (Singletons.getModel().getPreferences().getPrefBoolean(FPref.UI_MANABURN)) { p.loseLife(burn, null); @@ -482,7 +489,7 @@ public class PhaseHandler extends MyObservable implements java.io.Serializable { } if (this.getPhase() == PhaseType.COMBAT_DECLARE_ATTACKERS) { - Singletons.getModel().getGame().getStack().unfreezeStack(); + game.getStack().unfreezeStack(); this.nCombatsThisTurn++; } else if (this.getPhase() == PhaseType.UNTAP) { this.nCombatsThisTurn = 0; @@ -490,7 +497,7 @@ public class PhaseHandler extends MyObservable implements java.io.Serializable { if (this.getPhase() == PhaseType.COMBAT_END) { //SDisplayUtil.showTab(EDocID.REPORT_STACK.getDoc()); - Singletons.getModel().getGame().getCombat().reset(); + game.getCombat().reset(); this.resetAttackedThisCombat(this.getPlayerTurn()); this.bCombat = false; } @@ -503,7 +510,7 @@ public class PhaseHandler extends MyObservable implements java.io.Serializable { } if (this.is(PhaseType.COMBAT_DECLARE_BLOCKERS)) { - Singletons.getModel().getGame().getStack().unfreezeStack(); + game.getStack().unfreezeStack(); } if (this.is(PhaseType.COMBAT_END) && (this.extraCombats > 0)) { @@ -516,9 +523,9 @@ public class PhaseHandler extends MyObservable implements java.io.Serializable { this.bCombat = true; this.extraCombats--; - Singletons.getModel().getGame().getCombat().reset(); - Singletons.getModel().getGame().getCombat().setAttackingPlayer(player); - Singletons.getModel().getGame().getCombat().setDefendingPlayer(opp); + game.getCombat().reset(); + game.getCombat().setAttackingPlayer(player); + game.getCombat().setDefendingPlayer(opp); this.phaseIndex = PhaseType.COMBAT_DECLARE_ATTACKERS.Index; } else { if (!this.bRepeat) { // for when Cleanup needs to repeat itself @@ -529,13 +536,13 @@ public class PhaseHandler extends MyObservable implements java.io.Serializable { } } - Singletons.getModel().getGame().getGameLog().add("Phase", this.getPlayerTurn() + " " + this.getPhase().Name, 6); + game.getGameLog().add("Phase", this.getPlayerTurn() + " " + this.getPhase().Name, 6); // **** Anything BELOW Here is actually in the next phase. Maybe move // this to handleBeginPhase if (this.getPhase() == PhaseType.UNTAP) { this.turn++; - Singletons.getModel().getGame().getGameLog().add("Turn", "Turn " + this.turn + " (" + this.getPlayerTurn() + ")", 0); + game.getGameLog().add("Turn", "Turn " + this.turn + " (" + this.getPlayerTurn() + ")", 0); } PhaseUtil.visuallyActivatePhase(this.getPhase()); @@ -559,15 +566,15 @@ public class PhaseHandler extends MyObservable implements java.io.Serializable { */ private Player handleNextTurn() { - Singletons.getModel().getGame().getStack().setCardsCastLastTurn(); - Singletons.getModel().getGame().getStack().clearCardsCastThisTurn(); + game.getStack().setCardsCastLastTurn(); + game.getStack().clearCardsCastThisTurn(); - for (final Player p1 : Singletons.getModel().getGame().getPlayers()) { + for (final Player p1 : game.getPlayers()) { for (final ZoneType z : Player.ALL_ZONES) { p1.getZone(z).resetCardsAddedThisTurn(); } } - for( Player p : Singletons.getModel().getGame().getPlayers() ) + for( Player p : game.getPlayers() ) { p.resetProwl(); p.setLifeLostThisTurn(0); @@ -826,20 +833,20 @@ public class PhaseHandler extends MyObservable implements java.io.Serializable { // pass the priority to other player this.setPriorityPlayer(actingPlayer.getOpponent()); Singletons.getModel().getMatch().getInput().resetInput(); - Singletons.getModel().getGame().getStack().chooseOrderOfSimultaneousStackEntryAll(); + game.getStack().chooseOrderOfSimultaneousStackEntryAll(); } else { - if (Singletons.getModel().getGame().getStack().size() == 0) { + if (game.getStack().size() == 0) { // end phase this.needToNextPhase = true; this.pPlayerPriority = this.getPlayerTurn(); // this needs to be // set early // as we exit the phase } else { - if (!Singletons.getModel().getGame().getStack().hasSimultaneousStackEntries()) { - Singletons.getModel().getGame().getStack().resolveStack(); + if (!game.getStack().hasSimultaneousStackEntries()) { + game.getStack().resolveStack(); } } - Singletons.getModel().getGame().getStack().chooseOrderOfSimultaneousStackEntryAll(); + game.getStack().chooseOrderOfSimultaneousStackEntryAll(); } } @@ -910,50 +917,6 @@ public class PhaseHandler extends MyObservable implements java.io.Serializable { return false; } - /** - *

- * canCastSorcery. - *

- * - * @param player - * a {@link forge.game.player.Player} object. - * @return a boolean. - */ - public static boolean canCastSorcery(final Player player) { - PhaseHandler now = Singletons.getModel().getGame().getPhaseHandler(); - return now.isPlayerTurn(player) && now.getPhase().isMain() && Singletons.getModel().getGame().getStack().size() == 0; - } - - /** - *

- * couldCastSorcery. - * for conditions the stack must only have the sa being checked - *

- * - * @param player - * a {@link forge.game.player.Player} object. - * @param sa - * a {@link forge.game.player.SpellAbility} object. - * @return a boolean . - */ - public static boolean couldCastSorcery(final Player player, final SpellAbility sa) { - PhaseHandler now = Singletons.getModel().getGame().getPhaseHandler(); - final Card source = sa.getRootSpellAbility().getSourceCard(); - boolean onlyThis = true; - if (Singletons.getModel().getGame().getStack().size() != 0) { - for (final Card card : Singletons.getModel().getGame().getCardsIn(ZoneType.Stack)) { - if (card != source) { - onlyThis = false; - //System.out.println("StackCard: " + card + " vs SourceCard: " + source); - } - } - } - //System.out.println("now.isPlayerTurn(player) - " + now.isPlayerTurn(player)); - //System.out.println("now.getPhase().isMain() - " + now.getPhase().isMain()); - //System.out.println("onlyThis - " + onlyThis); - return now.isPlayerTurn(player) && now.getPhase().isMain() && onlyThis; - } - // this is a hack for the setup game state mode, do not use outside of // devSetupGameState code // as it avoids calling any of the phase effects that may be necessary in a diff --git a/src/main/java/forge/game/player/Player.java b/src/main/java/forge/game/player/Player.java index de4c2485a34..2d66a2d9d46 100644 --- a/src/main/java/forge/game/player/Player.java +++ b/src/main/java/forge/game/player/Player.java @@ -1824,7 +1824,7 @@ public abstract class Player extends GameEntity implements Comparable { if (Singletons.getModel().getPreferences().getPrefBoolean(FPref.DEV_UNLIMITED_LAND) && this.isHuman() && Preferences.DEV_MODE) { - return PhaseHandler.canCastSorcery(this); + return Player.canCastSorcery(this); } // CantBeCast static abilities @@ -1838,7 +1838,7 @@ public abstract class Player extends GameEntity implements Comparable { } } - return PhaseHandler.canCastSorcery(this) + return Player.canCastSorcery(this) && ((this.numLandsPlayed < this.maxLandsToPlay) || (this.getCardsIn(ZoneType.Battlefield, "Fastbond") .size() > 0)); } @@ -2779,5 +2779,49 @@ public abstract class Player extends GameEntity implements Comparable { // ... no worries about size = // 0 } + + /** + *

+ * canCastSorcery. + *

+ * + * @param player + * a {@link forge.game.player.Player} object. + * @return a boolean. + */ + public static boolean canCastSorcery(final Player player) { + PhaseHandler now = Singletons.getModel().getGame().getPhaseHandler(); + return now.isPlayerTurn(player) && now.getPhase().isMain() && Singletons.getModel().getGame().getStack().size() == 0; + } + + /** + *

+ * couldCastSorcery. + * for conditions the stack must only have the sa being checked + *

+ * + * @param player + * a {@link forge.game.player.Player} object. + * @param sa + * a {@link forge.game.player.SpellAbility} object. + * @return a boolean . + */ + public static boolean couldCastSorcery(final Player player, final SpellAbility sa) { + PhaseHandler now = Singletons.getModel().getGame().getPhaseHandler(); + final Card source = sa.getRootSpellAbility().getSourceCard(); + boolean onlyThis = true; + if (Singletons.getModel().getGame().getStack().size() != 0) { + for (final Card card : Singletons.getModel().getGame().getCardsIn(ZoneType.Stack)) { + if (card != source) { + onlyThis = false; + //System.out.println("StackCard: " + card + " vs SourceCard: " + source); + } + } + } + //System.out.println("now.isPlayerTurn(player) - " + now.isPlayerTurn(player)); + //System.out.println("now.getPhase().isMain() - " + now.getPhase().isMain()); + //System.out.println("onlyThis - " + onlyThis); + return now.isPlayerTurn(player) && now.getPhase().isMain() && onlyThis; + } }