diff --git a/.gitattributes b/.gitattributes index 002c1b29644..8b053dcbc72 100644 --- a/.gitattributes +++ b/.gitattributes @@ -9449,6 +9449,7 @@ src/main/java/forge/Card_Color.java svneol=native#text/plain src/main/java/forge/Card_PT.java svneol=native#text/plain src/main/java/forge/Card_Type.java svneol=native#text/plain src/main/java/forge/Color.java svneol=native#text/plain +src/main/java/forge/ColorChanger.java -text src/main/java/forge/Combat.java svneol=native#text/plain src/main/java/forge/CombatUtil.java svneol=native#text/plain src/main/java/forge/Command.java svneol=native#text/plain @@ -9480,7 +9481,6 @@ src/main/java/forge/GUI_DeckAnalysis.java svneol=native#text/plain src/main/java/forge/GUI_ImportPicture.java svneol=native#text/plain src/main/java/forge/GameAction.java svneol=native#text/plain src/main/java/forge/GameActionUtil.java svneol=native#text/plain -src/main/java/forge/GameInfo.java svneol=native#text/plain src/main/java/forge/GuiDisplay4.java svneol=native#text/plain src/main/java/forge/GuiDisplayUtil.java svneol=native#text/plain src/main/java/forge/GuiFilter.java svneol=native#text/plain @@ -9663,6 +9663,12 @@ src/main/java/forge/error/BugzReporter.java svneol=native#text/plain src/main/java/forge/error/ErrorViewer.java svneol=native#text/plain src/main/java/forge/error/ExceptionHandler.java svneol=native#text/plain src/main/java/forge/error/package-info.java svneol=native#text/plain +src/main/java/forge/game/GameEndReason.java -text +src/main/java/forge/game/GameLossReason.java -text +src/main/java/forge/game/GamePlayerRating.java -text +src/main/java/forge/game/GameSummary.java svneol=native#text/plain +src/main/java/forge/game/PlayerIndex.java -text +src/main/java/forge/game/package-info.java -text src/main/java/forge/gui/ForgeAction.java svneol=native#text/plain src/main/java/forge/gui/GuiUtils.java svneol=native#text/plain src/main/java/forge/gui/ListChooser.java svneol=native#text/plain diff --git a/src/main/java/forge/AllZone.java b/src/main/java/forge/AllZone.java index 2871340e86b..1ce82889873 100644 --- a/src/main/java/forge/AllZone.java +++ b/src/main/java/forge/AllZone.java @@ -6,9 +6,11 @@ import forge.card.cardFactory.PreloadingCardFactory; import forge.card.mana.ManaPool; import forge.card.trigger.TriggerHandler; import forge.deck.DeckManager; +import forge.game.GameSummary; import forge.gui.input.InputControl; import forge.properties.ForgeProps; import forge.properties.NewConstants; +import forge.quest.data.QuestMatchState; import java.util.HashMap; import java.util.Iterator; @@ -40,6 +42,8 @@ public class AllZone implements NewConstants { private static Quest_Assignment QuestAssignment = null; /** Constant NameChanger */ private static final NameChanger NameChanger = new NameChanger(); + /** Constant ColorChanger */ + private static final ColorChanger colorChanger = new ColorChanger(); /** Constant EndOfTurn */ private static EndOfTurn EndOfTurn = new EndOfTurn(); @@ -62,8 +66,11 @@ public class AllZone implements NewConstants { private static final GameAction GameAction = new GameAction(); /** Constant StaticEffects */ private static final StaticEffects StaticEffects = new StaticEffects(); - /** Constant GameInfo */ - private static final GameInfo GameInfo = new GameInfo(); + + /** Game state observer GameSummary collects statistics and players' performance*/ + private static GameSummary gameInfo = new GameSummary(); + /** Match State for quests are stored in a QuestMatchState class instance*/ + public static QuestMatchState matchState = new QuestMatchState(); /** Constant TriggerHandler */ private static final TriggerHandler TriggerHandler = new TriggerHandler(); @@ -308,11 +315,11 @@ public class AllZone implements NewConstants { /** *

getGameInfo.

