Applied visitor to FControl loop.

put 'give priority' on top of game loop, so that we never give anyone priority if game is over
This commit is contained in:
Maxmtg
2013-05-29 12:36:23 +00:00
parent aaeb0a2505
commit 4cbe3237af
7 changed files with 134 additions and 95 deletions

1
.gitattributes vendored
View File

@@ -14162,6 +14162,7 @@ src/main/java/forge/card/trigger/package-info.java svneol=native#text/plain
src/main/java/forge/control/ChatArea.java -text
src/main/java/forge/control/ControlBazaarUI.java -text
src/main/java/forge/control/FControl.java -text
src/main/java/forge/control/FControlGameEventHandler.java -text
src/main/java/forge/control/KeyboardShortcuts.java -text
src/main/java/forge/control/Lobby.java -text
src/main/java/forge/control/RestartUtil.java -text

View File

@@ -31,28 +31,17 @@ import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.WindowConstants;
import org.apache.commons.lang3.tuple.Pair;
import com.google.common.eventbus.Subscribe;
import forge.Card;
import forge.FThreads;
import forge.Constant.Preferences;
import forge.Singletons;
import forge.control.KeyboardShortcuts.Shortcut;
import forge.control.input.InputQueue;
import forge.game.GameState;
import forge.game.ai.AiProfileUtil;
import forge.game.event.GameEventAnteCardsSelected;
import forge.game.event.GameEventDuelFinished;
import forge.game.event.GameEvent;
import forge.game.event.GameEventTurnPhase;
import forge.game.event.GameEventPlayerControl;
import forge.game.phase.PhaseType;
import forge.game.phase.PhaseUtil;
import forge.game.player.LobbyPlayer;
import forge.game.player.Player;
import forge.gui.GuiDialog;
import forge.gui.SOverlayUtils;
import forge.gui.deckeditor.CDeckEditorUI;
import forge.gui.deckeditor.VDeckEditorUI;
@@ -64,14 +53,12 @@ import forge.gui.home.CHomeUI;
import forge.gui.home.VHomeUI;
import forge.gui.match.CMatchUI;
import forge.gui.match.VMatchUI;
import forge.gui.match.ViewWinLose;
import forge.gui.match.controllers.CCombat;
import forge.gui.match.controllers.CDock;
import forge.gui.match.controllers.CLog;
import forge.gui.match.controllers.CMessage;
import forge.gui.match.controllers.CStack;
import forge.gui.match.nonsingleton.VField;
import forge.gui.match.nonsingleton.VHand;
import forge.gui.match.views.VAntes;
import forge.gui.toolbox.CardFaceSymbols;
import forge.gui.toolbox.FSkin;
@@ -371,6 +358,7 @@ public enum FControl {
}
private final FControlGameEventHandler fcVisitor = new FControlGameEventHandler(this);
public void attachToGame(GameState game0) {
// TODO: Detach from other game we might be looking at
@@ -401,7 +389,7 @@ public enum FControl {
// some observers were set in CMatchUI.initMatch
// Listen to DuelOutcome event to show ViewWinLose
game.subscribeToEvents(this);
game.subscribeToEvents(fcVisitor);
VAntes.SINGLETON_INSTANCE.setModel(game.getRegisteredPlayers());
@@ -416,37 +404,6 @@ public enum FControl {
SDisplayUtil.showTab(nextField);
}
@Subscribe
public void receiveGameEvent(final GameEvent ev) {
if( ev instanceof GameEventDuelFinished ) {
FThreads.invokeInEdtNowOrLater(new Runnable() { @Override public void run() {
getInputQueue().onGameOver();
new ViewWinLose(game.getMatch());
SOverlayUtils.showOverlay();
} });
} else if ( ev instanceof GameEventAnteCardsSelected ) {
// Require EDT here?
final String nl = System.getProperty("line.separator");
final StringBuilder msg = new StringBuilder();
for (final Pair<Player, Card> kv : ((GameEventAnteCardsSelected) ev).cards) {
msg.append(kv.getKey().getName()).append(" ante: ").append(kv.getValue()).append(nl);
}
GuiDialog.message(msg.toString(), "Ante");
} else if ( ev instanceof GameEventPlayerControl ) {
FThreads.invokeInEdtNowOrLater(new Runnable() { @Override public void run() {
CMatchUI.SINGLETON_INSTANCE.initHandViews(getLobby().getGuiPlayer());
VMatchUI.SINGLETON_INSTANCE.populate();
for(VHand h : VMatchUI.SINGLETON_INSTANCE.getHands()) {
h.getLayoutControl().updateHand();
}
} });
} else if ( ev instanceof GameEventTurnPhase ) {
FThreads.invokeInEdtNowOrLater(new Runnable() { @Override public void run() {
Player p = ((GameEventTurnPhase) ev).playerTurn;
PhaseType ph = ((GameEventTurnPhase) ev).phase;
PhaseUtil.visuallyActivatePhase(p, ph);
} });
}
}
}

View File

@@ -0,0 +1,84 @@
package forge.control;
import org.apache.commons.lang3.tuple.Pair;
import com.google.common.eventbus.Subscribe;
import forge.Card;
import forge.FThreads;
import forge.game.event.GameEvent;
import forge.game.event.GameEventAnteCardsSelected;
import forge.game.event.GameEventDuelFinished;
import forge.game.event.GameEventDuelOutcome;
import forge.game.event.GameEventPlayerControl;
import forge.game.event.GameEventTurnPhase;
import forge.game.event.IGameEventVisitor;
import forge.game.phase.PhaseUtil;
import forge.game.player.Player;
import forge.gui.GuiDialog;
import forge.gui.SOverlayUtils;
import forge.gui.match.CMatchUI;
import forge.gui.match.VMatchUI;
import forge.gui.match.ViewWinLose;
import forge.gui.match.nonsingleton.VHand;
public class FControlGameEventHandler extends IGameEventVisitor.Base<Void, Void> {
public final FControl fc;
public FControlGameEventHandler(FControl fc ) {
this.fc = fc;
}
@Subscribe
public void receiveGameEvent(final GameEvent ev) { ev.visit(this, null); }
@Override
public Void visit(final GameEventTurnPhase ev, Void params) {
FThreads.invokeInEdtNowOrLater(new Runnable() { @Override public void run() {
PhaseUtil.visuallyActivatePhase(ev.playerTurn, ev.phase);
} });
return null;
}
@Override
public Void visit(GameEventAnteCardsSelected ev, Void params) {
// Require EDT here?
final String nl = System.getProperty("line.separator");
final StringBuilder msg = new StringBuilder();
for (final Pair<Player, Card> kv : ((GameEventAnteCardsSelected) ev).cards) {
msg.append(kv.getKey().getName()).append(" ante: ").append(kv.getValue()).append(nl);
}
GuiDialog.message(msg.toString(), "Ante");
return null;
}
@Override
public Void visit(GameEventPlayerControl ev, Void params) {
FThreads.invokeInEdtNowOrLater(new Runnable() { @Override public void run() {
CMatchUI.SINGLETON_INSTANCE.initHandViews(fc.getLobby().getGuiPlayer());
VMatchUI.SINGLETON_INSTANCE.populate();
for(VHand h : VMatchUI.SINGLETON_INSTANCE.getHands()) {
h.getLayoutControl().updateHand();
}
} });
return null;
}
@Override
public Void visit(GameEventDuelOutcome ev, Void params) {
FThreads.invokeInEdtNowOrLater(new Runnable() { @Override public void run() {
fc.getInputQueue().onGameOver();
} });
return null;
}
@Override
public Void visit(GameEventDuelFinished ev, Void params) {
FThreads.invokeInEdtNowOrLater(new Runnable() { @Override public void run() {
new ViewWinLose(fc.getObservedGame().getMatch());
SOverlayUtils.showOverlay();
} });
return null;
}
}

View File

@@ -62,6 +62,7 @@ import forge.game.ai.ComputerUtilCost;
import forge.game.event.GameEventCardDestroyed;
import forge.game.event.GameEventCardRegenerated;
import forge.game.event.GameEventCardSacrificed;
import forge.game.event.GameEventDuelFinished;
import forge.game.player.GameLossReason;
import forge.game.player.HumanPlay;
import forge.game.player.Player;
@@ -1506,7 +1507,8 @@ public class GameAction {
first = game.getPhaseHandler().getPlayerTurn(); // needed only for restart
} while( game.getAge() == GameAge.RestartedByKarn );
System.out.println(FThreads.prependThreadId("Thread exited game loop due to ... " + ( game.isGameOver() ? "game over" : "interrupt" )));
// will pull UI
game.fireEvent(new GameEventDuelFinished());
}
private void performMulligans(final Player firstPlayer, final boolean isCommander) {

View File

@@ -89,9 +89,6 @@ public class MatchState {
// The log shall listen to events and generate text internally
game.fireEvent(new GameEventDuelOutcome(result, gamesPlayedRo));
// will pull UI
game.fireEvent(new GameEventDuelFinished());
}

View File

@@ -681,52 +681,11 @@ public class PhaseHandler extends MyObservable implements java.io.Serializable {
onPhaseBegin();
updateObservers();
// don't even offer priority, because it's untap of 1st turn now
givePriorityToPlayer = false;
while (!game.isGameOver()) { // loop only while is playing
final Player actingPlayer = this.getPriorityPlayer();
final Player firstAction = this.getFirstPriority();
// actingPlayer is the player who may act
// the firstAction is the player who gained Priority First in this segment
// of Priority
Player nextPlayer = game.getNextPlayerAfter(actingPlayer);
// System.out.println(String.format("%s %s: %s passes priority to %s", playerTurn, phase, actingPlayer, nextPlayer));
if (firstAction.equals(nextPlayer)) {
if (game.getStack().isEmpty()) {
this.setPriority(this.getPlayerTurn()); // this needs to be set early as we exit the phase
// end phase
this.givePriorityToPlayer = true;
onPhaseEnd();
advanceToNextPhase();
onPhaseBegin();
} else if (!game.getStack().hasSimultaneousStackEntries()) {
game.getStack().resolveStack();
game.getStack().chooseOrderOfSimultaneousStackEntryAll();
}
} else {
// pass the priority to other player
this.pPlayerPriority = nextPlayer;
}
updateObservers();
// If ever the karn's ultimate resolved
if( game.getAge() == GameAge.RestartedByKarn) {
phase = null;
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();
boolean givePriority = givePriorityToPlayer;
boolean givePriority = givePriorityToPlayer ;
if ( phase == PhaseType.COMBAT_DECLARE_BLOCKERS)
givePriority = game.getCombat().isPlayerAttacked(pPlayerPriority);
@@ -755,6 +714,46 @@ public class PhaseHandler extends MyObservable implements java.io.Serializable {
System.out.print(" >>\n");
}
// actingPlayer is the player who may act
// the firstAction is the player who gained Priority First in this segment
// of Priority
Player nextPlayer = game.getNextPlayerAfter(this.getPriorityPlayer());
// System.out.println(String.format("%s %s: %s passes priority to %s", playerTurn, phase, actingPlayer, nextPlayer));
if (this.getFirstPriority().equals(nextPlayer)) {
if (game.getStack().isEmpty()) {
this.setPriority(this.getPlayerTurn()); // this needs to be set early as we exit the phase
// end phase
this.givePriorityToPlayer = true;
onPhaseEnd();
advanceToNextPhase();
onPhaseBegin();
} else if (!game.getStack().hasSimultaneousStackEntries()) {
game.getStack().resolveStack();
game.getStack().chooseOrderOfSimultaneousStackEntryAll();
}
} else {
// pass the priority to other player
this.pPlayerPriority = nextPlayer;
}
updateObservers();
// If ever the karn's ultimate resolved
if( game.getAge() == GameAge.RestartedByKarn) {
phase = null;
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();
}
}

View File

@@ -1,6 +1,5 @@
package forge.sound;
import java.util.List;
import forge.Card;
import forge.Singletons;
import forge.card.spellability.SpellAbility;