From 0db4131009fa0ce66c707a86759cc9b061ee9382 Mon Sep 17 00:00:00 2001 From: Maxmtg Date: Sun, 2 Jun 2013 06:41:12 +0000 Subject: [PATCH] Deleted 2 steps that never existed in original game rules: COMBAT_DECLARE_ATTACKERS_INSTANT_ABILITY and COMBAT_DECLARE_BLOCKERS_INSTANT_ABILITY --- .../java/forge/card/ability/ai/AnimateAi.java | 2 +- .../java/forge/card/ability/ai/AttachAi.java | 2 +- .../card/ability/ai/BecomesBlockedAi.java | 2 +- .../forge/card/ability/ai/ChangeZoneAi.java | 4 +- .../forge/card/ability/ai/ChooseCardAi.java | 2 +- .../forge/card/ability/ai/ChooseSourceAi.java | 3 +- .../java/forge/card/ability/ai/CloneAi.java | 2 +- .../card/ability/ai/CountersPutAllAi.java | 2 +- .../card/ability/ai/DamagePreventAi.java | 6 +- .../card/ability/ai/DamagePreventAllAi.java | 2 +- .../java/forge/card/ability/ai/DebuffAi.java | 6 +- .../java/forge/card/ability/ai/EffectAi.java | 2 +- .../java/forge/card/ability/ai/FogAi.java | 2 +- .../java/forge/card/ability/ai/ProtectAi.java | 2 +- .../java/forge/card/ability/ai/PumpAi.java | 2 +- .../forge/card/ability/ai/PumpAiBase.java | 46 +++++++-------- .../java/forge/card/ability/ai/PumpAllAi.java | 10 ++-- .../forge/card/ability/ai/RegenerateAi.java | 8 +-- .../card/ability/ai/RegenerateAllAi.java | 2 +- .../java/forge/card/ability/ai/TokenAi.java | 4 +- .../forge/card/ability/ai/UnattachAllAi.java | 2 +- .../card/spellability/SpellPermanent.java | 2 +- .../forge/control/FControlGamePlayback.java | 4 +- src/main/java/forge/game/ai/AiController.java | 18 +++--- src/main/java/forge/game/ai/ComputerUtil.java | 2 +- .../java/forge/game/phase/PhaseHandler.java | 57 +++++++------------ src/main/java/forge/game/phase/PhaseType.java | 8 +-- .../forge/game/player/PlayerController.java | 3 + .../forge/game/player/PlayerControllerAi.java | 11 ++++ .../game/player/PlayerControllerHuman.java | 51 ++++++++--------- .../forge/gui/match/nonsingleton/VField.java | 2 - 31 files changed, 130 insertions(+), 141 deletions(-) diff --git a/src/main/java/forge/card/ability/ai/AnimateAi.java b/src/main/java/forge/card/ability/ai/AnimateAi.java index 58e332b7612..814b88b6053 100644 --- a/src/main/java/forge/card/ability/ai/AnimateAi.java +++ b/src/main/java/forge/card/ability/ai/AnimateAi.java @@ -60,7 +60,7 @@ public class AnimateAi extends SpellAbilityAi { // don't use instant speed animate abilities outside humans // Combat_Declare_Attackers_InstantAbility step - if ((!game.getPhaseHandler().is(PhaseType.COMBAT_DECLARE_ATTACKERS_INSTANT_ABILITY) + if ((!game.getPhaseHandler().is(PhaseType.COMBAT_DECLARE_ATTACKERS) || (game.getCombat().getAttackers().isEmpty())) && game.getPhaseHandler().isPlayerTurn(opponent)) { return false; diff --git a/src/main/java/forge/card/ability/ai/AttachAi.java b/src/main/java/forge/card/ability/ai/AttachAi.java index 6b87b26a79e..4d1d1ca31db 100644 --- a/src/main/java/forge/card/ability/ai/AttachAi.java +++ b/src/main/java/forge/card/ability/ai/AttachAi.java @@ -77,7 +77,7 @@ public class AttachAi extends SpellAbilityAi { source.setSVar("PayX", Integer.toString(xPay)); } - if (ai.getGame().getPhaseHandler().getPhase().isAfter(PhaseType.COMBAT_DECLARE_BLOCKERS_INSTANT_ABILITY) + if (ai.getGame().getPhaseHandler().getPhase().isAfter(PhaseType.COMBAT_DECLARE_BLOCKERS) && !"Curse".equals(sa.getParam("AILogic"))) { return false; } diff --git a/src/main/java/forge/card/ability/ai/BecomesBlockedAi.java b/src/main/java/forge/card/ability/ai/BecomesBlockedAi.java index b4bd54d56cf..9757a940277 100644 --- a/src/main/java/forge/card/ability/ai/BecomesBlockedAi.java +++ b/src/main/java/forge/card/ability/ai/BecomesBlockedAi.java @@ -22,7 +22,7 @@ public class BecomesBlockedAi extends SpellAbilityAi { final Target tgt = sa.getTarget(); final Game game = aiPlayer.getGame(); - if (!game.getPhaseHandler().is(PhaseType.COMBAT_DECLARE_BLOCKERS_INSTANT_ABILITY) + if (!game.getPhaseHandler().is(PhaseType.COMBAT_DECLARE_BLOCKERS) || !game.getPhaseHandler().getPlayerTurn().isOpponentOf(aiPlayer)) { return false; } diff --git a/src/main/java/forge/card/ability/ai/ChangeZoneAi.java b/src/main/java/forge/card/ability/ai/ChangeZoneAi.java index 91632e94307..7bb1f28d707 100644 --- a/src/main/java/forge/card/ability/ai/ChangeZoneAi.java +++ b/src/main/java/forge/card/ability/ai/ChangeZoneAi.java @@ -743,7 +743,7 @@ public class ChangeZoneAi extends SpellAbilityAi { } } // Save combatants - else if (ai.getGame().getPhaseHandler().is(PhaseType.COMBAT_DECLARE_BLOCKERS_INSTANT_ABILITY)) { + else if (ai.getGame().getPhaseHandler().is(PhaseType.COMBAT_DECLARE_BLOCKERS)) { final List combatants = CardLists.filter(aiPermanents, CardPredicates.Presets.CREATURES); CardLists.sortByEvaluateCreature(combatants); @@ -799,7 +799,7 @@ public class ChangeZoneAi extends SpellAbilityAi { if (origin.equals(ZoneType.Battlefield) && destination.equals(ZoneType.Exile) && (subApi == ApiType.DelayedTrigger || (subApi == ApiType.ChangeZone && subAffected.equals("Remembered"))) - && !(ai.getGame().getPhaseHandler().is(PhaseType.COMBAT_DECLARE_ATTACKERS_INSTANT_ABILITY) || sa + && !(ai.getGame().getPhaseHandler().is(PhaseType.COMBAT_DECLARE_ATTACKERS) || sa .isAbility())) { return false; } diff --git a/src/main/java/forge/card/ability/ai/ChooseCardAi.java b/src/main/java/forge/card/ability/ai/ChooseCardAi.java index 7144ad273f7..1de212d6e02 100644 --- a/src/main/java/forge/card/ability/ai/ChooseCardAi.java +++ b/src/main/java/forge/card/ability/ai/ChooseCardAi.java @@ -62,7 +62,7 @@ public class ChooseCardAi extends SpellAbilityAi { } else if (sa.getParam("AILogic").equals("Never")) { return false; } else if (sa.getParam("AILogic").equals("NeedsPrevention")) { - if (!game.getPhaseHandler().getPhase() .equals(PhaseType.COMBAT_DECLARE_BLOCKERS_INSTANT_ABILITY)) { + if (!game.getPhaseHandler().getPhase() .equals(PhaseType.COMBAT_DECLARE_BLOCKERS)) { return false; } choices = CardLists.filter(choices, new Predicate() { diff --git a/src/main/java/forge/card/ability/ai/ChooseSourceAi.java b/src/main/java/forge/card/ability/ai/ChooseSourceAi.java index 51181bf2171..148b84ac7fe 100644 --- a/src/main/java/forge/card/ability/ai/ChooseSourceAi.java +++ b/src/main/java/forge/card/ability/ai/ChooseSourceAi.java @@ -99,8 +99,7 @@ public class ChooseSourceAi extends SpellAbilityAi { } return true; } - if (!game.getPhaseHandler().getPhase() - .equals(PhaseType.COMBAT_DECLARE_BLOCKERS_INSTANT_ABILITY)) { + if (game.getPhaseHandler().getPhase() != PhaseType.COMBAT_DECLARE_BLOCKERS) { return false; } List choices = game.getCardsIn(ZoneType.Battlefield); diff --git a/src/main/java/forge/card/ability/ai/CloneAi.java b/src/main/java/forge/card/ability/ai/CloneAi.java index 5bf3b9d44f5..0bb52337d95 100644 --- a/src/main/java/forge/card/ability/ai/CloneAi.java +++ b/src/main/java/forge/card/ability/ai/CloneAi.java @@ -45,7 +45,7 @@ public class CloneAi extends SpellAbilityAi { // don't use instant speed clone abilities outside humans // Combat_Declare_Attackers_InstantAbility step - if ((!phase.is(PhaseType.COMBAT_DECLARE_ATTACKERS_INSTANT_ABILITY) + if ((!phase.is(PhaseType.COMBAT_DECLARE_ATTACKERS) || game.getCombat().getAttackers().isEmpty()) && !phase.isPlayerTurn(ai)) { return false; diff --git a/src/main/java/forge/card/ability/ai/CountersPutAllAi.java b/src/main/java/forge/card/ability/ai/CountersPutAllAi.java index b31df9bbae7..3fe9e66f4a8 100644 --- a/src/main/java/forge/card/ability/ai/CountersPutAllAi.java +++ b/src/main/java/forge/card/ability/ai/CountersPutAllAi.java @@ -108,7 +108,7 @@ public class CountersPutAllAi extends SpellAbilityAi { && sa.getPayCosts() != null && sa.getPayCosts().hasTapCost() && sa instanceof AbilitySub && (!phase.getNextTurn().equals(ai) - || phase.getPhase().isBefore(PhaseType.COMBAT_DECLARE_BLOCKERS_INSTANT_ABILITY))) { + || phase.getPhase().isBefore(PhaseType.COMBAT_DECLARE_BLOCKERS))) { boolean combatants = false; for (Card c : hList) { if (!c.equals(source) && c.isUntapped()) { diff --git a/src/main/java/forge/card/ability/ai/DamagePreventAi.java b/src/main/java/forge/card/ability/ai/DamagePreventAi.java index a4eae39779b..ac47a6a454a 100644 --- a/src/main/java/forge/card/ability/ai/DamagePreventAi.java +++ b/src/main/java/forge/card/ability/ai/DamagePreventAi.java @@ -65,7 +65,7 @@ public class DamagePreventAi extends SpellAbilityAi { } } else { PhaseHandler handler = game.getPhaseHandler(); - if (handler.is(PhaseType.COMBAT_DECLARE_BLOCKERS_INSTANT_ABILITY)) { + if (handler.is(PhaseType.COMBAT_DECLARE_BLOCKERS)) { boolean flag = false; for (final Object o : objects) { if (o instanceof Card) { @@ -119,7 +119,7 @@ public class DamagePreventAi extends SpellAbilityAi { } } // Protect combatants - else if (game.getPhaseHandler().is(PhaseType.COMBAT_DECLARE_BLOCKERS_INSTANT_ABILITY)) { + else if (game.getPhaseHandler().is(PhaseType.COMBAT_DECLARE_BLOCKERS)) { if (sa.canTarget(ai) && ComputerUtilCombat.wouldLoseLife(ai, game.getCombat()) && (ComputerUtilCombat.lifeInDanger(ai, game.getCombat()) || sa.isAbility()) && game.getPhaseHandler().isPlayerTurn(ai.getOpponent())) { @@ -198,7 +198,7 @@ public class DamagePreventAi extends SpellAbilityAi { if (compTargetables.size() > 0) { final List combatants = CardLists.filter(compTargetables, CardPredicates.Presets.CREATURES); CardLists.sortByEvaluateCreature(combatants); - if (game.getPhaseHandler().is(PhaseType.COMBAT_DECLARE_BLOCKERS_INSTANT_ABILITY)) { + if (game.getPhaseHandler().is(PhaseType.COMBAT_DECLARE_BLOCKERS)) { for (final Card c : combatants) { if (ComputerUtilCombat.combatantWouldBeDestroyed(ai, c)) { tgt.addTarget(c); diff --git a/src/main/java/forge/card/ability/ai/DamagePreventAllAi.java b/src/main/java/forge/card/ability/ai/DamagePreventAllAi.java index c32dbbbd4d5..e8a8ce58251 100644 --- a/src/main/java/forge/card/ability/ai/DamagePreventAllAi.java +++ b/src/main/java/forge/card/ability/ai/DamagePreventAllAi.java @@ -43,7 +43,7 @@ public class DamagePreventAllAi extends SpellAbilityAi { // control } // Protect combatants - else if (ai.getGame().getPhaseHandler().is(PhaseType.COMBAT_DECLARE_BLOCKERS_INSTANT_ABILITY)) { + else if (ai.getGame().getPhaseHandler().is(PhaseType.COMBAT_DECLARE_BLOCKERS)) { // TODO } diff --git a/src/main/java/forge/card/ability/ai/DebuffAi.java b/src/main/java/forge/card/ability/ai/DebuffAi.java index 8e87797b0f7..7f9c45f1c79 100644 --- a/src/main/java/forge/card/ability/ai/DebuffAi.java +++ b/src/main/java/forge/card/ability/ai/DebuffAi.java @@ -53,8 +53,8 @@ public class DebuffAi extends SpellAbilityAi { final PhaseHandler ph = ai.getGame().getPhaseHandler(); // Phase Restrictions - if (ph.getPhase().isBefore(PhaseType.COMBAT_DECLARE_ATTACKERS_INSTANT_ABILITY) - || ph.getPhase().isAfter(PhaseType.COMBAT_DECLARE_BLOCKERS_INSTANT_ABILITY) + if (ph.getPhase().isBefore(PhaseType.COMBAT_DECLARE_ATTACKERS) + || ph.getPhase().isAfter(PhaseType.COMBAT_DECLARE_BLOCKERS) || !ai.getGame().getStack().isEmpty()) { // Instant-speed pumps should not be cast outside of combat when the // stack is empty @@ -124,7 +124,7 @@ public class DebuffAi extends SpellAbilityAi { */ private boolean debuffTgtAI(final Player ai, final SpellAbility sa, final List kws, final boolean mandatory) { // this would be for evasive things like Flying, Unblockable, etc - if (!mandatory && ai.getGame().getPhaseHandler().getPhase().isAfter(PhaseType.COMBAT_DECLARE_BLOCKERS_INSTANT_ABILITY)) { + if (!mandatory && ai.getGame().getPhaseHandler().getPhase().isAfter(PhaseType.COMBAT_DECLARE_BLOCKERS)) { return false; } diff --git a/src/main/java/forge/card/ability/ai/EffectAi.java b/src/main/java/forge/card/ability/ai/EffectAi.java index 2c1b1bbfbf4..90e9383056f 100644 --- a/src/main/java/forge/card/ability/ai/EffectAi.java +++ b/src/main/java/forge/card/ability/ai/EffectAi.java @@ -46,7 +46,7 @@ public class EffectAi extends SpellAbilityAi { if (game.getPhaseHandler().isPlayerTurn(sa.getActivatingPlayer())) { return false; } - if (!game.getPhaseHandler().is(PhaseType.COMBAT_DECLARE_BLOCKERS_INSTANT_ABILITY)) { + if (!game.getPhaseHandler().is(PhaseType.COMBAT_DECLARE_BLOCKERS)) { return false; } if (!game.getStack().isEmpty()) { diff --git a/src/main/java/forge/card/ability/ai/FogAi.java b/src/main/java/forge/card/ability/ai/FogAi.java index dd83302f09e..39976929714 100644 --- a/src/main/java/forge/card/ability/ai/FogAi.java +++ b/src/main/java/forge/card/ability/ai/FogAi.java @@ -20,7 +20,7 @@ public class FogAi extends SpellAbilityAi { if (game.getPhaseHandler().isPlayerTurn(sa.getActivatingPlayer())) { return false; } - if (!game.getPhaseHandler().is(PhaseType.COMBAT_DECLARE_BLOCKERS_INSTANT_ABILITY)) { + if (!game.getPhaseHandler().is(PhaseType.COMBAT_DECLARE_BLOCKERS)) { return false; } diff --git a/src/main/java/forge/card/ability/ai/ProtectAi.java b/src/main/java/forge/card/ability/ai/ProtectAi.java index 1ca8df3891e..4047555084f 100644 --- a/src/main/java/forge/card/ability/ai/ProtectAi.java +++ b/src/main/java/forge/card/ability/ai/ProtectAi.java @@ -172,7 +172,7 @@ public class ProtectAi extends SpellAbilityAi { private boolean protectTgtAI(final Player ai, final SpellAbility sa, final boolean mandatory) { final Game game = ai.getGame(); - if (!mandatory && game.getPhaseHandler().getPhase().isAfter(PhaseType.COMBAT_DECLARE_BLOCKERS_INSTANT_ABILITY)) { + if (!mandatory && game.getPhaseHandler().getPhase().isAfter(PhaseType.COMBAT_DECLARE_BLOCKERS)) { return false; } diff --git a/src/main/java/forge/card/ability/ai/PumpAi.java b/src/main/java/forge/card/ability/ai/PumpAi.java index 11de5a2fd29..12e61530c70 100644 --- a/src/main/java/forge/card/ability/ai/PumpAi.java +++ b/src/main/java/forge/card/ability/ai/PumpAi.java @@ -186,7 +186,7 @@ public class PumpAi extends PumpAiBase { if (!mandatory && !sa.isTrigger() - && game.getPhaseHandler().getPhase().isAfter(PhaseType.COMBAT_DECLARE_BLOCKERS_INSTANT_ABILITY) + && game.getPhaseHandler().getPhase().isAfter(PhaseType.COMBAT_DECLARE_BLOCKERS) && !(sa.isCurse() && (defense < 0)) && !this.containsNonCombatKeyword(keywords) && !sa.hasParam("UntilYourNextTurn")) { diff --git a/src/main/java/forge/card/ability/ai/PumpAiBase.java b/src/main/java/forge/card/ability/ai/PumpAiBase.java index 5b1864a7d1b..9e703ad7a81 100644 --- a/src/main/java/forge/card/ability/ai/PumpAiBase.java +++ b/src/main/java/forge/card/ability/ai/PumpAiBase.java @@ -117,7 +117,7 @@ public abstract class PumpAiBase extends SpellAbilityAi { || keyword.endsWith("Prevent all damage that would be dealt by CARDNAME.")) { if (ph.isPlayerTurn(ai) && (!(CombatUtil.canBlock(card) || card.isBlocking()) || card.getNetCombatDamage() <= 0 - || ph.getPhase().isAfter(PhaseType.COMBAT_DECLARE_BLOCKERS_INSTANT_ABILITY) + || ph.getPhase().isAfter(PhaseType.COMBAT_DECLARE_BLOCKERS) || ph.getPhase().isBefore(PhaseType.MAIN1) || CardLists.getNotKeyword(ai.getCreaturesInPlay(), "Defender").isEmpty())) { return false; @@ -172,14 +172,14 @@ public abstract class PumpAiBase extends SpellAbilityAi { // give evasive keywords to creatures that can or do attack if (evasive) { if (ph.isPlayerTurn(opp) || !(CombatUtil.canAttack(card, opp) || card.isAttacking()) - || ph.getPhase().isAfter(PhaseType.COMBAT_DECLARE_ATTACKERS_INSTANT_ABILITY) + || ph.getPhase().isAfter(PhaseType.COMBAT_DECLARE_ATTACKERS) || card.getNetCombatDamage() <= 0 || CardLists.filter(opp.getCreaturesInPlay(), CardPredicates.possibleBlockers(card)).isEmpty()) { return false; } } else if (keyword.endsWith("Flying")) { if (ph.isPlayerTurn(opp) - && ph.getPhase().equals(PhaseType.COMBAT_DECLARE_ATTACKERS_INSTANT_ABILITY) + && ph.getPhase() == PhaseType.COMBAT_DECLARE_ATTACKERS && !CardLists.getKeyword(game.getCombat().getAttackers(), "Flying").isEmpty() && !card.hasKeyword("Reach") && CombatUtil.canBlock(card) @@ -188,7 +188,7 @@ public abstract class PumpAiBase extends SpellAbilityAi { } Predicate flyingOrReach = Predicates.or(CardPredicates.hasKeyword("Flying"), CardPredicates.hasKeyword("Reach")); if (ph.isPlayerTurn(opp) || !(CombatUtil.canAttack(card, opp) || card.isAttacking()) - || ph.getPhase().isAfter(PhaseType.COMBAT_DECLARE_ATTACKERS_INSTANT_ABILITY) + || ph.getPhase().isAfter(PhaseType.COMBAT_DECLARE_ATTACKERS) || card.getNetCombatDamage() <= 0 || !Iterables.any(CardLists.filter(opp.getCreaturesInPlay(), CardPredicates.possibleBlockers(card)), Predicates.not(flyingOrReach))) { @@ -196,14 +196,14 @@ public abstract class PumpAiBase extends SpellAbilityAi { } } else if (keyword.endsWith("Horsemanship")) { if (ph.isPlayerTurn(opp) - && ph.getPhase().equals(PhaseType.COMBAT_DECLARE_ATTACKERS_INSTANT_ABILITY) + && ph.getPhase().equals(PhaseType.COMBAT_DECLARE_ATTACKERS) && !CardLists.getKeyword(game.getCombat().getAttackers(), "Horsemanship").isEmpty() && CombatUtil.canBlock(card) && ComputerUtilCombat.lifeInDanger(ai, game.getCombat())) { return true; } if (ph.isPlayerTurn(opp) || !(CombatUtil.canAttack(card, opp) || card.isAttacking()) - || ph.getPhase().isAfter(PhaseType.COMBAT_DECLARE_ATTACKERS_INSTANT_ABILITY) + || ph.getPhase().isAfter(PhaseType.COMBAT_DECLARE_ATTACKERS) || card.getNetCombatDamage() <= 0 || CardLists.getNotKeyword(CardLists.filter(opp.getCreaturesInPlay(), CardPredicates.possibleBlockers(card)), "Horsemanship").isEmpty()) { @@ -221,7 +221,7 @@ public abstract class PumpAiBase extends SpellAbilityAi { return true; } else if (keyword.endsWith("Deathtouch")) { Combat combat = game.getCombat(); - if (ph.isPlayerTurn(opp) && ph.getPhase().equals(PhaseType.COMBAT_DECLARE_ATTACKERS_INSTANT_ABILITY)) { + if (ph.isPlayerTurn(opp) && ph.getPhase().equals(PhaseType.COMBAT_DECLARE_ATTACKERS)) { List attackers = combat.getAttackers(); for (Card attacker : attackers) { if (CombatUtil.canBlock(attacker, card, combat) @@ -242,7 +242,7 @@ public abstract class PumpAiBase extends SpellAbilityAi { return false; } else if (combatRelevant) { if (ph.isPlayerTurn(opp) || !(CombatUtil.canAttack(card, opp) || card.isAttacking()) - || ph.getPhase().isAfter(PhaseType.COMBAT_DECLARE_BLOCKERS_INSTANT_ABILITY) + || ph.getPhase().isAfter(PhaseType.COMBAT_DECLARE_BLOCKERS) || (opp.getCreaturesInPlay().size() < 1) || CardLists.filter(opp.getCreaturesInPlay(), CardPredicates.possibleBlockers(card)).isEmpty()) { return false; @@ -250,18 +250,18 @@ public abstract class PumpAiBase extends SpellAbilityAi { } else if (keyword.equals("Double Strike")) { if (ph.isPlayerTurn(opp) || !(CombatUtil.canAttack(card, opp) || card.isAttacking()) || card.getNetCombatDamage() <= 0 - || ph.getPhase().isAfter(PhaseType.COMBAT_DECLARE_BLOCKERS_INSTANT_ABILITY)) { + || ph.getPhase().isAfter(PhaseType.COMBAT_DECLARE_BLOCKERS)) { return false; } } else if (keyword.startsWith("Rampage")) { if (ph.isPlayerTurn(opp) || !(CombatUtil.canAttack(card, opp) || card.isAttacking()) - || ph.getPhase().isAfter(PhaseType.COMBAT_DECLARE_ATTACKERS_INSTANT_ABILITY) + || ph.getPhase().isAfter(PhaseType.COMBAT_DECLARE_ATTACKERS) || CardLists.filter(opp.getCreaturesInPlay(), CardPredicates.possibleBlockers(card)).size() < 2) { return false; } } else if (keyword.startsWith("Flanking")) { if (ph.isPlayerTurn(opp) || !(CombatUtil.canAttack(card, opp) || card.isAttacking()) - || ph.getPhase().isAfter(PhaseType.COMBAT_DECLARE_ATTACKERS_INSTANT_ABILITY) + || ph.getPhase().isAfter(PhaseType.COMBAT_DECLARE_ATTACKERS) || CardLists.getNotKeyword(CardLists.filter(opp.getCreaturesInPlay(), CardPredicates.possibleBlockers(card)), "Flanking").isEmpty()) { return false; @@ -269,7 +269,7 @@ public abstract class PumpAiBase extends SpellAbilityAi { } else if (keyword.startsWith("Trample")) { if (ph.isPlayerTurn(opp) || !(CombatUtil.canAttack(card, opp) || card.isAttacking()) || !CombatUtil.canBeBlocked(card) - || ph.getPhase().isAfter(PhaseType.COMBAT_DECLARE_ATTACKERS_INSTANT_ABILITY) + || ph.getPhase().isAfter(PhaseType.COMBAT_DECLARE_ATTACKERS) || card.getNetCombatDamage() + attack <= 1 || CardLists.filter(opp.getCreaturesInPlay(), CardPredicates.possibleBlockers(card)).isEmpty()) { return false; @@ -283,7 +283,7 @@ public abstract class PumpAiBase extends SpellAbilityAi { } if ((ph.isPlayerTurn(opp)) || !(CombatUtil.canAttack(card, opp) || card.isAttacking()) - || ph.getPhase().isAfter(PhaseType.COMBAT_DECLARE_BLOCKERS_INSTANT_ABILITY)) { + || ph.getPhase().isAfter(PhaseType.COMBAT_DECLARE_BLOCKERS)) { return false; } } else if (keyword.endsWith("Wither")) { @@ -312,7 +312,7 @@ public abstract class PumpAiBase extends SpellAbilityAi { } } else if (keyword.equals("Reach")) { if (ph.isPlayerTurn(ai) - || !ph.getPhase().equals(PhaseType.COMBAT_DECLARE_ATTACKERS_INSTANT_ABILITY) + || !ph.getPhase().equals(PhaseType.COMBAT_DECLARE_ATTACKERS) || CardLists.getKeyword(game.getCombat().getAttackers(), "Flying").isEmpty() || card.hasKeyword("Flying") || !CombatUtil.canBlock(card)) { @@ -320,7 +320,7 @@ public abstract class PumpAiBase extends SpellAbilityAi { } } else if (keyword.endsWith("CARDNAME can block an additional creature.")) { if (ph.isPlayerTurn(ai) - || !ph.getPhase().equals(PhaseType.COMBAT_DECLARE_ATTACKERS_INSTANT_ABILITY)) { + || !ph.getPhase().equals(PhaseType.COMBAT_DECLARE_ATTACKERS)) { return false; } int canBlockNum = 1 + card.getKeywordAmount("CARDNAME can block an additional creature."); @@ -342,7 +342,7 @@ public abstract class PumpAiBase extends SpellAbilityAi { } } else if (keyword.equals("Islandwalk")) { if (ph.isPlayerTurn(opp) || !(CombatUtil.canAttack(card, opp) || card.isAttacking()) - || ph.getPhase().isAfter(PhaseType.COMBAT_DECLARE_ATTACKERS_INSTANT_ABILITY) + || ph.getPhase().isAfter(PhaseType.COMBAT_DECLARE_ATTACKERS) || card.getNetCombatDamage() <= 0 || CardLists.getType(opp.getLandsInPlay(), "Island").isEmpty() || CardLists.filter(opp.getCreaturesInPlay(), CardPredicates.possibleBlockers(card)).isEmpty()) { @@ -350,7 +350,7 @@ public abstract class PumpAiBase extends SpellAbilityAi { } } else if (keyword.equals("Swampwalk")) { if (ph.isPlayerTurn(opp) || !(CombatUtil.canAttack(card, opp) || card.isAttacking()) - || ph.getPhase().isAfter(PhaseType.COMBAT_DECLARE_ATTACKERS_INSTANT_ABILITY) + || ph.getPhase().isAfter(PhaseType.COMBAT_DECLARE_ATTACKERS) || card.getNetCombatDamage() <= 0 || CardLists.getType(opp.getLandsInPlay(), "Swamp").isEmpty() || CardLists.filter(opp.getCreaturesInPlay(), CardPredicates.possibleBlockers(card)).isEmpty()) { @@ -358,7 +358,7 @@ public abstract class PumpAiBase extends SpellAbilityAi { } } else if (keyword.equals("Mountainwalk")) { if (ph.isPlayerTurn(opp) || !(CombatUtil.canAttack(card, opp) || card.isAttacking()) - || ph.getPhase().isAfter(PhaseType.COMBAT_DECLARE_ATTACKERS_INSTANT_ABILITY) + || ph.getPhase().isAfter(PhaseType.COMBAT_DECLARE_ATTACKERS) || card.getNetCombatDamage() <= 0 || CardLists.getType(opp.getLandsInPlay(), "Mountain").isEmpty() || CardLists.filter(opp.getCreaturesInPlay(), CardPredicates.possibleBlockers(card)).isEmpty()) { @@ -366,7 +366,7 @@ public abstract class PumpAiBase extends SpellAbilityAi { } } else if (keyword.equals("Forestwalk")) { if (ph.isPlayerTurn(opp) || !(CombatUtil.canAttack(card, opp) || card.isAttacking()) - || ph.getPhase().isAfter(PhaseType.COMBAT_DECLARE_ATTACKERS_INSTANT_ABILITY) + || ph.getPhase().isAfter(PhaseType.COMBAT_DECLARE_ATTACKERS) || card.getNetCombatDamage() <= 0 || CardLists.getType(opp.getLandsInPlay(), "Forest").isEmpty() || CardLists.filter(opp.getCreaturesInPlay(), CardPredicates.possibleBlockers(card)).isEmpty()) { @@ -422,7 +422,7 @@ public abstract class PumpAiBase extends SpellAbilityAi { // is the creature blocking and unable to destroy the attacker // or would be destroyed itself? - if (phase.is(PhaseType.COMBAT_DECLARE_BLOCKERS_INSTANT_ABILITY) && c.isBlocking()) { + if (phase.is(PhaseType.COMBAT_DECLARE_BLOCKERS) && c.isBlocking()) { if (defense > 0 && ComputerUtilCombat.blockerWouldBeDestroyed(ai, c)) { return true; } @@ -435,13 +435,13 @@ public abstract class PumpAiBase extends SpellAbilityAi { } // is the creature unblocked and the spell will pump its power? - if (phase.is(PhaseType.COMBAT_DECLARE_BLOCKERS_INSTANT_ABILITY) + if (phase.is(PhaseType.COMBAT_DECLARE_BLOCKERS) && game.getCombat().isAttacking(c) && game.getCombat().isUnblocked(c) && attack > 0) { return true; } // is the creature blocked and the blocker would survive - if (phase.is(PhaseType.COMBAT_DECLARE_BLOCKERS_INSTANT_ABILITY) && attack > 0 + if (phase.is(PhaseType.COMBAT_DECLARE_BLOCKERS) && attack > 0 && game.getCombat().isAttacking(c) && game.getCombat().isBlocked(c) && game.getCombat().getBlockers(c) != null @@ -457,7 +457,7 @@ public abstract class PumpAiBase extends SpellAbilityAi { attackerHasTrample |= b.hasKeyword("Trample"); } - if (phase.getPhase().equals(PhaseType.COMBAT_DECLARE_BLOCKERS_INSTANT_ABILITY) + if (phase.getPhase().equals(PhaseType.COMBAT_DECLARE_BLOCKERS) && phase.isPlayerTurn(ai.getOpponent()) && c.isBlocking() && defense > 0 diff --git a/src/main/java/forge/card/ability/ai/PumpAllAi.java b/src/main/java/forge/card/ability/ai/PumpAllAi.java index 07886f06cec..9bb9bbe11d5 100644 --- a/src/main/java/forge/card/ability/ai/PumpAllAi.java +++ b/src/main/java/forge/card/ability/ai/PumpAllAi.java @@ -78,8 +78,8 @@ public class PumpAllAi extends PumpAiBase { }); // leaves all creatures that will be destroyed } // -X/-X end else if (power < 0) { // -X/-0 - if (phase.isAfter(PhaseType.COMBAT_DECLARE_BLOCKERS_INSTANT_ABILITY) - || phase.isBefore(PhaseType.COMBAT_DECLARE_ATTACKERS_INSTANT_ABILITY) + if (phase.isAfter(PhaseType.COMBAT_DECLARE_BLOCKERS) + || phase.isBefore(PhaseType.COMBAT_DECLARE_ATTACKERS) || game.getPhaseHandler().isPlayerTurn(sa.getActivatingPlayer()) || game.getPhaseHandler().isPreventCombatDamageThisTurn()) { return false; @@ -90,7 +90,7 @@ public class PumpAllAi extends PumpAiBase { continue; } totalPower += Math.min(c.getNetAttack(), power * -1); - if (phase == PhaseType.COMBAT_DECLARE_BLOCKERS_INSTANT_ABILITY + if (phase == PhaseType.COMBAT_DECLARE_BLOCKERS && game.getCombat().getUnblockedAttackers().contains(c)) { if (ComputerUtilCombat.lifeInDanger(sa.getActivatingPlayer(), game.getCombat())) { return true; @@ -113,7 +113,7 @@ public class PumpAllAi extends PumpAiBase { } // end Curse // don't use non curse PumpAll after Combat_Begin until AI is improved - if (phase.isAfter(PhaseType.COMBAT_DECLARE_ATTACKERS_INSTANT_ABILITY) || phase.isBefore(PhaseType.MAIN1)) { + if (phase.isAfter(PhaseType.COMBAT_DECLARE_ATTACKERS) || phase.isBefore(PhaseType.MAIN1)) { return false; } @@ -124,7 +124,7 @@ public class PumpAllAi extends PumpAiBase { if (power <= 0 && !containsUsefulKeyword(ai, keywords, c, sa, power)) { return false; } - if (phase.equals(PhaseType.COMBAT_DECLARE_ATTACKERS_INSTANT_ABILITY) && c.isAttacking()) { + if (phase.equals(PhaseType.COMBAT_DECLARE_ATTACKERS) && c.isAttacking()) { return true; } if (phase.isBefore(PhaseType.COMBAT_DECLARE_ATTACKERS) && CombatUtil.canAttack(c, opp)) { diff --git a/src/main/java/forge/card/ability/ai/RegenerateAi.java b/src/main/java/forge/card/ability/ai/RegenerateAi.java index 2e817e7f8b2..410b414ed0b 100644 --- a/src/main/java/forge/card/ability/ai/RegenerateAi.java +++ b/src/main/java/forge/card/ability/ai/RegenerateAi.java @@ -92,7 +92,7 @@ public class RegenerateAi extends SpellAbilityAi { } } } else { - if (game.getPhaseHandler().is(PhaseType.COMBAT_DECLARE_BLOCKERS_INSTANT_ABILITY)) { + if (game.getPhaseHandler().is(PhaseType.COMBAT_DECLARE_BLOCKERS)) { boolean flag = false; for (final Card c : list) { @@ -136,7 +136,7 @@ public class RegenerateAi extends SpellAbilityAi { chance = true; } } else { - if (game.getPhaseHandler().is(PhaseType.COMBAT_DECLARE_BLOCKERS_INSTANT_ABILITY)) { + if (game.getPhaseHandler().is(PhaseType.COMBAT_DECLARE_BLOCKERS)) { final List combatants = CardLists.filter(targetables, CardPredicates.Presets.CREATURES); CardLists.sortByEvaluateCreature(combatants); @@ -194,7 +194,7 @@ public class RegenerateAi extends SpellAbilityAi { if (compTargetables.size() > 0) { final List combatants = CardLists.filter(compTargetables, CardPredicates.Presets.CREATURES); CardLists.sortByEvaluateCreature(combatants); - if (game.getPhaseHandler().is(PhaseType.COMBAT_DECLARE_BLOCKERS_INSTANT_ABILITY)) { + if (game.getPhaseHandler().is(PhaseType.COMBAT_DECLARE_BLOCKERS)) { for (final Card c : combatants) { if ((c.getShield() == 0) && ComputerUtilCombat.combatantWouldBeDestroyed(ai, c)) { tgt.addTarget(c); @@ -207,7 +207,7 @@ public class RegenerateAi extends SpellAbilityAi { // can target // choose my best X without regen - if (CardLists.getNotType(compTargetables, "Creature").size() == 0) { + if (CardLists.getNotType(compTargetables, "Creature").isEmpty()) { for (final Card c : combatants) { if (c.getShield() == 0) { tgt.addTarget(c); diff --git a/src/main/java/forge/card/ability/ai/RegenerateAllAi.java b/src/main/java/forge/card/ability/ai/RegenerateAllAi.java index 870b083290c..db5a0e329ec 100644 --- a/src/main/java/forge/card/ability/ai/RegenerateAllAi.java +++ b/src/main/java/forge/card/ability/ai/RegenerateAllAi.java @@ -65,7 +65,7 @@ public class RegenerateAllAi extends SpellAbilityAi { } } } else { - if (game.getPhaseHandler().is(PhaseType.COMBAT_DECLARE_BLOCKERS_INSTANT_ABILITY)) { + if (game.getPhaseHandler().is(PhaseType.COMBAT_DECLARE_BLOCKERS)) { final List combatants = CardLists.filter(list, CardPredicates.Presets.CREATURES); for (final Card c : combatants) { diff --git a/src/main/java/forge/card/ability/ai/TokenAi.java b/src/main/java/forge/card/ability/ai/TokenAi.java index 66af9c553e5..e7c5deb9c1e 100644 --- a/src/main/java/forge/card/ability/ai/TokenAi.java +++ b/src/main/java/forge/card/ability/ai/TokenAi.java @@ -111,7 +111,7 @@ public class TokenAi extends SpellAbilityAi { } if ((ph.isPlayerTurn(ai) || ph.getPhase().isBefore( - PhaseType.COMBAT_DECLARE_ATTACKERS_INSTANT_ABILITY)) + PhaseType.COMBAT_DECLARE_ATTACKERS)) && !sa.hasParam("ActivationPhases") && !sa.hasParam("PlayerTurn") && !SpellAbilityAi.isSorcerySpeed(sa) && !haste) { return false; @@ -170,7 +170,7 @@ public class TokenAi extends SpellAbilityAi { return true; } - if (game.getPhaseHandler().is(PhaseType.COMBAT_DECLARE_ATTACKERS_INSTANT_ABILITY)) { + if (game.getPhaseHandler().is(PhaseType.COMBAT_DECLARE_ATTACKERS)) { return true; } if (sa.isAbility()) { diff --git a/src/main/java/forge/card/ability/ai/UnattachAllAi.java b/src/main/java/forge/card/ability/ai/UnattachAllAi.java index b4c5ee03b7e..0adeb287f6f 100644 --- a/src/main/java/forge/card/ability/ai/UnattachAllAi.java +++ b/src/main/java/forge/card/ability/ai/UnattachAllAi.java @@ -49,7 +49,7 @@ public class UnattachAllAi extends SpellAbilityAi { source.setSVar("PayX", Integer.toString(xPay)); } - if (ai.getGame().getPhaseHandler().getPhase().isAfter(PhaseType.COMBAT_DECLARE_BLOCKERS_INSTANT_ABILITY) + if (ai.getGame().getPhaseHandler().getPhase().isAfter(PhaseType.COMBAT_DECLARE_BLOCKERS) && !"Curse".equals(sa.getParam("AILogic"))) { return false; } diff --git a/src/main/java/forge/card/spellability/SpellPermanent.java b/src/main/java/forge/card/spellability/SpellPermanent.java index 8e3f5dafae3..9de16104a10 100644 --- a/src/main/java/forge/card/spellability/SpellPermanent.java +++ b/src/main/java/forge/card/spellability/SpellPermanent.java @@ -128,7 +128,7 @@ public class SpellPermanent extends Spell { && (ai.isUnlimitedHandSize() || ai.getCardsIn(ZoneType.Hand).size() <= ai.getMaxHandSize()) && ai.getManaPool().totalMana() <= 0 && (game.getPhaseHandler().isPlayerTurn(ai) - || game.getPhaseHandler().getPhase().isBefore(PhaseType.COMBAT_DECLARE_ATTACKERS_INSTANT_ABILITY) + || game.getPhaseHandler().getPhase().isBefore(PhaseType.COMBAT_DECLARE_ATTACKERS) && !card.hasETBTrigger()) && !ComputerUtil.castPermanentInMain1(ai, this)) { return false; diff --git a/src/main/java/forge/control/FControlGamePlayback.java b/src/main/java/forge/control/FControlGamePlayback.java index ed5140fdfe5..38bf9aaa252 100644 --- a/src/main/java/forge/control/FControlGamePlayback.java +++ b/src/main/java/forge/control/FControlGamePlayback.java @@ -68,8 +68,8 @@ public class FControlGamePlayback extends IGameEventVisitor.Base { switch(ev.phase) { case COMBAT_END: - case COMBAT_DECLARE_ATTACKERS_INSTANT_ABILITY: - case COMBAT_DECLARE_BLOCKERS_INSTANT_ABILITY: + case COMBAT_DECLARE_ATTACKERS: + case COMBAT_DECLARE_BLOCKERS: if( fc.getObservedGame().getPhaseHandler().inCombat() ) pauseForEvent(combatDelay); break; diff --git a/src/main/java/forge/game/ai/AiController.java b/src/main/java/forge/game/ai/AiController.java index ad62ef26014..a54f3bbea21 100644 --- a/src/main/java/forge/game/ai/AiController.java +++ b/src/main/java/forge/game/ai/AiController.java @@ -787,16 +787,6 @@ public class AiController { public void onPriorityRecieved() { final PhaseType phase = game.getPhaseHandler().getPhase(); switch(phase) { - case COMBAT_DECLARE_ATTACKERS: - declareAttackers(); - break; - - case COMBAT_DECLARE_BLOCKERS: - final List blockers = player.getCreaturesInPlay(); - game.setCombat(ComputerUtilBlock.getBlockers(player, game.getCombat(), blockers)); - CombatUtil.orderMultipleCombatants(game.getCombat()); - break; - case MAIN1: case MAIN2: Log.debug("Computer " + phase.nameForUi); @@ -809,9 +799,15 @@ public class AiController { break; } } + + public void declateBlockers() { + final List blockers = player.getCreaturesInPlay(); + game.setCombat(ComputerUtilBlock.getBlockers(player, game.getCombat(), blockers)); + CombatUtil.orderMultipleCombatants(game.getCombat()); + } - private void declareAttackers() { + public void declareAttackers() { // 12/2/10(sol) the decision making here has moved to getAttackers() game.setCombat(new AiAttackController(player, player.getOpponent()).getAttackers()); diff --git a/src/main/java/forge/game/ai/ComputerUtil.java b/src/main/java/forge/game/ai/ComputerUtil.java index 74703c4e77f..4b273da70b1 100644 --- a/src/main/java/forge/game/ai/ComputerUtil.java +++ b/src/main/java/forge/game/ai/ComputerUtil.java @@ -1017,7 +1017,7 @@ public class ComputerUtil { return (sa.getSourceCard().isCreature() && sa.getPayCosts().hasTapCost() - && (ph.getPhase().isBefore(PhaseType.COMBAT_DECLARE_BLOCKERS_INSTANT_ABILITY) + && (ph.getPhase().isBefore(PhaseType.COMBAT_DECLARE_BLOCKERS) || !ph.getNextTurn().equals(sa.getActivatingPlayer()))); } diff --git a/src/main/java/forge/game/phase/PhaseHandler.java b/src/main/java/forge/game/phase/PhaseHandler.java index afa1c03b0ea..0adc37d60a1 100644 --- a/src/main/java/forge/game/phase/PhaseHandler.java +++ b/src/main/java/forge/game/phase/PhaseHandler.java @@ -264,17 +264,30 @@ public class PhaseHandler implements java.io.Serializable { break; case COMBAT_DECLARE_ATTACKERS: - break; - - case COMBAT_DECLARE_ATTACKERS_INSTANT_ABILITY: + game.getStack().freezeStack(); + + playerTurn.getController().declareAttackers(); + PhaseUtil.handleDeclareAttackers(game); + + this.bCombat = !game.getCombat().getAttackers().isEmpty(); + game.getStack().unfreezeStack(); + this.nCombatsThisTurn++; + break; case COMBAT_DECLARE_BLOCKERS: game.getCombat().verifyCreaturesInPlay(); - break; - - case COMBAT_DECLARE_BLOCKERS_INSTANT_ABILITY: + game.getStack().freezeStack(); + + Player p = playerTurn; + do { + p = game.getNextPlayerAfter(p); + if ( game.getCombat().isPlayerAttacked(p) ) + p.getController().declareBlockers(); + } while(p != playerTurn); + + game.getStack().unfreezeStack(); PhaseUtil.handleDeclareBlockers(game); break; @@ -402,17 +415,7 @@ public class PhaseHandler implements java.io.Serializable { case UNTAP: this.nCombatsThisTurn = 0; break; - - case COMBAT_DECLARE_ATTACKERS: - this.bCombat = !game.getCombat().getAttackers().isEmpty(); - game.getStack().unfreezeStack(); - this.nCombatsThisTurn++; - break; - - case COMBAT_DECLARE_BLOCKERS: - game.getStack().unfreezeStack(); - break; - + case COMBAT_END: game.getCombat().reset(playerTurn); this.getPlayerTurn().resetAttackedThisCombat(); @@ -445,9 +448,7 @@ public class PhaseHandler implements java.io.Serializable { case COMBAT_DECLARE_ATTACKERS: return playerTurn.isSkippingCombat(); - case COMBAT_DECLARE_ATTACKERS_INSTANT_ABILITY: case COMBAT_DECLARE_BLOCKERS: - case COMBAT_DECLARE_BLOCKERS_INSTANT_ABILITY: case COMBAT_FIRST_STRIKE_DAMAGE: case COMBAT_DAMAGE: return !this.inCombat(); @@ -684,20 +685,13 @@ public class PhaseHandler implements java.io.Serializable { while (!game.isGameOver()) { // loop only while is playing - boolean givePriority = givePriorityToPlayer ; - if ( phase == PhaseType.COMBAT_DECLARE_BLOCKERS) - givePriority = game.getCombat().isPlayerAttacked(pPlayerPriority); - - if ( phase == PhaseType.COMBAT_DECLARE_ATTACKERS && playerTurn != pPlayerPriority ) - givePriority = false; - if( DEBUG_PHASES ) { System.out.println("\t\tStack: " + game.getStack()); - System.out.print(FThreads.prependThreadId(debugPrintState(givePriority))); + System.out.print(FThreads.prependThreadId(debugPrintState(givePriorityToPlayer))); } - if( givePriority ) { + if( givePriorityToPlayer ) { if( DEBUG_PHASES ) sw.start(); @@ -747,13 +741,6 @@ public class PhaseHandler implements java.io.Serializable { game.fireEvent(new GameEventGameRestarted(playerTurn)); return; } - - - // Time to handle priority to next player. - if ( phase == PhaseType.COMBAT_DECLARE_ATTACKERS || phase == PhaseType.COMBAT_DECLARE_BLOCKERS) - game.getStack().freezeStack(); - - } } diff --git a/src/main/java/forge/game/phase/PhaseType.java b/src/main/java/forge/game/phase/PhaseType.java index 81849eed29c..9cadf7094a6 100644 --- a/src/main/java/forge/game/phase/PhaseType.java +++ b/src/main/java/forge/game/phase/PhaseType.java @@ -15,9 +15,9 @@ public enum PhaseType { MAIN1("Main, precombat", "Main1"), COMBAT_BEGIN("Begin Combat", "BeginCombat"), COMBAT_DECLARE_ATTACKERS("Declare Attackers"), - COMBAT_DECLARE_ATTACKERS_INSTANT_ABILITY("Declare Attackers - Play Instants and Abilities"), + //COMBAT_DECLARE_ATTACKERS_INSTANT_ABILITY("Declare Attackers - Play Instants and Abilities"), COMBAT_DECLARE_BLOCKERS("Declare Blockers"), - COMBAT_DECLARE_BLOCKERS_INSTANT_ABILITY("Declare Blockers - Play Instants and Abilities"), + //COMBAT_DECLARE_BLOCKERS_INSTANT_ABILITY("Declare Blockers - Play Instants and Abilities"), COMBAT_FIRST_STRIKE_DAMAGE("First Strike Damage"), COMBAT_DAMAGE("Combat Damage"), COMBAT_END("End Combat", "EndCombat"), @@ -28,8 +28,8 @@ public enum PhaseType { public static final List ALL_PHASES = Collections.unmodifiableList( Arrays.asList( UNTAP, UPKEEP, DRAW, MAIN1, - COMBAT_BEGIN, COMBAT_DECLARE_ATTACKERS, COMBAT_DECLARE_ATTACKERS_INSTANT_ABILITY, - COMBAT_DECLARE_BLOCKERS, COMBAT_DECLARE_BLOCKERS_INSTANT_ABILITY, + COMBAT_BEGIN, COMBAT_DECLARE_ATTACKERS, //COMBAT_DECLARE_ATTACKERS_INSTANT_ABILITY, + COMBAT_DECLARE_BLOCKERS, // COMBAT_DECLARE_BLOCKERS_INSTANT_ABILITY, COMBAT_FIRST_STRIKE_DAMAGE, COMBAT_DAMAGE, COMBAT_END, MAIN2, END_OF_TURN, CLEANUP ) diff --git a/src/main/java/forge/game/player/PlayerController.java b/src/main/java/forge/game/player/PlayerController.java index 8939e93494f..9b2746229a7 100644 --- a/src/main/java/forge/game/player/PlayerController.java +++ b/src/main/java/forge/game/player/PlayerController.java @@ -135,7 +135,10 @@ public abstract class PlayerController { public abstract boolean confirmReplacementEffect(ReplacementEffect replacementEffect, SpellAbility effectSA, String question); public abstract List getCardsToMulligan(boolean isCommander, Player firstPlayer); + public abstract void declareAttackers(); + public abstract void declareBlockers(); public abstract void takePriority(); + public abstract List chooseCardsToDiscardToMaximumHandSize(int numDiscard); public abstract boolean payManaOptional(Card card, Cost cost, String prompt, ManaPaymentPurpose purpose); } diff --git a/src/main/java/forge/game/player/PlayerControllerAi.java b/src/main/java/forge/game/player/PlayerControllerAi.java index 7fc2ead5ccd..971d9c63dc4 100644 --- a/src/main/java/forge/game/player/PlayerControllerAi.java +++ b/src/main/java/forge/game/player/PlayerControllerAi.java @@ -286,6 +286,17 @@ public class PlayerControllerAi extends PlayerController { return ComputerUtil.getPartialParisCandidates(player); } + @Override + public void declareAttackers() { + brains.declareAttackers(); + } + + + @Override + public void declareBlockers() { + brains.declateBlockers(); + } + @Override public void takePriority() { if ( !game.isGameOver() ) diff --git a/src/main/java/forge/game/player/PlayerControllerHuman.java b/src/main/java/forge/game/player/PlayerControllerHuman.java index a7c4ccd4c01..59715a533e4 100644 --- a/src/main/java/forge/game/player/PlayerControllerHuman.java +++ b/src/main/java/forge/game/player/PlayerControllerHuman.java @@ -469,19 +469,21 @@ public class PlayerControllerHuman extends PlayerController { return inp.isKeepHand() ? null : isCommander ? inp.getSelectedCards() : player.getCardsIn(ZoneType.Hand); } - - private void showDefaultInput() { - SpellAbility chosenSa = null; - do { - if (chosenSa != null) { - HumanPlay.playSpellAbility(player, chosenSa); - } - InputPassPriority defaultInput = new InputPassPriority(player); - Singletons.getControl().getInputQueue().setInputAndWait(defaultInput); - chosenSa = defaultInput.getChosenSa(); - } while( chosenSa != null ); + @Override + public void declareAttackers() { + game.getCombat().initiatePossibleDefenders(player.getOpponents()); + // This input should not modify combat object itself, but should return user choice + InputSynchronized inpAttack = new InputAttack(player, game.getCombat()); + Singletons.getControl().getInputQueue().setInputAndWait(inpAttack); } - + + @Override + public void declareBlockers() { + // This input should not modify combat object itself, but should return user choice + InputSynchronized inpBlock = new InputBlock(player, game.getCombat()); + Singletons.getControl().getInputQueue().setInputAndWait(inpBlock); + } + @Override public void takePriority() { @@ -492,22 +494,15 @@ public class PlayerControllerHuman extends PlayerController { } else autoPassCancel(); // probably cancel, since something has happened - switch(phase) { - - case COMBAT_DECLARE_ATTACKERS: - game.getCombat().initiatePossibleDefenders(player.getOpponents()); - InputSynchronized inpAttack = new InputAttack(player, game.getCombat()); - Singletons.getControl().getInputQueue().setInputAndWait(inpAttack); - return; - - case COMBAT_DECLARE_BLOCKERS: - InputSynchronized inpBlock = new InputBlock(player, game.getCombat()); - Singletons.getControl().getInputQueue().setInputAndWait(inpBlock); - return; - - default: - showDefaultInput(); - } + SpellAbility chosenSa = null; + do { + if (chosenSa != null) { + HumanPlay.playSpellAbility(player, chosenSa); + } + InputPassPriority defaultInput = new InputPassPriority(player); + Singletons.getControl().getInputQueue().setInputAndWait(defaultInput); + chosenSa = defaultInput.getChosenSa(); + } while( chosenSa != null ); } @Override diff --git a/src/main/java/forge/gui/match/nonsingleton/VField.java b/src/main/java/forge/gui/match/nonsingleton/VField.java index 325a632e01d..be3e5af868e 100644 --- a/src/main/java/forge/gui/match/nonsingleton/VField.java +++ b/src/main/java/forge/gui/match/nonsingleton/VField.java @@ -532,10 +532,8 @@ public class VField implements IVDoc { case COMBAT_BEGIN: return this.getLblBeginCombat(); case COMBAT_DECLARE_ATTACKERS: - case COMBAT_DECLARE_ATTACKERS_INSTANT_ABILITY: return this.getLblDeclareAttackers(); case COMBAT_DECLARE_BLOCKERS: - case COMBAT_DECLARE_BLOCKERS_INSTANT_ABILITY: return this.getLblDeclareBlockers(); case COMBAT_DAMAGE: return this.getLblCombatDamage();