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;