From 559b62d10a80412012d09b5208496672fa14bab4 Mon Sep 17 00:00:00 2001 From: Sloth Date: Mon, 30 Apr 2012 15:37:33 +0000 Subject: [PATCH] - Added the player keyword "At the beginning of the end step, you lose the game.". - Added Final Fortune, Last Chance and Warrior's Oath. --- .gitattributes | 4 + res/cardsfolder/f/final_fortune.txt | 13 +++ res/cardsfolder/l/last_chance.txt | 12 +++ res/cardsfolder/w/warriors_oath.txt | 11 +++ .../abilityfactory/AbilityFactoryTurns.java | 6 +- src/main/java/forge/game/phase/EndOfTurn.java | 17 +++- src/main/java/forge/game/phase/ExtraTurn.java | 86 +++++++++++++++++++ .../java/forge/game/phase/PhaseHandler.java | 49 ++++++++--- 8 files changed, 182 insertions(+), 16 deletions(-) create mode 100644 res/cardsfolder/f/final_fortune.txt create mode 100644 res/cardsfolder/l/last_chance.txt create mode 100644 res/cardsfolder/w/warriors_oath.txt create mode 100644 src/main/java/forge/game/phase/ExtraTurn.java diff --git a/.gitattributes b/.gitattributes index 88dcb56f7f6..2786f490f94 100644 --- a/.gitattributes +++ b/.gitattributes @@ -3095,6 +3095,7 @@ res/cardsfolder/f/filigree_sages.txt svneol=native#text/plain res/cardsfolder/f/fill_with_fright.txt svneol=native#text/plain res/cardsfolder/f/filth.txt svneol=native#text/plain res/cardsfolder/f/filthy_cur.txt svneol=native#text/plain +res/cardsfolder/f/final_fortune.txt -text res/cardsfolder/f/final_judgment.txt svneol=native#text/plain res/cardsfolder/f/final_revels.txt svneol=native#text/plain res/cardsfolder/f/final_sting_faerie.txt svneol=native#text/plain @@ -5096,6 +5097,7 @@ res/cardsfolder/l/lashknife_barrier.txt svneol=native#text/plain res/cardsfolder/l/lashwrithe.txt svneol=native#text/plain res/cardsfolder/l/last_breath.txt svneol=native#text/plain res/cardsfolder/l/last_caress.txt svneol=native#text/plain +res/cardsfolder/l/last_chance.txt -text res/cardsfolder/l/last_gasp.txt svneol=native#text/plain res/cardsfolder/l/last_kiss.txt svneol=native#text/plain res/cardsfolder/l/last_laugh.txt svneol=native#text/plain @@ -10376,6 +10378,7 @@ res/cardsfolder/w/warren_scourge_elf.txt svneol=native#text/plain res/cardsfolder/w/warrior_angel.txt svneol=native#text/plain res/cardsfolder/w/warriors_charge.txt svneol=native#text/plain res/cardsfolder/w/warriors_honor.txt svneol=native#text/plain +res/cardsfolder/w/warriors_oath.txt -text res/cardsfolder/w/warriors_stand.txt -text res/cardsfolder/w/warstorm_surge.txt svneol=native#text/plain res/cardsfolder/w/warthog.txt svneol=native#text/plain @@ -11845,6 +11848,7 @@ src/main/java/forge/game/phase/Combat.java svneol=native#text/plain src/main/java/forge/game/phase/CombatUtil.java svneol=native#text/plain src/main/java/forge/game/phase/EndOfCombat.java svneol=native#text/plain src/main/java/forge/game/phase/EndOfTurn.java svneol=native#text/plain +src/main/java/forge/game/phase/ExtraTurn.java -text src/main/java/forge/game/phase/Phase.java svneol=native#text/plain src/main/java/forge/game/phase/PhaseHandler.java -text src/main/java/forge/game/phase/PhaseType.java -text diff --git a/res/cardsfolder/f/final_fortune.txt b/res/cardsfolder/f/final_fortune.txt new file mode 100644 index 00000000000..a77d9b6cf0f --- /dev/null +++ b/res/cardsfolder/f/final_fortune.txt @@ -0,0 +1,13 @@ +Name:Final Fortune +ManaCost:R R +Types:Instant +Text:no text +A:SP$ AddTurn | Cost$ R R | NumTurns$ 1 | loseAtEndStep$ True | SpellDescription$ Take an extra turn after this one. At the beginning of that turn's end step, you lose the game. +SVar:RemAIDeck:True +SVar:Rarity:Rare +SVar:Picture:http://www.wizards.com/global/images/magic/general/final_fortune.jpg +SetInfo:6ED|Rare|http://magiccards.info/scans/en/6e/175.jpg +SetInfo:MIR|Rare|http://magiccards.info/scans/en/mr/173.jpg +SetInfo:7ED|Rare|http://magiccards.info/scans/en/7e/182.jpg +Oracle:Take an extra turn after this one. At the beginning of that turn's end step, you lose the game. +End \ No newline at end of file diff --git a/res/cardsfolder/l/last_chance.txt b/res/cardsfolder/l/last_chance.txt new file mode 100644 index 00000000000..7c9340f216f --- /dev/null +++ b/res/cardsfolder/l/last_chance.txt @@ -0,0 +1,12 @@ +Name:Last Chance +ManaCost:R R +Types:Sorcery +Text:no text +A:SP$ AddTurn | Cost$ R R | NumTurns$ 1 | loseAtEndStep$ True | SpellDescription$ Take an extra turn after this one. At the beginning of that turn's end step, you lose the game. +SVar:RemAIDeck:True +SVar:Rarity:Rare +SVar:Picture:http://www.wizards.com/global/images/magic/general/last_chance.jpg +SetInfo:S99|Rare|http://magiccards.info/scans/en/st/110.jpg +SetInfo:POR|Rare|http://magiccards.info/scans/en/po/141.jpg +Oracle:Take an extra turn after this one. At the beginning of that turn's end step, you lose the game. +End \ No newline at end of file diff --git a/res/cardsfolder/w/warriors_oath.txt b/res/cardsfolder/w/warriors_oath.txt new file mode 100644 index 00000000000..76463efbb0e --- /dev/null +++ b/res/cardsfolder/w/warriors_oath.txt @@ -0,0 +1,11 @@ +Name:Warrior's Oath +ManaCost:R R +Types:Sorcery +Text:no text +A:SP$ AddTurn | Cost$ R R | NumTurns$ 1 | loseAtEndStep$ True | SpellDescription$ Take an extra turn after this one. At the beginning of that turn's end step, you lose the game. +SVar:RemAIDeck:True +SVar:Rarity:Rare +SVar:Picture:http://www.wizards.com/global/images/magic/general/warriors_oath.jpg +SetInfo:PTK|Rare|http://magiccards.info/scans/en/p3k/124.jpg +Oracle:Take an extra turn after this one. At the beginning of that turn's end step, you lose the game. +End \ No newline at end of file diff --git a/src/main/java/forge/card/abilityfactory/AbilityFactoryTurns.java b/src/main/java/forge/card/abilityfactory/AbilityFactoryTurns.java index e38a203ca27..cd9413a665a 100644 --- a/src/main/java/forge/card/abilityfactory/AbilityFactoryTurns.java +++ b/src/main/java/forge/card/abilityfactory/AbilityFactoryTurns.java @@ -28,6 +28,7 @@ import forge.card.spellability.AbilitySub; import forge.card.spellability.Spell; import forge.card.spellability.SpellAbility; import forge.card.spellability.Target; +import forge.game.phase.ExtraTurn; import forge.game.phase.PhaseType; import forge.game.player.ComputerUtil; import forge.game.player.Player; @@ -319,7 +320,10 @@ public class AbilityFactoryTurns { for (final Player p : tgtPlayers) { if ((tgt == null) || p.canBeTargetedBy(sa)) { for (int i = 0; i < numTurns; i++) { - Singletons.getModel().getGameState().getPhaseHandler().addExtraTurn(p); + ExtraTurn extra = Singletons.getModel().getGameState().getPhaseHandler().addExtraTurn(p); + if (params.containsKey("loseAtEndStep")) { + extra.setLoseAtEndStep(true); + } } } } diff --git a/src/main/java/forge/game/phase/EndOfTurn.java b/src/main/java/forge/game/phase/EndOfTurn.java index 0f7cc8e31ff..855ce6e226e 100644 --- a/src/main/java/forge/game/phase/EndOfTurn.java +++ b/src/main/java/forge/game/phase/EndOfTurn.java @@ -27,6 +27,7 @@ import forge.Counters; import forge.Singletons; import forge.card.spellability.Ability; import forge.card.spellability.SpellAbility; +import forge.game.GameLossReason; import forge.game.player.Player; import forge.game.zone.ZoneType; import forge.gui.GuiUtils; @@ -53,7 +54,6 @@ public class EndOfTurn extends Phase implements java.io.Serializable { // TODO - should this freeze the Stack? - // Pyrohemia and Pestilence final CardList all = AllZoneUtil.getCardsIn(ZoneType.Battlefield); EndOfTurn.endOfTurnWallOfReverence(); @@ -209,6 +209,21 @@ public class EndOfTurn extends Phase implements java.io.Serializable { } } + Player activePlayer = Singletons.getModel().getGameState().getPhaseHandler().getPlayerTurn(); + if (activePlayer.hasKeyword("At the beginning of the end step, you lose the game.")) { + final Card source = new Card(); + final SpellAbility change = new Ability(source, "0") { + @Override + public void resolve() { + this.getActivatingPlayer().loseConditionMet(GameLossReason.SpellEffect, ""); + } + }; + change.setStackDescription("At the beginning of the end step, you lose the game."); + change.setDescription("At the beginning of the end step, you lose the game."); + change.setActivatingPlayer(activePlayer); + + AllZone.getStack().addSimultaneousStackEntry(change); + } this.execute(this.getAt()); diff --git a/src/main/java/forge/game/phase/ExtraTurn.java b/src/main/java/forge/game/phase/ExtraTurn.java new file mode 100644 index 00000000000..71ad954b889 --- /dev/null +++ b/src/main/java/forge/game/phase/ExtraTurn.java @@ -0,0 +1,86 @@ +/* + * Forge: Play Magic: the Gathering. + * Copyright (C) 2011 Forge Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package forge.game.phase; + +import forge.game.player.Player; + +/** + *

