passPriority is called from PlayerController, to avoid priority being passed by players who don't have it.

This commit is contained in:
Maxmtg
2013-01-25 23:42:49 +00:00
parent 5a65d60d5f
commit 278e44667e
12 changed files with 143 additions and 100 deletions

View File

@@ -24,6 +24,7 @@ import java.util.List;
import forge.Card; import forge.Card;
import forge.Singletons; import forge.Singletons;
import forge.control.FControl;
import forge.game.GameState; import forge.game.GameState;
import forge.game.phase.CombatUtil; import forge.game.phase.CombatUtil;
import forge.game.player.Player; import forge.game.player.Player;
@@ -103,7 +104,7 @@ public class InputBlock extends Input {
ButtonUtil.reset(); ButtonUtil.reset();
CombatUtil.orderMultipleCombatants(game.getCombat()); CombatUtil.orderMultipleCombatants(game.getCombat());
game.getPhaseHandler().passPriority(); FControl.SINGLETON_INSTANCE.getPlayer().getController().passPriority();
} }
} }

View File

@@ -40,18 +40,15 @@ public class InputCleanup extends Input {
/** {@inheritDoc} */ /** {@inheritDoc} */
@Override @Override
public final void showMessage() { public final void showMessage() {
final Player active = Singletons.getModel().getGame().getPhaseHandler().getPlayerTurn(); final Player active = Singletons.getModel().getGame().getPhaseHandler().getPriorityPlayer();
if (active.isComputer()) {
this.aiCleanupDiscard(active);
Singletons.getModel().getGame().getPhaseHandler().passPriority();
return;
}
final int n = active.getCardsIn(ZoneType.Hand).size(); final int n = active.getCardsIn(ZoneType.Hand).size();
final int max = active.getMaxHandSize(); final int max = active.getMaxHandSize();
// goes to the next phase // goes to the next phase
if (active.isUnlimitedHandSize() || n <= max || n <= 0) { if (active.isUnlimitedHandSize() || n <= max || n <= 0) {
Singletons.getModel().getGame().getPhaseHandler().passPriority(); active.getController().passPriority();
return; return;
} }
ButtonUtil.disableAll(); ButtonUtil.disableAll();
@@ -81,14 +78,7 @@ public class InputCleanup extends Input {
* AI_CleanupDiscard. * AI_CleanupDiscard.
* </p> * </p>
*/ */
public void aiCleanupDiscard(final Player ai) {
final int size = ai.getCardsIn(ZoneType.Hand).size();
if (!ai.isUnlimitedHandSize()) {
final int numDiscards = size - ai.getMaxHandSize();
ai.discard(numDiscards, null);
}
}
/* (non-Javadoc) /* (non-Javadoc)
* @see forge.control.input.Input#isClassUpdated() * @see forge.control.input.Input#isClassUpdated()

View File

@@ -194,6 +194,10 @@ public class InputControl extends MyObservable implements java.io.Serializable {
return null; return null;
} }
if (priority == null)
return null;
PlayerController pc = priority.getController();
// Special Inputs needed for the following phases: // Special Inputs needed for the following phases:
switch (phase) { switch (phase) {
case COMBAT_DECLARE_ATTACKERS: case COMBAT_DECLARE_ATTACKERS:
@@ -208,19 +212,18 @@ public class InputControl extends MyObservable implements java.io.Serializable {
stack.freezeStack(); stack.freezeStack();
if (game.getCombat().isPlayerAttacked(priority)) { if (game.getCombat().isPlayerAttacked(priority)) {
return priority.getController().getBlockInput(); return pc.getBlockInput();
} }
// noone attacks you // noone attacks you
handler.passPriority(); pc.passPriority();
return null; return null;
case CLEANUP: case CLEANUP:
// discard // discard
if (stack.isEmpty()) { if (stack.isEmpty()) {
// resolve things // resolve things like Madness
// like Madness return pc.getCleanupInput();
return new InputCleanup();
} }
break; break;
default: default:
@@ -230,14 +233,10 @@ public class InputControl extends MyObservable implements java.io.Serializable {
// ********************* // *********************
// Special phases handled above, everything else is handled simply by // Special phases handled above, everything else is handled simply by
// priority // priority
if (priority == null)
return null;
PlayerController pc = priority.getController();
boolean prioritySkip = pc.mayAutoPass(phase) || pc.isUiSetToSkipPhase(playerTurn, phase); boolean prioritySkip = pc.mayAutoPass(phase) || pc.isUiSetToSkipPhase(playerTurn, phase);
if (this.game.getStack().isEmpty() && prioritySkip) { if (this.game.getStack().isEmpty() && prioritySkip) {
handler.passPriority(); pc.passPriority();
return null; return null;
} else } else
pc.autoPassCancel(); // probably cancel, since something has happened pc.autoPassCancel(); // probably cancel, since something has happened

View File

@@ -20,6 +20,7 @@ package forge.control.input;
import forge.Card; import forge.Card;
import forge.Singletons; import forge.Singletons;
import forge.card.spellability.SpellAbility; import forge.card.spellability.SpellAbility;
import forge.control.FControl;
import forge.game.GameState; import forge.game.GameState;
import forge.game.phase.PhaseType; import forge.game.phase.PhaseType;
import forge.game.player.Player; import forge.game.player.Player;
@@ -73,7 +74,7 @@ public class InputPassPriority extends Input {
/** {@inheritDoc} */ /** {@inheritDoc} */
@Override @Override
public final void selectButtonOK() { public final void selectButtonOK() {
Singletons.getModel().getGame().getPhaseHandler().passPriority(); FControl.SINGLETON_INSTANCE.getPlayer().getController().passPriority();
} }
/** {@inheritDoc} */ /** {@inheritDoc} */

View File

@@ -37,6 +37,7 @@ import forge.StaticEffects;
import forge.card.replacement.ReplacementHandler; import forge.card.replacement.ReplacementHandler;
import forge.card.spellability.Ability; import forge.card.spellability.Ability;
import forge.card.spellability.SpellAbility; import forge.card.spellability.SpellAbility;
import forge.card.spellability.SpellAbilityStackInstance;
import forge.card.trigger.TriggerHandler; import forge.card.trigger.TriggerHandler;
import forge.card.trigger.TriggerType; import forge.card.trigger.TriggerType;
import forge.game.phase.Cleanup; import forge.game.phase.Cleanup;
@@ -623,4 +624,38 @@ public class GameState {
getTriggerHandler().clearSuppression(TriggerType.PlaneswalkedTo); getTriggerHandler().clearSuppression(TriggerType.PlaneswalkedTo);
} }
public void archenemy904_10() {
//904.10. If a non-ongoing scheme card is face up in the
//command zone, and it isn't the source of a triggered ability
//that has triggered but not yet left the stack, that scheme card
//is turned face down and put on the bottom of its owner's scheme
//deck the next time a player would receive priority.
//(This is a state-based action. See rule 704.)
for (int i = 0; i < getCardsIn(ZoneType.Command).size(); i++) {
Card c = getCardsIn(ZoneType.Command).get(i);
if (c.isScheme() && !c.isType("Ongoing")) {
boolean foundonstack = false;
for (SpellAbilityStackInstance si : getStack().getStack()) {
if (si.getSourceCard().equals(c)) {
foundonstack = true;
break;
}
}
if (!foundonstack) {
getTriggerHandler().suppressMode(TriggerType.ChangesZone);
c.getController().getZone(ZoneType.Command).remove(c);
i--;
getTriggerHandler().clearSuppression(TriggerType.ChangesZone);
c.getController().getSchemeDeck().add(c);
}
}
}
}
} }

View File

@@ -480,5 +480,14 @@ public class AiController {
return p; return p;
} }
}; // Comparator }; // Comparator
public void cleanupDiscard() {
final int size = player.getCardsIn(ZoneType.Hand).size();
if (!player.isUnlimitedHandSize()) {
final int numDiscards = size - player.getMaxHandSize();
player.discard(numDiscards, null);
}
}
} }

