Turn counting removed from GameState (cause phaseHandler already did it)

Inlined some static methods called from phaseHandler
PhaseType: index is not a field, yet the order is set by a list initialized statically
GetLabelForPhase - moved to VField from PhaseUtil
Game has a method to determine the next player who takes turn/priority after the given one.
This commit is contained in:
Maxmtg
2012-10-20 12:29:48 +00:00
parent bf1f64d8f2
commit b0e7d92dea
7 changed files with 176 additions and 234 deletions

View File

@@ -70,7 +70,6 @@ public class GameState {
private final Zone stackZone = new Zone(ZoneType.Stack); private final Zone stackZone = new Zone(ZoneType.Stack);
private long timestamp = 0; private long timestamp = 0;
private int nTurn = 0;
private final GameAction action; private final GameAction action;
/** /**
@@ -269,21 +268,6 @@ public class GameState {
} }
} }
/**
* TODO: Write javadoc for this method.
* @return
*/
public int getTurnNumber() {
return nTurn;
}
/**
* TODO: Write javadoc for this method.
*/
public void notifyNextTurn() {
nTurn++;
}
// THESE WERE MOVED HERE FROM AllZoneUtil // THESE WERE MOVED HERE FROM AllZoneUtil
// They must once become non-static members of this class // They must once become non-static members of this class
@@ -441,4 +425,19 @@ public class GameState {
public GameAction getAction() { public GameAction getAction() {
return action; return action;
} }
/**
* TODO: Write javadoc for this method.
* @param playerTurn
* @return
*/
public Player getNextPlayerAfter(Player playerTurn) {
int iPlayer = roPlayers.indexOf(playerTurn);
if( iPlayer == roPlayers.size() - 1)
iPlayer = -1;
iPlayer++;
// should also check that he has not lost yet.
return roPlayers.get(iPlayer);
}
} }

View File

@@ -87,7 +87,7 @@ public class MatchController {
throw new RuntimeException("Game is not over yet."); throw new RuntimeException("Game is not over yet.");
GameOutcome result = new GameOutcome(reason, game.getPlayers()); GameOutcome result = new GameOutcome(reason, game.getPlayers());
result.setTurnsPlayed(game.getTurnNumber()); result.setTurnsPlayed(game.getPhaseHandler().getTurn());
gamesPlayed.add(result); gamesPlayed.add(result);
} }

View File

