mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-17 19:28:01 +00:00
break out main loop step
This commit is contained in:
@@ -1030,136 +1030,139 @@ public class PhaseHandler implements java.io.Serializable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void mainGameLoop() {
|
public void mainGameLoop() {
|
||||||
StopWatch sw = new StopWatch();
|
|
||||||
|
|
||||||
// MAIN GAME LOOP
|
// MAIN GAME LOOP
|
||||||
while (!game.isGameOver()) {
|
while (!game.isGameOver() && !(game.getAge() == GameStage.RestartedByKarn)) {
|
||||||
if (givePriorityToPlayer) {
|
mainLoopStep();
|
||||||
if (DEBUG_PHASES) {
|
}
|
||||||
sw.start();
|
}
|
||||||
}
|
|
||||||
|
|
||||||
game.fireEvent(new GameEventPlayerPriority(playerTurn, phase, getPriorityPlayer()));
|
public void mainLoopStep() {
|
||||||
List<SpellAbility> chosenSa = null;
|
StopWatch sw = new StopWatch();
|
||||||
|
if (givePriorityToPlayer) {
|
||||||
int loopCount = 0;
|
if (DEBUG_PHASES) {
|
||||||
do {
|
sw.start();
|
||||||
if (checkStateBasedEffects()) {
|
|
||||||
// state-based effects check could lead to game over
|
|
||||||
// TODO: handle game over return
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
game.stashGameState();
|
|
||||||
|
|
||||||
chosenSa = pPlayerPriority.getController().chooseSpellAbilityToPlay();
|
|
||||||
|
|
||||||
// this needs to come after chosenSa so it sees you conceding on own turn
|
|
||||||
if (playerTurn.hasLost() && pPlayerPriority.equals(playerTurn) && pFirstPriority.equals(playerTurn)) {
|
|
||||||
// If the active player has lost, and they have priority, set the next player to have priority
|
|
||||||
System.out.println("Active player is no longer in the game...");
|
|
||||||
pPlayerPriority = game.getNextPlayerAfter(getPriorityPlayer());
|
|
||||||
pFirstPriority = pPlayerPriority;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (chosenSa == null) {
|
|
||||||
break; // that means 'I pass'
|
|
||||||
}
|
|
||||||
if (DEBUG_PHASES) {
|
|
||||||
System.out.print("... " + pPlayerPriority + " plays " + chosenSa);
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean rollback = false;
|
|
||||||
for (SpellAbility sa : chosenSa) {
|
|
||||||
Card saHost = sa.getHostCard();
|
|
||||||
final Zone originZone = saHost.getZone();
|
|
||||||
final CardZoneTable triggerList = new CardZoneTable(game.getLastStateBattlefield(), game.getLastStateGraveyard());
|
|
||||||
|
|
||||||
if (pPlayerPriority.getController().playChosenSpellAbility(sa)) {
|
|
||||||
// 117.3c If a player has priority when they cast a spell, activate an ability, [play a land]
|
|
||||||
// that player receives priority afterward.
|
|
||||||
pFirstPriority = pPlayerPriority; // all opponents have to pass before stack is allowed to resolve
|
|
||||||
} else if (game.EXPERIMENTAL_RESTORE_SNAPSHOT) {
|
|
||||||
rollback = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
saHost = game.getCardState(saHost);
|
|
||||||
final Zone currentZone = saHost.getZone();
|
|
||||||
|
|
||||||
// Need to check if Zone did change
|
|
||||||
if (currentZone != null && originZone != null && !currentZone.equals(originZone) && (sa.isSpell() || sa.isLandAbility())) {
|
|
||||||
// currently there can be only one Spell put on the Stack at once, or Land Abilities be played
|
|
||||||
triggerList.put(originZone.getZoneType(), currentZone.getZoneType(), saHost);
|
|
||||||
triggerList.triggerChangesZoneAll(game, sa);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Don't copy last state if we're in the middle of rolling back a spell...
|
|
||||||
if (!rollback) {
|
|
||||||
game.copyLastState();
|
|
||||||
}
|
|
||||||
loopCount++;
|
|
||||||
} while (loopCount < 999 || !pPlayerPriority.getController().isAI());
|
|
||||||
|
|
||||||
if (loopCount >= 999 && pPlayerPriority.getController().isAI()) {
|
|
||||||
System.out.print("AI looped too much with: " + chosenSa);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (DEBUG_PHASES) {
|
|
||||||
sw.stop();
|
|
||||||
System.out.print("... passed in " + sw.getTime()/1000f + " s\n");
|
|
||||||
System.out.println("\t\tStack: " + game.getStack());
|
|
||||||
sw.reset();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (DEBUG_PHASES) {
|
|
||||||
System.out.print(" >> (no priority given to " + getPriorityPlayer() + ")\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// actingPlayer is the player who may act
|
game.fireEvent(new GameEventPlayerPriority(playerTurn, phase, getPriorityPlayer()));
|
||||||
// the firstAction is the player who gained Priority First in this segment
|
List<SpellAbility> chosenSa = null;
|
||||||
// of Priority
|
|
||||||
Player nextPlayer = game.getNextPlayerAfter(getPriorityPlayer());
|
|
||||||
|
|
||||||
// TODO handle concession return
|
int loopCount = 0;
|
||||||
if (game.isGameOver() || nextPlayer == null) { return; } // conceded?
|
do {
|
||||||
|
if (checkStateBasedEffects()) {
|
||||||
|
// state-based effects check could lead to game over
|
||||||
|
// TODO: handle game over return
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
game.stashGameState();
|
||||||
|
|
||||||
|
chosenSa = pPlayerPriority.getController().chooseSpellAbilityToPlay();
|
||||||
|
|
||||||
|
// this needs to come after chosenSa so it sees you conceding on own turn
|
||||||
|
if (playerTurn.hasLost() && pPlayerPriority.equals(playerTurn) && pFirstPriority.equals(playerTurn)) {
|
||||||
|
// If the active player has lost, and they have priority, set the next player to have priority
|
||||||
|
System.out.println("Active player is no longer in the game...");
|
||||||
|
pPlayerPriority = game.getNextPlayerAfter(getPriorityPlayer());
|
||||||
|
pFirstPriority = pPlayerPriority;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (chosenSa == null) {
|
||||||
|
break; // that means 'I pass'
|
||||||
|
}
|
||||||
|
if (DEBUG_PHASES) {
|
||||||
|
System.out.print("... " + pPlayerPriority + " plays " + chosenSa);
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean rollback = false;
|
||||||
|
for (SpellAbility sa : chosenSa) {
|
||||||
|
Card saHost = sa.getHostCard();
|
||||||
|
final Zone originZone = saHost.getZone();
|
||||||
|
final CardZoneTable triggerList = new CardZoneTable(game.getLastStateBattlefield(), game.getLastStateGraveyard());
|
||||||
|
|
||||||
|
if (pPlayerPriority.getController().playChosenSpellAbility(sa)) {
|
||||||
|
// 117.3c If a player has priority when they cast a spell, activate an ability, [play a land]
|
||||||
|
// that player receives priority afterward.
|
||||||
|
pFirstPriority = pPlayerPriority; // all opponents have to pass before stack is allowed to resolve
|
||||||
|
} else if (game.EXPERIMENTAL_RESTORE_SNAPSHOT) {
|
||||||
|
rollback = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
saHost = game.getCardState(saHost);
|
||||||
|
final Zone currentZone = saHost.getZone();
|
||||||
|
|
||||||
|
// Need to check if Zone did change
|
||||||
|
if (currentZone != null && originZone != null && !currentZone.equals(originZone) && (sa.isSpell() || sa.isLandAbility())) {
|
||||||
|
// currently there can be only one Spell put on the Stack at once, or Land Abilities be played
|
||||||
|
triggerList.put(originZone.getZoneType(), currentZone.getZoneType(), saHost);
|
||||||
|
triggerList.triggerChangesZoneAll(game, sa);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Don't copy last state if we're in the middle of rolling back a spell...
|
||||||
|
if (!rollback) {
|
||||||
|
game.copyLastState();
|
||||||
|
}
|
||||||
|
loopCount++;
|
||||||
|
} while (loopCount < 999 || !pPlayerPriority.getController().isAI());
|
||||||
|
|
||||||
|
if (loopCount >= 999 && pPlayerPriority.getController().isAI()) {
|
||||||
|
System.out.print("AI looped too much with: " + chosenSa);
|
||||||
|
}
|
||||||
|
|
||||||
if (DEBUG_PHASES) {
|
if (DEBUG_PHASES) {
|
||||||
System.out.println(TextUtil.concatWithSpace(playerTurn.toString(),TextUtil.addSuffix(phase.toString(),":"), pPlayerPriority.toString(),"is active, previous was", nextPlayer.toString()));
|
sw.stop();
|
||||||
|
System.out.print("... passed in " + sw.getTime()/1000f + " s\n");
|
||||||
|
System.out.println("\t\tStack: " + game.getStack());
|
||||||
|
sw.reset();
|
||||||
}
|
}
|
||||||
if (pFirstPriority == nextPlayer) {
|
}
|
||||||
if (game.getStack().isEmpty()) {
|
else if (DEBUG_PHASES) {
|
||||||
if (playerTurn.hasLost()) {
|
System.out.print(" >> (no priority given to " + getPriorityPlayer() + ")\n");
|
||||||
setPriority(game.getNextPlayerAfter(playerTurn));
|
}
|
||||||
} else {
|
|
||||||
setPriority(playerTurn);
|
|
||||||
}
|
|
||||||
|
|
||||||
// end phase
|
// actingPlayer is the player who may act
|
||||||
givePriorityToPlayer = true;
|
// the firstAction is the player who gained Priority First in this segment
|
||||||
onPhaseEnd();
|
// of Priority
|
||||||
advanceToNextPhase();
|
Player nextPlayer = game.getNextPlayerAfter(getPriorityPlayer());
|
||||||
onPhaseBegin();
|
|
||||||
|
// TODO handle concession return
|
||||||
|
if (game.isGameOver() || nextPlayer == null) { return; } // conceded?
|
||||||
|
|
||||||
|
if (DEBUG_PHASES) {
|
||||||
|
System.out.println(TextUtil.concatWithSpace(playerTurn.toString(),TextUtil.addSuffix(phase.toString(),":"), pPlayerPriority.toString(),"is active, previous was", nextPlayer.toString()));
|
||||||
|
}
|
||||||
|
if (pFirstPriority == nextPlayer) {
|
||||||
|
if (game.getStack().isEmpty()) {
|
||||||
|
if (playerTurn.hasLost()) {
|
||||||
|
setPriority(game.getNextPlayerAfter(playerTurn));
|
||||||
|
} else {
|
||||||
|
setPriority(playerTurn);
|
||||||
}
|
}
|
||||||
else if (!game.getStack().hasSimultaneousStackEntries()) {
|
|
||||||
game.getStack().resolveStack();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// pass the priority to other player
|
|
||||||
pPlayerPriority = nextPlayer;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If ever the karn's ultimate resolved
|
// end phase
|
||||||
if (game.getAge() == GameStage.RestartedByKarn) {
|
givePriorityToPlayer = true;
|
||||||
setPhase(null);
|
onPhaseEnd();
|
||||||
game.updatePhaseForView();
|
advanceToNextPhase();
|
||||||
game.fireEvent(new GameEventGameRestarted(playerTurn));
|
onPhaseBegin();
|
||||||
// TODO: handle karn restart return
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
else if (!game.getStack().hasSimultaneousStackEntries()) {
|
||||||
|
game.getStack().resolveStack();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// pass the priority to other player
|
||||||
|
pPlayerPriority = nextPlayer;
|
||||||
|
}
|
||||||
|
|
||||||
// update Priority for all players
|
// If ever the karn's ultimate resolved
|
||||||
for (final Player p : game.getPlayers()) {
|
if (game.getAge() == GameStage.RestartedByKarn) {
|
||||||
p.setHasPriority(getPriorityPlayer() == p);
|
setPhase(null);
|
||||||
}
|
game.updatePhaseForView();
|
||||||
|
game.fireEvent(new GameEventGameRestarted(playerTurn));
|
||||||
|
// TODO: handle karn restart return
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// update Priority for all players
|
||||||
|
for (final Player p : game.getPlayers()) {
|
||||||
|
p.setHasPriority(getPriorityPlayer() == p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user