Game starts with phase = NULL and turn = 0. This lets us log turn 1 beginning properly.

Some effects may not work during turn 0 (leylines/chancellors) - if they do, convert them to T:Phase Upkeep | Turn$ 1
This commit is contained in:
Maxmtg
2013-05-26 21:36:58 +00:00
parent 3eb9aed797
commit f9f0a77cd9
7 changed files with 85 additions and 102 deletions

View File

@@ -43,14 +43,10 @@ public class InputQueue extends MyObservable implements java.io.Serializable {
private static final long serialVersionUID = 3955194449319994301L; private static final long serialVersionUID = 3955194449319994301L;
private final BlockingDeque<Input> inputStack = new LinkedBlockingDeque<Input>(); private final BlockingDeque<Input> inputStack = new LinkedBlockingDeque<Input>();
private final GameState game;
private final InputLockUI inputLock; private final InputLockUI inputLock;
public InputQueue(GameState game0) { public InputQueue() {
game = game0;
inputLock = new InputLockUI(this); inputLock = new InputLockUI(this);
} }
@@ -80,17 +76,6 @@ public class InputQueue extends MyObservable implements java.io.Serializable {
return inputStack.isEmpty() ? null : this.inputStack.peek(); return inputStack.isEmpty() ? null : this.inputStack.peek();
} }
/**
* <p>
* clearInput.
* </p>
*/
public final void clearInput() {
this.inputStack.clear();
this.updateObservers();
}
/** /**
* <p> * <p>
* resetInput. * resetInput.
@@ -101,19 +86,11 @@ public class InputQueue extends MyObservable implements java.io.Serializable {
*/ */
final void removeInput(Input inp) { final void removeInput(Input inp) {
FThreads.assertExecutedByEdt(false); FThreads.assertExecutedByEdt(false);
Input topMostInput = inputStack.isEmpty() ? null : inputStack.pop(); Input topMostInput = inputStack.isEmpty() ? null : inputStack.pop();
// StackTraceElement[] trace = Thread.currentThread().getStackTrace();
// System.out.printf("%s > Remove input %s -- called from %s%n", FThreads.isEDT() ? "EDT" : "TRD", topMostInput, trace[2].toString());
// if( trace[2].toString().contains("InputBase.stop"))
// for(StackTraceElement se : trace) {
// System.out.println(se.toString());
// }
if( topMostInput != inp ) if( topMostInput != inp )
throw new RuntimeException("Inputs adding/removal into stack is imbalanced! Check your code again!"); throw new RuntimeException("Inputs adding/removal into stack is imbalanced! Check your code again!");
this.updateObservers(); this.updateObservers();
} }
@@ -128,7 +105,7 @@ public class InputQueue extends MyObservable implements java.io.Serializable {
* *
* @return a {@link forge.control.input.InputBase} object. * @return a {@link forge.control.input.InputBase} object.
*/ */
public final Input getActualInput() { public final Input getActualInput(GameState game) {
GameAge age = game.getAge(); GameAge age = game.getAge();
if ( game.isGameOver() ) if ( game.isGameOver() )
@@ -142,7 +119,7 @@ public class InputQueue extends MyObservable implements java.io.Serializable {
return inputLock; return inputLock;
final PhaseHandler handler = game.getPhaseHandler(); final PhaseHandler handler = game.getPhaseHandler();
final PhaseType phase = handler.getPhase();
final Player playerTurn = handler.getPlayerTurn(); final Player playerTurn = handler.getPlayerTurn();
final Player priority = handler.getPriorityPlayer(); final Player priority = handler.getPriorityPlayer();
if (priority == null) if (priority == null)
@@ -155,6 +132,7 @@ public class InputQueue extends MyObservable implements java.io.Serializable {
} }
// Special Inputs needed for the following phases: // Special Inputs needed for the following phases:
final PhaseType phase = handler.getPhase();
final MagicStack stack = game.getStack(); final MagicStack stack = game.getStack();
switch (phase) { switch (phase) {
case COMBAT_DECLARE_ATTACKERS: case COMBAT_DECLARE_ATTACKERS:
@@ -168,12 +146,8 @@ public class InputQueue extends MyObservable implements java.io.Serializable {
case COMBAT_DECLARE_BLOCKERS: case COMBAT_DECLARE_BLOCKERS:
stack.freezeStack(); stack.freezeStack();
if (game.getCombat().isPlayerAttacked(priority)) { boolean isAttacked = game.getCombat().isPlayerAttacked(priority);
return pc.getBlockInput(); return isAttacked ? pc.getBlockInput() : pc.getAutoPassPriorityInput();
}
// noone attacks you
return pc.getAutoPassPriorityInput();
case CLEANUP: case CLEANUP:
// discard // discard

View File

@@ -1476,12 +1476,16 @@ public class GameAction {
public void mulligan(final Player firstPlayer) { public void mulligan(final Player firstPlayer) {
performMulligans(firstPlayer, game.getType() == GameType.Commander); performMulligans(firstPlayer, game.getType() == GameType.Commander);
handleLeylinesAndChancellors();
// Run Trigger beginning of the game
final HashMap<String, Object> runParams = new HashMap<String, Object>();
game.getTriggerHandler().runTrigger(TriggerType.NewGame, runParams, false);
game.setAge(GameAge.Play); game.setAge(GameAge.Play);
game.getInputQueue().clearInput();
// THIS CODE WILL WORK WITH PHASE = NULL {
handleLeylinesAndChancellors();
// Run Trigger beginning of the game
final HashMap<String, Object> runParams = new HashMap<String, Object>();
game.getTriggerHandler().runTrigger(TriggerType.NewGame, runParams, false);
// }
game.getPhaseHandler().startFirstTurn(firstPlayer);
} }
private void performMulligans(final Player firstPlayer, final boolean isCommander) { private void performMulligans(final Player firstPlayer, final boolean isCommander) {

View File

@@ -89,7 +89,7 @@ public class GameState {
private final MatchController match; private final MatchController match;
private GameAge age = GameAge.BeforeMulligan; private GameAge age = GameAge.BeforeMulligan;
private final InputQueue inputQueue; private final InputQueue inputQueue = new InputQueue();
/** /**
* Constructor. * Constructor.
@@ -128,8 +128,6 @@ public class GameState {
endOfTurn = new EndOfTurn(this); endOfTurn = new EndOfTurn(this);
endOfCombat = new EndOfCombat(this); endOfCombat = new EndOfCombat(this);
inputQueue = new InputQueue(this);
if ( match0.getGameType() == GameType.Quest) if ( match0.getGameType() == GameType.Quest)
events.register(Singletons.getModel().getQuest()); // this one listens to player's mulligans ATM events.register(Singletons.getModel().getQuest()); // this one listens to player's mulligans ATM

View File

@@ -132,7 +132,6 @@ public class MatchController {
currentGame.getInputQueue().invokeGameAction(new Runnable() { currentGame.getInputQueue().invokeGameAction(new Runnable() {
@Override @Override
public void run() { public void run() {
currentGame.getInputQueue().clearInput();
if(currentGame.getType() == GameType.Planechase) if(currentGame.getType() == GameType.Planechase)
firstPlayer.initPlane(); firstPlayer.initPlane();
@@ -266,7 +265,6 @@ public class MatchController {
boolean willPlay = goesFirst.getController().getWillPlayOnFirstTurn(message); boolean willPlay = goesFirst.getController().getWillPlayOnFirstTurn(message);
goesFirst = willPlay ? goesFirst : goesFirst.getOpponent(); goesFirst = willPlay ? goesFirst : goesFirst.getOpponent();
game.getPhaseHandler().setPlayerTurn(goesFirst);
return goesFirst; return goesFirst;
} }

View File

@@ -56,9 +56,10 @@ 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 PhaseType phase = PhaseType.UNTAP; // Start turn at 0, since we start even before first untap
private int turn = 1; private PhaseType phase = null;
// Start turn at 1, since first untap is where we start private int turn = 0;
private final transient Stack<ExtraTurn> extraTurns = new Stack<ExtraTurn>(); private final transient Stack<ExtraTurn> extraTurns = new Stack<ExtraTurn>();
private final transient Map<PhaseType, Stack<PhaseType>> extraPhases = new HashMap<PhaseType, Stack<PhaseType>>(); private final transient Map<PhaseType, Stack<PhaseType>> extraPhases = new HashMap<PhaseType, Stack<PhaseType>>();
@@ -232,38 +233,39 @@ public class PhaseHandler extends MyObservable implements java.io.Serializable {
p.updateObservers(); p.updateObservers();
} }
switch (this.phase) { if( phase != null ) {
case UNTAP: switch (this.phase) {
this.nCombatsThisTurn = 0; case UNTAP:
break; this.nCombatsThisTurn = 0;
break;
case COMBAT_DECLARE_ATTACKERS:
game.getStack().unfreezeStack(); case COMBAT_DECLARE_ATTACKERS:
this.nCombatsThisTurn++; game.getStack().unfreezeStack();
break; this.nCombatsThisTurn++;
break;
case COMBAT_DECLARE_BLOCKERS:
game.getStack().unfreezeStack(); case COMBAT_DECLARE_BLOCKERS:
break; game.getStack().unfreezeStack();
break;
case COMBAT_END:
//SDisplayUtil.showTab(EDocID.REPORT_STACK.getDoc()); case COMBAT_END:
game.getCombat().reset(playerTurn); game.getCombat().reset(playerTurn);
this.getPlayerTurn().resetAttackedThisCombat(); this.getPlayerTurn().resetAttackedThisCombat();
this.bCombat.set(false); this.bCombat.set(false);
break; break;
case CLEANUP: case CLEANUP:
this.bPreventCombatDamageThisTurn = false; this.bPreventCombatDamageThisTurn = false;
if (!this.bRepeatCleanup) { if (!this.bRepeatCleanup) {
this.setPlayerTurn(this.handleNextTurn()); this.setPlayerTurn(this.handleNextTurn());
} }
this.planarDiceRolledthisTurn = 0; this.planarDiceRolledthisTurn = 0;
// Play the End Turn sound // Play the End Turn sound
game.getEvents().post(new EndOfTurnEvent()); game.getEvents().post(new EndOfTurnEvent());
break; break;
default: // no action default: // no action
}
} }
String phaseType = ""; String phaseType = "";
@@ -283,7 +285,7 @@ public class PhaseHandler extends MyObservable implements java.io.Serializable {
this.phase = nextPhase; this.phase = nextPhase;
phaseType = "Additional "; phaseType = "Additional ";
} else { } else {
this.phase = phase.getNextPhase(); this.phase = PhaseType.getNext(phase);
} }
} }
@@ -712,15 +714,7 @@ public class PhaseHandler extends MyObservable implements java.io.Serializable {
// System.out.println(String.format("%s %s: %s passes priority to %s", playerTurn, phase, actingPlayer, nextPlayer)); // System.out.println(String.format("%s %s: %s passes priority to %s", playerTurn, phase, actingPlayer, nextPlayer));
if (firstAction.equals(nextPlayer)) { if (firstAction.equals(nextPlayer)) {
if (game.getStack().isEmpty()) { if (game.getStack().isEmpty()) {
this.setPriority(this.getPlayerTurn()); // this needs to be set early as we exit the phase advancePhase();
// end phase
setPlayersPriorityPermission(true);
nextPhase();
// When consecutively skipping phases (like in combat) this section
// pushes through that block
handleBeginPhase();
// it no longer does.
updateObservers();
} else if (!game.getStack().hasSimultaneousStackEntries()) { } else if (!game.getStack().hasSimultaneousStackEntries()) {
game.getStack().resolveStack(); game.getStack().resolveStack();
game.getStack().chooseOrderOfSimultaneousStackEntryAll(); game.getStack().chooseOrderOfSimultaneousStackEntryAll();
@@ -733,6 +727,26 @@ public class PhaseHandler extends MyObservable implements java.io.Serializable {
} }
} }
public void startFirstTurn(Player goesFirst) {
if(phase != null)
throw new IllegalStateException("Turns already started, call this only once per game");
setPlayerTurn(goesFirst);
advancePhase();
}
private void advancePhase() { // may be called externally only from gameAction after mulligans
this.setPriority(this.getPlayerTurn()); // this needs to be set early as we exit the phase
// end phase
setPlayersPriorityPermission(true);
nextPhase();
// When consecutively skipping phases (like in combat) this section
// pushes through that block
handleBeginPhase();
// it no longer does.
updateObservers();
}
/** /**
* <p> * <p>

View File

@@ -106,9 +106,9 @@ public enum PhaseType {
* Get the next PhaseType in turn order. * Get the next PhaseType in turn order.
* @return * @return
*/ */
public PhaseType getNextPhase() { public static PhaseType getNext(PhaseType current) {
int iNext = ALL_PHASES.indexOf(this) + 1; int iNext = ALL_PHASES.indexOf(current) + 1;
while (iNext >= ALL_PHASES.size()) { if (iNext >= ALL_PHASES.size()) {
iNext = 0; iNext = 0;
} }
return ALL_PHASES.get(iNext); return ALL_PHASES.get(iNext);

View File

@@ -43,11 +43,10 @@ public class InputProxy implements Observer {
private AtomicReference<Input> input = new AtomicReference<Input>(); private AtomicReference<Input> input = new AtomicReference<Input>();
private GameState game = null; private GameState game = null;
private static final boolean INPUT_DEBUG = false; private static final boolean DEBUG_INPUT = false;
public void setGame(GameState game0) { public void setGame(GameState game0) {
game = game0; game = game0;
// game.getStack().addObserver(this);
game.getPhaseHandler().addObserver(this); game.getPhaseHandler().addObserver(this);
game.getInputQueue().addObserver(this); game.getInputQueue().addObserver(this);
} }
@@ -58,19 +57,15 @@ public class InputProxy implements Observer {
FThreads.assertExecutedByEdt(false); FThreads.assertExecutedByEdt(false);
final PhaseHandler ph = game.getPhaseHandler(); final PhaseHandler ph = game.getPhaseHandler();
final Input nextInput = game.getInputQueue().getActualInput(); final Input nextInput = game.getInputQueue().getActualInput(game);
if(DEBUG_INPUT)
if(INPUT_DEBUG) { System.out.printf("%s ... \t%s on %s, \tstack = %s%n", FThreads.debugGetStackTraceItem(6, true), nextInput == null ? "null" : nextInput.getClass().getSimpleName(), ph.debugPrintState(), game.getInputQueue().printInputStack());
System.out.print(FThreads.debugGetStackTraceItem(6, true) + " ... ");
System.out.printf("\t%s on %s, \tstack = %s%n", nextInput == null ? "null" : nextInput.getClass().getSimpleName(), ph.debugPrintState(), game.getInputQueue().printInputStack());
}
this.input.set(nextInput); this.input.set(nextInput);
Runnable showMessage = new Runnable() { Runnable showMessage = new Runnable() {
@Override public void run() { @Override public void run() {
//if(INPUT_DEBUG) // System.out.printf("%s > showMessage @ %s/%s during %s%n%n", FThreads.debugGetCurrThreadId(), nextInput.getClass().getSimpleName(), getInput().getClass().getSimpleName(), ph.debugPrintState());
// System.out.printf("%s > showMessage @ %s/%s during %s%n%n", FThreads.debugGetCurrThreadId(), nextInput.getClass().getSimpleName(), getInput().getClass().getSimpleName(), ph.debugPrintState());
getInput().showMessage(game.getInputQueue()); getInput().showMessage(game.getInputQueue());
} }
}; };