+ * ExtraTurn class. + * Stores informations about extra turns + *

+ * + * @author Forge + * @version $Id: ExtraTurn 12482 2011-12-06 11:14:11Z Sloth $ + */ +public class ExtraTurn { + + private Player player = null; + private boolean loseAtEndStep = false; + private boolean skipUntap = false; + /** + * TODO: Write javadoc for Constructor. + * @param player + */ + public ExtraTurn(Player player) { + this.player = player; + } + + /** + * @return the player + */ + public Player getPlayer() { + return player; + } + + /** + * @param player the player to set + */ + public void setPlayer(Player player) { + this.player = player; + } + + /** + * @return the loseAtEndStep + */ + public boolean isLoseAtEndStep() { + return loseAtEndStep; + } + + /** + * @param loseAtEndStep the loseAtEndStep to set + */ + public void setLoseAtEndStep(boolean loseAtEndStep) { + this.loseAtEndStep = loseAtEndStep; + } + + /** + * @return the skipUntap + */ + public boolean isSkipUntap() { + return skipUntap; + } + + /** + * @param skipUntap the skipUntap to set + */ + public void setSkipUntap(boolean skipUntap) { + this.skipUntap = skipUntap; + } + +} //end class Untap diff --git a/src/main/java/forge/game/phase/PhaseHandler.java b/src/main/java/forge/game/phase/PhaseHandler.java index c3545592505..2fd746a51de 100644 --- a/src/main/java/forge/game/phase/PhaseHandler.java +++ b/src/main/java/forge/game/phase/PhaseHandler.java @@ -32,12 +32,8 @@ import forge.GameActionUtil; import forge.MyObservable; import forge.Singletons; import forge.card.trigger.TriggerType; -import forge.control.input.Input; -import forge.control.input.InputControl; import forge.game.player.Player; import forge.game.zone.ZoneType; -import forge.gui.framework.EDocID; -import forge.gui.framework.SDisplayUtil; import forge.properties.ForgePreferences.FPref; /** @@ -61,7 +57,7 @@ public class PhaseHandler extends MyObservable implements java.io.Serializable { /** Constant GameBegins=0. */ private static int gameBegins = 0; - private final Stack extraTurns = new Stack(); + private final Stack extraTurns = new Stack(); private int extraCombats; @@ -608,7 +604,6 @@ public class PhaseHandler extends MyObservable implements java.io.Serializable { * @return a {@link forge.game.player.Player} object. */ private Player handleNextTurn() { - final Player nextTurn = this.extraTurns.isEmpty() ? this.getPlayerTurn().getOpponent() : this.extraTurns.pop(); AllZone.getStack().setCardsCastLastTurn(); AllZone.getStack().clearCardsCastThisTurn(); @@ -618,7 +613,33 @@ public class PhaseHandler extends MyObservable implements java.io.Serializable { AllZone.getComputerPlayer().setLifeLostThisTurn(0); AllZone.getHumanPlayer().setLifeLostThisTurn(0); - return this.skipTurnTimeVault(nextTurn); + return getNextActivePlayer(); + } + + /** + *

