From 8f023aaed36b4f86f5ed484683035e18da4b5423 Mon Sep 17 00:00:00 2001
From: drdev
Date: Thu, 9 Oct 2014 15:01:45 +0000
Subject: [PATCH] Support updating game view
---
forge-game/src/main/java/forge/game/Game.java | 175 ++------
.../src/main/java/forge/game/GameView.java | 95 ++++-
.../src/main/java/forge/game/Match.java | 38 +-
.../src/main/java/forge/game/card/Card.java | 2 +-
.../java/forge/game/card/CardFactoryUtil.java | 2 +-
.../main/java/forge/game/card/CardUtil.java | 4 +-
.../main/java/forge/game/combat/Combat.java | 195 ++++-----
.../forge/game/mana/ManaCostAdjustment.java | 4 +-
.../java/forge/game/phase/PhaseHandler.java | 401 ++++++------------
.../StaticAbilityCantBeCast.java | 2 +-
.../main/java/forge/game/zone/MagicStack.java | 358 +++++-----------
.../forge/trackable/TrackableProperty.java | 17 +-
12 files changed, 478 insertions(+), 815 deletions(-)
diff --git a/forge-game/src/main/java/forge/game/Game.java b/forge-game/src/main/java/forge/game/Game.java
index d86ac62e7f1..bdd9e9e6912 100644
--- a/forge-game/src/main/java/forge/game/Game.java
+++ b/forge-game/src/main/java/forge/game/Game.java
@@ -97,7 +97,7 @@ public class Game {
private GameOutcome outcome;
private boolean disableAutoYields;
- private final GameView view = new GameView();
+ private final GameView view;
public Game(List players0, GameRules rules0, Match match0) { /* no more zones to map here */
rules = rules0;
@@ -147,6 +147,8 @@ public class Game {
endOfTurn = new EndOfTurn(this);
endOfCombat = new Phase(PhaseType.COMBAT_END);
+ view = new GameView(this);
+
subscribeToEvents(gameLog.getEventVisitor());
}
@@ -154,10 +156,15 @@ public class Game {
return view;
}
+ /**
+ * Gets the players who are still fighting to win.
+ */
+ public final List getPlayers() {
+ return roIngamePlayers;
+ }
+
/**
* Gets the players who are still fighting to win, in turn order.
- *
- * @return the players
*/
public final List getPlayersInTurnOrder() {
if (turnOrder.isDefaultDirection()) {
@@ -165,130 +172,73 @@ public class Game {
}
return roIngamePlayersReversed;
}
-
- /**
- * Gets the players who are still fighting to win.
- *
- * @return the players
- */
- public final List getPlayers() {
- return roIngamePlayers;
- }
/**
* Gets the players who participated in match (regardless of outcome).
* Use this in UI and after match calculations
- *
- * @return the players
*/
public final List getRegisteredPlayers() {
return allPlayers;
}
- /**
- * Gets the cleanup step.
- *
- * @return the cleanup step
- */
+ public final Untap getUntap() {
+ return untap;
+ }
+ public final Upkeep getUpkeep() {
+ return upkeep;
+ }
+ public final Phase getEndOfCombat() {
+ return endOfCombat;
+ }
+ public final EndOfTurn getEndOfTurn() {
+ return endOfTurn;
+ }
public final Phase getCleanup() {
return cleanup;
}
- /**
- * Gets the end of turn.
- *
- * @return the endOfTurn
- */
- public final EndOfTurn getEndOfTurn() {
- return endOfTurn;
- }
-
- /**
- * Gets the end of combat.
- *
- * @return the endOfCombat
- */
- public final Phase getEndOfCombat() {
- return endOfCombat;
- }
-
- /**
- * Gets the upkeep.
- *
- * @return the upkeep
- */
- public final Upkeep getUpkeep() {
- return upkeep;
- }
-
- /**
- * Gets the untap.
- *
- * @return the upkeep
- */
- public final Untap getUntap() {
- return untap;
- }
-
- /**
- * Gets the phaseHandler.
- *
- * @return the phaseHandler
- */
public final PhaseHandler getPhaseHandler() {
return phaseHandler;
}
+ public final void updateTurnForView() {
+ view.updateTurn(phaseHandler);
+ }
+ public final void updatePhaseForView() {
+ view.updatePhase(phaseHandler);
+ }
+ public final void updatePlayerTurnForView() {
+ view.updatePlayerTurn(phaseHandler);
+ }
- /**
- * Gets the stack.
- *
- * @return the stack
- */
public final MagicStack getStack() {
return stack;
}
+ public final void updateStackForView() {
+ view.updateStack(stack);
+ }
- /**
- * Gets the static effects.
- *
- * @return the staticEffects
- */
public final StaticEffects getStaticEffects() {
return staticEffects;
}
- /**
- * Gets the trigger handler.
- *
- * @return the triggerHandler
- */
public final TriggerHandler getTriggerHandler() {
return triggerHandler;
}
- /**
- * Gets the combat.
- *
- * @return the combat
- */
public final Combat getCombat() {
return getPhaseHandler().getCombat();
}
+ public final void updateCombatForView() {
+ view.updateCombat(getCombat());
+ }
- /**
- * Gets the game log.
- *
- * @return the game log
- */
public final GameLog getGameLog() {
return gameLog;
}
+ public final void updateGameLogForView() {
+ view.updateGameLog(gameLog);
+ }
- /**
- * Gets the stack zone.
- *
- * @return the stackZone
- */
public final Zone getStackZone() {
return stackZone;
}
@@ -311,37 +261,25 @@ public class Game {
}
/**
- * Get the turn order.
- * @return the Direction in which the turn order of this Game currently
- * proceeds.
+ * The Direction in which the turn order of this Game currently proceeds.
*/
public final Direction getTurnOrder() {
return turnOrder;
}
-
public final void reverseTurnOrder() {
turnOrder = turnOrder.getOtherDirection();
}
-
public final void resetTurnOrder() {
turnOrder = Direction.getDefaultDirection();
}
/**
* Create and return the next timestamp.
- *
- * @return the next timestamp
*/
public final long getNextTimestamp() {
timestamp = getTimestamp() + 1;
return getTimestamp();
}
-
- /**
- * Gets the timestamp.
- *
- * @return the timestamp
- */
public final long getTimestamp() {
return timestamp;
}
@@ -350,24 +288,14 @@ public class Game {
return outcome;
}
- /**
- * @return the replacementHandler
- */
public ReplacementHandler getReplacementHandler() {
return replacementHandler;
}
- /**
- * @return the gameOver
- */
public synchronized boolean isGameOver() {
return age == GameStage.GameOver;
}
- /**
- * @param reason
- * @param go the gameOver to set
- */
public synchronized void setGameOver(GameEndReason reason) {
age = GameStage.GameOver;
for (Player p : allPlayers) {
@@ -380,10 +308,12 @@ public class Game {
final GameOutcome result = new GameOutcome(reason, getRegisteredPlayers());
result.setTurnsPlayed(getPhaseHandler().getTurn());
-
+
outcome = result;
match.addGamePlayed(this);
+ view.updateGameOver(this);
+
// The log shall listen to events and generate text internally
fireEvent(new GameEventGameOutcome(result, match.getPlayedGames()));
}
@@ -544,10 +474,6 @@ public class Game {
return position;
}
- /**
- * TODO: Write javadoc for this method.
- * @param p
- */
public void onPlayerLost(Player p) {
ingamePlayers.remove(p);
@@ -571,23 +497,13 @@ public class Game {
events.register(subscriber);
}
- /**
- * @return the type of game (Constructed/Limited/Planechase/etc...)
- */
public GameRules getRules() {
return rules;
}
- /**
- * @return the activePlane
- */
public List getActivePlanes() {
return activePlanes;
}
-
- /**
- * @param activePlane0 the activePlane to set
- */
public void setActivePlanes(List activePlane0) {
activePlanes = activePlane0;
}
@@ -604,7 +520,7 @@ public class Game {
Card c = getCardsIn(ZoneType.Command).get(i);
if (c.isScheme() && !c.isType("Ongoing")) {
boolean foundonstack = false;
- for (SpellAbilityStackInstance si : getStack()) {
+ for (SpellAbilityStackInstance si : stack) {
if (si.getSourceCard().equals(c)) {
foundonstack = true;
break;
@@ -719,7 +635,6 @@ public class Game {
chooseRandomCardsForAnte(player, anteed);
}
}
-
return anteed;
}
diff --git a/forge-game/src/main/java/forge/game/GameView.java b/forge-game/src/main/java/forge/game/GameView.java
index b907b530c62..8bbfca0a89e 100644
--- a/forge-game/src/main/java/forge/game/GameView.java
+++ b/forge-game/src/main/java/forge/game/GameView.java
@@ -7,28 +7,109 @@ import forge.game.card.CardView;
import forge.game.combat.AttackingBand;
import forge.game.combat.Combat;
import forge.game.combat.CombatView;
+import forge.game.phase.PhaseHandler;
+import forge.game.phase.PhaseType;
import forge.game.player.PlayerView;
import forge.game.spellability.SpellAbilityView;
import forge.game.spellability.StackItemView;
+import forge.game.zone.MagicStack;
import forge.trackable.TrackableIndex;
+import forge.trackable.TrackableObject;
+import forge.trackable.TrackableProperty;
-public class GameView {
+public class GameView extends TrackableObject {
private final TrackableIndex cards = new TrackableIndex();
private final TrackableIndex players = new TrackableIndex();
private final TrackableIndex spellAbilities = new TrackableIndex();
private final TrackableIndex stackItems = new TrackableIndex();
private CombatView combatView;
- public GameView() {
-
+ public GameView(Game game) {
+ super(-1); //ID not needed
+ set(TrackableProperty.WinningTeam, -1);
+
+ GameRules rules = game.getRules();
+ set(TrackableProperty.Commander, rules.hasAppliedVariant(GameType.Commander));
+ set(TrackableProperty.GameType, rules.getGameType());
+ set(TrackableProperty.PoisonCountersToLose, rules.getPoisonCountersToLose());
+ set(TrackableProperty.NumGamesInMatch, rules.getGamesPerMatch());
+
+ set(TrackableProperty.GameLog, game.getGameLog());
+ set(TrackableProperty.NumPlayedGamesInMatch, game.getMatch().getPlayedGames().size());
}
- public CombatView getCombatView() {
+ public boolean isCommander() {
+ return get(TrackableProperty.Commander);
+ }
+ public GameType getGameType() {
+ return get(TrackableProperty.GameType);
+ }
+ public int getPoisonCountersToLose() {
+ return get(TrackableProperty.PoisonCountersToLose);
+ }
+ public int getNumGamesInMatch() {
+ return get(TrackableProperty.NumGamesInMatch);
+ }
+
+ public int getTurn() {
+ return get(TrackableProperty.Turn);
+ }
+ void updateTurn(PhaseHandler phaseHandler) {
+ set(TrackableProperty.Turn, phaseHandler.getTurn());
+ }
+ public PhaseType getPhase() {
+ return get(TrackableProperty.Phase);
+ }
+ void updatePhase(PhaseHandler phaseHandler) {
+ set(TrackableProperty.Phase, phaseHandler.getPhase());
+ }
+ public PlayerView getPlayerTurn() {
+ return get(TrackableProperty.PlayerTurn);
+ }
+ void updatePlayerTurn(PhaseHandler phaseHandler) {
+ set(TrackableProperty.PlayerTurn, PlayerView.get(phaseHandler.getPlayerTurn()));
+ }
+
+ public int getStormCount() {
+ return get(TrackableProperty.StormCount);
+ }
+ void updateStack(MagicStack stack) {
+ set(TrackableProperty.StormCount, stack.getSpellsCastThisTurn().size());
+ }
+
+ public boolean isFirstGameInMatch() {
+ return getNumPlayedGamesInMatch() == 0;
+ }
+ public int getNumPlayedGamesInMatch() {
+ return get(TrackableProperty.NumPlayedGamesInMatch);
+ }
+
+ public boolean isGameOver() {
+ return get(TrackableProperty.GameOver);
+ }
+ public boolean isMatchOver() {
+ return get(TrackableProperty.MatchOver);
+ }
+ public int getWinningTeam() {
+ return get(TrackableProperty.WinningTeam);
+ }
+ void updateGameOver(Game game) {
+ set(TrackableProperty.GameOver, game.isGameOver());
+ set(TrackableProperty.MatchOver, game.getMatch().isMatchOver());
+ set(TrackableProperty.WinningTeam, game.getOutcome() == null ? -1 : game.getOutcome().getWinningTeam());
+ }
+
+ public GameLog getGameLog() {
+ return get(TrackableProperty.GameLog);
+ }
+ void updateGameLog(GameLog gameLog) {
+ flagAsChanged(TrackableProperty.GameLog); //don't need to set the property since it won't change
+ }
+
+ public CombatView getCombat() {
return combatView;
}
-
- public void refreshCombat(Game game) {
- final Combat combat = game.getCombat();
+ void updateCombat(Combat combat) {
if (combat == null) {
combatView = null;
return;
diff --git a/forge-game/src/main/java/forge/game/Match.java b/forge-game/src/main/java/forge/game/Match.java
index 3ac00bb9a7d..4e3e07f069c 100644
--- a/forge-game/src/main/java/forge/game/Match.java
+++ b/forge-game/src/main/java/forge/game/Match.java
@@ -27,26 +27,20 @@ public class Match {
private final List gamesPlayed = new ArrayList();
private final List gamesPlayedRo;
- public Match(GameRules rules, List players0) {
+ public Match(GameRules rules0, List players0) {
gamesPlayedRo = Collections.unmodifiableList(gamesPlayed);
players = Collections.unmodifiableList(Lists.newArrayList(players0));
- this.rules = rules;
+ rules = rules0;
}
public GameRules getRules() {
return rules;
}
- /**
- * Gets the games played.
- *
- * @return the games played
- */
public final List getPlayedGames() {
- return this.gamesPlayedRo;
+ return gamesPlayedRo;
}
-
public void addGamePlayed(Game finished) {
if (!finished.isGameOver()) {
throw new IllegalStateException("Game is not over yet.");
@@ -54,17 +48,11 @@ public class Match {
gamesPlayed.add(finished.getOutcome());
}
- /**
- * TODO: Write javadoc for this method.
- */
public Game createGame() {
Game game = new Game(players, rules, this);
return game;
}
- /**
- * TODO: Write javadoc for this method.
- */
public void startGame(final Game game) {
prepareAllZones(game);
if (rules.useAnte()) { // Deciding which cards go to ante
@@ -103,11 +91,6 @@ public class Match {
return gamesPlayedRo;
}
- /**
- * TODO: Write javadoc for this method.
- *
- * @return
- */
public boolean isMatchOver() {
int[] victories = new int[players.size()];
for (GameOutcome go : gamesPlayed) {
@@ -130,12 +113,6 @@ public class Match {
return gamesPlayed.size() >= rules.getGamesPerMatch();
}
- /**
- * TODO: Write javadoc for this method.
- *
- * @param questPlayer
- * @return
- */
public int getGamesWonBy(LobbyPlayer questPlayer) {
int sum = 0;
for (GameOutcome go : gamesPlayed) {
@@ -146,12 +123,6 @@ public class Match {
return sum;
}
- /**
- * TODO: Write javadoc for this method.
- *
- * @param questPlayer
- * @return
- */
public boolean isWonBy(LobbyPlayer questPlayer) {
return getGamesWonBy(questPlayer) >= rules.getGamesToWinMatch();
}
@@ -170,7 +141,6 @@ public class Match {
}
}
}
-
return myRemovedAnteCards;
}
@@ -274,7 +244,6 @@ public class Match {
private void executeAnte(Game lastGame) {
GameOutcome outcome = lastGame.getOutcome();
-
// remove all the lost cards from owners' decks
List losses = new ArrayList();
int cntPlayers = players.size();
@@ -358,7 +327,6 @@ public class Match {
}
}
}
-
// Other game types (like Quest) need to do something in their own calls to actually update data
}
}
diff --git a/forge-game/src/main/java/forge/game/card/Card.java b/forge-game/src/main/java/forge/game/card/Card.java
index d09cc360619..cece1ec3f1b 100644
--- a/forge-game/src/main/java/forge/game/card/Card.java
+++ b/forge-game/src/main/java/forge/game/card/Card.java
@@ -4029,7 +4029,7 @@ public class Card extends GameEntity implements Comparable, IIdentifiable
if (!CardUtil.getColors(this).hasAnyColor(mask))
return false;
} else if (restriction.equals("LastCastThisTurn")) {
- final List c = game.getStack().getCardsCastThisTurn();
+ final List c = game.getStack().getSpellsCastThisTurn();
if (c.isEmpty() || !sharesColorWith(c.get(c.size() - 1))) {
return false;
}
diff --git a/forge-game/src/main/java/forge/game/card/CardFactoryUtil.java b/forge-game/src/main/java/forge/game/card/CardFactoryUtil.java
index cb7a208d4a1..b9217b01d29 100644
--- a/forge-game/src/main/java/forge/game/card/CardFactoryUtil.java
+++ b/forge-game/src/main/java/forge/game/card/CardFactoryUtil.java
@@ -1029,7 +1029,7 @@ public class CardFactoryUtil {
return doXMath(c.getFirstSpellAbility().getTotalManaSpent(), m, c);
}
if (sq[0].equals("StormCount")) {
- return doXMath(game.getStack().getCardsCastThisTurn().size() - 1, m, c);
+ return doXMath(game.getStack().getSpellsCastThisTurn().size() - 1, m, c);
}
if (sq[0].equals("DamageDoneThisTurn")) {
return doXMath(c.getDamageDoneThisTurn(), m, c);
diff --git a/forge-game/src/main/java/forge/game/card/CardUtil.java b/forge-game/src/main/java/forge/game/card/CardUtil.java
index 7e63acae98a..576b12599ea 100644
--- a/forge-game/src/main/java/forge/game/card/CardUtil.java
+++ b/forge-game/src/main/java/forge/game/card/CardUtil.java
@@ -191,7 +191,7 @@ public final class CardUtil {
public static List getThisTurnCast(final String valid, final Card src) {
List res = new ArrayList();
final Game game = src.getGame();
- res.addAll(game.getStack().getCardsCastThisTurn());
+ res.addAll(game.getStack().getSpellsCastThisTurn());
res = CardLists.getValidCards(res, valid, src.getController(), src);
@@ -201,7 +201,7 @@ public final class CardUtil {
public static List getLastTurnCast(final String valid, final Card src) {
List res = new ArrayList();
final Game game = src.getGame();
- res.addAll(game.getStack().getCardsCastLastTurn());
+ res.addAll(game.getStack().getSpellsCastLastTurn());
res = CardLists.getValidCards(res, valid, src.getController(), src);
diff --git a/forge-game/src/main/java/forge/game/combat/Combat.java b/forge-game/src/main/java/forge/game/combat/Combat.java
index c29b80604fe..c089f041cbd 100644
--- a/forge-game/src/main/java/forge/game/combat/Combat.java
+++ b/forge-game/src/main/java/forge/game/combat/Combat.java
@@ -59,7 +59,6 @@ public class Combat {
// List holds creatures who have dealt 1st strike damage to disallow them deal damage on regular basis (unless they have double-strike KW)
private List combatantsThatDealtFirstStrikeDamage = Lists.newArrayList();
-
public Combat(Player attacker) {
playerWhoAttacks = attacker;
@@ -72,7 +71,7 @@ public class Combat {
}
}
}
-
+
public final Player getAttackingPlayer() {
return this.playerWhoAttacks;
}
@@ -83,14 +82,14 @@ public class Combat {
public final List getDefendersControlledBy(Player who) {
List res = Lists.newArrayList();
- for(GameEntity ge : attackableEntries) {
+ for (GameEntity ge : attackableEntries) {
// if defender is the player himself or his cards
if (ge == who || ge instanceof Card && ((Card) ge).getController() == who)
res.add(ge);
}
return res;
}
-
+
public final List getDefendingPlaneswalkers() {
final List pwDefending = new ArrayList();
for (final GameEntity o : attackableEntries) {
@@ -104,10 +103,10 @@ public class Combat {
public final List getAttackingBandsOf(GameEntity defender) {
return Lists.newArrayList(attackedByBands.get(defender));
}
-
+
public final List getAttackersOf(GameEntity defender) {
List result = new ArrayList();
- for(AttackingBand v : attackedByBands.get(defender)) {
+ for (AttackingBand v : attackedByBands.get(defender)) {
result.addAll(v.getAttackers());
}
return result;
@@ -116,7 +115,7 @@ public class Combat {
public final void addAttacker(final Card c, GameEntity defender) {
addAttacker(c, defender, null);
}
-
+
public final void addAttacker(final Card c, GameEntity defender, AttackingBand band) {
Collection attackersOfDefender = attackedByBands.get(defender);
if (attackersOfDefender == null) {
@@ -133,7 +132,8 @@ public class Combat {
if (band == null || !attackersOfDefender.contains(band)) {
band = new AttackingBand(c, defender);
attackersOfDefender.add(band);
- } else {
+ }
+ else {
band.addAttacker(c);
}
}
@@ -141,11 +141,12 @@ public class Combat {
public final GameEntity getDefenderByAttacker(final Card c) {
return getDefenderByAttacker(getBandOfAttacker(c));
}
-
+
public final GameEntity getDefenderByAttacker(final AttackingBand c) {
- for(Entry e : attackedByBands.entries()) {
- if ( e.getValue() == c )
+ for (Entry e : attackedByBands.entries()) {
+ if (e.getValue() == c) {
return e.getKey();
+ }
}
return null;
}
@@ -167,8 +168,8 @@ public class Combat {
// takes LKI into consideration, should use it at all times (though a single iteration over multimap seems faster)
public final AttackingBand getBandOfAttacker(final Card c) {
- for(AttackingBand ab : attackedByBands.values()) {
- if ( ab.contains(c) )
+ for (AttackingBand ab : attackedByBands.values()) {
+ if (ab.contains(c))
return ab;
}
CombatLki lki = lkiCache.get(c);
@@ -186,16 +187,19 @@ public class Combat {
public boolean isAttacking(Card card, GameEntity defender) {
AttackingBand ab = getBandOfAttacker(card);
- for(Entry ee : attackedByBands.entries())
- if ( ee.getValue() == ab )
+ for (Entry ee : attackedByBands.entries()) {
+ if (ee.getValue() == ab) {
return ee.getKey() == defender;
+ }
+ }
return false;
}
public final List getAttackers() {
List result = Lists.newArrayList();
- for(AttackingBand ab : attackedByBands.values())
+ for (AttackingBand ab : attackedByBands.values()) {
result.addAll(ab.getAttackers());
+ }
return result;
}
@@ -230,7 +234,7 @@ public class Combat {
public final void removeBlockAssignment(final Card attacker, final Card blocker) {
AttackingBand band = getBandOfAttacker(attacker);
Collection cc = blockedBands.get(band);
- if( cc != null)
+ if (cc != null)
cc.remove(blocker);
}
@@ -242,8 +246,8 @@ public class Combat {
public final List getAllBlockers() {
List result = new ArrayList();
- for(Card blocker : blockedBands.values()) {
- if(!result.contains(blocker))
+ for (Card blocker : blockedBands.values()) {
+ if (!result.contains(blocker))
result.add(blocker);
}
return result;
@@ -254,19 +258,19 @@ public class Combat {
return blockers == null ? Lists.newArrayList() : Lists.newArrayList(blockers);
}
-
public final List getAttackersBlockedBy(final Card blocker) {
List blocked = new ArrayList();
- for(Entry s : blockedBands.entries()) {
- if (s.getValue().equals(blocker))
+ for (Entry s : blockedBands.entries()) {
+ if (s.getValue().equals(blocker)) {
blocked.addAll(s.getKey().getAttackers());
+ }
}
return blocked;
}
public final List getAttackingBandsBlockedBy(Card blocker) {
List bands = Lists.newArrayList();
- for( Entry kv : blockedBands.entries()) {
+ for (Entry kv : blockedBands.entries()) {
if (kv.getValue().equals(blocker))
bands.add(kv.getKey());
}
@@ -277,9 +281,11 @@ public class Combat {
Card attacker = source;
if (source.isAura()) {
attacker = source.getEnchantingCard();
- } else if (source.isEquipment()) {
+ }
+ else if (source.isEquipment()) {
attacker = source.getEquipping();
- } else if (source.isFortification()) {
+ }
+ else if (source.isFortification()) {
attacker = source.getFortifying();
}
@@ -292,16 +298,16 @@ public class Combat {
List>> blockersNeedManualOrdering = new ArrayList<>();
- for(AttackingBand band : attackedByBands.values())
+ for (AttackingBand band : attackedByBands.values())
{
if (band.isEmpty()) continue;
Collection blockers = blockedBands.get(band);
- if ( blockers == null || blockers.isEmpty() )
+ if (blockers == null || blockers.isEmpty())
continue;
- for(Card attacker : band.getAttackers()) {
- if ( blockers.size() <= 1 )
+ for (Card attacker : band.getAttackers()) {
+ if (blockers.size() <= 1)
blockersOrderedForDamageAssignment.put(attacker, Lists.newArrayList(blockers));
else // process it a bit later
blockersNeedManualOrdering.add(Pair.of(attacker, (List)blockers)); // we know there's a list
@@ -309,7 +315,7 @@ public class Combat {
}
// brought this out of iteration on bands to avoid concurrency problems
- for(Pair> pair : blockersNeedManualOrdering){
+ for (Pair> pair : blockersNeedManualOrdering){
// Damage Ordering needs to take cards like Melee into account, is that happening?
List orderedBlockers = playerWhoAttacks.getController().orderBlockers(pair.getLeft(), pair.getRight()); // we know there's a list
blockersOrderedForDamageAssignment.put(pair.getLeft(), orderedBlockers);
@@ -358,7 +364,7 @@ public class Combat {
blockersOrderedForDamageAssignment.remove(c);
Collection blockers = blockedBands.get(ab);
- if ( blockers != null ) {
+ if (blockers != null) {
for (Card b : blockers) {
// Clear removed attacker from assignment order
if (this.attackersOrderedForDamageAssignment.containsKey(b)) {
@@ -372,7 +378,7 @@ public class Combat {
// removes references to this defender from all indices and orders
private void unregisterDefender(final Card c, AttackingBand bandBeingBlocked) {
this.attackersOrderedForDamageAssignment.remove(c);
- for(Card atk : bandBeingBlocked.getAttackers()) {
+ for (Card atk : bandBeingBlocked.getAttackers()) {
if (this.blockersOrderedForDamageAssignment.containsKey(atk)) {
this.blockersOrderedForDamageAssignment.get(atk).remove(c);
}
@@ -388,49 +394,52 @@ public class Combat {
}
// if not found in attackers, look for this card in blockers
- for(Entry be : blockedBands.entries()) {
- if(be.getValue().equals(c)) {
+ for (Entry be : blockedBands.entries()) {
+ if (be.getValue().equals(c)) {
unregisterDefender(c, be.getKey());
}
}
// remove card from map
while(blockedBands.values().remove(c));
-
} // removeFromCombat()
- public final void removeAbsentCombatants() {
+ public final boolean removeAbsentCombatants() {
// iterate all attackers and remove them
List missingCombatants = new ArrayList<>();
- for(Entry ee : attackedByBands.entries()) {
+ for (Entry ee : attackedByBands.entries()) {
List atk = ee.getValue().getAttackers();
- for(int i = atk.size() - 1; i >= 0; i--) { // might remove items from collection, so no iterators
+ for (int i = atk.size() - 1; i >= 0; i--) { // might remove items from collection, so no iterators
Card c = atk.get(i);
- if ( !c.isInPlay() || !c.isCreature() ) {
+ if (!c.isInPlay() || !c.isCreature()) {
missingCombatants.add(c);
}
}
}
- for(Entry be : blockedBands.entries()) {
+ for (Entry be : blockedBands.entries()) {
Card blocker = be.getValue();
- if ( !blocker.isInPlay() || !blocker.isCreature() ) {
+ if (!blocker.isInPlay() || !blocker.isCreature()) {
missingCombatants.add(blocker);
}
}
+
+ if (missingCombatants.isEmpty()) { return false; }
+
for (Card c : missingCombatants) {
removeFromCombat(c);
}
+ return true;
}
// Call this method right after turn-based action of declare blockers has been performed
public final void fireTriggersForUnblockedAttackers() {
- for(AttackingBand ab : attackedByBands.values()) {
+ for (AttackingBand ab : attackedByBands.values()) {
Collection blockers = blockedBands.get(ab);
boolean isBlocked = blockers != null && !blockers.isEmpty();
ab.setBlocked(isBlocked);
- if (!isBlocked )
+ if (!isBlocked) {
for (Card attacker : ab.getAttackers()) {
// Run Unblocked Trigger
final HashMap runParams = new HashMap();
@@ -438,6 +447,7 @@ public class Combat {
runParams.put("Defender",this.getDefenderByAttacker(attacker));
attacker.getGame().getTriggerHandler().runTrigger(TriggerType.AttackerUnblocked, runParams, false);
}
+ }
}
}
@@ -473,12 +483,11 @@ public class Combat {
}
}
}
-
return assignedDamage;
}
private final boolean assignAttackersDamage(boolean firstStrikeDamage) {
- // Assign damage by Attackers
+ // Assign damage by Attackers
this.defendingDamageMap.clear(); // this should really happen in deal damage
List orderedBlockers = null;
final List attackers = this.getAttackers();
@@ -511,27 +520,28 @@ public class Combat {
if (trampler || !band.isBlocked()) { // this is called after declare blockers, no worries 'bout nulls in isBlocked
this.addDefendingDamage(damageDealt, attacker);
} // No damage happens if blocked but no blockers left
- } else {
+ }
+ else {
GameEntity defender = getDefenderByAttacker(band);
Player assigningPlayer = this.getAttackingPlayer();
// Defensive Formation is very similar to Banding with Blockers
// It allows the defending player to assign damage instead of the attacking player
if (defender instanceof Player && defender.hasKeyword("You assign combat damage of each creature attacking you.")) {
assigningPlayer = (Player)defender;
- } else if ( AttackingBand.isValidBand(orderedBlockers, true)){
+ }
+ else if (AttackingBand.isValidBand(orderedBlockers, true)){
assigningPlayer = orderedBlockers.get(0).getController();
}
Map map = assigningPlayer.getController().assignCombatDamage(attacker, orderedBlockers, damageDealt, defender, this.getAttackingPlayer() != assigningPlayer);
for (Entry dt : map.entrySet()) {
- if( dt.getKey() == null) {
+ if (dt.getKey() == null) {
if (dt.getValue() > 0)
addDefendingDamage(dt.getValue(), attacker);
} else {
dt.getKey().addAssignedDamage(dt.getValue(), attacker);
}
}
-
} // if !hasFirstStrike ...
} // for
return assignedDamage;
@@ -540,29 +550,29 @@ public class Combat {
private final boolean dealDamageThisPhase(Card combatant, boolean firstStrikeDamage) {
// During first strike damage, double strike and first strike deal damage
// During regular strike damage, double strike and anyone who hasn't dealt damage deal damage
- if (combatant.hasDoubleStrike())
+ if (combatant.hasDoubleStrike()) {
return true;
-
- if (firstStrikeDamage && combatant.hasFirstStrike())
+ }
+ if (firstStrikeDamage && combatant.hasFirstStrike()) {
return true;
-
+ }
return !firstStrikeDamage && !this.combatantsThatDealtFirstStrikeDamage.contains(combatant);
}
// Damage to whatever was protected there.
private final void addDefendingDamage(final int n, final Card source) {
final GameEntity ge = this.getDefenderByAttacker(source);
-
+
if (ge instanceof Card) {
final Card planeswalker = (Card) ge;
planeswalker.addAssignedDamage(n, source);
-
return;
}
-
+
if (!this.defendingDamageMap.containsKey(source)) {
this.defendingDamageMap.put(source, n);
- } else {
+ }
+ else {
this.defendingDamageMap.put(source, this.defendingDamageMap.get(source) + n);
}
}
@@ -577,14 +587,8 @@ public class Combat {
return assignedDamage;
}
- /**
- *
- * dealAssignedDamage.
- *
- */
public void dealAssignedDamage() {
// This function handles both Regular and First Strike combat assignment
-
final HashMap defMap = this.defendingDamageMap;
final HashMap> wasDamaged = new HashMap>();
@@ -600,11 +604,13 @@ public class Combat {
wasDamaged.put(defender, l);
}
}
- } else if (defender instanceof Card) { // planeswalker
+ }
+ else if (defender instanceof Card) { // planeswalker
if (((Card) defender).getController().addCombatDamage(entry.getValue(), entry.getKey())) {
if (wasDamaged.containsKey(defender)) {
wasDamaged.get(defender).add(entry.getKey());
- } else {
+ }
+ else {
List l = new ArrayList();
l.add(entry.getKey());
wasDamaged.put(defender, l);
@@ -649,59 +655,42 @@ public class Combat {
runParams.put("DamageTarget", ge);
ge.getGame().getTriggerHandler().runTrigger(TriggerType.CombatDamageDoneOnce, runParams, false);
}
-
- // This was deeper before, but that resulted in the stack entry acting
- // like before.
-
+ // This was deeper before, but that resulted in the stack entry acting like before.
}
- /**
- *
- * isUnblocked.
- *
- *
- * @param att
- * a {@link forge.game.card.Card} object.
- * @return a boolean.
- */
public final boolean isUnblocked(final Card att) {
AttackingBand band = getBandOfAttacker(att);
return band == null ? false : Boolean.FALSE.equals(band.isBlocked());
}
- /**
- *
- * getUnblockedAttackers.
- *
- *
- * @return an array of {@link forge.game.card.Card} objects.
- */
public final List getUnblockedAttackers() {
List unblocked = new ArrayList();
- for (AttackingBand ab : attackedByBands.values())
- if ( Boolean.TRUE.equals(ab.isBlocked()) )
+ for (AttackingBand ab : attackedByBands.values()) {
+ if (Boolean.TRUE.equals(ab.isBlocked())) {
unblocked.addAll(ab.getAttackers());
-
+ }
+ }
return unblocked;
}
public boolean isPlayerAttacked(Player who) {
- for(GameEntity defender : attackedByBands.keySet() ) {
+ for (GameEntity defender : attackedByBands.keySet()) {
Card defenderAsCard = defender instanceof Card ? (Card)defender : null;
- if ((null != defenderAsCard && defenderAsCard.getController() != who ) ||
- (null == defenderAsCard && defender != who) )
+ if ((null != defenderAsCard && defenderAsCard.getController() != who) ||
+ (null == defenderAsCard && defender != who)) {
continue; // defender is not related to player 'who'
-
- for(AttackingBand ab : attackedByBands.get(defender)) {
- if ( !ab.isEmpty() )
+ }
+ for (AttackingBand ab : attackedByBands.get(defender)) {
+ if (!ab.isEmpty()) {
return true;
+ }
}
}
return false;
}
public boolean isBlocking(Card blocker) {
- if ( !blocker.isInPlay() ) {
+ if (!blocker.isInPlay()) {
CombatLki lki = lkiCache.get(blocker);
return null != lki && !lki.isAttacker; // was blocking something anyway
}
@@ -710,7 +699,7 @@ public class Combat {
public boolean isBlocking(Card blocker, Card attacker) {
AttackingBand ab = getBandOfAttacker(attacker);
- if ( !blocker.isInPlay() ) {
+ if (!blocker.isInPlay()) {
CombatLki lki = lkiCache.get(blocker);
return null != lki && !lki.isAttacker && lki.relatedBands.contains(ab); // was blocking that very band
}
@@ -718,21 +707,17 @@ public class Combat {
return blockers != null && blockers.contains(blocker);
}
- /**
- * TODO: Write javadoc for this method.
- * @param lastKnownInfo
- */
public void saveLKI(Card lastKnownInfo) {
List attackersBlocked = null;
AttackingBand attackingBand = getBandOfAttacker(lastKnownInfo);
boolean isAttacker = attackingBand != null;
- if ( !isAttacker ) {
+ if (!isAttacker) {
attackersBlocked= getAttackingBandsBlockedBy(lastKnownInfo);
- if ( attackersBlocked.isEmpty() )
- return; // card was not even in combat
+ if (attackersBlocked.isEmpty()) {
+ return; // card was not even in combat
+ }
}
List relatedBands = isAttacker ? Lists.newArrayList(attackingBand) : attackersBlocked;
lkiCache.put(lastKnownInfo, new CombatLki(isAttacker, relatedBands));
}
-
-} // Class Combat
+}
diff --git a/forge-game/src/main/java/forge/game/mana/ManaCostAdjustment.java b/forge-game/src/main/java/forge/game/mana/ManaCostAdjustment.java
index 310e0a6bf0d..8be89eb1f4f 100644
--- a/forge-game/src/main/java/forge/game/mana/ManaCostAdjustment.java
+++ b/forge-game/src/main/java/forge/game/mana/ManaCostAdjustment.java
@@ -227,7 +227,7 @@ public class ManaCostAdjustment {
if (activator == null ) {
return;
}
- if (CardLists.filterControlledBy(activator.getGame().getStack().getCardsCastThisTurn(),
+ if (CardLists.filterControlledBy(activator.getGame().getStack().getSpellsCastThisTurn(),
activator).size() > 0) {
return;
}
@@ -368,7 +368,7 @@ public class ManaCostAdjustment {
if (activator == null ) {
return;
}
- if (CardLists.filterControlledBy(activator.getGame().getStack().getCardsCastThisTurn(),
+ if (CardLists.filterControlledBy(activator.getGame().getStack().getSpellsCastThisTurn(),
activator).size() > 0) {
return;
}
diff --git a/forge-game/src/main/java/forge/game/phase/PhaseHandler.java b/forge-game/src/main/java/forge/game/phase/PhaseHandler.java
index ab039d57dd9..d1dcbb194c7 100644
--- a/forge-game/src/main/java/forge/game/phase/PhaseHandler.java
+++ b/forge-game/src/main/java/forge/game/phase/PhaseHandler.java
@@ -57,15 +57,12 @@ import java.util.*;
* @version $Id: PhaseHandler.java 13001 2012-01-08 12:25:25Z Sloth $
*/
public class PhaseHandler implements java.io.Serializable {
-
- /** Constant serialVersionUID=5207222278370963197L. */
private static final long serialVersionUID = 5207222278370963197L;
// Start turn at 0, since we start even before first untap
private PhaseType phase = null;
private int turn = 0;
-
private final transient Stack extraTurns = new Stack();
private final transient Map> extraPhases = new HashMap>();
@@ -93,97 +90,70 @@ public class PhaseHandler implements java.io.Serializable {
private final transient Game game;
public PhaseHandler(final Game game0) {
-
game = game0;
}
+ public final PhaseType getPhase() {
+ return phase;
+ }
+ private final void setPhase(final PhaseType phase0) {
+ if (phase == phase0) { return; }
+ phase = phase0;
+ game.updatePhaseForView();
+ }
+
+ public final int getTurn() {
+ return turn;
+ }
public final boolean isPlayerTurn(final Player player) {
- return player.equals(this.playerTurn);
+ return player.equals(playerTurn);
}
- private final void setPlayerTurn(final Player s) {
- this.playerTurn = s;
- this.setPriority(s);
- }
-
- /**
- *
- * Getter for the field playerTurn.
- *
- *
- * @return a {@link forge.game.player.Player} object.
- */
public final Player getPlayerTurn() {
- return this.playerTurn;
+ return playerTurn;
+ }
+ private final void setPlayerTurn(final Player playerTurn0) {
+ if (playerTurn == playerTurn0) { return; }
+ playerTurn = playerTurn0;
+ game.updatePlayerTurnForView();
+ setPriority(playerTurn);
}
- // priority player
-
- /**
- *
- * getPriorityPlayer.
- *
- *
- * @return a {@link forge.game.player.Player} object.
- */
public final Player getPriorityPlayer() {
- return this.pPlayerPriority;
+ return pPlayerPriority;
}
-
-
- /**
- *
- * setPriority.
- *
- *
- * @param p
- * a {@link forge.game.player.Player} object.
- */
public final void setPriority(final Player p) {
- this.pFirstPriority = p;
- this.pPlayerPriority = p;
+ pFirstPriority = p;
+ pPlayerPriority = p;
}
-
- /**
- *
- * resetPriority.
- *
- */
public final void resetPriority() {
- this.setPriority(this.playerTurn);
+ setPriority(playerTurn);
}
- /**
- *
- * inCombat.
- *
- *
- * @return a boolean.
- */
public final boolean inCombat() { return combat != null; }
- public final Combat getCombat() { return this.combat; }
+ public final Combat getCombat() { return combat; }
private void advanceToNextPhase() {
PhaseType oldPhase = phase;
- if (this.bRepeatCleanup) { // for when Cleanup needs to repeat itself
- this.bRepeatCleanup = false;
+ if (bRepeatCleanup) { // for when Cleanup needs to repeat itself
+ bRepeatCleanup = false;
}
else {
// If the phase that's ending has a stack of additional phases
// Take the LIFO one and move to that instead of the normal one
- if (this.extraPhases.containsKey(phase)) {
- PhaseType nextPhase = this.extraPhases.get(phase).pop();
+ if (extraPhases.containsKey(phase)) {
+ PhaseType nextPhase = extraPhases.get(phase).pop();
// If no more additional phases are available, remove it from the map
// and let the next add, reput the key
- if (this.extraPhases.get(phase).isEmpty()) {
- this.extraPhases.remove(phase);
+ if (extraPhases.get(phase).isEmpty()) {
+ extraPhases.remove(phase);
}
- this.phase = nextPhase;
+ setPhase(nextPhase);
}
else {
- this.phase = PhaseType.getNext(phase);
+ setPhase(PhaseType.getNext(phase));
}
}
@@ -191,8 +161,9 @@ public class PhaseHandler implements java.io.Serializable {
String phaseType = oldPhase == phase ? "Repeat" : phase == PhaseType.getNext(oldPhase) ? "" : "Additional";
- if (this.phase == PhaseType.UNTAP) {
- this.turn++;
+ if (phase == PhaseType.UNTAP) {
+ turn++;
+ game.updateTurnForView();
game.fireEvent(new GameEventTurnBegan(playerTurn, turn));
// Tokens starting game in play should suffer from Sum. Sickness
@@ -210,7 +181,7 @@ public class PhaseHandler implements java.io.Serializable {
playerTurn.setNumPowerSurgeLands(lands.size());
}
- game.fireEvent(new GameEventTurnPhase(this.getPlayerTurn(), this.getPhase(), phaseType));
+ game.fireEvent(new GameEventTurnPhase(playerTurn, phase, phaseType));
}
private boolean isSkippingPhase(PhaseType phase) {
@@ -224,10 +195,10 @@ public class PhaseHandler implements java.io.Serializable {
return playerTurn.hasKeyword("Skip the untap step of this turn.") || playerTurn.hasKeyword("Skip your untap step.");
case UPKEEP:
- return getPlayerTurn().hasKeyword("Skip your upkeep step.");
+ return playerTurn.hasKeyword("Skip your upkeep step.");
case DRAW:
- return getPlayerTurn().isSkippingDraw() || getTurn() == 1 && game.getPlayers().size() == 2;
+ return playerTurn.isSkippingDraw() || turn == 1 && game.getPlayers().size() == 2;
case COMBAT_BEGIN:
case COMBAT_DECLARE_ATTACKERS:
@@ -236,7 +207,7 @@ public class PhaseHandler implements java.io.Serializable {
case COMBAT_DECLARE_BLOCKERS:
case COMBAT_FIRST_STRIKE_DAMAGE:
case COMBAT_DAMAGE:
- return !this.inCombat();
+ return !inCombat();
default:
return false;
@@ -256,7 +227,7 @@ public class PhaseHandler implements java.io.Serializable {
}
else {
// Perform turn-based actions
- switch(this.getPhase()) {
+ switch (phase) {
case UNTAP:
givePriorityToPlayer = false;
game.getUntap().executeUntil(playerTurn);
@@ -264,19 +235,19 @@ public class PhaseHandler implements java.io.Serializable {
break;
case UPKEEP:
- this.nUpkeepsThisTurn++;
- this.nUpkeepsThisGame++;
- game.getUpkeep().executeUntil(this.getPlayerTurn());
+ nUpkeepsThisTurn++;
+ nUpkeepsThisGame++;
+ game.getUpkeep().executeUntil(playerTurn);
game.getUpkeep().executeAt();
break;
case DRAW:
- this.getPlayerTurn().drawCard();
+ playerTurn.drawCard();
break;
case MAIN1:
- if (this.getPlayerTurn().isArchenemy() && this.isPreCombatMain()) {
- this.getPlayerTurn().setSchemeInMotion();
+ if (playerTurn.isArchenemy() && isPreCombatMain()) {
+ playerTurn.setSchemeInMotion();
}
break;
@@ -294,6 +265,7 @@ public class PhaseHandler implements java.io.Serializable {
if (combat != null && combat.getAttackers().isEmpty()
&& !game.getTriggerHandler().hasDelayedTriggers()) {
combat = null;
+ game.updateCombatForView();
}
}
@@ -308,11 +280,13 @@ public class PhaseHandler implements java.io.Serializable {
break;
case COMBAT_FIRST_STRIKE_DAMAGE:
- combat.removeAbsentCombatants();
+ if (combat.removeAbsentCombatants()) {
+ game.updateCombatForView();
+ }
// no first strikers, skip this step
if (!combat.assignCombatDamage(true)) {
- this.givePriorityToPlayer = false;
+ givePriorityToPlayer = false;
}
else {
combat.dealAssignedDamage();
@@ -320,10 +294,12 @@ public class PhaseHandler implements java.io.Serializable {
break;
case COMBAT_DAMAGE:
- combat.removeAbsentCombatants();
+ if (combat.removeAbsentCombatants()) {
+ game.updateCombatForView();
+ }
if (!combat.assignCombatDamage(false)) {
- this.givePriorityToPlayer = false;
+ givePriorityToPlayer = false;
}
else {
combat.dealAssignedDamage();
@@ -374,9 +350,9 @@ public class PhaseHandler implements java.io.Serializable {
player.onCleanupPhase();
player.getController().autoPassCancel(); // autopass won't wrap to next turn
}
- this.getPlayerTurn().removeKeyword("Skip all combat phases of this turn.");
- game.getCleanup().executeUntil(this.getNextTurn());
- this.nUpkeepsThisTurn = 0;
+ playerTurn.removeKeyword("Skip all combat phases of this turn.");
+ game.getCleanup().executeUntil(getNextTurn());
+ nUpkeepsThisTurn = 0;
// Rule 514.3
givePriorityToPlayer = false;
@@ -393,8 +369,8 @@ public class PhaseHandler implements java.io.Serializable {
if (!skipped) {
// Run triggers if phase isn't being skipped
final HashMap runParams = new HashMap();
- runParams.put("Phase", this.getPhase().nameForScripts);
- runParams.put("Player", this.getPlayerTurn());
+ runParams.put("Phase", phase.nameForScripts);
+ runParams.put("Player", playerTurn);
game.getTriggerHandler().runTrigger(TriggerType.Phase, runParams, false);
}
@@ -408,7 +384,6 @@ public class PhaseHandler implements java.io.Serializable {
}
}
-
private void onPhaseEnd() {
// If the Stack isn't empty why is nextPhase being called?
if (!game.getStack().isEmpty()) {
@@ -428,19 +403,19 @@ public class PhaseHandler implements java.io.Serializable {
}
}
- switch (this.phase) {
+ switch (phase) {
case UNTAP:
- this.nCombatsThisTurn = 0;
+ nCombatsThisTurn = 0;
break;
case UPKEEP:
for (Card c : game.getCardsIn(ZoneType.Battlefield)) {
- c.getDamageHistory().setNotAttackedSinceLastUpkeepOf(this.getPlayerTurn());
- c.getDamageHistory().setNotBlockedSinceLastUpkeepOf(this.getPlayerTurn());
- c.getDamageHistory().setNotBeenBlockedSinceLastUpkeepOf(this.getPlayerTurn());
+ c.getDamageHistory().setNotAttackedSinceLastUpkeepOf(playerTurn);
+ c.getDamageHistory().setNotBlockedSinceLastUpkeepOf(playerTurn);
+ c.getDamageHistory().setNotBeenBlockedSinceLastUpkeepOf(playerTurn);
}
- game.getUpkeep().executeUntilEndOfPhase(this.getPlayerTurn());
- game.getUpkeep().registerUntilEndCommand(this.getPlayerTurn());
+ game.getUpkeep().executeUntilEndOfPhase(playerTurn);
+ game.getUpkeep().registerUntilEndCommand(playerTurn);
break;
case COMBAT_END:
@@ -451,7 +426,7 @@ public class PhaseHandler implements java.io.Serializable {
eventEndCombat = new GameEventCombatEnded(attackers, blockers);
}
combat = null;
- this.getPlayerTurn().resetAttackedThisCombat();
+ playerTurn.resetAttackedThisCombat();
if (eventEndCombat != null) {
game.fireEvent(eventEndCombat);
@@ -459,11 +434,11 @@ public class PhaseHandler implements java.io.Serializable {
break;
case CLEANUP:
- this.bPreventCombatDamageThisTurn = false;
- if (!this.bRepeatCleanup) {
- this.setPlayerTurn(this.handleNextTurn());
+ bPreventCombatDamageThisTurn = false;
+ if (!bRepeatCleanup) {
+ setPlayerTurn(handleNextTurn());
}
- this.planarDiceRolledthisTurn = 0;
+ planarDiceRolledthisTurn = 0;
// Play the End Turn sound
game.fireEvent(new GameEventTurnEnded());
break;
@@ -498,7 +473,7 @@ public class PhaseHandler implements java.io.Serializable {
}
}
- this.nCombatsThisTurn++;
+ nCombatsThisTurn++;
// Prepare and fire event 'attackers declared'
Multimap attackersMap = ArrayListMultimap.create();
@@ -544,11 +519,10 @@ public class PhaseHandler implements java.io.Serializable {
}
game.getTriggerHandler().resetActiveTriggers();
-
+ game.updateCombatForView();
game.fireEvent(new GameEventCombatChanged());
}
-
private void declareBlockersTurnBasedAction() {
Player p = playerTurn;
@@ -688,10 +662,10 @@ public class PhaseHandler implements java.io.Serializable {
a.getDamageHistory().setCreatureGotBlockedThisCombat(true);
}
+ game.updateCombatForView();
game.fireEvent(new GameEventCombatChanged());
}
-
private static boolean payRequiredBlockCosts(Game game, Card blocker, Card attacker) {
Cost blockCost = new Cost(ManaCost.ZERO, true);
// Sort abilities to apply them in proper order
@@ -711,24 +685,11 @@ public class PhaseHandler implements java.io.Serializable {
return noCost || blocker.getController().getController().payManaOptional(blocker, blockCost, fakeSA, "Pay cost to declare " + blocker + " a blocker. ", ManaPaymentPurpose.DeclareBlocker);
}
- /**
- * Checks if is prevent combat damage this turn.
- *
- * @return true, if is prevent combat damage this turn
- */
public final boolean isPreventCombatDamageThisTurn() {
- return this.bPreventCombatDamageThisTurn;
+ return bPreventCombatDamageThisTurn;
}
- /**
- *
- * handleNextTurn.
- *
- *
- * @return a {@link forge.game.player.Player} object.
- */
private Player handleNextTurn() {
-
game.getStack().onNextTurn();
for (final Player p1 : game.getPlayers()) {
@@ -762,35 +723,28 @@ public class PhaseHandler implements java.io.Serializable {
}
}
}
-
return next;
}
- /**
- *
- * getNextActivePlayer.
- *
- *
- * @return a {@link forge.game.player.Player} object.
- */
private Player getNextActivePlayer() {
-
- ExtraTurn extraTurn = !this.extraTurns.isEmpty() ? this.extraTurns.pop() : null;
- Player nextPlayer = extraTurn != null ? extraTurn.getPlayer() : game.getNextPlayerAfter(this.getPlayerTurn());
+ ExtraTurn extraTurn = !extraTurns.isEmpty() ? extraTurns.pop() : null;
+ Player nextPlayer = extraTurn != null ? extraTurn.getPlayer() : game.getNextPlayerAfter(playerTurn);
if (extraTurn != null) {
// The bottom of the extra turn stack is the normal turn
- nextPlayer.setExtraTurn(!this.extraTurns.isEmpty());
+ nextPlayer.setExtraTurn(!extraTurns.isEmpty());
if (nextPlayer.hasKeyword("If you would begin an extra turn, skip that turn instead.")) {
return getNextActivePlayer();
}
- } else
+ }
+ else {
nextPlayer.setExtraTurn(false);
+ }
if (nextPlayer.hasKeyword("Skip your next turn.")) {
nextPlayer.removeKeyword("Skip your next turn.");
if( null == extraTurn )
- this.setPlayerTurn(nextPlayer);
+ setPlayerTurn(nextPlayer);
return getNextActivePlayer();
}
@@ -808,7 +762,7 @@ public class PhaseHandler implements java.io.Serializable {
}
crd.untap();
if( null == extraTurn )
- this.setPlayerTurn(nextPlayer);
+ setPlayerTurn(nextPlayer);
return getNextActivePlayer();
}
}
@@ -824,152 +778,55 @@ public class PhaseHandler implements java.io.Serializable {
nextPlayer.addKeyword("Schemes can't be set in motion this turn.");
}
}
-
return nextPlayer;
}
- /**
- *
- * is.
- *
- *
- * @param phase
- * a {@link java.lang.String} object.
- * @param player
- * a {@link forge.game.player.Player} object.
- * @return a boolean.
- */
- public final synchronized boolean is(final PhaseType phase, final Player player) {
- return this.getPhase() == phase && this.getPlayerTurn().equals(player);
+ public final synchronized boolean is(final PhaseType phase0, final Player player0) {
+ return phase == phase0 && playerTurn.equals(player0);
}
-
- /**
- *
- * is.
- *
- *
- * @param phase0
- * a {@link forge.game.phase.PhaseType} object.
- * @return a boolean.
- */
public final synchronized boolean is(final PhaseType phase0) {
- return this.getPhase() == phase0;
+ return phase == phase0;
}
- /**
- *
- * getPhase.
- *
- *
- * @return a {@link java.lang.String} object.
- */
- public final PhaseType getPhase() {
- return phase;
- }
-
- /**
- *
- * Getter for the field turn.
- *
- *
- * @return a int.
- */
- public final int getTurn() {
- return this.turn;
- }
-
- /**
- *
- * getNextTurn.
- *
- *
- * @return a {@link forge.game.player.Player} object.
- */
public final Player getNextTurn() {
- if (this.extraTurns.isEmpty()) {
- return game.getNextPlayerAfter(this.getPlayerTurn());
+ if (extraTurns.isEmpty()) {
+ return game.getNextPlayerAfter(playerTurn);
}
-
- return this.extraTurns.peek().getPlayer();
+ return extraTurns.peek().getPlayer();
}
-
- /**
- *
- * addExtraTurn.
- *
- *
- * @param player
- * a {@link forge.game.player.Player} object.
- */
public final ExtraTurn addExtraTurn(final Player player) {
// use a stack to handle extra turns, make sure the bottom of the stack
// restores original turn order
- if (this.extraTurns.isEmpty()) {
- this.extraTurns.push(new ExtraTurn(game.getNextPlayerAfter(this.getPlayerTurn())));
+ if (extraTurns.isEmpty()) {
+ extraTurns.push(new ExtraTurn(game.getNextPlayerAfter(playerTurn)));
}
-
- return this.extraTurns.push(new ExtraTurn(player));
+ return extraTurns.push(new ExtraTurn(player));
}
- /**
- *
- * addExtraPhase.
- *
- *
- */
public final void addExtraPhase(final PhaseType afterPhase, final PhaseType extraPhase) {
// 500.8. Some effects can add phases to a turn. They do this by adding the phases directly after the specified phase.
// If multiple extra phases are created after the same phase, the most recently created phase will occur first.
- if (!this.extraPhases.containsKey(afterPhase)) {
- this.extraPhases.put(afterPhase, new Stack());
+ if (!extraPhases.containsKey(afterPhase)) {
+ extraPhases.put(afterPhase, new Stack());
}
-
- this.extraPhases.get(afterPhase).push(extraPhase);
+ extraPhases.get(afterPhase).push(extraPhase);
}
- /**
- *
- * isFirstCombat.
- *
- *
- * @return a boolean.
- */
public final boolean isFirstCombat() {
- return (this.nCombatsThisTurn == 1);
+ return (nCombatsThisTurn == 1);
}
- /**
- *
- * isFirstUpkeep.
- *
- *
- * @return a boolean.
- */
public final boolean isFirstUpkeep() {
- return (this.nUpkeepsThisTurn == 0);
+ return (nUpkeepsThisTurn == 0);
}
- /**
- *
- * isFirstUpkeepThisGame.
- *
- *
- * @return a boolean.
- */
public final boolean isFirstUpkeepThisGame() {
- return (this.nUpkeepsThisGame == 0);
+ return (nUpkeepsThisGame == 0);
}
- /**
- *
- * isPreCombatMain.
- *
- *
- * @return a boolean.
- */
public final boolean isPreCombatMain() {
- return (this.nCombatsThisTurn == 0);
+ return (nCombatsThisTurn == 0);
}
private final static boolean DEBUG_PHASES = false;
@@ -996,7 +853,7 @@ public class PhaseHandler implements java.io.Serializable {
sw.start();
}
- game.fireEvent(new GameEventPlayerPriority(getPlayerTurn(), getPhase(), getPriorityPlayer()));
+ game.fireEvent(new GameEventPlayerPriority(playerTurn, phase, getPriorityPlayer()));
SpellAbility chosenSa = null;
int loopCount = 0;
@@ -1017,7 +874,7 @@ public class PhaseHandler implements java.io.Serializable {
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(this.getPriorityPlayer());
+ pPlayerPriority = game.getNextPlayerAfter(getPriorityPlayer());
pFirstPriority = pPlayerPriority;
}
@@ -1045,13 +902,13 @@ public class PhaseHandler implements java.io.Serializable {
}
}
else if (DEBUG_PHASES){
- System.out.print(" >> (no priority given to " + this.getPriorityPlayer() + ")\n");
+ System.out.print(" >> (no priority given to " + getPriorityPlayer() + ")\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());
+ Player nextPlayer = game.getNextPlayerAfter(getPriorityPlayer());
if (game.isGameOver() || nextPlayer == null) { return; } // conceded?
@@ -1060,13 +917,13 @@ public class PhaseHandler implements java.io.Serializable {
if (pFirstPriority == nextPlayer) {
if (game.getStack().isEmpty()) {
if (playerTurn.hasLost()) {
- this.setPriority(game.getNextPlayerAfter(playerTurn));
+ setPriority(game.getNextPlayerAfter(playerTurn));
} else {
- this.setPriority(playerTurn);
+ setPriority(playerTurn);
}
// end phase
- this.givePriorityToPlayer = true;
+ givePriorityToPlayer = true;
onPhaseEnd();
advanceToNextPhase();
onPhaseBegin();
@@ -1075,12 +932,13 @@ public class PhaseHandler implements java.io.Serializable {
}
else {
// pass the priority to other player
- this.pPlayerPriority = nextPlayer;
+ pPlayerPriority = nextPlayer;
}
// If ever the karn's ultimate resolved
if (game.getAge() == GameStage.RestartedByKarn) {
- phase = null;
+ setPhase(null);
+ game.updatePhaseForView();
game.fireEvent(new GameEventGameRestarted(playerTurn));
return;
}
@@ -1090,53 +948,50 @@ public class PhaseHandler implements java.io.Serializable {
// this is a hack for the setup game state mode, do not use outside of devSetupGameState code
// as it avoids calling any of the phase effects that may be necessary in a less enforced context
public final void devModeSet(final PhaseType phase0, final Player player0) {
- if (null != phase0) this.phase = phase0;
- if (null != player0) {
+ if (phase0 != null) {
+ setPhase(phase0);
+ }
+ if (player0 != null) {
setPlayerTurn(player0);
}
- game.fireEvent(new GameEventTurnPhase(this.getPlayerTurn(), this.getPhase(), ""));
+ game.fireEvent(new GameEventTurnPhase(playerTurn, phase, ""));
combat = null; // not-null can be created only when declare attackers phase begins
}
public final void endTurnByEffect() {
- this.combat = null;
- this.extraPhases.clear();
- this.phase = PhaseType.CLEANUP;
- this.onPhaseBegin();
+ combat = null;
+ extraPhases.clear();
+ setPhase(PhaseType.CLEANUP);
+ onPhaseBegin();
}
-
public final void setPreventCombatDamageThisTurn(final boolean b) {
- this.bPreventCombatDamageThisTurn = true;
+ bPreventCombatDamageThisTurn = true;
}
- /**
- * @return the planarDiceRolledthisTurn
- */
public int getPlanarDiceRolledthisTurn() {
return planarDiceRolledthisTurn;
}
-
public void incPlanarDiceRolledthisTurn() {
- this.planarDiceRolledthisTurn++;
+ planarDiceRolledthisTurn++;
}
public String debugPrintState(boolean hasPriority) {
- return String.format("%s's %s [%sP] %s", getPlayerTurn(), getPhase().nameForUi, hasPriority ? "+" : "-", getPriorityPlayer());
+ return String.format("%s's %s [%sP] %s", playerTurn, phase.nameForUi, hasPriority ? "+" : "-", getPriorityPlayer());
}
- // just to avoid exposing variable to oute classes
+ // just to avoid exposing variable to outer classes
public void onStackResolved() {
givePriorityToPlayer = true;
}
- public final void setPlayerDeclaresBlockers(Player player) {
- this.playerDeclaresBlockers = player;
+ public final void setPlayerDeclaresAttackers(Player player) {
+ playerDeclaresAttackers = player;
}
- public final void setPlayerDeclaresAttackers(Player player) {
- this.playerDeclaresAttackers = player;
+ public final void setPlayerDeclaresBlockers(Player player) {
+ playerDeclaresBlockers = player;
}
public void endCombat() {
diff --git a/forge-game/src/main/java/forge/game/staticability/StaticAbilityCantBeCast.java b/forge-game/src/main/java/forge/game/staticability/StaticAbilityCantBeCast.java
index 4d27dbc4c74..4103815b9c9 100644
--- a/forge-game/src/main/java/forge/game/staticability/StaticAbilityCantBeCast.java
+++ b/forge-game/src/main/java/forge/game/staticability/StaticAbilityCantBeCast.java
@@ -70,7 +70,7 @@ public class StaticAbilityCantBeCast {
if (params.containsKey("NumLimitEachTurn") && activator != null) {
int limit = Integer.parseInt(params.get("NumLimitEachTurn"));
String valid = params.containsKey("ValidCard") ? params.get("ValidCard") : "Card";
- List thisTurnCast = CardLists.getValidCards(card.getGame().getStack().getCardsCastThisTurn(),
+ List thisTurnCast = CardLists.getValidCards(card.getGame().getStack().getSpellsCastThisTurn(),
valid, card.getController(), card);
if (CardLists.filterControlledBy(thisTurnCast, activator).size() < limit) {
return false;
diff --git a/forge-game/src/main/java/forge/game/zone/MagicStack.java b/forge-game/src/main/java/forge/game/zone/MagicStack.java
index c9a11c13606..18ea86cd95d 100644
--- a/forge-game/src/main/java/forge/game/zone/MagicStack.java
+++ b/forge-game/src/main/java/forge/game/zone/MagicStack.java
@@ -80,62 +80,31 @@ public class MagicStack /* extends MyObservable */ implements Iterable
- * isFrozen.
- *
- *
- * @return a boolean.
- */
public final boolean isFrozen() {
- return this.frozen;
+ return frozen;
}
-
- /**
- *
- * Setter for the field frozen.
- *
- *
- * @param frozen0
- * a boolean.
- */
public final void setFrozen(final boolean frozen0) {
- this.frozen = frozen0;
+ frozen = frozen0;
}
- /**
- *
- * reset.
- *
- */
public final void reset() {
- this.clear();
- this.simultaneousStackEntryList.clear();
- this.frozen = false;
- this.lastTurnCast.clear();
- this.thisTurnCast.clear();
- this.curResolvingCard = null;
- this.frozenStack.clear();
- this.clearUndoStack();
+ clear();
+ simultaneousStackEntryList.clear();
+ frozen = false;
+ lastTurnCast.clear();
+ thisTurnCast.clear();
+ curResolvingCard = null;
+ frozenStack.clear();
+ clearUndoStack();
+ game.updateStackForView();
}
- /**
- *
- * isSplitSecondOnStack.
- *
- *
- * @return a boolean.
- */
public final boolean isSplitSecondOnStack() {
- for(SpellAbilityStackInstance si : this.stack) {
+ for(SpellAbilityStackInstance si : stack) {
if (si.isSpell() && si.getSourceCard().hasKeyword("Split second")) {
return true;
}
@@ -143,23 +112,10 @@ public class MagicStack /* extends MyObservable */ implements Iterable
- * freezeStack.
- *
- */
public final void freezeStack() {
- this.frozen = true;
+ frozen = true;
}
- /**
- *
- * addAndUnfreeze.
- *
- *
- * @param ability
- * a {@link forge.game.spellability.SpellAbility} object.
- */
public final void addAndUnfreeze(final SpellAbility ability) {
ability.getRestrictions().abilityActivated();
ability.checkActivationResloveSubs();
@@ -174,80 +130,39 @@ public class MagicStack /* extends MyObservable */ implements Iterable
- * unfreezeStack.
- *
- */
public final void unfreezeStack() {
- this.frozen = false;
+ frozen = false;
// Add all Frozen Abilities onto the stack
- while (!this.frozenStack.isEmpty()) {
- final SpellAbility sa = this.frozenStack.pop().getSpellAbility(true);
- this.add(sa);
+ while (!frozenStack.isEmpty()) {
+ final SpellAbility sa = frozenStack.pop().getSpellAbility(true);
+ add(sa);
}
// Add all waiting triggers onto the stack
game.getTriggerHandler().runWaitingTriggers();
}
- /**
- *
- * clearFrozen.
- *
- */
public final void clearFrozen() {
// TODO: frozen triggered abilities and undoable costs have nasty
// consequences
- this.frozen = false;
- this.frozenStack.clear();
+ frozen = false;
+ frozenStack.clear();
}
- /**
- *
- * setResolving.
- *
- *
- * @param b
- * a boolean.
- */
- public final void setResolving(final boolean b) {
- this.bResolving = b;
- }
-
- /**
- *
- * getResolving.
- *
- *
- * @return a boolean.
- */
public final boolean isResolving() {
- return this.bResolving;
+ return bResolving;
+ }
+ public final void setResolving(final boolean b) {
+ bResolving = b;
}
- /**
- *
- * undo.
- *
- *
- * @return a boolean.
- */
public final boolean canUndo(Player player) {
return undoStackOwner == player;
}
-
- /**
- *
- * undo.
- *
- *
- * @return a boolean.
- */
public final boolean undo() {
if (undoStack.isEmpty()) { return false; }
@@ -259,26 +174,12 @@ public class MagicStack /* extends MyObservable */ implements Iterable
- * clearUndoStack.
- *
- */
public final void clearUndoStack() {
if (undoStackOwner == null) { return; }
undoStack.clear();
undoStackOwner = null;
}
- /**
- *
- * add.
- *
- *
- * @param sp
- * a {@link forge.game.spellability.SpellAbility} object.
- */
public final void add(final SpellAbility sp) {
SpellAbilityStackInstance si = null;
final Card source = sp.getHostCard();
@@ -327,9 +228,9 @@ public class MagicStack /* extends MyObservable */ implements Iterable
- * size.
- *
- *
- * @return a int.
- */
public final int size() {
- return this.stack.size();
+ return stack.size();
}
- /**
- *
- * isEmpty.
- *
- *
- * @return a boolean.
- */
public final boolean isEmpty() {
- return this.stack.isEmpty();
+ return stack.isEmpty();
}
// Push should only be used by add.
@@ -518,9 +405,8 @@ public class MagicStack /* extends MyObservable */ implements Iterable
- * resolveStack.
- *
- */
public final void resolveStack() {
// Resolving the Stack
// freeze the stack while we're in the middle of resolving
- this.freezeStack();
- this.setResolving(true);
+ freezeStack();
+ setResolving(true);
// The SpellAbility isn't removed from the Stack until it finishes resolving
// temporarily reverted removing SAs after resolution
- final SpellAbility sa = this.peekAbility();
- //final SpellAbility sa = this.pop();
+ final SpellAbility sa = peekAbility();
+ //final SpellAbility sa = pop();
// ActivePlayer gains priority first after Resolve
game.getPhaseHandler().resetPriority();
@@ -562,7 +445,7 @@ public class MagicStack /* extends MyObservable */ implements Iterable
- * hasFizzled.
- *
- *
- * @param sa
- * a {@link forge.game.spellability.SpellAbility} object.
- * @param source
- * a {@link forge.game.card.Card} object.
- * @return a boolean.
- */
private final boolean hasFizzled(final SpellAbility sa, final Card source, final boolean parentFizzled) {
// Can't fizzle unless there are some targets
boolean fizzle = false;
@@ -768,27 +639,26 @@ public class MagicStack /* extends MyObservable */ implements Iterable activePlayerSAs = new ArrayList();
- for (int i = 0; i < this.simultaneousStackEntryList.size(); i++) {
- SpellAbility sa = this.simultaneousStackEntryList.get(i);
+ for (int i = 0; i < simultaneousStackEntryList.size(); i++) {
+ SpellAbility sa = simultaneousStackEntryList.get(i);
Player activator = sa.getActivatingPlayer();
if (activator == null) {
if (sa.getHostCard().getController().equals(activePlayer)) {
activePlayerSAs.add(sa);
- this.simultaneousStackEntryList.remove(i);
+ simultaneousStackEntryList.remove(i);
i--;
}
} else {
if (activator.equals(activePlayer)) {
activePlayerSAs.add(sa);
- this.simultaneousStackEntryList.remove(i);
+ simultaneousStackEntryList.remove(i);
i--;
}
}
@@ -856,73 +726,58 @@ public class MagicStack /* extends MyObservable */ implements Iterable getCardsCastThisTurn() {
- return this.thisTurnCast;
+ public final List getSpellsCastThisTurn() {
+ return thisTurnCast;
}
- /**
- * clearCardsCastThisTurn.
- */
public final void onNextTurn() {
- this.lastTurnCast = new ArrayList(this.thisTurnCast);
- this.thisTurnCast.clear();
+ if (thisTurnCast.isEmpty()) {
+ lastTurnCast = new ArrayList();
+ return;
+ }
+ lastTurnCast = new ArrayList(thisTurnCast);
+ thisTurnCast.clear();
+ game.updateStackForView();
}
- /**
- * Accessor for the field lastTurnCast.
- *
- * @return a CardList.
- */
- public final List getCardsCastLastTurn() {
- return this.lastTurnCast;
+ public final List getSpellsCastLastTurn() {
+ return lastTurnCast;
}
public final void addCastCommand(final String valid, final GameCommand c) {
- if (this.commandList.containsKey(valid)) {
- this.commandList.get(valid).add(0, c);
- } else {
- this.commandList.put(valid, Lists.newArrayList(c));
+ if (commandList.containsKey(valid)) {
+ commandList.get(valid).add(0, c);
+ }
+ else {
+ commandList.put(valid, Lists.newArrayList(c));
}
}
private void executeCastCommand(final Card cast) {
- for (Entry> ev : this.commandList.entrySet()) {
+ for (Entry> ev : commandList.entrySet()) {
if (cast.isType(ev.getKey())) {
- this.execute(ev.getValue());
+ execute(ev.getValue());
}
}
}
@@ -934,23 +789,13 @@ public class MagicStack /* extends MyObservable */ implements Iterable iterator() {
return stack.iterator();
@@ -960,11 +805,10 @@ public class MagicStack /* extends MyObservable */ implements Iterable type;