the 'state' of GameState added - named it GameAge

this should prevent wrong inputs before mulligan (problem reported by sol)
This commit is contained in:
Maxmtg
2013-04-04 05:16:46 +00:00
parent 3b88eae063
commit 16414982a8
7 changed files with 100 additions and 83 deletions

1
.gitattributes vendored
View File

@@ -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

View File

@@ -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);

View File

@@ -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.

View File

@@ -0,0 +1,8 @@
package forge.game;
public enum GameAge {
BeforeMulligan,
Mulligan,
Play,
GameOver
}

View File

@@ -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();

View File

@@ -18,6 +18,7 @@
package forge.game;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
@@ -55,8 +56,7 @@ 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;
}
}

View File

@@ -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();
}
}