* - * @return a {@link forge.GameInfo} object. + * @return a {@link forge.GameSummary} object. * @since 1.0.15 */ - public static GameInfo getGameInfo() { - return GameInfo; + public static GameSummary getGameInfo() { + return gameInfo; } /** @@ -606,4 +613,54 @@ public class AllZone implements NewConstants { timestamp++; return timestamp; } + + /** + *

Resets everything possible to set a new game

+ */ + public static void newGameCleanup() { + + gameInfo = new GameSummary(); + + getHumanPlayer().reset(); + getComputerPlayer().reset(); + + getPhase().reset(); + getStack().reset(); + getCombat().reset(); + getDisplay().showCombat(""); + getDisplay().loadPrefs(); + + getHumanGraveyard().reset(); + getHumanHand().reset(); + getHumanLibrary().reset(); + getHumanBattlefield().reset(); + getHumanExile().reset(); + + getComputerGraveyard().reset(); + getComputerHand().reset(); + getComputerLibrary().reset(); + getComputerBattlefield().reset(); + getComputerExile().reset(); + + getInputControl().clearInput(); + + getStaticEffects().reset(); + getColorChanger().reset(); + + // player.reset() now handles this + //AllZone.getHumanPlayer().clearHandSizeOperations(); + //AllZone.getComputerPlayer().clearHandSizeOperations(); + + getTriggerHandler().clearRegistered(); + + } + + public static QuestMatchState getMatchState() { + return matchState; + } + + public static ColorChanger getColorChanger() { + // TODO Auto-generated method stub + return colorChanger; + } }//AllZone diff --git a/src/main/java/forge/Card.java b/src/main/java/forge/Card.java index dcc9aaa62ea..b99495e59eb 100644 --- a/src/main/java/forge/Card.java +++ b/src/main/java/forge/Card.java @@ -1200,7 +1200,7 @@ public class Card extends MyObservable implements Comparable { return new Card_Color(this); } Card_Color colors = null; - ArrayList globalChanges = AllZone.getGameInfo().getColorChanges(); + ArrayList globalChanges = AllZone.getColorChanger().getColorChanges(); colors = determineColor(globalChanges); colors.fixColorless(); return colors; @@ -1227,7 +1227,8 @@ public class Card extends MyObservable implements Comparable { Card_Color determineColor(ArrayList globalChanges) { Card_Color colors = new Card_Color(this); int i = cardColor.size() - 1; - int j = globalChanges.size() - 1; + int j = -1; + if (globalChanges != null) { j = globalChanges.size() - 1; } // if both have changes, see which one is most recent while (i >= 0 && j >= 0) { Card_Color cc = null; diff --git a/src/main/java/forge/ColorChanger.java b/src/main/java/forge/ColorChanger.java new file mode 100644 index 00000000000..d5addea90aa --- /dev/null +++ b/src/main/java/forge/ColorChanger.java @@ -0,0 +1,72 @@ +package forge; + +import java.util.ArrayList; + +import forge.card.mana.ManaCost; + +public class ColorChanger { + private ArrayList globalColorChanges = new ArrayList(); + + + /** + *

addColorChanges.

+ * + * @param s a {@link java.lang.String} object. + * @param c a {@link forge.Card} object. + * @param addToColors a boolean. + * @param bIncrease a boolean. + * @return a long. + */ + public long addColorChanges(String s, Card c, boolean addToColors, boolean bIncrease) { + if (bIncrease) { + Card_Color.increaseTimestamp(); + } + globalColorChanges.add(new Card_Color(new ManaCost(s), c, addToColors, false)); + return Card_Color.getTimestamp(); + } + + /** + *

removeColorChanges.

+ * + * @param s a {@link java.lang.String} object. + * @param c a {@link forge.Card} object. + * @param addTo a boolean. + * @param timestamp a long. + */ + public final void removeColorChanges(String s, Card c, boolean addTo, long timestamp) { + Card_Color removeCol = null; + for (Card_Color cc : globalColorChanges) { + if (cc.equals(s, c, addTo, timestamp)) { + removeCol = cc; + } + } + + if (removeCol != null) { + globalColorChanges.remove(removeCol); + } + } + + /** + *

reset = clearColorChanges.

+ */ + public final void reset() { + clearColorChanges(); + } + + /** + *

clearColorChanges.

+ */ + public final void clearColorChanges() { + // clear the global color changes at end of each game + globalColorChanges.clear(); + } + + /** + *

getColorChanges.

+ * + * @return a {@link java.util.ArrayList} object. + */ + public final ArrayList getColorChanges() { + return globalColorChanges; + } +} diff --git a/src/main/java/forge/Constant.java b/src/main/java/forge/Constant.java index bfb642a9cfb..d0145a86d64 100644 --- a/src/main/java/forge/Constant.java +++ b/src/main/java/forge/Constant.java @@ -2,7 +2,6 @@ package forge; import forge.deck.Deck; -import forge.quest.data.QuestMatchState; import java.util.Arrays; import java.util.Collections; @@ -24,7 +23,7 @@ public interface Constant { public static final Deck[] HumanDeck = new Deck[1]; public static final Deck[] ComputerDeck = new Deck[1]; public static final String[] GameType = new String[1]; - public static final QuestMatchState matchState = new QuestMatchState(); + public static final boolean[] Smooth = new boolean[1]; public static final boolean[] Mill = new boolean[1]; public static final boolean[] DevMode = new boolean[1]; // one for normal mode one for quest mode @@ -161,6 +160,11 @@ public interface Constant { public static final boolean loaded[] = {false}; public static final Constant_StringArrayList NonStackingList[] = new Constant_StringArrayList[1]; } + + + + + }//Constant diff --git a/src/main/java/forge/EndOfTurn.java b/src/main/java/forge/EndOfTurn.java index 1f70b79c7c7..c315aae9fbf 100644 --- a/src/main/java/forge/EndOfTurn.java +++ b/src/main/java/forge/EndOfTurn.java @@ -61,7 +61,6 @@ public class EndOfTurn implements java.io.Serializable { AllZone.getPhase().getPlayerTurn().setMustAttackEntity(null); GameActionUtil.removeAttackedBlockedThisTurn(); - AllZone.getGameInfo().setPreventCombatDamageThisTurn(false); AllZone.getStaticEffects().rePopulateStateBasedList(); diff --git a/src/main/java/forge/GameAction.java b/src/main/java/forge/GameAction.java index fd04544c3aa..be59cfbfc68 100644 --- a/src/main/java/forge/GameAction.java +++ b/src/main/java/forge/GameAction.java @@ -11,6 +11,9 @@ import forge.card.spellability.*; import forge.card.staticAbility.StaticAbility; import forge.card.trigger.Trigger; import forge.deck.Deck; +import forge.game.GameEndReason; +import forge.game.GameSummary; +import forge.game.PlayerIndex; import forge.gui.GuiUtils; import forge.gui.input.Input_Mulligan; import forge.gui.input.Input_PayManaCost; @@ -559,43 +562,48 @@ public class GameAction { */ public boolean checkEndGameSate() { // Win / Lose + GameSummary game = AllZone.getGameInfo(); boolean humanWins = false; boolean computerWins = false; Player computer = AllZone.getComputerPlayer(); Player human = AllZone.getHumanPlayer(); - int gameWon = Constant.Runtime.matchState.getWin(); - - if (human.hasWon()) { // Winning Conditions can be worth more than losing conditions + if ( human.hasWon() || computer.hasLost() ) { // Winning Conditions can be worth more than losing conditions // Human wins humanWins = true; + if (human.getAltWin()) { - Constant.Runtime.matchState.setWinMethod(gameWon, human.getWinCondition()); + game.end(GameEndReason.WinsGameSpellEffect, PlayerIndex.HUMAN, human.getWinConditionSource()); + } else { + game.end(GameEndReason.AllOpponentsLost, PlayerIndex.HUMAN, null); } - Constant.Runtime.matchState.addWin(); - } else if (computer.hasLost()) { - // Human wins - humanWins = true; - - if (computer.getAltLose()) { - Constant.Runtime.matchState.setWinMethod(gameWon, computer.getLoseCondition()); - } - Constant.Runtime.matchState.addWin(); } if (computer.hasWon() || human.hasLost()) { if (humanWins) { // both players won/lost at the same time. - // TODO: Handle a Draw here + game.end(GameEndReason.Draw, PlayerIndex.DRAW, null); + } else { + computerWins = true; + + if (computer.getAltWin()) { + game.end(GameEndReason.WinsGameSpellEffect, PlayerIndex.AI, computer.getWinConditionSource()); + } else { + game.end(GameEndReason.AllOpponentsLost, PlayerIndex.AI, null); + } + } - - // Computer wins - computerWins = true; - Constant.Runtime.matchState.addLose(); } - return humanWins || computerWins; + boolean isGameDone = humanWins || computerWins; + if (isGameDone) { + game.getPlayerRating(PlayerIndex.AI).setLossReason(computer.getLossState()); + game.getPlayerRating(PlayerIndex.HUMAN).setLossReason(human.getLossState()); + AllZone.getMatchState().addGamePlayed(game); + } + + return isGameDone; } @@ -616,7 +624,7 @@ public class GameAction { if (checkEndGameSate()) { AllZone.getDisplay().savePrefs(); frame.dispose(); - new Gui_WinLose(); + new Gui_WinLose( AllZone.getMatchState(), AllZone.getQuestData(), AllZone.getQuestAssignment() ); return; } @@ -1044,41 +1052,7 @@ public class GameAction { //AllZone.getComputer() = new ComputerAI_Input(new ComputerAI_General()); Constant.Quest.fantasyQuest[0] = false; - AllZone.getGameInfo().setPreventCombatDamageThisTurn(false); - AllZone.getGameInfo().setHumanNumberOfTimesMulliganed(0); - AllZone.getGameInfo().setHumanMulliganedToZero(false); - AllZone.getGameInfo().setComputerStartedThisGame(false); - - AllZone.getHumanPlayer().reset(); - AllZone.getComputerPlayer().reset(); - - AllZone.getPhase().reset(); - AllZone.getStack().reset(); - AllZone.getCombat().reset(); - AllZone.getDisplay().showCombat(""); - AllZone.getDisplay().loadPrefs(); - - AllZone.getHumanGraveyard().reset(); - AllZone.getHumanHand().reset(); - AllZone.getHumanLibrary().reset(); - AllZone.getHumanBattlefield().reset(); - AllZone.getHumanExile().reset(); - - AllZone.getComputerGraveyard().reset(); - AllZone.getComputerHand().reset(); - AllZone.getComputerLibrary().reset(); - AllZone.getComputerBattlefield().reset(); - AllZone.getComputerExile().reset(); - - AllZone.getInputControl().clearInput(); - - AllZone.getStaticEffects().reset(); - - // player.reset() now handles this - //AllZone.getHumanPlayer().clearHandSizeOperations(); - //AllZone.getComputerPlayer().clearHandSizeOperations(); - - AllZone.getTriggerHandler().clearRegistered(); + AllZone.newGameCleanup(); forge.card.trigger.Trigger.resetIDs(); @@ -1216,13 +1190,13 @@ public class GameAction { } // Only cut/coin toss if it's the first game of the match - if (Constant.Runtime.matchState.countWinLose() == 0) { + if (AllZone.getMatchState().getGamesPlayedCount() == 0) { // New code to determine who goes first. Delete this if it doesn't work properly if (isStartCut()) seeWhoPlaysFirst(); else seeWhoPlaysFirst_CoinToss(); - } else if (Constant.Runtime.matchState.didWinRecently()) // if player won last, AI starts + } else if (AllZone.getMatchState().hasHumanWonLastGame()) // if player won last, AI starts computerStartsGame(); for (int i = 0; i < 7; i++) { @@ -1482,7 +1456,7 @@ public class GameAction { */ public void computerStartsGame() { AllZone.getPhase().setPlayerTurn(AllZone.getComputerPlayer()); - AllZone.getGameInfo().setComputerStartedThisGame(true); + AllZone.getGameInfo().setPlayerWhoGotFirstTurn(PlayerIndex.AI); } //if Card had the type "Aura" this method would always return true, since local enchantments are always attached to something diff --git a/src/main/java/forge/GameActionUtil.java b/src/main/java/forge/GameActionUtil.java index 33f7af8c595..7d1cde67ade 100644 --- a/src/main/java/forge/GameActionUtil.java +++ b/src/main/java/forge/GameActionUtil.java @@ -4,6 +4,7 @@ package forge; import forge.card.abilityFactory.AbilityFactory; import forge.card.cardFactory.CardFactoryUtil; import forge.card.spellability.*; +import forge.game.GameLossReason; import forge.gui.GuiUtils; import forge.gui.input.Input; import forge.gui.input.Input_PayManaCostUtil; @@ -632,9 +633,6 @@ public class GameActionUtil { if (c.getCreatureGotBlockedThisCombat()) c.setCreatureGotBlockedThisCombat(false); } - - AllZone.getGameInfo().setAssignedFirstStrikeDamageThisCombat(false); - AllZone.getGameInfo().setResolvedFirstStrikeDamageThisCombat(false); } /** @@ -1025,7 +1023,7 @@ public class GameActionUtil { CardList nonTokens = AllZoneUtil.getPlayerCardsInPlay(player); nonTokens = nonTokens.filter(AllZoneUtil.nonToken); if (nonTokens.size() == 0) { - player.altLoseConditionMet("Lich"); + player.loseConditionMet( GameLossReason.SpellEffect, lich.getName()); } else player.sacrificePermanent("Select a permanent to sacrifice", nonTokens); } } diff --git a/src/main/java/forge/GameInfo.java b/src/main/java/forge/GameInfo.java deleted file mode 100644 index 51c920a5a6e..00000000000 --- a/src/main/java/forge/GameInfo.java +++ /dev/null @@ -1,194 +0,0 @@ -package forge; - -import forge.card.mana.ManaCost; - -import java.util.ArrayList; - -/** - *

GameInfo class.

- * - * @author Forge - * @version $Id$ - */ -public class GameInfo { - private boolean computerStartedThisGame = false; - - private int humanNumberOfTimesMulliganed; - private boolean humanMulliganedToZero; - - private boolean preventCombatDamageThisTurn; - private boolean assignedFirstStrikeDamageThisCombat; - private boolean resolvedFirstStrikeDamageThisCombat; - - private ArrayList globalColorChanges = new ArrayList(); - - /** - *

Getter for the field humanNumberOfTimesMulliganed.

- * - * @return a int. - */ - public int getHumanNumberOfTimesMulliganed() { - return humanNumberOfTimesMulliganed; - } - - /** - *

addHumanNumberOfTimesMulliganed.

- * - * @param n a int. - */ - public void addHumanNumberOfTimesMulliganed(int n) { - humanNumberOfTimesMulliganed += n; - } - - /** - *

Setter for the field humanNumberOfTimesMulliganed.

- * - * @param n a int. - */ - public void setHumanNumberOfTimesMulliganed(int n) { - humanNumberOfTimesMulliganed = n; - } - - /** - *

Getter for the field humanMulliganedToZero.

- * - * @return a boolean. - */ - public boolean getHumanMulliganedToZero() { - return humanMulliganedToZero; - } - - /** - *

Setter for the field humanMulliganedToZero.

- * - * @param b a boolean. - */ - public void setHumanMulliganedToZero(boolean b) { - humanMulliganedToZero = b; - } - - /** - *

Setter for the field preventCombatDamageThisTurn.

- * - * @param b a boolean. - */ - public void setPreventCombatDamageThisTurn(boolean b) { - preventCombatDamageThisTurn = b; - } - - /** - *

isPreventCombatDamageThisTurn.

- * - * @return a boolean. - */ - public boolean isPreventCombatDamageThisTurn() { - return preventCombatDamageThisTurn; - } - - /** - *

Setter for the field assignedFirstStrikeDamageThisCombat.

- * - * @param b a boolean. - */ - public void setAssignedFirstStrikeDamageThisCombat(boolean b) { - assignedFirstStrikeDamageThisCombat = b; - } - - /** - *

Getter for the field assignedFirstStrikeDamageThisCombat.

- * - * @return a boolean. - */ - public boolean getAssignedFirstStrikeDamageThisCombat() { - return assignedFirstStrikeDamageThisCombat; - } - - /** - *

Setter for the field resolvedFirstStrikeDamageThisCombat.

- * - * @param b a boolean. - */ - public void setResolvedFirstStrikeDamageThisCombat(boolean b) { - resolvedFirstStrikeDamageThisCombat = b; - } - - /** - *

Getter for the field resolvedFirstStrikeDamageThisCombat.

- * - * @return a boolean. - */ - public boolean getResolvedFirstStrikeDamageThisCombat() { - return resolvedFirstStrikeDamageThisCombat; - } - - /** - *

Setter for the field computerStartedThisGame.

- * - * @param computerStartedThisGame a boolean. - */ - public void setComputerStartedThisGame(boolean computerStartedThisGame) { - this.computerStartedThisGame = computerStartedThisGame; - } - - /** - *

isComputerStartedThisGame.

- * - * @return a boolean. - */ - public boolean isComputerStartedThisGame() { - return computerStartedThisGame; - } - - /** - *

addColorChanges.

- * - * @param s a {@link java.lang.String} object. - * @param c a {@link forge.Card} object. - * @param addToColors a boolean. - * @param bIncrease a boolean. - * @return a long. - */ - public long addColorChanges(String s, Card c, boolean addToColors, boolean bIncrease) { - if (bIncrease) - Card_Color.increaseTimestamp(); - globalColorChanges.add(new Card_Color(new ManaCost(s), c, addToColors, false)); - return Card_Color.getTimestamp(); - } - - /** - *

removeColorChanges.

- * - * @param s a {@link java.lang.String} object. - * @param c a {@link forge.Card} object. - * @param addTo a boolean. - * @param timestamp a long. - */ - public void removeColorChanges(String s, Card c, boolean addTo, long timestamp) { - Card_Color removeCol = null; - for (Card_Color cc : globalColorChanges) - if (cc.equals(s, c, addTo, timestamp)) - removeCol = cc; - - if (removeCol != null) - globalColorChanges.remove(removeCol); - } - - /** - *

clearColorChanges.

- */ - public void clearColorChanges() { - // clear the global color changes at end of each game - globalColorChanges.clear(); - } - - /** - *

getColorChanges.

- * - * @return a {@link java.util.ArrayList} object. - */ - public ArrayList getColorChanges() { - return globalColorChanges; - } - - -} diff --git a/src/main/java/forge/GuiDisplay4.java b/src/main/java/forge/GuiDisplay4.java index b9a80621810..433b5008b0c 100644 --- a/src/main/java/forge/GuiDisplay4.java +++ b/src/main/java/forge/GuiDisplay4.java @@ -7,6 +7,7 @@ import arcane.ui.ViewPanel; import arcane.ui.util.Animation; import forge.card.cardFactory.CardFactoryUtil; import forge.error.ErrorViewer; +import forge.game.GameLossReason; import forge.gui.ForgeAction; import forge.gui.GuiUtils; import forge.gui.game.CardDetailPanel; @@ -59,7 +60,6 @@ public class GuiDisplay4 extends JFrame implements CardContainer, Display, NewCo Font lifeFont = new Font("Dialog", Font.PLAIN, 40); // Font checkboxFont = new Font("Dialog", Font.PLAIN, 9); - /** Constant greenColor */ public static Color greenColor = new Color(0, 164, 0); @@ -1134,10 +1134,8 @@ public class GuiDisplay4 extends JFrame implements CardContainer, Display, NewCo * Exit the Application */ private void concede() { - savePrefs(); - dispose(); - Constant.Runtime.matchState.addLose(); - new Gui_WinLose(); + AllZone.getHumanPlayer().loseConditionMet(GameLossReason.Conceded, null ); + AllZone.getGameAction().checkStateEffects(); } // ********** Phase stuff in Display ****************** diff --git a/src/main/java/forge/Gui_WinLose.java b/src/main/java/forge/Gui_WinLose.java index 9b12e97ef13..c9b1d2d88fa 100644 --- a/src/main/java/forge/Gui_WinLose.java +++ b/src/main/java/forge/Gui_WinLose.java @@ -1,25 +1,38 @@ package forge; - -import forge.error.ErrorViewer; +import forge.error.E +import forge.game.GameEndReason; +rrorViewer; +import forge.game.GameLossReason; +import forge.game.GamePlayerRating; +import forge.game.GameSummary; +import forge.game.PlayerIndex; import forge.properties.ForgeProps; import forge.properties.NewConstants; import forge.properties.NewConstants.LANG.Gui_WinLose.WINLOSE_TEXT; +import forge.quest.data.QuestData; import forge.quest.data.QuestMatchState; import forge.quest.data.QuestPreferences; import forge.quest.gui.QuestFrame; import forge.view.swing.OldGuiNewGame; import net.miginfocom.swing.MigLayout; -import javax.swing.*; +import javax.swing.BorderFactory; +import javax.swing.ImageIcon; +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.SwingConstants; import javax.swing.border.Border; import javax.swing.border.TitledBorder; import java.awt.Color; -import java.awt.*; +import java.awt.Dimension; import java.awt.event.ActionEvent; import java.awt.event.WindowEvent; import java.io.File; - +import java.util.ArrayList; /** *

Gui_WinLose class.

@@ -31,14 +44,6 @@ public class Gui_WinLose extends JFrame implements NewConstants { /** Constant serialVersionUID=-5800412940994975483L */ private static final long serialVersionUID = -5800412940994975483L; - //private CardList humanList; - //private CardList computerList; - - //private int humanLife; - //private int computerLife; - - //private boolean fantasyQuest = false; - private JLabel titleLabel = new JLabel(); private JButton continueButton = new JButton(); private JButton restartButton = new JButton(); @@ -52,51 +57,22 @@ public class Gui_WinLose extends JFrame implements NewConstants { // border1 private Border border1; - /** - *

Constructor for Gui_WinLose.

- * - * @param human a {@link forge.CardList} object. - * @param computer a {@link forge.CardList} object. - * @param hLife a int. - * @param cLife a int. - */ - public Gui_WinLose(CardList human, CardList computer, int hLife, int cLife) { - /* - fantasyQuest = true; - - humanList = human; - computerList = computer; - - humanLife = hLife; - computerLife= cLife; - */ - try { - jbInit(); - } catch (Exception ex) { - ErrorViewer.showError(ex); - } - - setup(); - - Dimension screen = this.getToolkit().getScreenSize(); - setBounds(screen.width / 3, 100, //position - 215, 370); //size - setVisible(true); + private class WinLoseModel { + public QuestMatchState match; + public QuestData quest; + public Quest_Assignment qa; } + private WinLoseModel model; + /** *

Constructor for Gui_WinLose.

*/ - public Gui_WinLose() { - /* - fantasyQuest = false; - - humanList = new CardList(); - computerList = new CardList(); - - humanLife = 20; - computerLife= 20; - */ + public Gui_WinLose(final QuestMatchState matchState, final QuestData quest, final Quest_Assignment qa) { + model = new WinLoseModel(); + model.match = matchState; + model.quest = quest; + model.qa = qa; try { jbInit(); @@ -107,8 +83,7 @@ public class Gui_WinLose extends JFrame implements NewConstants { setup(); Dimension screen = this.getToolkit().getScreenSize(); - setBounds(screen.width / 3, 100, //position - 215, 370); //size + setBounds(screen.width / 3, 100 /*position*/, 215, 370 /*size*/); setVisible(true); } @@ -116,47 +91,28 @@ public class Gui_WinLose extends JFrame implements NewConstants { *

setup.

*/ private void setup() { - AllZone.getGameInfo().clearColorChanges(); - QuestMatchState winLose = Constant.Runtime.matchState; Phase.setGameBegins(0); - //3 is the match length, 3 is the number of games - //disable buttons if match is up, or human player won 2 or lost 2 games already - if ((winLose.countWinLose() == 3) || (winLose.getWin() == 2) || (winLose.getLose() == 2)) { + + if (model.match.isMatchOver()) { // editDeckButton.setEnabled(false); continueButton.setEnabled(false); quitButton.grabFocus(); } - if (winLose.getWin() == 2) - restartButton.setEnabled(false); + restartButton.setEnabled(!model.match.isMatchWonByHuman()); //show Wins and Loses - statsLabel.setText(ForgeProps.getLocalized(WINLOSE_TEXT.WON) + winLose.getWin() + ForgeProps.getLocalized(WINLOSE_TEXT.LOST) + winLose.getLose()); + int humanWins = model.match.getGamesCountWonByHuman(); + int humanLosses = model.match.getGamesCountLostByHuman(); + statsLabel.setText(ForgeProps.getLocalized(WINLOSE_TEXT.WON) + humanWins + + ForgeProps.getLocalized(WINLOSE_TEXT.LOST) + humanLosses); + //show "You Won" or "You Lost" - if (winLose.didWinRecently()) { + if (model.match.hasHumanWonLastGame()) { titleLabel.setText(ForgeProps.getLocalized(WINLOSE_TEXT.WIN)); - - int game = 0; - if (winLose.getWinTurns()[0] != 0) - game = 1; - int turn = AllZone.getPhase().getTurn(); - if (AllZone.getGameInfo().isComputerStartedThisGame()) - turn--; - - if (turn < 1) - turn = 1; - - winLose.setWinTurn(game, turn); - winLose.setMulliganedToZero(game, AllZone.getGameInfo().getHumanMulliganedToZero()); - - //winLose.setWinTurn(winLose.countWinLose()-1, AllZone.getPhase().getTurn()); - - //System.out.println("CountwinLose:" + winLose.countWinLose()); - //System.out.println("You won by turn: " + AllZone.getPhase().getTurn()); } else { titleLabel.setText(ForgeProps.getLocalized(WINLOSE_TEXT.LOSE)); - //System.out.println("You lost by turn: " + AllZone.getPhase().getTurn()); } }//setup(); @@ -174,21 +130,15 @@ public class Gui_WinLose extends JFrame implements NewConstants { this.getContentPane().setLayout(new MigLayout("fill")); continueButton.setText(ForgeProps.getLocalized(WINLOSE_TEXT.CONTINUE)); continueButton.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(ActionEvent e) { - continueButton_actionPerformed(e); - } + public void actionPerformed(ActionEvent e) { continueButton_actionPerformed(e); } }); restartButton.setText(ForgeProps.getLocalized(WINLOSE_TEXT.RESTART)); restartButton.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(ActionEvent e) { - restartButton_actionPerformed(e); - } + public void actionPerformed(ActionEvent e) { restartButton_actionPerformed(e); } }); quitButton.setText(ForgeProps.getLocalized(WINLOSE_TEXT.QUIT)); quitButton.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(ActionEvent e) { - quitButton_actionPerformed(e); - } + public void actionPerformed(ActionEvent e) { quitButton_actionPerformed(e); } }); statsLabel.setFont(new java.awt.Font("Dialog", 0, 16)); statsLabel.setHorizontalAlignment(SwingConstants.CENTER); @@ -196,9 +146,7 @@ public class Gui_WinLose extends JFrame implements NewConstants { jPanel2.setLayout(new MigLayout("align center")); this.addWindowListener(new java.awt.event.WindowAdapter() { @Override - public void windowClosing(WindowEvent e) { - this_windowClosing(e); - } + public void windowClosing(WindowEvent e) { this_windowClosing(e); } }); this.getContentPane().add(titleLabel, "align center, grow, wrap"); this.getContentPane().add(statsLabel, "align center, grow, wrap"); @@ -209,26 +157,6 @@ public class Gui_WinLose extends JFrame implements NewConstants { } - /** - *

editDeckButton_actionPerformed.

- * - * @param e a {@link java.awt.event.ActionEvent} object. - */ - void editDeckButton_actionPerformed(ActionEvent e) { - Command exit = new Command() { - private static final long serialVersionUID = 4735992294414389187L; - - public void execute() { - new Gui_WinLose(); - } - }; - Gui_DeckEditor editor = new Gui_DeckEditor(); - - editor.show(exit); - - dispose(); - }//editDeckButton_actionPerformed() - /** *

continueButton_actionPerformed.

* @@ -236,32 +164,36 @@ public class Gui_WinLose extends JFrame implements NewConstants { */ void continueButton_actionPerformed(ActionEvent e) { //open up "Game" screen - //AllZone.getComputerPlay().reset();//sometimes computer has creature in play in the 2nd game of the match - - if (!Constant.Quest.fantasyQuest[0]) - AllZone.getGameAction().newGame(Constant.Runtime.HumanDeck[0], Constant.Runtime.ComputerDeck[0]); - else { + + PrepareForNextRound(); + AllZone.getDisplay().setVisible(true); + dispose(); + } + + void PrepareForNextRound() + { + if (Constant.Quest.fantasyQuest[0]) { int extraLife = 0; - if (AllZone.getQuestAssignment() != null) { - forge.quest.data.QuestUtil.setupQuest(AllZone.getQuestAssignment()); - if (AllZone.getQuestData().getInventory().hasItem("Zeppelin")) + if (model.qa != null) { + forge.quest.data.QuestUtil.setupQuest(model.qa); + if (model.quest.getInventory().hasItem("Zeppelin")) extraLife = 3; } //AllZone.getGameAction().newGame(Constant.Runtime.HumanDeck[0], Constant.Runtime.ComputerDeck[0], humanList, computerList, humanLife, computerLife); - CardList humanList = forge.quest.data.QuestUtil.getHumanPlantAndPet(AllZone.getQuestData(), AllZone.getQuestAssignment()); + CardList humanList = forge.quest.data.QuestUtil.getHumanPlantAndPet(model.quest, model.qa); CardList computerList = new CardList(); - int humanLife = AllZone.getQuestData().getLife() + extraLife; + int humanLife = model.quest.getLife() + extraLife; int computerLife = 20; - if (AllZone.getQuestAssignment() != null) - computerLife = AllZone.getQuestAssignment().getComputerLife(); + if ( model.qa != null ) + computerLife = model.qa.getComputerLife(); - AllZone.getGameAction().newGame(Constant.Runtime.HumanDeck[0], Constant.Runtime.ComputerDeck[0], humanList, computerList, humanLife, computerLife, AllZone.getQuestAssignment()); + AllZone.getGameAction().newGame(Constant.Runtime.HumanDeck[0], Constant.Runtime.ComputerDeck[0], humanList, computerList, humanLife, computerLife, model.qa ); + } else { + AllZone.getGameAction().newGame(Constant.Runtime.HumanDeck[0], Constant.Runtime.ComputerDeck[0]); } - AllZone.getDisplay().setVisible(true); - dispose(); } /** @@ -270,33 +202,9 @@ public class Gui_WinLose extends JFrame implements NewConstants { * @param e a {@link java.awt.event.ActionEvent} object. */ void restartButton_actionPerformed(ActionEvent e) { - Constant.Runtime.matchState.reset(); - - if (!Constant.Quest.fantasyQuest[0]) - AllZone.getGameAction().newGame(Constant.Runtime.HumanDeck[0], Constant.Runtime.ComputerDeck[0]); - else { - int extraLife = 0; - //AllZone.getGameAction().newGame(Constant.Runtime.HumanDeck[0], Constant.Runtime.ComputerDeck[0], humanList, computerList, humanLife, computerLife); - if (AllZone.getQuestAssignment() != null) { - forge.quest.data.QuestUtil.setupQuest(AllZone.getQuestAssignment()); - if (AllZone.getQuestData().getInventory().hasItem("Zeppelin")) - extraLife = 3; - } - - CardList humanList = forge.quest.data.QuestUtil.getHumanPlantAndPet(AllZone.getQuestData(), AllZone.getQuestAssignment()); - //CardList computerList = QuestUtil.getComputerCreatures(AllZone.getQuestData(), AllZone.getQuestAssignment()); - CardList computerList = new CardList(); - - int humanLife = AllZone.getQuestData().getLife() + extraLife; - int computerLife = 20; - - if (AllZone.getQuestAssignment() != null) - computerLife = AllZone.getQuestAssignment().getComputerLife(); - - AllZone.getGameAction().newGame(Constant.Runtime.HumanDeck[0], Constant.Runtime.ComputerDeck[0], humanList, computerList, humanLife, computerLife, AllZone.getQuestAssignment()); - } + model.match.reset(); + PrepareForNextRound(); AllZone.getDisplay().setVisible(true); - dispose(); } @@ -304,88 +212,82 @@ public class Gui_WinLose extends JFrame implements NewConstants { *

getWinText.

* * @param creds a long. - * @param winLose a {@link forge.quest.data.QuestMatchState} object. + * @param matchState a {@link forge.quest.data.QuestMatchState} object. * @param q a {@link forge.quest.data.QuestData} object. * @return a {@link java.lang.String} object. */ - private String getWinText(long creds, QuestMatchState winLose, forge.quest.data.QuestData q) { + private String getCreditsAwardedText(final long creds, final QuestMatchState matchState, final forge.quest.data.QuestData q) { // TODO use q.qdPrefs to write bonus credits in prefs file - StringBuilder sb = new StringBuilder(); - String[] wins = winLose.getWinMethods(); + StringBuilder sb = new StringBuilder(""); - sb.append(""); + boolean hasNeverLost = true; + for (GameSummary game : matchState.getGamesPlayed()) { + if (game.isAIWinner()) { + hasNeverLost = true; + continue; // no rewards for losing a game + } - for (String s : wins) { - if (s != null) { - sb.append("Alternate win condition: "); - sb.append(""); - sb.append(s); - sb.append(""); - sb.append("! Bonus: +"); + GamePlayerRating aiRating = game.getPlayerRating(PlayerIndex.AI); + GamePlayerRating humanRating = game.getPlayerRating(PlayerIndex.HUMAN); + GameLossReason whyAiLost = aiRating.getLossReason(); - if (s.equals("Poison Counters")) - sb.append(QuestPreferences.getMatchRewardPoisonWinBonus()); - else if (s.equals("Milled")) - sb.append(QuestPreferences.getMatchRewardMilledWinBonus()); - else if (s.equals("Battle of Wits") || - s.equals("Felidar Sovereign") || s.equals("Helix Pinnacle") || s.equals("Epic Struggle") || - s.equals("Door to Nothingness") || s.equals("Barren Glory") || s.equals("Near-Death Experience") || - s.equals("Mortal Combat") || s.equals("Test of Endurance")) { - - sb.append(QuestPreferences.getMatchRewardAltWinBonus()); + int rewardAltWinCondition = q.getCreditsRewardForAltWin(whyAiLost); + if (rewardAltWinCondition > 0) { + String winConditionName = "Unknown (bug)"; + if ( game.getWinCondition() == GameEndReason.WinsGameSpellEffect ) { + winConditionName = game.getWinSpellEffect(); + } else { + switch( whyAiLost ) { + case Poisoned: winConditionName = "Poison"; break; + case Milled: winConditionName = "Milled"; break; + default: break; + } } - sb.append(" credits.
"); + String bonus = String.format("Alternate win condition: %s! Bonus: +%d credits.
", + winConditionName, rewardAltWinCondition); + sb.append(bonus); + } + + int winTurn = game.getTurnGameEnded(); + + int turnCredits = q.getCreditsRewardForWinByTurn(winTurn); + + if (winTurn == 0) { // this case should never happen - anyway, no reward if we got here + } else if (winTurn == 1) { sb.append("Won in one turn!"); + } else if (winTurn <= 5) { sb.append("Won by turn 5!"); + } else if (winTurn <= 10) { sb.append("Won by turn 10!"); + } else if (winTurn <= 15) { sb.append("Won by turn 15!"); + } + + if (turnCredits > 0) { + sb.append(String.format(" Bonus: +%d credits.
", turnCredits)); + } + + int cntCardsHumanStartedWith = humanRating.getOpeningHandSize(); + if ( 0 == cntCardsHumanStartedWith ) + { + int reward = QuestPreferences.getMatchMullToZero(); + sb.append(String.format("Mulliganed to zero and still won! Bonus: %d credits.
", reward)); } } - int[] winTurns = winLose.getWinTurns(); - for (int i : winTurns) { - System.out.println("Quest, won by turn:" + i); - - if (i != 0) { - int turnCredits = 0; - - if (i == 1) { - sb.append("Won in one turn!"); - turnCredits += QuestPreferences.getMatchRewardWinFirst(); - } else if (i <= 5) { - sb.append("Won by turn 5!"); - turnCredits += QuestPreferences.getMatchRewardWinByFifth(); - } else if (i <= 10) { - sb.append("Won by turn 10!"); - turnCredits += QuestPreferences.getMatchRewardWinByTen(); - } else if (i <= 15) { - sb.append("Won by turn 15!"); - turnCredits += QuestPreferences.getMatchRewardWinByFifteen(); - } - if (turnCredits > 0) - sb.append(" Bonus: +").append(turnCredits).append(" credits.
"); - } + if (hasNeverLost) { + int reward = QuestPreferences.getMatchRewardNoLosses(); + sb.append(String.format("You have not lost once! Bonus: +%d credits.
", reward)); } - boolean[] mulliganedToZero = winLose.getMulliganedToZero(); + int estatesLevel = q.getInventory().getItemLevel("Estates"); - for (boolean b : mulliganedToZero) { - if (b) { - sb.append("Mulliganed to zero and still won! Bonus: +"); - sb.append(QuestPreferences.getMatchMullToZero()).append(" credits.
"); - } - } - - if (winLose.getLose() == 0) - sb.append("You have not lost once! Bonus: +"); - sb.append(QuestPreferences.getMatchRewardNoLosses()).append(" credits.
"); - - if (q.getInventory().getItemLevel("Estates") == 1) + if (estatesLevel == 1) { sb.append("Estates bonus: 10%.
"); - else if (q.getInventory().getItemLevel("Estates") == 2) + } else if (estatesLevel == 2) { sb.append("Estates bonus: 15%.
"); - else if (q.getInventory().getItemLevel("Estates") == 3) + } else if (estatesLevel == 3) { sb.append("Estates bonus: 20%.
"); - + } sb.append("You have earned " + creds + " credits in total."); sb.append(""); @@ -428,110 +330,30 @@ public class Gui_WinLose extends JFrame implements NewConstants { if (AllZone.getQuestData() == null) { new OldGuiNewGame(); } else { //Quest - QuestMatchState matchState = Constant.Runtime.matchState; - forge.quest.data.QuestData quest = AllZone.getQuestData(); boolean wonMatch = false; - if (matchState.getWin() == 2) { - quest.addWin(); + if (model.match.isMatchWonByHuman()) { + model.quest.addWin(); wonMatch = true; - } else quest.addLost(); + } else { + model.quest.addLost(); + } //System.out.println("QuestData cardpoolsize:" + AllZone.getQuestData().getCardpool().size()); - if (AllZone.getQuestData().getShopList() != null) - AllZone.getQuestData().clearShopList(); - - if (AllZone.getQuestData().getAvailableQuests() != null) - AllZone.getQuestData().clearAvailableQuests(); - - if (quest.shouldAddCards(wonMatch)) { - quest.addCards(); - String fileName = "BookIcon.png"; - ImageIcon icon = getIcon(fileName); - - StringBuilder sb = new StringBuilder(); - sb.append("You have won the following new cards:\n"); - for (int i = 0; i < quest.getAddedCards().size(); i++) - sb.append(quest.getAddedCards().get(i) + "\n"); - - JOptionPane.showMessageDialog(null, sb.toString(), "", JOptionPane.INFORMATION_MESSAGE, icon); + if (model.quest.getShopList() != null) { + model.quest.clearShopList(); } - if (wonMatch) { - long creds = quest.getCreditsToAdd(matchState); - String s = getWinText(creds, matchState, quest); - - String fileName = "GoldIcon.png"; - ImageIcon icon = getIcon(fileName); - - JOptionPane.showMessageDialog(null, s, "", JOptionPane.INFORMATION_MESSAGE, icon); - int wins = quest.getWin(); - if (wins > 0 && wins % 80 == 0) // at every 80 wins, give 10 random rares - { - quest.addRandomRare(10); - fileName = "BoxIcon.png"; - icon = getIcon(fileName); - JOptionPane.showMessageDialog(null, "You just won 10 random rares!", "", JOptionPane.INFORMATION_MESSAGE, icon); - } - - if (AllZone.getQuestAssignment() != null) { - AllZone.getQuestData().addQuestsPlayed(); - Quest_Assignment qa = AllZone.getQuestAssignment(); - - StringBuilder sb = new StringBuilder(); - sb.append("Quest Completed - \r\n"); - - if (qa.getCardRewardList() != null) { - sb.append("You won the following cards:\r\n\r\n"); - for (String cardName : qa.getCardRewardList()) { - sb.append(cardName); - sb.append("\r\n"); - - AllZone.getQuestData().addCard(cardName); - } - AllZone.getQuestData().addToNewList(qa.getCardRewardList()); - sb.append("\r\n"); - } - sb.append("Quest Bounty: "); - sb.append(qa.getCreditsReward()); - - AllZone.getQuestData().addCredits(qa.getCreditsReward()); - - fileName = "BoxIcon.png"; - icon = getIcon(fileName); - JOptionPane.showMessageDialog(null, sb.toString(), "Quest Rewards for " + qa.getName(), JOptionPane.INFORMATION_MESSAGE, icon); - }/* - else if(quest.getDifficultyIndex() == 4) { - Card c = AllZone.getCardFactory().getCard(quest.addRandomRare(), AllZone.getHumanPlayer()); - c.setCurSetCode(c.getMostRecentSet()); - fileName = CardUtil.buildFilename(c) +".jpg"; - icon = getCardIcon(fileName); - - JOptionPane.showMessageDialog(null, "", "You have won a random rare for winning against a very hard deck.", JOptionPane.INFORMATION_MESSAGE, icon); - }*/ - - } else { - quest.subtractCredits(15); - String fileName = "HeartIcon.png"; - ImageIcon icon = getIcon(fileName); - - JOptionPane.showMessageDialog(null, "You lose! You have lost 15 credits.", "Awwww", JOptionPane.INFORMATION_MESSAGE, icon); + if (model.quest.getAvailableQuests() != null) { + model.quest.clearAvailableQuests(); } - if (quest.shouldAddAdditionalCards(wonMatch)) { - Card c = AllZone.getCardFactory().getCard(quest.addRandomRare(), AllZone.getHumanPlayer()); - c.setCurSetCode(c.getMostRecentSet()); - String fileName = CardUtil.buildFilename(c) + ".jpg"; - ImageIcon icon = getCardIcon(fileName); - - JOptionPane.showMessageDialog(null, "", "You have won a random rare.", JOptionPane.INFORMATION_MESSAGE, icon); - } - - matchState.reset(); + giveQuestRewards(wonMatch); + model.match.reset(); AllZone.setQuestAssignment(null); - quest.saveData(); + model.quest.saveData(); new QuestFrame(); }//else - on quest @@ -552,4 +374,106 @@ public class Gui_WinLose extends JFrame implements NewConstants { void this_windowClosing(WindowEvent e) { quitButton_actionPerformed(null); } + + protected void giveQuestRewards(final boolean wonMatch) { + // Award a random booster, as frequent as set in difficulty setup + if (model.quest.shouldAddCards(wonMatch)) { + ArrayList cardsWon = model.quest.addCards(); + + StringBuilder sb = new StringBuilder(); + sb.append("You have won the following new cards:\n"); + for (String cardName : cardsWon) { + sb.append(cardName + "\n"); + } + + String fileName = "BookIcon.png"; + ImageIcon icon = getIcon(fileName); + JOptionPane.showMessageDialog(null, sb.toString(), "", JOptionPane.INFORMATION_MESSAGE, icon); + } + + // Award credits + if (wonMatch) { + long creds = model.quest.getCreditsToAdd(model.match); + model.quest.addCredits(creds); + + String s = getCreditsAwardedText(creds, model.match, model.quest); + String fileName = "GoldIcon.png"; + ImageIcon icon = getIcon(fileName); + + JOptionPane.showMessageDialog(null, s, "", JOptionPane.INFORMATION_MESSAGE, icon); + } + + // Award 10 rares for 80 games won + if (wonMatch) { + int wins = model.quest.getWin(); + if (wins > 0 && wins % 80 == 0) // at every 80 wins, give 10 random rares + { + model.quest.addRandomRare(10); + String fileName = "BoxIcon.png"; + ImageIcon icon = getIcon(fileName); + String title = "You just won 10 random rares!"; + JOptionPane.showMessageDialog(null, title, "", JOptionPane.INFORMATION_MESSAGE, icon); + } + } + + // Rewards from QuestAssignment + if (wonMatch && model.qa != null) { + model.quest.addQuestsPlayed(); + + ArrayList questRewardCards = model.qa.getCardRewardList(); + long questRewardCredits = model.qa.getCreditsReward(); + + StringBuilder sb = new StringBuilder(); + sb.append("Quest Completed - \r\n"); + + if (questRewardCards != null) { + sb.append("You won the following cards:\r\n\r\n"); + for (String cardName : questRewardCards) { + sb.append(cardName); + sb.append("\r\n"); + + model.quest.addCard(cardName); + } + model.quest.addToNewList(questRewardCards); + sb.append("\r\n"); + } + sb.append("Quest Bounty: "); + sb.append(questRewardCredits); + + model.quest.addCredits(questRewardCredits); + + String fileName = "BoxIcon.png"; + ImageIcon icon = getIcon(fileName); + String title = "Quest Rewards for " + model.qa.getName(); + JOptionPane.showMessageDialog(null, sb.toString(), title, JOptionPane.INFORMATION_MESSAGE, icon); + } + /* + else if(quest.getDifficultyIndex() == 4) { + Card c = AllZone.getCardFactory().getCard(quest.addRandomRare(), AllZone.getHumanPlayer()); + c.setCurSetCode(c.getMostRecentSet()); + fileName = CardUtil.buildFilename(c) +".jpg"; + icon = getCardIcon(fileName); + + JOptionPane.showMessageDialog(null, "", "You have won a random rare for winning against a very hard deck.", JOptionPane.INFORMATION_MESSAGE, icon); + }*/ + + // Loss match penalty + if (!wonMatch) { + model.quest.subtractCredits(15); + String fileName = "HeartIcon.png"; + ImageIcon icon = getIcon(fileName); + String text = "You lose! You have lost 15 credits."; + JOptionPane.showMessageDialog(null, text, "Awwww", JOptionPane.INFORMATION_MESSAGE, icon); + } + + // Random rare given at 50% chance (65% with luck upgrade) + if (model.quest.shouldAddAdditionalCards(wonMatch)) { + Card c = AllZone.getCardFactory().getCard(model.quest.addRandomRare(), AllZone.getHumanPlayer()); + c.setCurSetCode(c.getMostRecentSet()); + String fileName = CardUtil.buildFilename(c) + ".jpg"; + ImageIcon icon = getCardIcon(fileName); + String title = "You have won a random rare."; + JOptionPane.showMessageDialog(null, "", title, JOptionPane.INFORMATION_MESSAGE, icon); + } + } } diff --git a/src/main/java/forge/Phase.java b/src/main/java/forge/Phase.java index e2bb50255e3..1ae748d0859 100644 --- a/src/main/java/forge/Phase.java +++ b/src/main/java/forge/Phase.java @@ -46,6 +46,7 @@ public class Phase extends MyObservable implements java.io.Serializable { private int extraCombats; private int nCombatsThisTurn; + private boolean bPreventCombatDamageThisTurn; private Player playerTurn = AllZone.getHumanPlayer(); @@ -247,6 +248,7 @@ public class Phase extends MyObservable implements java.io.Serializable { extraTurns.clear(); nCombatsThisTurn = 0; extraCombats = 0; + bPreventCombatDamageThisTurn = false; bCombat = false; bRepeat = false; this.updateObservers(); @@ -316,7 +318,7 @@ public class Phase extends MyObservable implements java.io.Serializable { AllZone.getPhase().setNeedToNextPhase(true); else { - if (!AllZone.getGameInfo().isPreventCombatDamageThisTurn()) + if (!AllZone.getPhase().isPreventCombatDamageThisTurn()) Combat.dealAssignedDamage(); AllZone.getGameAction().checkStateEffects(); @@ -331,7 +333,7 @@ public class Phase extends MyObservable implements java.io.Serializable { AllZone.getCombat().setAssignedDamage(); - if (!AllZone.getGameInfo().isPreventCombatDamageThisTurn()) + if (!AllZone.getPhase().isPreventCombatDamageThisTurn()) Combat.dealAssignedDamage(); AllZone.getGameAction().checkStateEffects(); @@ -383,6 +385,10 @@ public class Phase extends MyObservable implements java.io.Serializable { resetPriority(); } + public boolean isPreventCombatDamageThisTurn() { + return bPreventCombatDamageThisTurn; + } + /** *

nextPhase.

*/ @@ -420,9 +426,11 @@ public class Phase extends MyObservable implements java.io.Serializable { this.bCombat = false; } - if (phaseOrder[phaseIndex].equals(Constant.Phase.Cleanup)) + if (phaseOrder[phaseIndex].equals(Constant.Phase.Cleanup)) { + bPreventCombatDamageThisTurn = false; if (!bRepeat) AllZone.getPhase().setPlayerTurn(handleNextTurn()); + } if (is(Constant.Phase.Combat_Declare_Blockers)) { AllZone.getStack().unfreezeStack(); @@ -666,9 +674,6 @@ public class Phase extends MyObservable implements java.io.Serializable { if (c.getCreatureBlockedThisCombat()) c.setCreatureBlockedThisCombat(false); if (c.getCreatureGotBlockedThisCombat()) c.setCreatureGotBlockedThisCombat(false); - - AllZone.getGameInfo().setAssignedFirstStrikeDamageThisCombat(false); - AllZone.getGameInfo().setResolvedFirstStrikeDamageThisCombat(false); } } @@ -1026,4 +1031,8 @@ public class Phase extends MyObservable implements java.io.Serializable { static void setComputerInstantSpellCount(int i) { ComputerInstantSpellCount = (i); } + + public void setPreventCombatDamageThisTurn(boolean b) { + bPreventCombatDamageThisTurn = true; + } } diff --git a/src/main/java/forge/PhaseUtil.java b/src/main/java/forge/PhaseUtil.java index afcdbb7d768..ab6088e5458 100644 --- a/src/main/java/forge/PhaseUtil.java +++ b/src/main/java/forge/PhaseUtil.java @@ -38,6 +38,7 @@ public class PhaseUtil { Player turn = AllZone.getPhase().getPlayerTurn(); AllZone.getPhase().turnReset(); + AllZone.getGameInfo().notifyNextTurn(); AllZone.getCombat().reset(); AllZone.getCombat().setAttackingPlayer(turn); diff --git a/src/main/java/forge/Player.java b/src/main/java/forge/Player.java index a4da061ad16..b134810a0fd 100644 --- a/src/main/java/forge/Player.java +++ b/src/main/java/forge/Player.java @@ -1,5 +1,6 @@ package forge; +import forge.game.GameLossReason; import forge.card.cardFactory.CardFactoryUtil; import forge.card.mana.ManaPool; import forge.card.spellability.Ability; @@ -24,9 +25,10 @@ public abstract class Player extends MyObservable { protected int numPowerSurgeLands; protected boolean altWin = false; - protected String winCondition = ""; + protected String altWinSourceName; protected boolean altLose = false; - protected String loseCondition = ""; + protected GameLossReason lossState = GameLossReason.DidNotLoseYet; + protected String loseConditionSpell; protected int nTurns = 0; protected boolean skipNextUntap = false; @@ -43,6 +45,7 @@ public abstract class Player extends MyObservable { protected ManaPool manaPool = null; protected Object mustAttackEntity = null; + /** *

Constructor for Player.

@@ -81,9 +84,10 @@ public abstract class Player extends MyObservable { slowtripList = new CardList(); nTurns = 0; altWin = false; + altWinSourceName = null; altLose = false; - winCondition = ""; - loseCondition = ""; + lossState = GameLossReason.DidNotLoseYet; + loseConditionSpell = null; maxLandsToPlay = 1; numLandsPlayed = 0; @@ -907,7 +911,8 @@ public abstract class Player extends MyObservable { //lose: else if (!Constant.Runtime.DevMode[0] || AllZone.getDisplay().canLoseByDecking()) { // if devMode is off, or canLoseByDecking is Enabled, run Lose Condition - if (altLoseConditionMet("Milled")) { + if (!cantLose()) { + loseConditionMet(GameLossReason.Milled, null); AllZone.getGameAction().checkStateEffects(); } } @@ -1424,22 +1429,14 @@ public abstract class Player extends MyObservable { return altWin; } - /** - *

Getter for the field altLose.

- * - * @return a boolean. - */ - public boolean getAltLose() { - return altLose; - } - /** *

Getter for the field winCondition.

* * @return a {@link java.lang.String} object. */ - public String getWinCondition() { - return winCondition; + public String getWinConditionSource() + { + return altWinSourceName; } /** @@ -1447,8 +1444,8 @@ public abstract class Player extends MyObservable { * * @return a {@link java.lang.String} object. */ - public String getLoseCondition() { - return loseCondition; + public GameLossReason getLossState() { + return lossState; } /** @@ -1456,13 +1453,13 @@ public abstract class Player extends MyObservable { * * @param s a {@link java.lang.String} object. */ - public void altWinConditionMet(String s) { + public void altWinBySpellEffect( String sourceName ) { if (cantWin()) { System.out.println("Tried to win, but currently can't."); return; } altWin = true; - winCondition = s; + altWinSourceName = sourceName; } /** @@ -1471,15 +1468,17 @@ public abstract class Player extends MyObservable { * @param s a {@link java.lang.String} object. * @return a boolean. */ - public boolean altLoseConditionMet(String s) { + public boolean loseConditionMet(GameLossReason state, String spellName ) { if (cantLose()) { System.out.println("Tried to lose, but currently can't."); return false; } - altLose = true; - loseCondition = s; + lossState = state; + loseConditionSpell = spellName; return true; } + + /** *

cantLose.

@@ -1539,12 +1538,12 @@ public abstract class Player extends MyObservable { if (cantLose()) return false; - if (altLose) { + if (lossState != GameLossReason.DidNotLoseYet) { return true; } if (poisonCounters >= 10) { - altLoseConditionMet("Poison Counters"); + loseConditionMet( GameLossReason.Poisoned, null ); return true; } @@ -1552,7 +1551,13 @@ public abstract class Player extends MyObservable { return false; } - return getLife() <= 0; + boolean hasNoLife = getLife() <= 0; + if (hasNoLife) { + loseConditionMet( GameLossReason.LifeReachedZero, null); + return true; + } + + return false; } diff --git a/src/main/java/forge/Upkeep.java b/src/main/java/forge/Upkeep.java index bec2c6db9ca..3cf9aa33e20 100644 --- a/src/main/java/forge/Upkeep.java +++ b/src/main/java/forge/Upkeep.java @@ -2345,7 +2345,7 @@ public class Upkeep implements java.io.Serializable { @Override public void resolve() { if (player.getLife() >= 40) - player.altWinConditionMet(source.getName()); + player.altWinBySpellEffect(source.getName()); } };// Ability @@ -2377,7 +2377,7 @@ public class Upkeep implements java.io.Serializable { CardList grave = AllZoneUtil.getPlayerGraveyard(player); grave = grave.filter(AllZoneUtil.creatures); if (grave.size() >= 20) - player.altWinConditionMet(source.getName()); + player.altWinBySpellEffect(source.getName()); } };// Ability @@ -2405,7 +2405,7 @@ public class Upkeep implements java.io.Serializable { @Override public void resolve() { if (c.getCounters(Counters.TOWER) >= 100) - player.altWinConditionMet(c.getName()); + player.altWinBySpellEffect(c.getName()); } };// Ability @@ -2435,7 +2435,7 @@ public class Upkeep implements java.io.Serializable { @Override public void resolve() { if (player.getLife() == 1) - player.altWinConditionMet(source.getName()); + player.altWinBySpellEffect(source.getName()); } };// Ability @@ -2465,7 +2465,7 @@ public class Upkeep implements java.io.Serializable { @Override public void resolve() { if (player.getLife() >= 50) - player.altWinConditionMet(source.getName()); + player.altWinBySpellEffect(source.getName()); } };// Ability @@ -2507,7 +2507,7 @@ public class Upkeep implements java.io.Serializable { playList.remove(source); if (playList.size() == 0 && handList.size() == 0) - player.altWinConditionMet(source.getName()); + player.altWinBySpellEffect(source.getName()); } };// Ability diff --git a/src/main/java/forge/card/abilityFactory/AbilityFactory_Combat.java b/src/main/java/forge/card/abilityFactory/AbilityFactory_Combat.java index 1e837e2ecdc..9b4b0b39253 100644 --- a/src/main/java/forge/card/abilityFactory/AbilityFactory_Combat.java +++ b/src/main/java/forge/card/abilityFactory/AbilityFactory_Combat.java @@ -166,7 +166,7 @@ public class AbilityFactory_Combat { if (AllZone.getStack().size() != 0) return false; // Don't cast it, if the effect is already in place - if (AllZone.getGameInfo().isPreventCombatDamageThisTurn()) return false; + if (AllZone.getPhase().isPreventCombatDamageThisTurn()) return false; Ability_Sub subAb = sa.getSubAbility(); if (subAb != null) @@ -234,7 +234,7 @@ public class AbilityFactory_Combat { public static void fogResolve(final AbilityFactory af, final SpellAbility sa) { // Expand Fog keyword here depending on what we need out of it. - AllZone.getGameInfo().setPreventCombatDamageThisTurn(true); + AllZone.getPhase().setPreventCombatDamageThisTurn(true); } //************************************************************** diff --git a/src/main/java/forge/card/abilityFactory/AbilityFactory_EndGameCondition.java b/src/main/java/forge/card/abilityFactory/AbilityFactory_EndGameCondition.java index 66260e34be9..ff4fddfe713 100644 --- a/src/main/java/forge/card/abilityFactory/AbilityFactory_EndGameCondition.java +++ b/src/main/java/forge/card/abilityFactory/AbilityFactory_EndGameCondition.java @@ -5,6 +5,7 @@ import forge.Card; import forge.ComputerUtil; import forge.Player; import forge.card.spellability.*; +import forge.game.GameLossReason; import java.util.ArrayList; @@ -213,7 +214,7 @@ public class AbilityFactory_EndGameCondition { ArrayList players = AbilityFactory.getDefinedPlayers(card, af.getMapParams().get("Defined"), sa); for (Player p : players) - p.altWinConditionMet(card.getName()); + p.altWinBySpellEffect(card.getName()); } // *********************************************************************************************** @@ -449,7 +450,7 @@ public class AbilityFactory_EndGameCondition { } for (Player p : players) - p.altLoseConditionMet(card.getName()); + p.loseConditionMet( GameLossReason.SpellEffect, card.getName()); } } diff --git a/src/main/java/forge/card/cardFactory/AbstractCardFactory.java b/src/main/java/forge/card/cardFactory/AbstractCardFactory.java index 3fc83b39993..e9bf5375c3e 100644 --- a/src/main/java/forge/card/cardFactory/AbstractCardFactory.java +++ b/src/main/java/forge/card/cardFactory/AbstractCardFactory.java @@ -26,6 +26,7 @@ import forge.PlayerZone; import forge.card.abilityFactory.AbilityFactory; import forge.card.spellability.*; import forge.card.trigger.Trigger; +import forge.game.GameLossReason; import forge.gui.GuiUtils; import forge.gui.input.Input; import forge.gui.input.Input_PayManaCost; @@ -1804,7 +1805,7 @@ public abstract class AbstractCardFactory implements NewConstants, CardFactoryIn final SpellAbility loseGame = new Ability(card, "0") { @Override public void resolve() { - card.getController().altLoseConditionMet(card.getName()); + card.getController().loseConditionMet( GameLossReason.SpellEffect, card.getName()); } }; diff --git a/src/main/java/forge/card/cardFactory/CardFactory_Creatures.java b/src/main/java/forge/card/cardFactory/CardFactory_Creatures.java index c3498f523cd..56a528e678a 100644 --- a/src/main/java/forge/card/cardFactory/CardFactory_Creatures.java +++ b/src/main/java/forge/card/cardFactory/CardFactory_Creatures.java @@ -876,7 +876,6 @@ public class CardFactory_Creatures { Object o = GuiUtils.getChoice("Choose color", colors); color[0] = (String) o; - card.setChosenColor(color[0]); } else { // AI chooses the color that appears in the keywords of the most cards in its deck, hand and on battlefield CardList list = new CardList(); @@ -895,11 +894,11 @@ public class CardFactory_Creatures { color[0] = c; } } - card.setChosenColor(color[0]); } - + card.setChosenColor(color[0]); String s = CardUtil.getShortColor(color[0]); - timeStamp[0] = AllZone.getGameInfo().addColorChanges(s, card, true, true); + + timeStamp[0] = AllZone.getColorChanger().addColorChanges(s, card, true, true); } };//Command @@ -908,7 +907,7 @@ public class CardFactory_Creatures { public void execute() { String s = CardUtil.getShortColor(color[0]); - AllZone.getGameInfo().removeColorChanges(s, card, true, timeStamp[0]); + AllZone.getColorChanger().removeColorChanges(s, card, true, timeStamp[0]); } }; diff --git a/src/main/java/forge/game/GameEndReason.java b/src/main/java/forge/game/GameEndReason.java new file mode 100644 index 00000000000..8c0bf5fd596 --- /dev/null +++ b/src/main/java/forge/game/GameEndReason.java @@ -0,0 +1,10 @@ +package forge.game; + +public enum GameEndReason { + AllOpponentsLost, + // Noone won + Draw, // Having little idea how they can reach a draw, so I didn't enumerate possible reasons here + // Special conditions, they force one player to win and thus end the game + + WinsGameSpellEffect // ones that could be both hardcoded (felidar) and scripted ( such as Mayael's Aria ) +} diff --git a/src/main/java/forge/game/GameLossReason.java b/src/main/java/forge/game/GameLossReason.java new file mode 100644 index 00000000000..d18f1e89abd --- /dev/null +++ b/src/main/java/forge/game/GameLossReason.java @@ -0,0 +1,36 @@ +package forge.game; + +public enum GameLossReason { + + DidNotLoseYet, // a winner must have this status by the end of the game + + Conceded, // rule 104.3a + LifeReachedZero, // rule 104.3b + Milled, // 104.3c + Poisoned, // 104.3d + + // 104.3e and others + SpellEffect + + /*DoorToNothingness, // Door To Nothingness's ability activated + + // TODO: Implement game logics for the ones below + Transcendence20Life, // When you have 20 or more life, you lose the game. + FailedToPayPactUpkeep, // Pacts from Future Sight series (cost 0 but you must pay their real cost at next turn's upkeep, otherwise GL) + PhageTheUntouchableDamage, // Whenever Phage deals combat damage to a player, that player loses the game. + PhageTheUntouchableWrongETB, // When Phage the Untouchable ETB, if you didn't cast it from your hand, you lose the game. + NefariousLichLeavesTB, // When Nefarious Lich leaves the battlefield, you lose the game. + NefariousLichCannotExileGrave, // If damage would be dealt to you, exile that many cards from your graveyard instead. If you can't, you lose the game. + LichWasPutToGraveyard, // When Lich is put into a graveyard from the battlefield, you lose the game. + FinalFortune, // same as Warrior's Oath - lose at the granted extra turn's end step + ImmortalCoilEmptyGraveyard, // When there are no cards in your graveyard, you lose the game. + ForbiddenCryptEmptyGraveyard, // If you would draw a card, return a card from your graveyard to your hand instead. If you can't, you lose the game. + + // Amulet of quoz skipped for using ante, + // Form of the Squirrel and Rocket-Powered Turbo Slug skipped for being part of UN- set + + */ + + // refer to http://gatherer.wizards.com/Pages/Search/Default.aspx?output=standard&text=+[%22lose+the+game%22] for more cards when they are printed +} + diff --git a/src/main/java/forge/game/GamePlayerRating.java b/src/main/java/forge/game/GamePlayerRating.java new file mode 100644 index 00000000000..65bca34d053 --- /dev/null +++ b/src/main/java/forge/game/GamePlayerRating.java @@ -0,0 +1,41 @@ +package forge.game; + +/** + * + * @author Max + * + */ +public class GamePlayerRating { + boolean hasWonTheCoin; + + protected int turnsMade = 0; + protected int openingHandSize = 7; + protected int timesMulliganed = 0; + + protected GameLossReason lossReason = GameLossReason.DidNotLoseYet; + + public final GameLossReason getLossReason() { + return lossReason; + } + public void setLossReason(GameLossReason loseCondition) { + lossReason = loseCondition; + } + + public final int getOpeningHandSize() { + return openingHandSize; + } + + public final void notifyHasMulliganed() { + timesMulliganed++; + } + + public final int getMulliganCount() { + return timesMulliganed; + } + + public final void notifyOpeningHandSize(final int newHand) { + openingHandSize = newHand; + } + + +} diff --git a/src/main/java/forge/game/GameSummary.java b/src/main/java/forge/game/GameSummary.java new file mode 100644 index 00000000000..c1076630078 --- /dev/null +++ b/src/main/java/forge/game/GameSummary.java @@ -0,0 +1,67 @@ +package forge.game; + + +/** + *

GameInfo class.

+ * + * @author Forge + * @version $Id$ + */ + +// This should be divided into two: the very summary (immutable with only getters) and +// GameObserver class - who should be notified of any considerable ingame event +public class GameSummary { + protected int playerWinner = PlayerIndex.UNDEFINED; + protected int playerGotFirstTurn = PlayerIndex.UNDEFINED; + protected int lastTurnNumber = 0; + + protected GameEndReason winCondition; + protected String spellEffectWin; + protected GamePlayerRating playerRating[] = new GamePlayerRating[2/*players*/]; + + public GameSummary() + { + playerRating[PlayerIndex.AI] = new GamePlayerRating(); + playerRating[PlayerIndex.HUMAN] = new GamePlayerRating(); + } + + public final void end( final GameEndReason condition, int iPlayerWinner, String spellEffectWin ) + { + winCondition = condition; + playerWinner = iPlayerWinner; + this.spellEffectWin = spellEffectWin; + } + + public final boolean isHumanWinner() { return PlayerIndex.HUMAN == playerWinner; } + public final boolean isAIWinner() { return PlayerIndex.AI == playerWinner; } + public final boolean isDraw() { return PlayerIndex.DRAW == playerWinner; } + + public GameEndReason getWinCondition() { return winCondition; } + public GamePlayerRating getPlayerRating(int iPlayer) { + if (iPlayer >= 0 && iPlayer < playerRating.length) { + return playerRating[iPlayer]; + } + return null; + } + + public int getTurnGameEnded() { + return lastTurnNumber; + } + + public final void setPlayerWhoGotFirstTurn(int iPlayer) + { + playerGotFirstTurn = iPlayer; + } + + public void notifyNextTurn() { + lastTurnNumber++; + } + + public String getWinSpellEffect() { + return spellEffectWin; + } + + + + +} diff --git a/src/main/java/forge/game/PlayerIndex.java b/src/main/java/forge/game/PlayerIndex.java new file mode 100644 index 00000000000..8a7b054bb68 --- /dev/null +++ b/src/main/java/forge/game/PlayerIndex.java @@ -0,0 +1,8 @@ +package forge.game; + +public interface PlayerIndex { + int UNDEFINED = Integer.MIN_VALUE; + int DRAW = -1; + int HUMAN = 0; + int AI = 1; +} diff --git a/src/main/java/forge/game/package-info.java b/src/main/java/forge/game/package-info.java new file mode 100644 index 00000000000..abf03bdb001 --- /dev/null +++ b/src/main/java/forge/game/package-info.java @@ -0,0 +1,2 @@ +/** Forge Card Game */ +package forge.game; diff --git a/src/main/java/forge/gui/input/Input_Mulligan.java b/src/main/java/forge/gui/input/Input_Mulligan.java index f02a1dfe611..21f9278864d 100644 --- a/src/main/java/forge/gui/input/Input_Mulligan.java +++ b/src/main/java/forge/gui/input/Input_Mulligan.java @@ -1,6 +1,9 @@ package forge.gui.input; import forge.*; +import forge.game.GamePlayerRating; +import forge.game.PlayerIndex; +import forge.quest.data.QuestData; /** *

Input_Mulligan class.

@@ -11,6 +14,9 @@ import forge.*; public class Input_Mulligan extends Input { /** Constant serialVersionUID=-8112954303001155622L */ private static final long serialVersionUID = -8112954303001155622L; + + private static final int MAGIC_NUMBER_OF_SHUFFLES = 100; + private static final int AI_MULLIGAN_THRESHOLD = 5; /** {@inheritDoc} */ @Override @@ -27,31 +33,32 @@ public class Input_Mulligan extends Input { end(); } + public int doMulligan( Player player, GamePlayerRating playerRating ) { + CardList hand = AllZoneUtil.getPlayerHand(player); + for (Card c : hand) { AllZone.getGameAction().moveToLibrary(c); } + for (int i = 0; i < MAGIC_NUMBER_OF_SHUFFLES; i++) { player.shuffle(); } + int newHand = hand.size() - 1; + for (int i = 0; i < newHand; i++) { player.drawCard(); } + playerRating.notifyHasMulliganed(); + playerRating.notifyOpeningHandSize(newHand); + return newHand; + } + /** {@inheritDoc} */ @Override public void selectButtonCancel() { - AllZone.getGameInfo().setHumanMulliganedToZero(false); + GamePlayerRating humanRating = AllZone.getGameInfo().getPlayerRating(PlayerIndex.HUMAN); + Player humanPlayer = AllZone.getHumanPlayer(); - CardList hand = AllZoneUtil.getPlayerHand(AllZone.getHumanPlayer()); - for (Card c : hand) - AllZone.getGameAction().moveToLibrary(c); + int newHand = doMulligan(humanPlayer, humanRating); - for (int i = 0; i < 100; i++) - AllZone.getHumanPlayer().shuffle(); - - int newHand = hand.size() - 1; - - AllZone.getGameInfo().addHumanNumberOfTimesMulliganed(1); - - if (AllZone.getQuestData() != null) { - if (AllZone.getQuestData().getInventory().hasItem("Sleight") && AllZone.getGameInfo().getHumanNumberOfTimesMulliganed() == 1) - newHand++; - } - for (int i = 0; i < newHand; i++) + QuestData quest = AllZone.getQuestData(); + if (quest != null && quest.getInventory().hasItem("Sleight") && humanRating.getMulliganCount() == 1) { AllZone.getHumanPlayer().drawCard(); + humanRating.notifyOpeningHandSize(newHand + 1); + } if (newHand == 0) { - AllZone.getGameInfo().setHumanMulliganedToZero(true); end(); } }//selectButtonOK() @@ -61,29 +68,27 @@ public class Input_Mulligan extends Input { */ void end() { //Computer mulligan - CardList CHandList = AllZoneUtil.getPlayerHand(AllZone.getComputerPlayer()); - - Card dummy = CHandList.get(0); + Player aiPlayer = AllZone.getComputerPlayer(); + GamePlayerRating aiRating = AllZone.getGameInfo().getPlayerRating(PlayerIndex.AI); + boolean aiTakesMulligan = true; + //Computer mulligans if there are no cards with converted mana cost of 0 in its hand - while (CHandList.size() > 5 && CHandList.getValidCards("Card.cmcEQ0", AllZone.getComputerPlayer(), dummy).size() < 2) { - for (Card c : CHandList) - AllZone.getGameAction().moveToLibrary(c); + while (aiTakesMulligan) { - for (int i = 0; i < 100; i++) - AllZone.getComputerPlayer().shuffle(); + CardList handList = AllZoneUtil.getPlayerHand(aiPlayer); + boolean hasLittleCmc0Cards = handList.getValidCards("Card.cmcEQ0", aiPlayer, null).size() < 2; + aiTakesMulligan = handList.size() > AI_MULLIGAN_THRESHOLD && hasLittleCmc0Cards; - int newHand = CHandList.size() - 1; - for (int i = 0; i < newHand; i++) - AllZone.getComputerPlayer().drawCard(); - - CHandList = AllZoneUtil.getPlayerHand(AllZone.getComputerPlayer()); + if (aiTakesMulligan) { + doMulligan(aiPlayer, aiRating); + } } //Human Leylines ButtonUtil.reset(); - CardList HHandList = AllZoneUtil.getPlayerHand(AllZone.getHumanPlayer()); + CardList humanOpeningHand = AllZoneUtil.getPlayerHand(AllZone.getHumanPlayer()); - for (Card c : HHandList) { + for (Card c : humanOpeningHand) { if (c.getName().startsWith("Leyline")) { if (GameActionUtil.showYesNoDialog(c, "Put onto Battlefield?")) AllZone.getGameAction().moveToPlay(c); @@ -91,7 +96,8 @@ public class Input_Mulligan extends Input { } //Computer Leylines - for (Card c : CHandList) { + CardList aiOpeningHand = AllZoneUtil.getPlayerHand(AllZone.getComputerPlayer()); + for (Card c : aiOpeningHand) { if (c.getName().startsWith("Leyline") && !(c.getName().startsWith("Leyline of Singularity") && AllZoneUtil.getCardsInPlay("Leyline of Singularity").size() > 0)) { AllZone.getGameAction().moveToPlay(c); @@ -99,8 +105,8 @@ public class Input_Mulligan extends Input { } } - if (AllZone.getGameAction().isStartCut() && !(HHandList.contains(AllZone.getGameAction().getHumanCut()) - || CHandList.contains(AllZone.getGameAction().getComputerCut()))) { + if (AllZone.getGameAction().isStartCut() && !(humanOpeningHand.contains(AllZone.getGameAction().getHumanCut()) + || aiOpeningHand.contains(AllZone.getGameAction().getComputerCut()))) { AllZone.getGameAction().moveTo(AllZone.getZone(Constant.Zone.Library, AllZone.getHumanPlayer()), AllZone.getGameAction().getHumanCut()); AllZone.getGameAction().moveTo(AllZone.getZone(Constant.Zone.Library, AllZone.getComputerPlayer()), AllZone.getGameAction().getComputerCut()); } diff --git a/src/main/java/forge/quest/data/QuestData.java b/src/main/java/forge/quest/data/QuestData.java index c3522f156dd..51f1b50a4c9 100644 --- a/src/main/java/forge/quest/data/QuestData.java +++ b/src/main/java/forge/quest/data/QuestData.java @@ -3,6 +3,10 @@ package forge.quest.data; import forge.*; import forge.deck.Deck; import forge.error.ErrorViewer; +import forge.game.GameLossReason; +import forge.game.GamePlayerRating; +import forge.game.GameSummary; +import forge.game.PlayerIndex; import forge.properties.ForgeProps; import forge.properties.NewConstants; import forge.quest.data.item.QuestInventory; @@ -482,63 +486,80 @@ public class QuestData { } } + + public final int getCreditsRewardForAltWin(final GameLossReason whyAiLost) { + int rewardAltWinCondition = 0; + switch (whyAiLost) { + case LifeReachedZero: + break; // nothing special here, ordinary kill + case Milled: + rewardAltWinCondition = QuestPreferences.getMatchRewardMilledWinBonus(); + break; + case Poisoned: + rewardAltWinCondition = QuestPreferences.getMatchRewardPoisonWinBonus(); + break; + case DidNotLoseYet: // must be player's alternate win condition: felidar, helix pinnacle and like this + rewardAltWinCondition = QuestPreferences.getMatchRewardAltWinBonus(); + break; + default: // this .checkstyle forces us to write some idiotic code + rewardAltWinCondition = 0; + } + return rewardAltWinCondition; + } + + public final int getCreditsRewardForWinByTurn(final int iTurn) { + if (iTurn == 1) { + return QuestPreferences.getMatchRewardWinFirst(); + } else if (iTurn <= 5) { + return QuestPreferences.getMatchRewardWinByFifth(); + } else if (iTurn <= 10) { + return QuestPreferences.getMatchRewardWinByTen(); + } else if (iTurn <= 15) { + return QuestPreferences.getMatchRewardWinByFifteen(); + } + return 0; + } + /** *

getCreditsToAdd.

* * @param matchState a {@link forge.quest.data.QuestMatchState} object. * @return a long. */ - public long getCreditsToAdd(QuestMatchState matchState) { - long creds = (long) (QuestPreferences.getMatchRewardBase() + (QuestPreferences.getMatchRewardTotalWins() * win)); - String[] wins = matchState.getWinMethods(); - int[] winTurns = matchState.getWinTurns(); - boolean[] mulliganedToZero = matchState.getMulliganedToZero(); + public final long getCreditsToAdd(final QuestMatchState matchState) { + long creds = (long) (QuestPreferences.getMatchRewardBase() + + (QuestPreferences.getMatchRewardTotalWins() * win)); - if (matchState.getLose() == 0) { - creds += QuestPreferences.getMatchRewardNoLosses(); - } - - for (String s : wins) { - if (s != null) { - if (s.equals("Poison Counters")) { - creds += QuestPreferences.getMatchRewardPoisonWinBonus(); - } else if (s.equals("Milled")) { - creds += QuestPreferences.getMatchRewardMilledWinBonus(); - } else if (s.equals("Battle of Wits") || s.equals("Felidar Sovereign") || s.equals("Helix Pinnacle") || - s.equals("Epic Struggle") || s.equals("Door to Nothingness") || s.equals("Barren Glory") || - s.equals("Near-Death Experience") || s.equals("Mortal Combat") || s.equals("Test of Endurance")) { - creds += QuestPreferences.getMatchRewardAltWinBonus(); - } + boolean hasNeverLost = true; + for (GameSummary game : matchState.getGamesPlayed()) { + if (game.isAIWinner()) { + hasNeverLost = true; + continue; // no rewards for losing a game } - } - for (int i : winTurns) { - if (i == 1) { - creds += QuestPreferences.getMatchRewardWinFirst(); - } else if (i <= 5) { - creds += QuestPreferences.getMatchRewardWinByFifth(); - } else if (i <= 10) { - creds += QuestPreferences.getMatchRewardWinByTen(); - } else if (i <= 15) { - creds += QuestPreferences.getMatchRewardWinByFifteen(); - } - } + GamePlayerRating aiRating = game.getPlayerRating(PlayerIndex.AI); + GamePlayerRating humanRating = game.getPlayerRating(PlayerIndex.HUMAN); + GameLossReason whyAiLost = aiRating.getLossReason(); - for (boolean b : mulliganedToZero) { - if (b == true) { + creds += getCreditsRewardForAltWin(whyAiLost); + creds += getCreditsRewardForWinByTurn(game.getTurnGameEnded()); + + int cntCardsHumanStartedWith = humanRating.getOpeningHandSize(); + if (0 == cntCardsHumanStartedWith) { creds += QuestPreferences.getMatchMullToZero(); } } - if (inventory.getItemLevel("Estates") == 1) { - creds *= 1.1; - } else if (inventory.getItemLevel("Estates") == 2) { - creds *= 1.15; - } else if (inventory.getItemLevel("Estates") == 3) { - creds *= 1.2; + if (hasNeverLost) { + creds += QuestPreferences.getMatchRewardNoLosses(); } - this.addCredits(creds); + switch(inventory.getItemLevel("Estates")) { + case 1: creds *= 1.1; break; + case 2: creds *= 1.15; break; + case 3: creds *= 1.2; break; + default: break; + } return creds; } diff --git a/src/main/java/forge/quest/data/QuestMatchState.java b/src/main/java/forge/quest/data/QuestMatchState.java index 37204ccd118..e94366cdb34 100644 --- a/src/main/java/forge/quest/data/QuestMatchState.java +++ b/src/main/java/forge/quest/data/QuestMatchState.java @@ -1,163 +1,79 @@ package forge.quest.data; +import java.util.ArrayList; +import java.util.List; + +import forge.game.GameSummary; + + /** *

QuestMatchState class.

* * @author Forge * @version $Id$ */ + + public class QuestMatchState { - //the way wins were achieved: - //Damage - //Poison Counters - //Battle of Wits - //Mortal Combat - //Milled - //Felidar Sovereign - //... - // - private String[] winMethods = new String[2]; - private int[] winTurns = new int[2]; + public static final int GAMES_PER_MATCH = 3; + public static final int MIN_GAMES_TO_WIN_MATCH = 2; - private boolean[] mulliganedToZero = new boolean[2]; + private List gamesPlayed = new ArrayList(); + //ArrayList - private int win; - private int lose; - private boolean winRecently; - - /** - *

reset.

- */ - public void reset() { - win = 0; - lose = 0; - winMethods = new String[2]; + public final void addGamePlayed(final GameSummary completedGame) { + gamesPlayed.add(completedGame); } - /** - *

addWin.

- */ - public void addWin() { - win++; - winRecently = true; + public final GameSummary[] getGamesPlayed() { + return gamesPlayed.toArray(new GameSummary[gamesPlayed.size()]); } - /** - *

addLose.

- */ - public void addLose() { - lose++; - winRecently = false; + public final int getGamesPlayedCount() { + return gamesPlayed.size(); } - /** - *

Getter for the field win.

- * - * @return a int. - */ - public int getWin() { - return win; + public final boolean hasHumanWonLastGame() { + int iLastGame = gamesPlayed.size() - 1; + return iLastGame >= 0 ? gamesPlayed.get(iLastGame).isHumanWinner() : false; } - /** - *

Getter for the field lose.

- * - * @return a int. - */ - public int getLose() { - return lose; + public final boolean isMatchOver() { + int winsHuman = 0; + int winsAI = 0; + int totalGames = 0; + + for (GameSummary game : gamesPlayed) { + if (game.isAIWinner()) { winsAI++; } + if (game.isHumanWinner()) { winsHuman++; } + totalGames++; + } + + return winsAI >= MIN_GAMES_TO_WIN_MATCH || winsHuman >= MIN_GAMES_TO_WIN_MATCH || totalGames >= GAMES_PER_MATCH; } - /** - *

countWinLose.

- * - * @return a int. - */ - public int countWinLose() { - return win + lose; + public final int getGamesCountWonByHuman() { + int winsHuman = 0; + for (GameSummary game : gamesPlayed) { + if (game.isHumanWinner()) { winsHuman++; } + } + return winsHuman; } - /** - *

setWinMethod.

- * - * @param gameNumber a int. - * @param method a {@link java.lang.String} object. - */ - public void setWinMethod(int gameNumber, String method) { - winMethods[gameNumber] = method; + public final int getGamesCountLostByHuman() { + int lossHuman = 0; + for (GameSummary game : gamesPlayed) { + if (!game.isHumanWinner()) { lossHuman++; } + } + return lossHuman; } - /** - *

Getter for the field winMethods.

- * - * @return an array of {@link java.lang.String} objects. - */ - public String[] getWinMethods() { - return winMethods; + public final boolean isMatchWonByHuman() { + return getGamesCountWonByHuman() >= MIN_GAMES_TO_WIN_MATCH; } - /** - *

setWinTurn.

- * - * @param gameNumber a int. - * @param turns a int. - */ - public void setWinTurn(int gameNumber, int turns) { - winTurns[gameNumber] = turns; + public final void reset() { + gamesPlayed.clear(); } - - /** - *

Getter for the field winTurns.

- * - * @return an array of int. - */ - public int[] getWinTurns() { - return winTurns; - } - - /** - *

Getter for the field mulliganedToZero.

- * - * @return an array of boolean. - */ - public boolean[] getMulliganedToZero() { - return mulliganedToZero; - } - - /** - *

Setter for the field mulliganedToZero.

- * - * @param gameNumber a int. - * @param b a boolean. - */ - public void setMulliganedToZero(int gameNumber, boolean b) { - mulliganedToZero[gameNumber] = b; - } - - /** - *

didWinRecently.

- * - * @return a boolean. - */ - public boolean didWinRecently() { - return winRecently; - } - - /** - *

isMatchOver.

- * @return whether match is complete - */ - public boolean isMatchOver() - { - return win == 2 || lose == 2; - } - /** - *

isMatchOver.

- * @return whether match is won - */ - public boolean isMatchWon() - { - return win == 2; - } } diff --git a/src/main/java/forge/quest/gui/main/QuestMainPanel.java b/src/main/java/forge/quest/gui/main/QuestMainPanel.java index ffcb0ad1d86..14a77a4928a 100644 --- a/src/main/java/forge/quest/gui/main/QuestMainPanel.java +++ b/src/main/java/forge/quest/gui/main/QuestMainPanel.java @@ -149,7 +149,7 @@ public class QuestMainPanel extends QuestAbstractPanel { */ private JPanel createSidePanel() { JPanel panel = new JPanel(); - JPanel optionsPanel;//Create options checkbox list + JPanel optionsPanel; //Create options checkbox list optionsPanel = createOptionsPanel(); List eastComponents = new ArrayList(); @@ -659,7 +659,7 @@ public class QuestMainPanel extends QuestAbstractPanel { Constant.Runtime.Smooth[0] = smoothLandCheckBox.isSelected(); - + AllZone.getMatchState().reset(); if (isShowingQuests) { setupQuest(humanDeck); } else { diff --git a/src/main/java/forge/view/swing/OldGuiNewGame.java b/src/main/java/forge/view/swing/OldGuiNewGame.java index 2d4919c330e..8700fd46ad2 100644 --- a/src/main/java/forge/view/swing/OldGuiNewGame.java +++ b/src/main/java/forge/view/swing/OldGuiNewGame.java @@ -126,7 +126,6 @@ public class OldGuiNewGame extends JFrame implements NewConstants, NewConstants. AllZone.setQuestData(null); allDecks = getDecks(); - Constant.Runtime.matchState.reset(); if (Constant.Runtime.width[0] == 0) { Constant.Runtime.width[0] = 70; diff --git a/src/test/java/forge/GuiWinLoseTest.java b/src/test/java/forge/GuiWinLoseTest.java index 113bcfd4d69..6da80b80cad 100644 --- a/src/test/java/forge/GuiWinLoseTest.java +++ b/src/test/java/forge/GuiWinLoseTest.java @@ -3,6 +3,8 @@ package forge; import org.testng.Assert; import org.testng.annotations.Test; +import forge.quest.data.QuestMatchState; + /** * Created by IntelliJ IDEA. * User: dhudson @@ -15,7 +17,7 @@ public class GuiWinLoseTest { */ @Test(groups = {"UnitTest", "fast"}) public void GuiWinLoseTest1() { - Gui_WinLose dialog = new Gui_WinLose(); + Gui_WinLose dialog = new Gui_WinLose( new QuestMatchState(), null, null ); dialog.setVisible(true); Assert.assertNotNull(dialog); dialog.dispose();