@@ -50,7 +50,7 @@ public class PhaseHandler extends MyObservable implements java.io.Serializable {
/** Constant <code>serialVersionUID=5207222278370963197L</code>. */ /** Constant <code>serialVersionUID=5207222278370963197L</code>. */
private static final long serialVersionUID = 5207222278370963197L; private static final long serialVersionUID = 5207222278370963197L;
private int phaseIndex = 0; private PhaseType phase = PhaseType.UNTAP;
private int turn = 1; private int turn = 1;
private final Stack<ExtraTurn> extraTurns = new Stack<ExtraTurn>(); private final Stack<ExtraTurn> extraTurns = new Stack<ExtraTurn>();
@@ -286,27 +286,37 @@ public class PhaseHandler extends MyObservable implements java.io.Serializable {
public final void handleBeginPhase() { public final void handleBeginPhase() {
this.setPhaseEffects(false); this.setPhaseEffects(false);
// Handle effects that happen at the beginning of phases // Handle effects that happen at the beginning of phases
final PhaseType phase = this.getPhase();
final Player turn = this.getPlayerTurn();
this.setSkipPhase(true); this.setSkipPhase(true);
game.getAction().checkStateEffects(); game.getAction().checkStateEffects();
if (this.isAutoPassedPhase(turn, phase)) { if (this.isAutoPassedPhase(this.getPlayerTurn(), this.getPhase())) {
this.setAutoPass(false); this.setAutoPass(false);
} }
switch(phase) { switch(this.getPhase()) {
case UNTAP: case UNTAP:
//SDisplayUtil.showTab(EDocID.REPORT_STACK.getDoc()); //SDisplayUtil.showTab(EDocID.REPORT_STACK.getDoc());
PhaseUtil.handleUntap(); PhaseUtil.handleUntap(game);
break; break;
case UPKEEP: case UPKEEP:
PhaseUtil.handleUpkeep(); if (PhaseUtil.skipUpkeep()) {
// Slowtrips all say "on the next turn's upkeep" if there is no
// upkeep next turn, the trigger will never occur.
for( Player p : game.getPlayers() )
p.clearSlowtripList();
game.getPhaseHandler().setNeedToNextPhase(true);
} else {
game.getUpkeep().executeUntil(this.getPlayerTurn());
game.getUpkeep().executeAt();
}
break; break;
case DRAW: case DRAW:
PhaseUtil.handleDraw(); if (getTurn() == 1 || PhaseUtil.skipDraw(this.getPlayerTurn()))
game.getPhaseHandler().setNeedToNextPhase(true);
else
this.getPlayerTurn().drawCards(1, true);
break; break;
case COMBAT_BEGIN: case COMBAT_BEGIN:
@@ -329,7 +339,7 @@ public class PhaseHandler extends MyObservable implements java.io.Serializable {
// we can skip AfterBlockers and AfterAttackers if necessary // we can skip AfterBlockers and AfterAttackers if necessary
case COMBAT_DECLARE_BLOCKERS: case COMBAT_DECLARE_BLOCKERS:
if (this.inCombat()) { if (this.inCombat()) {
PhaseUtil.verifyCombat(); Singletons.getModel().getGame().getCombat().verifyCreaturesInPlay();
CombatUtil.showCombat(); CombatUtil.showCombat();
} else { } else {
this.setNeedToNextPhase(true); this.setNeedToNextPhase(true);
@@ -340,7 +350,7 @@ public class PhaseHandler extends MyObservable implements java.io.Serializable {
// After declare blockers are finished being declared mark them // After declare blockers are finished being declared mark them
// blocked and trigger blocking things // blocked and trigger blocking things
if (this.inCombat()) { if (this.inCombat()) {
PhaseUtil.handleDeclareBlockers(); PhaseUtil.handleDeclareBlockers(game);
CombatUtil.showCombat(); CombatUtil.showCombat();
} else { } else {
this.setNeedToNextPhase(true); this.setNeedToNextPhase(true);
@@ -440,8 +450,8 @@ public class PhaseHandler extends MyObservable implements java.io.Serializable {
if (!this.isNeedToNextPhase()) { if (!this.isNeedToNextPhase()) {
// Run triggers if phase isn't being skipped // Run triggers if phase isn't being skipped
final HashMap<String, Object> runParams = new HashMap<String, Object>(); final HashMap<String, Object> runParams = new HashMap<String, Object>();
runParams.put("Phase", phase.Name); runParams.put("Phase", this.getPhase().Name);
runParams.put("Player", turn); runParams.put("Player", this.getPlayerTurn());
game.getTriggerHandler().runTrigger(TriggerType.Phase, runParams); game.getTriggerHandler().runTrigger(TriggerType.Phase, runParams);
} }
@@ -450,7 +460,7 @@ public class PhaseHandler extends MyObservable implements java.io.Serializable {
game.getStack().unfreezeStack(); game.getStack().unfreezeStack();
// UNTAP // UNTAP
if (phase != PhaseType.UNTAP) { if (this.getPhase() != PhaseType.UNTAP) {
// during untap // during untap
this.resetPriority(); this.resetPriority();
} }
@@ -502,7 +512,7 @@ public class PhaseHandler extends MyObservable implements java.io.Serializable {
this.bCombat = false; this.bCombat = false;
} }
if (this.phaseIndex == PhaseType.CLEANUP.Index) { if (this.phase == PhaseType.CLEANUP) {
this.bPreventCombatDamageThisTurn = false; this.bPreventCombatDamageThisTurn = false;
if (!this.bRepeat) { if (!this.bRepeat) {
this.setPlayerTurn(this.handleNextTurn()); this.setPlayerTurn(this.handleNextTurn());
@@ -526,11 +536,10 @@ public class PhaseHandler extends MyObservable implements java.io.Serializable {
game.getCombat().reset(); game.getCombat().reset();
game.getCombat().setAttackingPlayer(player); game.getCombat().setAttackingPlayer(player);
game.getCombat().setDefendingPlayer(opp); game.getCombat().setDefendingPlayer(opp);
this.phaseIndex = PhaseType.COMBAT_DECLARE_ATTACKERS.Index; this.phase = PhaseType.COMBAT_DECLARE_ATTACKERS;
} else { } else {
if (!this.bRepeat) { // for when Cleanup needs to repeat itself if (!this.bRepeat) { // for when Cleanup needs to repeat itself
this.phaseIndex++; this.phase = phase.getNextPhase();
this.phaseIndex %= PhaseType.values().length;
} else { } else {
this.bRepeat = false; this.bRepeat = false;
} }
@@ -594,7 +603,7 @@ public class PhaseHandler extends MyObservable implements java.io.Serializable {
* @return a {@link forge.game.player.Player} object. * @return a {@link forge.game.player.Player} object.
*/ */
private Player getNextActivePlayer() { private Player getNextActivePlayer() {
Player nextTurn = this.getPlayerTurn().getOpponent(); Player nextTurn = game.getNextPlayerAfter(this.getPlayerTurn());
if (!this.extraTurns.isEmpty()) { if (!this.extraTurns.isEmpty()) {
ExtraTurn extraTurn = this.extraTurns.pop(); ExtraTurn extraTurn = this.extraTurns.pop();
nextTurn = extraTurn.getPlayer(); nextTurn = extraTurn.getPlayer();
@@ -669,8 +678,8 @@ public class PhaseHandler extends MyObservable implements java.io.Serializable {
* a {@link java.lang.String} object. * a {@link java.lang.String} object.
* @return a boolean. * @return a boolean.
*/ */
public final synchronized boolean is(final PhaseType phase) { public final synchronized boolean is(final PhaseType phase0) {
return this.getPhase() == phase; return this.getPhase() == phase0;
} }
/** /**
@@ -681,7 +690,7 @@ public class PhaseHandler extends MyObservable implements java.io.Serializable {
* @return a {@link java.lang.String} object. * @return a {@link java.lang.String} object.
*/ */
public final PhaseType getPhase() { public final PhaseType getPhase() {
return PhaseType.getByIndex(this.phaseIndex); return phase;
} }
/** /**
@@ -704,7 +713,7 @@ public class PhaseHandler extends MyObservable implements java.io.Serializable {
*/ */
public final Player getNextTurn() { public final Player getNextTurn() {
if (this.extraTurns.isEmpty()) { if (this.extraTurns.isEmpty()) {
return this.getPlayerTurn().getOpponent(); return game.getNextPlayerAfter(this.getPlayerTurn());
} }
return this.extraTurns.peek().getPlayer(); return this.extraTurns.peek().getPlayer();
@@ -736,35 +745,12 @@ public class PhaseHandler extends MyObservable implements java.io.Serializable {
// use a stack to handle extra turns, make sure the bottom of the stack // use a stack to handle extra turns, make sure the bottom of the stack
// restores original turn order // restores original turn order
if (this.extraTurns.isEmpty()) { if (this.extraTurns.isEmpty()) {
this.extraTurns.push(new ExtraTurn(this.getPlayerTurn().getOpponent())); this.extraTurns.push(new ExtraTurn(game.getNextPlayerAfter(this.getPlayerTurn())));
} }
return this.extraTurns.push(new ExtraTurn(player)); return this.extraTurns.push(new ExtraTurn(player));
} }
/**
* <p>
* skipTurn.
* </p>
*
* @param player
* a {@link forge.game.player.Player} object.
*/
public final void skipTurn(final Player player) {
// skipping turn without having extras is equivalent to giving your
// opponent an extra turn
boolean skipped = false;
for (ExtraTurn turn : this.extraTurns) {
if (turn.getPlayer().equals(player)) {
this.extraTurns.remove(turn);
skipped = true;
break;
}
}
if (!skipped) {
this.addExtraTurn(player.getOpponent());
}
}
/** /**
* <p> * <p>
@@ -831,7 +817,7 @@ public class PhaseHandler extends MyObservable implements java.io.Serializable {
if (firstAction.equals(actingPlayer)) { if (firstAction.equals(actingPlayer)) {
// pass the priority to other player // pass the priority to other player
this.setPriorityPlayer(actingPlayer.getOpponent()); this.setPriorityPlayer(game.getNextPlayerAfter(actingPlayer));
Singletons.getModel().getMatch().getInput().resetInput(); Singletons.getModel().getMatch().getInput().resetInput();
game.getStack().chooseOrderOfSimultaneousStackEntryAll(); game.getStack().chooseOrderOfSimultaneousStackEntryAll();
} else { } else {
@@ -929,8 +915,8 @@ public class PhaseHandler extends MyObservable implements java.io.Serializable {
* @param phase * @param phase
* a {@link java.forge.game.phase.PhaseType} object. * a {@link java.forge.game.phase.PhaseType} object.
*/ */
public final void setDevPhaseState(final PhaseType phase) { public final void setDevPhaseState(final PhaseType phase0) {
this.phaseIndex = phase.Index; this.phase = phase0;
} }
/** /**
@@ -938,8 +924,8 @@ public class PhaseHandler extends MyObservable implements java.io.Serializable {
* *
* @param phaseID the new phase state * @param phaseID the new phase state
*/ */
public final void setPhaseState(final PhaseType phaseID) { public final void setPhaseState(final PhaseType phase0) {
this.phaseIndex = phaseID.Index; this.phase = phase0;
this.handleBeginPhase(); this.handleBeginPhase();
} }

View File

@@ -1,57 +1,55 @@
package forge.game.phase; package forge.game.phase;
import java.security.InvalidParameterException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List; import java.util.List;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
public enum PhaseType { public enum PhaseType {
UNTAP("Untap", 0), UNTAP("Untap"),
UPKEEP("Upkeep", 1), UPKEEP("Upkeep"),
DRAW("Draw", 2), DRAW("Draw"),
MAIN1("Main1", 3), MAIN1("Main1"),
COMBAT_BEGIN("BeginCombat", 4), COMBAT_BEGIN("BeginCombat"),
COMBAT_DECLARE_ATTACKERS("Declare Attackers", 5), COMBAT_DECLARE_ATTACKERS("Declare Attackers"),
COMBAT_DECLARE_ATTACKERS_INSTANT_ABILITY("Declare Attackers - Play Instants and Abilities", 6), COMBAT_DECLARE_ATTACKERS_INSTANT_ABILITY("Declare Attackers - Play Instants and Abilities"),
COMBAT_DECLARE_BLOCKERS("Declare Blockers", 7), COMBAT_DECLARE_BLOCKERS("Declare Blockers"),
COMBAT_DECLARE_BLOCKERS_INSTANT_ABILITY("Declare Blockers - Play Instants and Abilities", 8), COMBAT_DECLARE_BLOCKERS_INSTANT_ABILITY("Declare Blockers - Play Instants and Abilities"),
COMBAT_FIRST_STRIKE_DAMAGE("First Strike Damage", 9), COMBAT_FIRST_STRIKE_DAMAGE("First Strike Damage"),
COMBAT_DAMAGE("Combat Damage", 10), COMBAT_DAMAGE("Combat Damage"),
COMBAT_END("EndCombat", 11), COMBAT_END("EndCombat"),
MAIN2("Main2", 12), MAIN2("Main2"),
END_OF_TURN("End of Turn", 13), END_OF_TURN("End of Turn"),
CLEANUP("Cleanup", 14); CLEANUP("Cleanup");
public static final List<PhaseType> 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_FIRST_STRIKE_DAMAGE, COMBAT_DAMAGE, COMBAT_END,
MAIN2, END_OF_TURN, CLEANUP
)
);
public final String Name; public final String Name;
public final int Index; private PhaseType(String name) {
private PhaseType(String name, int index) {
Name = name; Name = name;
Index = index;
}
public static PhaseType getByIndex(int idx) {
for (PhaseType ph : PhaseType.values()) {
if (ph.Index == idx) {
return ph;
}
}
throw new InvalidParameterException("No PhaseType found with index " + idx);
} }
public final boolean isAfter(final PhaseType phase) { public final boolean isAfter(final PhaseType phase) {
return this.Index > phase.Index; return ALL_PHASES.indexOf(this) > ALL_PHASES.indexOf(phase);
} }
public final boolean isMain() { public final boolean isMain() {
return this == MAIN1 || this == MAIN2; return this == MAIN1 || this == MAIN2;
} }
public final boolean isBefore(final PhaseType phase) { public final boolean isBefore(final PhaseType phase) {
return this.Index < phase.Index; return ALL_PHASES.indexOf(this) < ALL_PHASES.indexOf(phase);
} }
public static PhaseType smartValueOf(final String value) { public static PhaseType smartValueOf(final String value) {
@@ -91,8 +89,10 @@ public enum PhaseType {
PhaseType from = PhaseType.smartValueOf(s.substring(0, idxArrow)); PhaseType from = PhaseType.smartValueOf(s.substring(0, idxArrow));
String sTo = s.substring(idxArrow + 2); String sTo = s.substring(idxArrow + 2);
PhaseType to = StringUtils.isBlank(sTo) ? PhaseType.CLEANUP : PhaseType.smartValueOf(sTo); PhaseType to = StringUtils.isBlank(sTo) ? PhaseType.CLEANUP : PhaseType.smartValueOf(sTo);
for (int i = from.Index; i <= to.Index; i++) { int iFrom = ALL_PHASES.indexOf(from);
result.add(PhaseType.getByIndex(i)); int iTo = ALL_PHASES.indexOf(to);
for (int i = iFrom; i <= iTo; i++) {
result.add(ALL_PHASES.get(i));
} }
} }
else { else {
@@ -101,4 +101,15 @@ public enum PhaseType {
} }
return result; return result;
} }
/**
* TODO: Write javadoc for this method.
* @return
*/
public PhaseType getNextPhase() {
int iNext = ALL_PHASES.indexOf(this) + 1;
while ( iNext >= ALL_PHASES.size() )
iNext = 0;
return ALL_PHASES.get(iNext);
}
} }

View File

@@ -28,13 +28,13 @@ import forge.CardLists;
import forge.CardPredicates.Presets; import forge.CardPredicates.Presets;
import forge.Singletons; import forge.Singletons;
import forge.card.trigger.TriggerType; import forge.card.trigger.TriggerType;
import forge.game.GameState;
import forge.game.player.Player; import forge.game.player.Player;
import forge.game.zone.ZoneType; import forge.game.zone.ZoneType;
import forge.gui.match.CMatchUI; import forge.gui.match.CMatchUI;
import forge.gui.match.controllers.CMessage; import forge.gui.match.controllers.CMessage;
import forge.gui.match.nonsingleton.VField.PhaseLabel; import forge.gui.match.nonsingleton.VField.PhaseLabel;
/** /**
* <p> * <p>
* PhaseUtil class. * PhaseUtil class.
@@ -64,7 +64,8 @@ public class PhaseUtil {
return true; return true;
} }
if (Singletons.getModel().getGame().isCardInPlay("Sands of Time") || Singletons.getModel().getGame().isCardInPlay("Stasis")) { if (Singletons.getModel().getGame().isCardInPlay("Sands of Time")
|| Singletons.getModel().getGame().isCardInPlay("Stasis")) {
return true; return true;
} }
@@ -81,18 +82,18 @@ public class PhaseUtil {
* handleUntap. * handleUntap.
* </p> * </p>
*/ */
public static void handleUntap() { public static void handleUntap(GameState game) {
final PhaseHandler ph = Singletons.getModel().getGame().getPhaseHandler(); final PhaseHandler ph = game.getPhaseHandler();
final Player turn = ph.getPlayerTurn(); final Player turn = ph.getPlayerTurn();
Singletons.getModel().getGame().notifyNextTurn();
CMessage.SINGLETON_INSTANCE.updateGameInfo(Singletons.getModel().getMatch()); CMessage.SINGLETON_INSTANCE.updateGameInfo(Singletons.getModel().getMatch());
Singletons.getModel().getGame().getCombat().reset(); game.getCombat().reset();
Singletons.getModel().getGame().getCombat().setAttackingPlayer(turn); game.getCombat().setAttackingPlayer(turn);
Singletons.getModel().getGame().getCombat().setDefendingPlayer(turn.getOpponent()); game.getCombat().setDefendingPlayer(turn.getOpponent());
// Tokens starting game in play now actually suffer from Sum. Sickness again // Tokens starting game in play now actually suffer from Sum. Sickness
// again
final List<Card> list = turn.getCardsIncludePhasingIn(ZoneType.Battlefield); final List<Card> list = turn.getCardsIncludePhasingIn(ZoneType.Battlefield);
for (final Card c : list) { for (final Card c : list) {
if (turn.getTurn() > 0 || !c.isStartsGameInPlay()) { if (turn.getTurn() > 0 || !c.isStartsGameInPlay()) {
@@ -101,7 +102,7 @@ public class PhaseUtil {
} }
turn.incrementTurn(); turn.incrementTurn();
Singletons.getModel().getGame().getAction().resetActivationsPerTurn(); game.getAction().resetActivationsPerTurn();
final List<Card> lands = CardLists.filter(turn.getLandsInPlay(), Presets.UNTAPPED); final List<Card> lands = CardLists.filter(turn.getLandsInPlay(), Presets.UNTAPPED);
turn.setNumPowerSurgeLands(lands.size()); turn.setNumPowerSurgeLands(lands.size());
@@ -110,39 +111,17 @@ public class PhaseUtil {
// phase is skipped // phase is skipped
if (PhaseUtil.skipUntap(turn)) { if (PhaseUtil.skipUntap(turn)) {
Singletons.getModel().getGame().getPhaseHandler().setNeedToNextPhase(true); game.getPhaseHandler().setNeedToNextPhase(true);
return; return;
} }
Singletons.getModel().getGame().getUntap().executeUntil(turn); game.getUntap().executeUntil(turn);
Singletons.getModel().getGame().getUntap().executeAt(); game.getUntap().executeAt();
// otherwise land seems to stay tapped when it is really untapped // otherwise land seems to stay tapped when it is really untapped
//AllZone.getHumanPlayer().getZone(ZoneType.Battlefield).updateObservers(); // AllZone.getHumanPlayer().getZone(ZoneType.Battlefield).updateObservers();
Singletons.getModel().getGame().getPhaseHandler().setNeedToNextPhase(true); game.getPhaseHandler().setNeedToNextPhase(true);
}
// ******* UPKEEP PHASE *****
/**
* <p>
* handleUpkeep.
* </p>
*/
public static void handleUpkeep() {
final Player turn = Singletons.getModel().getGame().getPhaseHandler().getPlayerTurn();
if (PhaseUtil.skipUpkeep()) {
// Slowtrips all say "on the next turn's upkeep" if there is no
// upkeep next turn, the trigger will never occur.
turn.clearSlowtripList();
turn.getOpponent().clearSlowtripList();
Singletons.getModel().getGame().getPhaseHandler().setNeedToNextPhase(true);
return;
}
Singletons.getModel().getGame().getUpkeep().executeUntil(turn);
Singletons.getModel().getGame().getUpkeep().executeAt();
} }
/** /**
@@ -166,23 +145,6 @@ public class PhaseUtil {
return false; return false;
} }
// ******* DRAW PHASE *****
/**
* <p>
* handleDraw.
* </p>
*/
public static void handleDraw() {
final Player playerTurn = Singletons.getModel().getGame().getPhaseHandler().getPlayerTurn();
if (PhaseUtil.skipDraw(playerTurn)) {
Singletons.getModel().getGame().getPhaseHandler().setNeedToNextPhase(true);
return;
}
playerTurn.drawCards(1, true);
}
/** /**
* <p> * <p>
* skipDraw. * skipDraw.
@@ -192,11 +154,7 @@ public class PhaseUtil {
* a {@link forge.game.player.Player} object. * a {@link forge.game.player.Player} object.
* @return a boolean. * @return a boolean.
*/ */
private static boolean skipDraw(final Player player) { public static boolean skipDraw(final Player player) {
// starting player skips his draw
if (Singletons.getModel().getGame().getPhaseHandler().getTurn() == 1) {
return true;
}
if (player.hasKeyword("Skip your next draw step.")) { if (player.hasKeyword("Skip your next draw step.")) {
player.removeKeyword("Skip your next draw step."); player.removeKeyword("Skip your next draw step.");
@@ -212,15 +170,6 @@ public class PhaseUtil {
// ********* Declare Attackers *********** // ********* Declare Attackers ***********
/**
* <p>
* verifyCombat.
* </p>
*/
public static void verifyCombat() {
Singletons.getModel().getGame().getCombat().verifyCreaturesInPlay();
}
/** /**
* <p> * <p>
* handleCombatBegin. * handleCombatBegin.
@@ -259,7 +208,7 @@ public class PhaseUtil {
* a {@link forge.game.player.Player} object. * a {@link forge.game.player.Player} object.
* @return a boolean. * @return a boolean.
*/ */
private static boolean skipCombat(final Player player) { public static boolean skipCombat(final Player player) {
if (player.hasKeyword("Skip your next combat phase.")) { if (player.hasKeyword("Skip your next combat phase.")) {
return true; return true;
@@ -285,9 +234,10 @@ public class PhaseUtil {
* </p> * </p>
*/ */
public static void handleDeclareAttackers() { public static void handleDeclareAttackers() {
PhaseUtil.verifyCombat(); Singletons.getModel().getGame().getCombat().verifyCreaturesInPlay();
// Handles removing cards like Mogg Flunkies from combat if group attack didn't occur // Handles removing cards like Mogg Flunkies from combat if group attack
// didn't occur
final List<Card> filterList = Singletons.getModel().getGame().getCombat().getAttackerList(); final List<Card> filterList = Singletons.getModel().getGame().getCombat().getAttackerList();
for (Card c : filterList) { for (Card c : filterList) {
if (c.hasKeyword("CARDNAME can't attack or block alone.") && c.isAttacking()) { if (c.hasKeyword("CARDNAME can't attack or block alone.") && c.isAttacking()) {
@@ -351,26 +301,29 @@ public class PhaseUtil {
* <p> * <p>
* handleDeclareBlockers. * handleDeclareBlockers.
* </p> * </p>
*
* @param game
*/ */
public static void handleDeclareBlockers() { public static void handleDeclareBlockers(GameState game) {
PhaseUtil.verifyCombat(); game.getCombat().verifyCreaturesInPlay();
// Handles removing cards like Mogg Flunkies from combat if group block didn't occur // Handles removing cards like Mogg Flunkies from combat if group block
final List<Card> filterList = Singletons.getModel().getGame().getCombat().getAllBlockers(); // didn't occur
final List<Card> filterList = game.getCombat().getAllBlockers();
for (Card c : filterList) { for (Card c : filterList) {
if (c.hasKeyword("CARDNAME can't attack or block alone.") && c.isBlocking()) { if (c.hasKeyword("CARDNAME can't attack or block alone.") && c.isBlocking()) {
if (Singletons.getModel().getGame().getCombat().getAllBlockers().size() < 2) { if (game.getCombat().getAllBlockers().size() < 2) {
Singletons.getModel().getGame().getCombat().undoBlockingAssignment(c); game.getCombat().undoBlockingAssignment(c);
} }
} }
} }
Singletons.getModel().getGame().getStack().freezeStack(); game.getStack().freezeStack();
Singletons.getModel().getGame().getCombat().setUnblocked(); game.getCombat().setUnblocked();
List<Card> list = new ArrayList<Card>(); List<Card> list = new ArrayList<Card>();
list.addAll(Singletons.getModel().getGame().getCombat().getAllBlockers()); list.addAll(game.getCombat().getAllBlockers());
list = CardLists.filter(list, new Predicate<Card>() { list = CardLists.filter(list, new Predicate<Card>() {
@Override @Override
@@ -379,20 +332,20 @@ public class PhaseUtil {
} }
}); });
final List<Card> attList = Singletons.getModel().getGame().getCombat().getAttackerList(); final List<Card> attList = game.getCombat().getAttackerList();
CombatUtil.checkDeclareBlockers(list); CombatUtil.checkDeclareBlockers(list);
for (final Card a : attList) { for (final Card a : attList) {
final List<Card> blockList = Singletons.getModel().getGame().getCombat().getBlockers(a); final List<Card> blockList = game.getCombat().getBlockers(a);
for (final Card b : blockList) { for (final Card b : blockList) {
CombatUtil.checkBlockedAttackers(a, b); CombatUtil.checkBlockedAttackers(a, b);
} }
} }
Singletons.getModel().getGame().getStack().unfreezeStack(); game.getStack().unfreezeStack();
Singletons.getModel().getGame().getGameLog().add("Combat", CombatUtil.getCombatBlockForLog(), 1); game.getGameLog().add("Combat", CombatUtil.getCombatBlockForLog(), 1);
} }
// ***** Combat Utility ********** // ***** Combat Utility **********
@@ -408,66 +361,27 @@ public class PhaseUtil {
public static boolean isBeforeAttackersAreDeclared() { public static boolean isBeforeAttackersAreDeclared() {
final PhaseType phase = Singletons.getModel().getGame().getPhaseHandler().getPhase(); final PhaseType phase = Singletons.getModel().getGame().getPhaseHandler().getPhase();
return phase == PhaseType.UNTAP || phase == PhaseType.UPKEEP || phase == PhaseType.DRAW return phase == PhaseType.UNTAP || phase == PhaseType.UPKEEP || phase == PhaseType.DRAW
|| phase == PhaseType.MAIN1 || phase == PhaseType.COMBAT_BEGIN; || phase == PhaseType.MAIN1 || phase == PhaseType.COMBAT_BEGIN;
} }
/** /**
* Retrieves and visually activates phase label for appropriate phase and * Retrieves and visually activates phase label for appropriate phase and
* player. * player.
* *
* @param s * @param phase
* &emsp; Phase state * &emsp; Phase state
*/ */
public static void visuallyActivatePhase(final PhaseType s) { public static void visuallyActivatePhase(final PhaseType phase) {
PhaseLabel lbl = null;
final Player p = Singletons.getModel().getGame().getPhaseHandler().getPlayerTurn(); final Player p = Singletons.getModel().getGame().getPhaseHandler().getPlayerTurn();
final CMatchUI t = CMatchUI.SINGLETON_INSTANCE; final CMatchUI matchUi = CMatchUI.SINGLETON_INSTANCE;
// Index of field; computer is 1, human is 0 // Index of field; computer is 1, human is 0
int i = p.isComputer() ? 1 : 0; int i = p.isComputer() ? 1 : 0;
switch(s) { PhaseLabel lbl = matchUi.getFieldControls().get(i).getView().getLabelFor(phase);
case UPKEEP:
lbl = t.getFieldControls().get(i).getView().getLblUpkeep();
break;
case DRAW:
lbl = t.getFieldControls().get(i).getView().getLblDraw();
break;
case MAIN1:
lbl = t.getFieldControls().get(i).getView().getLblMain1();
break;
case COMBAT_BEGIN:
lbl = t.getFieldControls().get(i).getView().getLblBeginCombat();
break;
case COMBAT_DECLARE_ATTACKERS:
lbl = t.getFieldControls().get(i).getView().getLblDeclareAttackers();
break;
case COMBAT_DECLARE_BLOCKERS:
lbl = t.getFieldControls().get(i).getView().getLblDeclareBlockers();
break;
case COMBAT_DAMAGE:
lbl = t.getFieldControls().get(i).getView().getLblCombatDamage();
break;
case COMBAT_FIRST_STRIKE_DAMAGE:
lbl = t.getFieldControls().get(i).getView().getLblFirstStrike();
break;
case COMBAT_END:
lbl = t.getFieldControls().get(i).getView().getLblEndCombat();
break;
case MAIN2:
lbl = t.getFieldControls().get(i).getView().getLblMain2();
break;
case END_OF_TURN:
lbl = t.getFieldControls().get(i).getView().getLblEndTurn();
break;
case CLEANUP:
lbl = t.getFieldControls().get(i).getView().getLblCleanup();
break;
default:
return;
}
t.resetAllPhaseButtons(); matchUi.resetAllPhaseButtons();
lbl.setActive(true); if (lbl != null)
lbl.setActive(true);
} }
} }

View File

@@ -91,7 +91,7 @@ public enum CMessage implements ICDoc {
match.getGameType().toString() + ": Game #" match.getGameType().toString() + ": Game #"
+ (match.getPlayedGames().size() + 1) + (match.getPlayedGames().size() + 1)
+ " of " + match.getGamesPerMatch() + " of " + match.getGamesPerMatch()
+ ", turn " + match.getCurrentGame().getTurnNumber()); + ", turn " + match.getCurrentGame().getPhaseHandler().getTurn());
} }
/** Flashes animation on input panel if play is currently waiting on input. */ /** Flashes animation on input panel if play is currently waiting on input. */

View File

@@ -35,6 +35,7 @@ import javax.swing.border.MatteBorder;
import net.miginfocom.swing.MigLayout; import net.miginfocom.swing.MigLayout;
import forge.card.cardfactory.CardFactoryUtil; import forge.card.cardfactory.CardFactoryUtil;
import forge.card.mana.ManaPool; import forge.card.mana.ManaPool;
import forge.game.phase.PhaseType;
import forge.game.player.Player; import forge.game.player.Player;
import forge.game.zone.ZoneType; import forge.game.zone.ZoneType;
import forge.gui.framework.DragCell; import forge.gui.framework.DragCell;
@@ -538,6 +539,37 @@ public class VField implements IVDoc {
//========== Custom class handling //========== Custom class handling
public PhaseLabel getLabelFor(final PhaseType s) {
switch (s) {
case UPKEEP:
return this.getLblUpkeep();
case DRAW:
return this.getLblDraw();
case MAIN1:
return this.getLblMain1();
case COMBAT_BEGIN:
return this.getLblBeginCombat();
case COMBAT_DECLARE_ATTACKERS:
return this.getLblDeclareAttackers();
case COMBAT_DECLARE_BLOCKERS:
return this.getLblDeclareBlockers();
case COMBAT_DAMAGE:
return this.getLblCombatDamage();
case COMBAT_FIRST_STRIKE_DAMAGE:
return this.getLblFirstStrike();
case COMBAT_END:
return this.getLblEndCombat();
case MAIN2:
return this.getLblMain2();
case END_OF_TURN:
return this.getLblEndTurn();
case CLEANUP:
return this.getLblCleanup();
default:
return null;
}
}
/** /**
* Shows phase labels, handles repainting and on/off states. A PhaseLabel * Shows phase labels, handles repainting and on/off states. A PhaseLabel
* has "skip" and "active" states, meaning "this phase is (not) skipped" and * has "skip" and "active" states, meaning "this phase is (not) skipped" and