View File

@@ -81,6 +81,10 @@ public class AiInputCommon extends Input {
playSpellAbilities(game); playSpellAbilities(game);
} else { } else {
switch(phase) { switch(phase) {
case CLEANUP:
computer.cleanupDiscard();
break;
case COMBAT_DECLARE_ATTACKERS: case COMBAT_DECLARE_ATTACKERS:
declareAttackers(); declareAttackers();
break; break;
@@ -95,7 +99,7 @@ public class AiInputCommon extends Input {
break; break;
} }
} }
game.getPhaseHandler().passPriority(); player.getController().passPriority();
} // getMessage(); } // getMessage();
/** /**
@@ -147,6 +151,7 @@ public class AiInputCommon extends Input {
do { do {
sa = computer.getSpellAbilityToPlay(); sa = computer.getSpellAbilityToPlay();
if ( sa == null ) break; if ( sa == null ) break;
//System.out.println("Playing sa: " + sa);
ComputerUtil.handlePlayingSpellAbility(player, sa, game); ComputerUtil.handlePlayingSpellAbility(player, sa, game);
} while ( sa != null ); } while ( sa != null );
} }

View File

@@ -18,17 +18,13 @@
package forge.game.phase; package forge.game.phase;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Stack; import java.util.Stack;
import com.esotericsoftware.minlog.Log; import com.esotericsoftware.minlog.Log;
import forge.Card; import forge.Card;
import forge.CardLists;
import forge.CardPredicates;
import forge.Singletons; import forge.Singletons;
import forge.card.spellability.SpellAbilityStackInstance;
import forge.card.trigger.TriggerType; import forge.card.trigger.TriggerType;
import forge.game.GameState; import forge.game.GameState;
import forge.game.GameType; import forge.game.GameType;
@@ -464,7 +460,7 @@ public class PhaseHandler extends MyObservable implements java.io.Serializable {
case COMBAT_END: case COMBAT_END:
//SDisplayUtil.showTab(EDocID.REPORT_STACK.getDoc()); //SDisplayUtil.showTab(EDocID.REPORT_STACK.getDoc());
game.getCombat().reset(); game.getCombat().reset();
this.resetAttackedThisCombat(this.getPlayerTurn()); this.getPlayerTurn().resetAttackedThisCombat();
this.bCombat = false; this.bCombat = false;
break; break;
@@ -704,33 +700,6 @@ public class PhaseHandler extends MyObservable implements java.io.Serializable {
return (this.nCombatsThisTurn == 1); return (this.nCombatsThisTurn == 1);
} }
/**
* <p>
* resetAttackedThisCombat.
* </p>
*
* @param player
* a {@link forge.game.player.Player} object.
*/
public final void resetAttackedThisCombat(final Player player) {
// resets the status of attacked/blocked this phase
List<Card> list = CardLists.filter(player.getCardsIn(ZoneType.Battlefield), CardPredicates.Presets.CREATURES);
for (int i = 0; i < list.size(); i++) {
final Card c = list.get(i);
if (c.getDamageHistory().getCreatureAttackedThisCombat()) {
c.getDamageHistory().setCreatureAttackedThisCombat(false);
}
if (c.getDamageHistory().getCreatureBlockedThisCombat()) {
c.getDamageHistory().setCreatureBlockedThisCombat(false);
}
if (c.getDamageHistory().getCreatureGotBlockedThisCombat()) {
c.getDamageHistory().setCreatureGotBlockedThisCombat(false);
}
}
}
/** /**
* <p> * <p>
* passPriority. * passPriority.
@@ -742,38 +711,8 @@ public class PhaseHandler extends MyObservable implements java.io.Serializable {
return; return;
} }
//904.10. If a non-ongoing scheme card is face up in the
//command zone, and it isn't the source of a triggered ability
//that has triggered but not yet left the stack, that scheme card
//is turned face down and put on the bottom of its owner's scheme
//deck the next time a player would receive priority.
//(This is a state-based action. See rule 704.)
if(game.getType() == GameType.Archenemy) if(game.getType() == GameType.Archenemy)
{ game.archenemy904_10();
for (int i = 0; i < game.getCardsIn(ZoneType.Command).size(); i++) {
Card c = game.getCardsIn(ZoneType.Command).get(i);
if (c.isScheme() && !c.isType("Ongoing")) {
boolean foundonstack = false;
for (SpellAbilityStackInstance si : game.getStack().getStack()) {
if (si.getSourceCard().equals(c)) {
foundonstack = true;
break;
}
}
if (!foundonstack) {
game.getTriggerHandler().suppressMode(TriggerType.ChangesZone);
c.getController().getZone(ZoneType.Command).remove(c);
i--;
game.getTriggerHandler().clearSuppression(TriggerType.ChangesZone);
c.getController().getSchemeDeck().add(c);
}
}
}
}
final Player actingPlayer = this.getPriorityPlayer(); final Player actingPlayer = this.getPriorityPlayer();
final Player firstAction = this.getFirstPriority(); final Player firstAction = this.getFirstPriority();
@@ -783,6 +722,8 @@ public class PhaseHandler extends MyObservable implements java.io.Serializable {
// of Priority // of Priority
Player nextPlayer = game.getNextPlayerAfter(actingPlayer); Player nextPlayer = game.getNextPlayerAfter(actingPlayer);
// System.out.println(String.format("%s %s: %s passes priority to %s", playerTurn, phase, actingPlayer, nextPlayer));
if (firstAction.equals(nextPlayer)) { if (firstAction.equals(nextPlayer)) {
if (game.getStack().isEmpty()) { if (game.getStack().isEmpty()) {
this.setPriority(this.getPlayerTurn()); // this needs to be set early as we exit the phase this.setPriority(this.getPlayerTurn()); // this needs to be set early as we exit the phase

View File

@@ -57,10 +57,12 @@ public class AIPlayer extends Player {
* a {@link java.lang.String} object. * a {@link java.lang.String} object.
*/ */
public AIPlayer(final LobbyPlayer player, final GameState game) { public AIPlayer(final LobbyPlayer player, final GameState game) {
super(player, game, new PlayerController()); super(player, game, new PlayerController(game));
brains = new AiController(this, game); brains = new AiController(this, game);
getController().setDefaultInput(new AiInputCommon(brains)); PlayerController pc = getController();
getController().setBlockInput(new AiInputBlock(game, this)); pc.setDefaultInput(new AiInputCommon(brains));
pc.setBlockInput(new AiInputBlock(game, this));
pc.setCleanupInput(pc.getDefaultInput());
} }

