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.Singletons;
import forge.control.FControl;
import forge.game.GameState;
import forge.game.phase.CombatUtil;
import forge.game.player.Player;
@@ -103,7 +104,7 @@ public class InputBlock extends Input {
ButtonUtil.reset();
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} */
@Override
public final void showMessage() {
final Player active = Singletons.getModel().getGame().getPhaseHandler().getPlayerTurn();
if (active.isComputer()) {
this.aiCleanupDiscard(active);
Singletons.getModel().getGame().getPhaseHandler().passPriority();
return;
}
final Player active = Singletons.getModel().getGame().getPhaseHandler().getPriorityPlayer();
final int n = active.getCardsIn(ZoneType.Hand).size();
final int max = active.getMaxHandSize();
// goes to the next phase
if (active.isUnlimitedHandSize() || n <= max || n <= 0) {
Singletons.getModel().getGame().getPhaseHandler().passPriority();
active.getController().passPriority();
return;
}
ButtonUtil.disableAll();
@@ -81,14 +78,7 @@ public class InputCleanup extends Input {
* AI_CleanupDiscard.
* </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)
* @see forge.control.input.Input#isClassUpdated()

View File

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

View File

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

View File

@@ -37,6 +37,7 @@ import forge.StaticEffects;
import forge.card.replacement.ReplacementHandler;
import forge.card.spellability.Ability;
import forge.card.spellability.SpellAbility;
import forge.card.spellability.SpellAbilityStackInstance;
import forge.card.trigger.TriggerHandler;
import forge.card.trigger.TriggerType;
import forge.game.phase.Cleanup;
@@ -623,4 +624,38 @@ public class GameState {
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;
}
}; // 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);
} else {
switch(phase) {
case CLEANUP:
computer.cleanupDiscard();
break;
case COMBAT_DECLARE_ATTACKERS:
declareAttackers();
break;
@@ -95,7 +99,7 @@ public class AiInputCommon extends Input {
break;
}
}
game.getPhaseHandler().passPriority();
player.getController().passPriority();
} // getMessage();
/**
@@ -147,6 +151,7 @@ public class AiInputCommon extends Input {
do {
sa = computer.getSpellAbilityToPlay();
if ( sa == null ) break;
//System.out.println("Playing sa: " + sa);
ComputerUtil.handlePlayingSpellAbility(player, sa, game);
} while ( sa != null );
}

View File

@@ -18,17 +18,13 @@
package forge.game.phase;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Stack;
import com.esotericsoftware.minlog.Log;
import forge.Card;
import forge.CardLists;
import forge.CardPredicates;
import forge.Singletons;
import forge.card.spellability.SpellAbilityStackInstance;
import forge.card.trigger.TriggerType;
import forge.game.GameState;
import forge.game.GameType;
@@ -464,7 +460,7 @@ public class PhaseHandler extends MyObservable implements java.io.Serializable {
case COMBAT_END:
//SDisplayUtil.showTab(EDocID.REPORT_STACK.getDoc());
game.getCombat().reset();
this.resetAttackedThisCombat(this.getPlayerTurn());
this.getPlayerTurn().resetAttackedThisCombat();
this.bCombat = false;
break;
@@ -704,33 +700,6 @@ public class PhaseHandler extends MyObservable implements java.io.Serializable {
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>
* passPriority.
@@ -742,38 +711,8 @@ public class PhaseHandler extends MyObservable implements java.io.Serializable {
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)
{
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);
}
}
}
}
game.archenemy904_10();
final Player actingPlayer = this.getPriorityPlayer();
final Player firstAction = this.getFirstPriority();
@@ -783,6 +722,8 @@ public class PhaseHandler extends MyObservable implements java.io.Serializable {
// of Priority
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 (game.getStack().isEmpty()) {
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.
*/
public AIPlayer(final LobbyPlayer player, final GameState game) {
super(player, game, new PlayerController());
super(player, game, new PlayerController(game));
brains = new AiController(this, game);
getController().setDefaultInput(new AiInputCommon(brains));
getController().setBlockInput(new AiInputBlock(game, this));
PlayerController pc = getController();
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.control.input.Input;
import forge.control.input.InputBlock;
import forge.control.input.InputCleanup;
import forge.control.input.InputPassPriority;
import forge.game.GameType;
import forge.game.GameState;
@@ -53,9 +54,10 @@ public class HumanPlayer extends Player {
* a {@link java.lang.String} object.
*/
public HumanPlayer(final LobbyPlayer player, GameState game) {
super(player, game, new PlayerController());
super(player, game, new PlayerController(game));
getController().setDefaultInput(new InputPassPriority());
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);
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.");
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 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.");
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)
&& 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);
// Play the Discard sound
Singletons.getModel().getGame().getEvents().post(new CardDiscardedEvent());
game.getEvents().post(new CardDiscardedEvent());
}
// Run triggers
@@ -3245,4 +3243,31 @@ public abstract class Player extends GameEntity implements Comparable<Player> {
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.card.spellability.SpellAbility;
import forge.control.input.Input;
import forge.game.GameState;
import forge.game.phase.PhaseHandler;
import forge.game.phase.PhaseType;
import forge.gui.GuiChoose;
import forge.gui.match.CMatchUI;
@@ -25,12 +27,18 @@ public class PlayerController {
private Input defaultInput;
private Input blockInput;
private Input cleanupInput;
private final GameState game;
public final Input getDefaultInput() {
return defaultInput;
}
public PlayerController() {}
public PlayerController(GameState game0) {
game = game0;
}
void setPlayer(Player p) {
player = p;
}
@@ -62,6 +70,12 @@ public class PlayerController {
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
*/
@@ -84,4 +98,23 @@ public class PlayerController {
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;
}
}