+ * getNextActivePlayer. + *

+ * + * @return a {@link forge.game.player.Player} object. + */ + private Player getNextActivePlayer() { + Player nextTurn = this.getPlayerTurn().getOpponent(); + if (!this.extraTurns.isEmpty()) { + ExtraTurn extraTurn = this.extraTurns.pop(); + nextTurn = extraTurn.getPlayer(); + if (skipTurnTimeVault(nextTurn)) { + return getNextActivePlayer(); + } + if (extraTurn.isLoseAtEndStep()) { + nextTurn.addKeyword("At the beginning of the end step, you lose the game."); + } + return nextTurn; + } + if (skipTurnTimeVault(nextTurn)) { + return getNextActivePlayer(); + } + return nextTurn; } /** @@ -630,7 +651,7 @@ public class PhaseHandler extends MyObservable implements java.io.Serializable { * a {@link forge.game.player.Player} object. * @return a {@link forge.game.player.Player} object. */ - private Player skipTurnTimeVault(Player turn) { + private boolean skipTurnTimeVault(Player turn) { // time vault: CardList vaults = turn.getCardsIn(ZoneType.Battlefield, "Time Vault"); vaults = vaults.filter(new CardListFilter() { @@ -646,13 +667,13 @@ public class PhaseHandler extends MyObservable implements java.io.Serializable { if (turn.isHuman()) { if (GameActionUtil.showYesNoDialog(crd, "Untap " + crd + "?")) { crd.untap(); - turn = this.extraTurns.isEmpty() ? turn.getOpponent() : this.extraTurns.pop(); + return true; } } else { // TODO Should AI skip his turn for time vault? } } - return turn; + return false; } /** @@ -717,7 +738,7 @@ public class PhaseHandler extends MyObservable implements java.io.Serializable { return this.getPlayerTurn().getOpponent(); } - return this.extraTurns.peek(); + return this.extraTurns.peek().getPlayer(); } /** @@ -742,14 +763,14 @@ public class PhaseHandler extends MyObservable implements java.io.Serializable { * @param player * a {@link forge.game.player.Player} object. */ - public final void addExtraTurn(final Player player) { + 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(this.getPlayerTurn().getOpponent()); + this.extraTurns.push(new ExtraTurn(this.getPlayerTurn().getOpponent())); } - this.extraTurns.push(player); + return this.extraTurns.push(new ExtraTurn(player)); } /**