View File

@@ -25,6 +25,7 @@ import forge.Singletons;
import forge.card.spellability.SpellAbility; import forge.card.spellability.SpellAbility;
import forge.control.input.Input; import forge.control.input.Input;
import forge.control.input.InputBlock; import forge.control.input.InputBlock;
import forge.control.input.InputCleanup;
import forge.control.input.InputPassPriority; import forge.control.input.InputPassPriority;
import forge.game.GameType; import forge.game.GameType;
import forge.game.GameState; import forge.game.GameState;
@@ -53,9 +54,10 @@ public class HumanPlayer extends Player {
* a {@link java.lang.String} object. * a {@link java.lang.String} object.
*/ */
public HumanPlayer(final LobbyPlayer player, GameState game) { public HumanPlayer(final LobbyPlayer player, GameState game) {
super(player, game, new PlayerController()); super(player, game, new PlayerController(game));
getController().setDefaultInput(new InputPassPriority()); getController().setDefaultInput(new InputPassPriority());
getController().setBlockInput(new InputBlock(this)); getController().setBlockInput(new InputBlock(this));
getController().setCleanupInput(new InputCleanup());
} }
// ////////////// // //////////////

View File

@@ -1704,10 +1704,8 @@ public abstract class Player extends GameEntity implements Comparable<Player> {
game.getAction().discardMadness(c, this); game.getAction().discardMadness(c, this);
boolean hasPutIntoPlayInsteadOfDiscard = c.hasKeyword("If a spell or ability an opponent controls causes you " boolean hasPutIntoPlayInsteadOfDiscard = c.hasKeyword("If a spell or ability an opponent controls causes you to discard CARDNAME, put it onto the battlefield instead of putting it into your graveyard.");
+ "to discard CARDNAME, put it onto the battlefield instead of putting it into your graveyard."); boolean hasPutIntoPlayWith2xP1P1InsteadOfDiscard = c.hasKeyword("If a spell or ability an opponent controls causes you to discard CARDNAME, put it onto the battlefield with two +1/+1 counters on it instead of putting it into your graveyard.");
boolean hasPutIntoPlayWith2xP1P1InsteadOfDiscard = c.hasKeyword("If a spell or ability an opponent controls causes you to discard CARDNAME, "
+ "put it onto the battlefield with two +1/+1 counters on it instead of putting it into your graveyard.");
if ((hasPutIntoPlayInsteadOfDiscard || hasPutIntoPlayWith2xP1P1InsteadOfDiscard) if ((hasPutIntoPlayInsteadOfDiscard || hasPutIntoPlayWith2xP1P1InsteadOfDiscard)
&& null != sa && sa.getSourceCard().getController().isHostileTo(c.getController())) { && null != sa && sa.getSourceCard().getController().isHostileTo(c.getController())) {
@@ -1722,7 +1720,7 @@ public abstract class Player extends GameEntity implements Comparable<Player> {
game.getAction().moveToGraveyard(c); game.getAction().moveToGraveyard(c);
// Play the Discard sound // Play the Discard sound
Singletons.getModel().getGame().getEvents().post(new CardDiscardedEvent()); game.getEvents().post(new CardDiscardedEvent());
} }
// Run triggers // Run triggers
@@ -3245,4 +3243,31 @@ public abstract class Player extends GameEntity implements Comparable<Player> {
game.setActivePlane(currentPlane); game.setActivePlane(currentPlane);
} }
/**
* <p>
* resetAttackedThisCombat.
* </p>
*
* @param player
* a {@link forge.game.player.Player} object.
*/
public final void resetAttackedThisCombat() {
// resets the status of attacked/blocked this phase
List<Card> list = CardLists.filter(getCardsIn(ZoneType.Battlefield), Presets.CREATURES);
for (int i = 0; i < list.size(); i++) {
final Card c = list.get(i);
if (c.getDamageHistory().getCreatureAttackedThisCombat()) {
c.getDamageHistory().setCreatureAttackedThisCombat(false);
}
if (c.getDamageHistory().getCreatureBlockedThisCombat()) {
c.getDamageHistory().setCreatureBlockedThisCombat(false);
}
if (c.getDamageHistory().getCreatureGotBlockedThisCombat()) {
c.getDamageHistory().setCreatureGotBlockedThisCombat(false);
}
}
}
} }

