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/game/GameAction.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/GameFormat.java -text
|
||||
src/main/java/forge/game/GameLossReason.java -text
|
||||
|
||||
@@ -20,6 +20,7 @@ package forge.control.input;
|
||||
import java.util.Stack;
|
||||
|
||||
import forge.Singletons;
|
||||
import forge.game.GameAge;
|
||||
import forge.game.GameState;
|
||||
import forge.game.GameType;
|
||||
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 MatchController match;
|
||||
public InputControl(MatchController matchController) {
|
||||
match = matchController;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 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.
|
||||
*/
|
||||
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
|
||||
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 PhaseType phase = handler.getPhase();
|
||||
final Player playerTurn = handler.getPlayerTurn();
|
||||
@@ -186,9 +197,7 @@ public class InputControl extends MyObservable implements java.io.Serializable {
|
||||
return pc.getDefaultInput();
|
||||
} // getInput()
|
||||
|
||||
/**
|
||||
* TODO: Write javadoc for this method.
|
||||
*/
|
||||
|
||||
private final static InputLockUI inputLock = new InputLockUI();
|
||||
public void lock() {
|
||||
setInput(inputLock);
|
||||
|
||||
@@ -38,6 +38,7 @@ import forge.CounterType;
|
||||
import forge.GameEntity;
|
||||
import forge.card.CardType;
|
||||
import forge.card.TriggerReplacementBase;
|
||||
import forge.card.ability.AbilityFactory;
|
||||
import forge.card.ability.effects.AttachEffect;
|
||||
import forge.card.cardfactory.CardFactory;
|
||||
import forge.card.cost.Cost;
|
||||
@@ -57,6 +58,7 @@ import forge.game.event.CardDestroyedEvent;
|
||||
import forge.game.event.CardRegeneratedEvent;
|
||||
import forge.game.event.CardSacrificedEvent;
|
||||
import forge.game.player.AIPlayer;
|
||||
import forge.game.player.HumanPlayer;
|
||||
import forge.game.player.Player;
|
||||
import forge.game.player.PlayerType;
|
||||
import forge.game.zone.PlayerZone;
|
||||
@@ -64,6 +66,7 @@ import forge.game.zone.PlayerZoneBattlefield;
|
||||
import forge.game.zone.Zone;
|
||||
import forge.game.zone.ZoneType;
|
||||
import forge.gui.GuiChoose;
|
||||
import forge.gui.GuiDialog;
|
||||
|
||||
/**
|
||||
* 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>
|
||||
* 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()));
|
||||
}
|
||||
|
||||
game.setMulliganned(false);
|
||||
game.setAge(GameAge.Mulligan);
|
||||
match.getInput().clearInput();
|
||||
|
||||
//Card.resetUniqueNumber();
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
package forge.game;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -54,9 +55,8 @@ import forge.game.zone.PlayerZone;
|
||||
import forge.game.zone.Zone;
|
||||
import forge.game.zone.ZoneType;
|
||||
|
||||
/**
|
||||
* Represents the state of a <i>single game</i> and is
|
||||
* "cleaned up" at each new game.
|
||||
/**
|
||||
* Represents the state of a <i>single game</i>, a new instance is created for each game.
|
||||
*/
|
||||
public class GameState {
|
||||
private final GameType type;
|
||||
@@ -82,13 +82,12 @@ public class GameState {
|
||||
private final GameLog gameLog = new GameLog();
|
||||
private final ColorChanger colorChanger = new ColorChanger();
|
||||
|
||||
private boolean gameOver = false;
|
||||
|
||||
private final Zone stackZone = new Zone(ZoneType.Stack);
|
||||
|
||||
private long timestamp = 0;
|
||||
public final GameAction action;
|
||||
private final MatchController match;
|
||||
private GameAge age = GameAge.BeforeMulligan;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
@@ -291,7 +290,7 @@ public class GameState {
|
||||
* @return the gameOver
|
||||
*/
|
||||
public synchronized boolean isGameOver() {
|
||||
return gameOver;
|
||||
return age == GameAge.GameOver;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -299,7 +298,7 @@ public class GameState {
|
||||
* @param go the gameOver to set
|
||||
*/
|
||||
public synchronized void setGameOver(GameEndReason reason) {
|
||||
this.gameOver = true;
|
||||
this.age = GameAge.GameOver;
|
||||
for (Player p : roIngamePlayers) {
|
||||
p.onGameOver();
|
||||
}
|
||||
@@ -661,7 +660,11 @@ public class GameState {
|
||||
}
|
||||
}
|
||||
|
||||
public boolean mulliganned = false;
|
||||
public boolean hasMulliganned(){ return mulliganned; }
|
||||
public void setMulliganned(boolean value) { mulliganned = value; }
|
||||
public GameAge getAge() {
|
||||
return age;
|
||||
}
|
||||
|
||||
void setAge(GameAge value) {
|
||||
age = value;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,20 +7,14 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import com.google.common.collect.Iterables;
|
||||
|
||||
import forge.Constant.Preferences;
|
||||
import forge.Card;
|
||||
import forge.CardPredicates;
|
||||
import forge.Singletons;
|
||||
import forge.card.ability.AbilityFactory;
|
||||
import forge.card.spellability.SpellAbility;
|
||||
import forge.control.FControl;
|
||||
import forge.control.input.InputControl;
|
||||
import forge.deck.Deck;
|
||||
import forge.error.BugReporter;
|
||||
import forge.game.ai.AiProfileUtil;
|
||||
import forge.game.ai.ComputerUtil;
|
||||
import forge.game.event.DuelOutcomeEvent;
|
||||
import forge.game.player.AIPlayer;
|
||||
import forge.game.player.HumanPlayer;
|
||||
@@ -29,7 +23,6 @@ import forge.game.player.Player;
|
||||
import forge.game.player.PlayerStatistics;
|
||||
import forge.game.player.PlayerType;
|
||||
import forge.game.zone.ZoneType;
|
||||
import forge.gui.GuiDialog;
|
||||
import forge.gui.InputProxy;
|
||||
import forge.gui.framework.EDocID;
|
||||
import forge.gui.framework.SDisplayUtil;
|
||||
@@ -137,8 +130,7 @@ public class MatchController {
|
||||
*/
|
||||
public void startRound() {
|
||||
|
||||
// Deal with circular dependencies here
|
||||
input = new InputControl();
|
||||
input = new InputControl(this);
|
||||
currentGame = Singletons.getModel().newGame(players.keySet(),gameType, this);
|
||||
|
||||
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;
|
||||
GameNew.newGame(this, startConditions, currentGame, canRandomFoil);
|
||||
|
||||
currentGame.setAge(GameAge.Mulligan);
|
||||
getInput().clearInput();
|
||||
//getInput().setNewInput(currentGame);
|
||||
|
||||
@@ -348,62 +341,10 @@ public class MatchController {
|
||||
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()
|
||||
{
|
||||
handleLeylinesAndChancellors();
|
||||
currentGame.setMulliganned(true);
|
||||
currentGame.getAction().handleLeylinesAndChancellors();
|
||||
currentGame.setAge(GameAge.Play);
|
||||
getInput().clearInput();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user