mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-19 20:28:00 +00:00
the 'state' of GameState added - named it GameAge
this should prevent wrong inputs before mulligan (problem reported by sol)
This commit is contained in:
1
.gitattributes
vendored
1
.gitattributes
vendored
@@ -13897,6 +13897,7 @@ 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/error/package-info.java svneol=native#text/plain
|
||||||
src/main/java/forge/game/GameAction.java svneol=native#text/plain
|
src/main/java/forge/game/GameAction.java svneol=native#text/plain
|
||||||
src/main/java/forge/game/GameActionUtil.java svneol=native#text/plain
|
src/main/java/forge/game/GameActionUtil.java svneol=native#text/plain
|
||||||
|
src/main/java/forge/game/GameAge.java -text
|
||||||
src/main/java/forge/game/GameEndReason.java -text
|
src/main/java/forge/game/GameEndReason.java -text
|
||||||
src/main/java/forge/game/GameFormat.java -text
|
src/main/java/forge/game/GameFormat.java -text
|
||||||
src/main/java/forge/game/GameLossReason.java -text
|
src/main/java/forge/game/GameLossReason.java -text
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ package forge.control.input;
|
|||||||
import java.util.Stack;
|
import java.util.Stack;
|
||||||
|
|
||||||
import forge.Singletons;
|
import forge.Singletons;
|
||||||
|
import forge.game.GameAge;
|
||||||
import forge.game.GameState;
|
import forge.game.GameState;
|
||||||
import forge.game.GameType;
|
import forge.game.GameType;
|
||||||
import forge.game.MatchController;
|
import forge.game.MatchController;
|
||||||
@@ -45,6 +46,11 @@ public class InputControl extends MyObservable implements java.io.Serializable {
|
|||||||
|
|
||||||
private final Stack<Input> inputStack = new Stack<Input>();
|
private final Stack<Input> inputStack = new Stack<Input>();
|
||||||
|
|
||||||
|
private final MatchController match;
|
||||||
|
public InputControl(MatchController matchController) {
|
||||||
|
match = matchController;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
* Setter for the field <code>input</code>.
|
* Setter for the field <code>input</code>.
|
||||||
@@ -118,15 +124,20 @@ public class InputControl extends MyObservable implements java.io.Serializable {
|
|||||||
* @return a {@link forge.control.input.InputBase} object.
|
* @return a {@link forge.control.input.InputBase} object.
|
||||||
*/
|
*/
|
||||||
public final Input getActualInput(GameState game) {
|
public final Input getActualInput(GameState game) {
|
||||||
|
GameAge age = game.getAge();
|
||||||
|
|
||||||
|
if ( age == GameAge.BeforeMulligan || age == GameAge.GameOver)
|
||||||
|
return inputLock;
|
||||||
|
|
||||||
|
if ( age == GameAge.Mulligan ) {
|
||||||
|
HumanPlayer human = Singletons.getControl().getPlayer();
|
||||||
|
return game.getType() == GameType.Commander ? new InputPartialParisMulligan(match, human) : new InputMulligan(match, human);
|
||||||
|
}
|
||||||
|
|
||||||
if (!this.inputStack.isEmpty()) { // incoming input to Control
|
if (!this.inputStack.isEmpty()) { // incoming input to Control
|
||||||
return this.inputStack.peek();
|
return this.inputStack.peek();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !game.hasMulliganned() ) {
|
|
||||||
HumanPlayer human = Singletons.getControl().getPlayer();
|
|
||||||
MatchController match = Singletons.getModel().getMatch();
|
|
||||||
return game.getType() == GameType.Commander ? new InputPartialParisMulligan(match, human) : new InputMulligan(match, human);
|
|
||||||
}
|
|
||||||
final PhaseHandler handler = game.getPhaseHandler();
|
final PhaseHandler handler = game.getPhaseHandler();
|
||||||
final PhaseType phase = handler.getPhase();
|
final PhaseType phase = handler.getPhase();
|
||||||
final Player playerTurn = handler.getPlayerTurn();
|
final Player playerTurn = handler.getPlayerTurn();
|
||||||
@@ -186,9 +197,7 @@ public class InputControl extends MyObservable implements java.io.Serializable {
|
|||||||
return pc.getDefaultInput();
|
return pc.getDefaultInput();
|
||||||
} // getInput()
|
} // getInput()
|
||||||
|
|
||||||
/**
|
|
||||||
* TODO: Write javadoc for this method.
|
|
||||||
*/
|
|
||||||
private final static InputLockUI inputLock = new InputLockUI();
|
private final static InputLockUI inputLock = new InputLockUI();
|
||||||
public void lock() {
|
public void lock() {
|
||||||
setInput(inputLock);
|
setInput(inputLock);
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ import forge.CounterType;
|
|||||||
import forge.GameEntity;
|
import forge.GameEntity;
|
||||||
import forge.card.CardType;
|
import forge.card.CardType;
|
||||||
import forge.card.TriggerReplacementBase;
|
import forge.card.TriggerReplacementBase;
|
||||||
|
import forge.card.ability.AbilityFactory;
|
||||||
import forge.card.ability.effects.AttachEffect;
|
import forge.card.ability.effects.AttachEffect;
|
||||||
import forge.card.cardfactory.CardFactory;
|
import forge.card.cardfactory.CardFactory;
|
||||||
import forge.card.cost.Cost;
|
import forge.card.cost.Cost;
|
||||||
@@ -57,6 +58,7 @@ import forge.game.event.CardDestroyedEvent;
|
|||||||
import forge.game.event.CardRegeneratedEvent;
|
import forge.game.event.CardRegeneratedEvent;
|
||||||
import forge.game.event.CardSacrificedEvent;
|
import forge.game.event.CardSacrificedEvent;
|
||||||
import forge.game.player.AIPlayer;
|
import forge.game.player.AIPlayer;
|
||||||
|
import forge.game.player.HumanPlayer;
|
||||||
import forge.game.player.Player;
|
import forge.game.player.Player;
|
||||||
import forge.game.player.PlayerType;
|
import forge.game.player.PlayerType;
|
||||||
import forge.game.zone.PlayerZone;
|
import forge.game.zone.PlayerZone;
|
||||||
@@ -64,6 +66,7 @@ import forge.game.zone.PlayerZoneBattlefield;
|
|||||||
import forge.game.zone.Zone;
|
import forge.game.zone.Zone;
|
||||||
import forge.game.zone.ZoneType;
|
import forge.game.zone.ZoneType;
|
||||||
import forge.gui.GuiChoose;
|
import forge.gui.GuiChoose;
|
||||||
|
import forge.gui.GuiDialog;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Methods for common actions performed during a game.
|
* Methods for common actions performed during a game.
|
||||||
@@ -1402,6 +1405,58 @@ public class GameAction {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void handleLeylinesAndChancellors() {
|
||||||
|
for (Player p : game.getPlayers()) {
|
||||||
|
final List<Card> openingHand = new ArrayList<Card>(p.getCardsIn(ZoneType.Hand));
|
||||||
|
|
||||||
|
for (final Card c : openingHand) {
|
||||||
|
if (p.isHuman()) {
|
||||||
|
for (String kw : c.getKeyword()) {
|
||||||
|
if (kw.startsWith("MayEffectFromOpeningHand")) {
|
||||||
|
final String effName = kw.split(":")[1];
|
||||||
|
|
||||||
|
final SpellAbility effect = AbilityFactory.getAbility(c.getSVar(effName), c);
|
||||||
|
if (GuiDialog.confirm(c, "Use " + c +"'s ability?")) {
|
||||||
|
// If we ever let the AI memorize cards in the players
|
||||||
|
// hand, this would be a place to do so.
|
||||||
|
((HumanPlayer)p).playSpellAbilityNoStack(effect);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (c.getName().startsWith("Leyline of")) {
|
||||||
|
if (GuiDialog.confirm(c, "Use " + c + "'s ability?")) {
|
||||||
|
game.getAction().moveToPlay(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else { // Computer Leylines & Chancellors
|
||||||
|
if (!c.getName().startsWith("Leyline of")) {
|
||||||
|
for (String kw : c.getKeyword()) {
|
||||||
|
if (kw.startsWith("MayEffectFromOpeningHand")) {
|
||||||
|
final String effName = kw.split(":")[1];
|
||||||
|
|
||||||
|
final SpellAbility effect = AbilityFactory.getAbility(c.getSVar(effName), c);
|
||||||
|
|
||||||
|
// Is there a better way for the AI to decide this?
|
||||||
|
if (effect.doTrigger(false, (AIPlayer)p)) {
|
||||||
|
GuiDialog.message("Computer reveals " + c.getName() + "(" + c.getUniqueNumber() + ").");
|
||||||
|
ComputerUtil.playNoStack((AIPlayer)p, effect, game);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (c.getName().startsWith("Leyline of")
|
||||||
|
&& !(c.getName().startsWith("Leyline of Singularity")
|
||||||
|
&& (Iterables.any(game.getCardsIn(ZoneType.Battlefield), CardPredicates.nameEquals("Leyline of Singularity"))))) {
|
||||||
|
game.getAction().moveToPlay(c);
|
||||||
|
//ga.checkStateEffects();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
game.getAction().checkStateEffects();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
* playCardWithoutManaCost.
|
* playCardWithoutManaCost.
|
||||||
|
|||||||
8
src/main/java/forge/game/GameAge.java
Normal file
8
src/main/java/forge/game/GameAge.java
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
package forge.game;
|
||||||
|
|
||||||
|
public enum GameAge {
|
||||||
|
BeforeMulligan,
|
||||||
|
Mulligan,
|
||||||
|
Play,
|
||||||
|
GameOver
|
||||||
|
}
|
||||||
@@ -220,7 +220,7 @@ public class GameNew {
|
|||||||
playersConditions.put(p, players.get(p.getLobbyPlayer()));
|
playersConditions.put(p, players.get(p.getLobbyPlayer()));
|
||||||
}
|
}
|
||||||
|
|
||||||
game.setMulliganned(false);
|
game.setAge(GameAge.Mulligan);
|
||||||
match.getInput().clearInput();
|
match.getInput().clearInput();
|
||||||
|
|
||||||
//Card.resetUniqueNumber();
|
//Card.resetUniqueNumber();
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
package forge.game;
|
package forge.game;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@@ -54,9 +55,8 @@ import forge.game.zone.PlayerZone;
|
|||||||
import forge.game.zone.Zone;
|
import forge.game.zone.Zone;
|
||||||
import forge.game.zone.ZoneType;
|
import forge.game.zone.ZoneType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents the state of a <i>single game</i> and is
|
* Represents the state of a <i>single game</i>, a new instance is created for each game.
|
||||||
* "cleaned up" at each new game.
|
|
||||||
*/
|
*/
|
||||||
public class GameState {
|
public class GameState {
|
||||||
private final GameType type;
|
private final GameType type;
|
||||||
@@ -82,13 +82,12 @@ public class GameState {
|
|||||||
private final GameLog gameLog = new GameLog();
|
private final GameLog gameLog = new GameLog();
|
||||||
private final ColorChanger colorChanger = new ColorChanger();
|
private final ColorChanger colorChanger = new ColorChanger();
|
||||||
|
|
||||||
private boolean gameOver = false;
|
|
||||||
|
|
||||||
private final Zone stackZone = new Zone(ZoneType.Stack);
|
private final Zone stackZone = new Zone(ZoneType.Stack);
|
||||||
|
|
||||||
private long timestamp = 0;
|
private long timestamp = 0;
|
||||||
public final GameAction action;
|
public final GameAction action;
|
||||||
private final MatchController match;
|
private final MatchController match;
|
||||||
|
private GameAge age = GameAge.BeforeMulligan;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor.
|
* Constructor.
|
||||||
@@ -291,7 +290,7 @@ public class GameState {
|
|||||||
* @return the gameOver
|
* @return the gameOver
|
||||||
*/
|
*/
|
||||||
public synchronized boolean isGameOver() {
|
public synchronized boolean isGameOver() {
|
||||||
return gameOver;
|
return age == GameAge.GameOver;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -299,7 +298,7 @@ public class GameState {
|
|||||||
* @param go the gameOver to set
|
* @param go the gameOver to set
|
||||||
*/
|
*/
|
||||||
public synchronized void setGameOver(GameEndReason reason) {
|
public synchronized void setGameOver(GameEndReason reason) {
|
||||||
this.gameOver = true;
|
this.age = GameAge.GameOver;
|
||||||
for (Player p : roIngamePlayers) {
|
for (Player p : roIngamePlayers) {
|
||||||
p.onGameOver();
|
p.onGameOver();
|
||||||
}
|
}
|
||||||
@@ -661,7 +660,11 @@ public class GameState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean mulliganned = false;
|
public GameAge getAge() {
|
||||||
public boolean hasMulliganned(){ return mulliganned; }
|
return age;
|
||||||
public void setMulliganned(boolean value) { mulliganned = value; }
|
}
|
||||||
|
|
||||||
|
void setAge(GameAge value) {
|
||||||
|
age = value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,20 +7,14 @@ import java.util.List;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
|
|
||||||
import com.google.common.collect.Iterables;
|
|
||||||
|
|
||||||
import forge.Constant.Preferences;
|
import forge.Constant.Preferences;
|
||||||
import forge.Card;
|
|
||||||
import forge.CardPredicates;
|
|
||||||
import forge.Singletons;
|
import forge.Singletons;
|
||||||
import forge.card.ability.AbilityFactory;
|
|
||||||
import forge.card.spellability.SpellAbility;
|
|
||||||
import forge.control.FControl;
|
import forge.control.FControl;
|
||||||
import forge.control.input.InputControl;
|
import forge.control.input.InputControl;
|
||||||
import forge.deck.Deck;
|
import forge.deck.Deck;
|
||||||
import forge.error.BugReporter;
|
import forge.error.BugReporter;
|
||||||
import forge.game.ai.AiProfileUtil;
|
import forge.game.ai.AiProfileUtil;
|
||||||
import forge.game.ai.ComputerUtil;
|
|
||||||
import forge.game.event.DuelOutcomeEvent;
|
import forge.game.event.DuelOutcomeEvent;
|
||||||
import forge.game.player.AIPlayer;
|
import forge.game.player.AIPlayer;
|
||||||
import forge.game.player.HumanPlayer;
|
import forge.game.player.HumanPlayer;
|
||||||
@@ -29,7 +23,6 @@ import forge.game.player.Player;
|
|||||||
import forge.game.player.PlayerStatistics;
|
import forge.game.player.PlayerStatistics;
|
||||||
import forge.game.player.PlayerType;
|
import forge.game.player.PlayerType;
|
||||||
import forge.game.zone.ZoneType;
|
import forge.game.zone.ZoneType;
|
||||||
import forge.gui.GuiDialog;
|
|
||||||
import forge.gui.InputProxy;
|
import forge.gui.InputProxy;
|
||||||
import forge.gui.framework.EDocID;
|
import forge.gui.framework.EDocID;
|
||||||
import forge.gui.framework.SDisplayUtil;
|
import forge.gui.framework.SDisplayUtil;
|
||||||
@@ -137,8 +130,7 @@ public class MatchController {
|
|||||||
*/
|
*/
|
||||||
public void startRound() {
|
public void startRound() {
|
||||||
|
|
||||||
// Deal with circular dependencies here
|
input = new InputControl(this);
|
||||||
input = new InputControl();
|
|
||||||
currentGame = Singletons.getModel().newGame(players.keySet(),gameType, this);
|
currentGame = Singletons.getModel().newGame(players.keySet(),gameType, this);
|
||||||
|
|
||||||
Map<Player, PlayerStartConditions> startConditions = new HashMap<Player, PlayerStartConditions>();
|
Map<Player, PlayerStartConditions> startConditions = new HashMap<Player, PlayerStartConditions>();
|
||||||
@@ -186,6 +178,7 @@ public class MatchController {
|
|||||||
final boolean canRandomFoil = Singletons.getModel().getPreferences().getPrefBoolean(FPref.UI_RANDOM_FOIL) && gameType == GameType.Constructed;
|
final boolean canRandomFoil = Singletons.getModel().getPreferences().getPrefBoolean(FPref.UI_RANDOM_FOIL) && gameType == GameType.Constructed;
|
||||||
GameNew.newGame(this, startConditions, currentGame, canRandomFoil);
|
GameNew.newGame(this, startConditions, currentGame, canRandomFoil);
|
||||||
|
|
||||||
|
currentGame.setAge(GameAge.Mulligan);
|
||||||
getInput().clearInput();
|
getInput().clearInput();
|
||||||
//getInput().setNewInput(currentGame);
|
//getInput().setNewInput(currentGame);
|
||||||
|
|
||||||
@@ -348,62 +341,10 @@ public class MatchController {
|
|||||||
return 10;
|
return 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleLeylinesAndChancellors() {
|
|
||||||
for (Player p : currentGame.getPlayers()) {
|
|
||||||
final List<Card> openingHand = new ArrayList<Card>(p.getCardsIn(ZoneType.Hand));
|
|
||||||
|
|
||||||
for (final Card c : openingHand) {
|
|
||||||
if (p.isHuman()) {
|
|
||||||
for (String kw : c.getKeyword()) {
|
|
||||||
if (kw.startsWith("MayEffectFromOpeningHand")) {
|
|
||||||
final String effName = kw.split(":")[1];
|
|
||||||
|
|
||||||
final SpellAbility effect = AbilityFactory.getAbility(c.getSVar(effName), c);
|
|
||||||
if (GuiDialog.confirm(c, "Use " + c +"'s ability?")) {
|
|
||||||
// If we ever let the AI memorize cards in the players
|
|
||||||
// hand, this would be a place to do so.
|
|
||||||
((HumanPlayer)p).playSpellAbilityNoStack(effect);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (c.getName().startsWith("Leyline of")) {
|
|
||||||
if (GuiDialog.confirm(c, "Use " + c + "'s ability?")) {
|
|
||||||
currentGame.getAction().moveToPlay(c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else { // Computer Leylines & Chancellors
|
|
||||||
if (!c.getName().startsWith("Leyline of")) {
|
|
||||||
for (String kw : c.getKeyword()) {
|
|
||||||
if (kw.startsWith("MayEffectFromOpeningHand")) {
|
|
||||||
final String effName = kw.split(":")[1];
|
|
||||||
|
|
||||||
final SpellAbility effect = AbilityFactory.getAbility(c.getSVar(effName), c);
|
|
||||||
|
|
||||||
// Is there a better way for the AI to decide this?
|
|
||||||
if (effect.doTrigger(false, (AIPlayer)p)) {
|
|
||||||
GuiDialog.message("Computer reveals " + c.getName() + "(" + c.getUniqueNumber() + ").");
|
|
||||||
ComputerUtil.playNoStack((AIPlayer)p, effect, currentGame);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (c.getName().startsWith("Leyline of")
|
|
||||||
&& !(c.getName().startsWith("Leyline of Singularity")
|
|
||||||
&& (Iterables.any(currentGame.getCardsIn(ZoneType.Battlefield), CardPredicates.nameEquals("Leyline of Singularity"))))) {
|
|
||||||
currentGame.getAction().moveToPlay(c);
|
|
||||||
//ga.checkStateEffects();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
currentGame.getAction().checkStateEffects();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void afterMulligans()
|
public void afterMulligans()
|
||||||
{
|
{
|
||||||
handleLeylinesAndChancellors();
|
currentGame.getAction().handleLeylinesAndChancellors();
|
||||||
currentGame.setMulliganned(true);
|
currentGame.setAge(GameAge.Play);
|
||||||
getInput().clearInput();
|
getInput().clearInput();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user