View File

@@ -5,6 +5,8 @@ import java.util.List;
import forge.Singletons; import forge.Singletons;
import forge.card.spellability.SpellAbility; import forge.card.spellability.SpellAbility;
import forge.control.input.Input; import forge.control.input.Input;
import forge.game.GameState;
import forge.game.phase.PhaseHandler;
import forge.game.phase.PhaseType; import forge.game.phase.PhaseType;
import forge.gui.GuiChoose; import forge.gui.GuiChoose;
import forge.gui.match.CMatchUI; import forge.gui.match.CMatchUI;
@@ -25,12 +27,18 @@ public class PlayerController {
private Input defaultInput; private Input defaultInput;
private Input blockInput; private Input blockInput;
private Input cleanupInput;
private final GameState game;
public final Input getDefaultInput() { public final Input getDefaultInput() {
return defaultInput; return defaultInput;
} }
public PlayerController() {} public PlayerController(GameState game0) {
game = game0;
}
void setPlayer(Player p) { void setPlayer(Player p) {
player = p; player = p;
} }
@@ -62,6 +70,12 @@ public class PlayerController {
defaultInput = input; defaultInput = input;
} }
void setCleanupInput(Input input) {
// TODO Auto-generated method stub
cleanupInput = input;
}
/** /**
* Uses GUI to learn which spell the player (human in our case) would like to play * Uses GUI to learn which spell the player (human in our case) would like to play
*/ */
@@ -84,4 +98,23 @@ public class PlayerController {
this.blockInput = blockInput0; this.blockInput = blockInput0;
} }
/**
* TODO: Write javadoc for this method.
*/
public void passPriority() {
PhaseHandler handler = game.getPhaseHandler();
// may pass only priority is has
if ( handler.getPriorityPlayer() == player )
game.getPhaseHandler().passPriority();
}
/**
* @return the cleanupInput
*/
public Input getCleanupInput() {
return cleanupInput;
}
} }