Added another class to indicate auto-pass of priority and keep the passPriority call in right thread (that is non-edt)

InputBase has player field and that passPriority method,
This commit is contained in:
Maxmtg
2013-03-31 10:49:35 +00:00
parent 750226b60f
commit 69dd8af584
30 changed files with 234 additions and 194 deletions

1
.gitattributes vendored
View File

@@ -13820,6 +13820,7 @@ src/main/java/forge/control/bazaar/ControlStall.java -text
src/main/java/forge/control/bazaar/package-info.java svneol=native#text/plain src/main/java/forge/control/bazaar/package-info.java svneol=native#text/plain
src/main/java/forge/control/input/Input.java -text src/main/java/forge/control/input/Input.java -text
src/main/java/forge/control/input/InputAttack.java svneol=native#text/plain src/main/java/forge/control/input/InputAttack.java svneol=native#text/plain
src/main/java/forge/control/input/InputAutoPassPriority.java -text
src/main/java/forge/control/input/InputBase.java svneol=native#text/plain src/main/java/forge/control/input/InputBase.java svneol=native#text/plain
src/main/java/forge/control/input/InputBlock.java svneol=native#text/plain src/main/java/forge/control/input/InputBlock.java svneol=native#text/plain
src/main/java/forge/control/input/InputCleanup.java svneol=native#text/plain src/main/java/forge/control/input/InputCleanup.java svneol=native#text/plain

View File

@@ -123,5 +123,9 @@ public class FThreads {
public static void delay(int milliseconds, Runnable inputUpdater) { public static void delay(int milliseconds, Runnable inputUpdater) {
getScheduledPool().schedule(inputUpdater, milliseconds, TimeUnit.MILLISECONDS); getScheduledPool().schedule(inputUpdater, milliseconds, TimeUnit.MILLISECONDS);
} }
public static String debugGetCurrThreadId() {
return isEDT() ? "EDT" : Long.toString(Thread.currentThread().getId());
}
} }

View File

@@ -223,7 +223,7 @@ public class CostPartMana extends CostPart {
} }
if (this.getAmountOfX() > 0) { if (this.getAmountOfX() > 0) {
source.setXManaCostPaid(0); source.setXManaCostPaid(0);
InputPayment inpPayment = new InputPayManaX(game, ability, this.getAmountOfX(), this.canXbe0()); InputPayment inpPayment = new InputPayManaX(ability, this.getAmountOfX(), this.canXbe0());
FThreads.setInputAndWait(inpPayment); FThreads.setInputAndWait(inpPayment);
if(!inpPayment.isPaid()) if(!inpPayment.isPaid())
return false; return false;

View File

@@ -23,83 +23,21 @@ import forge.Card;
import forge.CardLists; import forge.CardLists;
import forge.CardPredicates.Presets; import forge.CardPredicates.Presets;
import forge.FThreads; import forge.FThreads;
import forge.Singletons;
import forge.card.ability.AbilityUtils; import forge.card.ability.AbilityUtils;
import forge.card.spellability.SpellAbility; import forge.card.spellability.SpellAbility;
import forge.control.input.InputPayment; import forge.control.input.InputSelectCards;
import forge.control.input.InputSelectCardsFromList;
import forge.game.GameState; import forge.game.GameState;
import forge.game.ai.ComputerUtil; import forge.game.ai.ComputerUtil;
import forge.game.player.AIPlayer; import forge.game.player.AIPlayer;
import forge.game.player.Player; import forge.game.player.Player;
import forge.game.zone.Zone;
import forge.game.zone.ZoneType; import forge.game.zone.ZoneType;
import forge.view.ButtonUtil;
/** /**
* The Class CostTapType. * The Class CostTapType.
*/ */
public class CostTapType extends CostPartWithList { public class CostTapType extends CostPartWithList {
/**
* TODO: Write javadoc for this type.
*
*/
public static final class InputPayCostTapType extends InputPayCostBase {
private final CostTapType tapType;
private final int nCards;
private final List<Card> cardList;
private static final long serialVersionUID = 6438988130447851042L;
private int nTapped = 0;
/**
* TODO: Write javadoc for Constructor.
* @param sa
* @param tapType
* @param nCards
* @param cardList
* @param payment
*/
public InputPayCostTapType(CostTapType tapType, int nCards, List<Card> cardList) {
this.tapType = tapType;
this.nCards = nCards;
this.cardList = cardList;
}
@Override
public void showMessage() {
final int left = nCards - this.nTapped;
showMessage("Select a " + tapType.getDescription() + " to tap (" + left + " left)");
ButtonUtil.enableOnlyCancel();
if (nCards == 0) {
this.done();
}
}
@Override
public void selectCard(final Card card) {
Zone zone = Singletons.getModel().getGame().getZoneOf(card);
if (zone.is(ZoneType.Battlefield) && cardList.contains(card) && card.isUntapped()) {
// send in List<Card> for Typing
tapType.executePayment(null, card);
cardList.remove(card);
this.nTapped++;
if (this.nTapped == nCards) {
this.done();
} else if (cardList.size() == 0) {
// happen
this.cancel();
} else {
this.showMessage();
}
}
}
}
private final boolean canTapSource; private final boolean canTapSource;
/** /**
@@ -214,9 +152,15 @@ public class CostTapType extends CostPartWithList {
c = AbilityUtils.calculateAmount(source, amount, ability); c = AbilityUtils.calculateAmount(source, amount, ability);
} }
} }
InputPayment inp = new InputPayCostTapType(this, c, typeList);
InputSelectCards inp = new InputSelectCardsFromList(c, c, typeList);
inp.setMessage("Select a " + getDescription() + " to tap (%d left)");
FThreads.setInputAndWait(inp); FThreads.setInputAndWait(inp);
return inp.isPaid(); if ( inp.hasCancelled() )
return false;
return executePayment(ability, inp.getSelected());
} }
/* (non-Javadoc) /* (non-Javadoc)

View File

@@ -1,5 +1,6 @@
package forge.card.cost; package forge.card.cost;
import forge.Singletons;
import forge.control.input.InputPayment; import forge.control.input.InputPayment;
import forge.control.input.InputSyncronizedBase; import forge.control.input.InputSyncronizedBase;
@@ -8,6 +9,14 @@ import forge.control.input.InputSyncronizedBase;
* *
*/ */
abstract class InputPayCostBase extends InputSyncronizedBase implements InputPayment { abstract class InputPayCostBase extends InputSyncronizedBase implements InputPayment {
/**
* TODO: Write javadoc for Constructor.
* @param player
*/
public InputPayCostBase() {
super(Singletons.getControl().getPlayer());
}
private static final long serialVersionUID = -2967434867139585579L; private static final long serialVersionUID = -2967434867139585579L;
boolean bPaid = false; boolean bPaid = false;

View File

@@ -71,6 +71,7 @@ public class TargetSelection {
* @param mandatory * @param mandatory
*/ */
public InputSelectTargets(TargetSelection select, List<Card> choices, ArrayList<Object> alreadyTargeted, boolean targeted, Target tgt, SpellAbility sa, boolean mandatory) { public InputSelectTargets(TargetSelection select, List<Card> choices, ArrayList<Object> alreadyTargeted, boolean targeted, Target tgt, SpellAbility sa, boolean mandatory) {
super(sa.getActivatingPlayer());
this.select = select; this.select = select;
this.choices = choices; this.choices = choices;
this.alreadyTargeted = alreadyTargeted; this.alreadyTargeted = alreadyTargeted;

View File

@@ -47,8 +47,9 @@ public class InputAttack extends InputBase {
private static final long serialVersionUID = 7849903731842214245L; private static final long serialVersionUID = 7849903731842214245L;
private final GameState game; private final GameState game;
public InputAttack(GameState game0) { public InputAttack(Player human) {
game = game0; super(human);
game = human.getGame();
} }

View File

@@ -0,0 +1,21 @@
package forge.control.input;
import forge.game.player.Player;
/**
* TODO: Write javadoc for this type.
*
*/
public class InputAutoPassPriority extends InputBase {
private static final long serialVersionUID = -7520803307255234647L;
public InputAutoPassPriority(Player player) {
super(player);
}
@Override
public void showMessage() {
passPriority();
}
}

View File

@@ -18,6 +18,7 @@
package forge.control.input; package forge.control.input;
import forge.Card; import forge.Card;
import forge.FThreads;
import forge.Singletons; import forge.Singletons;
import forge.game.player.Player; import forge.game.player.Player;
import forge.gui.match.CMatchUI; import forge.gui.match.CMatchUI;
@@ -33,7 +34,11 @@ import forge.gui.match.CMatchUI;
public abstract class InputBase implements java.io.Serializable, Input { public abstract class InputBase implements java.io.Serializable, Input {
/** Constant <code>serialVersionUID=-6539552513871194081L</code>. */ /** Constant <code>serialVersionUID=-6539552513871194081L</code>. */
private static final long serialVersionUID = -6539552513871194081L; private static final long serialVersionUID = -6539552513871194081L;
protected final Player player;
public InputBase(Player player) {
this.player = player;
}
// showMessage() is always the first method called // showMessage() is always the first method called
@Override @Override
public abstract void showMessage(); public abstract void showMessage();
@@ -64,4 +69,18 @@ public abstract class InputBase implements java.io.Serializable, Input {
} }
protected void afterStop() { } protected void afterStop() { }
protected void passPriority() {
final Runnable pass = new Runnable() {
@Override public void run() {
player.getController().passPriority();
}
};
if( FThreads.isEDT() )
FThreads.invokeInNewThread(pass, true);
else
pass.run();
}
} }

View File

@@ -23,7 +23,6 @@ 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;
@@ -48,14 +47,13 @@ public class InputBlock extends InputBase {
private Card currentAttacker = null; private Card currentAttacker = null;
private final HashMap<Card, List<Card>> allBlocking = new HashMap<Card, List<Card>>(); private final HashMap<Card, List<Card>> allBlocking = new HashMap<Card, List<Card>>();
private final Player defender;
/** /**
* TODO: Write javadoc for Constructor. * TODO: Write javadoc for Constructor.
* @param priority * @param priority
*/ */
public InputBlock(Player priority) { public InputBlock(Player human) {
defender = priority; super(human);
} }
/** /**
@@ -98,14 +96,14 @@ public class InputBlock extends InputBase {
@Override @Override
public final void selectButtonOK() { public final void selectButtonOK() {
final GameState game = Singletons.getModel().getGame(); final GameState game = Singletons.getModel().getGame();
if (CombatUtil.finishedMandatoryBlocks(game.getCombat(), defender)) { if (CombatUtil.finishedMandatoryBlocks(game.getCombat(), player)) {
// Done blocking // Done blocking
ButtonUtil.reset(); ButtonUtil.reset();
CombatUtil.orderMultipleCombatants(game.getCombat()); CombatUtil.orderMultipleCombatants(game.getCombat());
currentAttacker = null; currentAttacker = null;
allBlocking.clear(); allBlocking.clear();
FControl.SINGLETON_INSTANCE.getPlayer().getController().passPriority(); passPriority();
} }
} }
@@ -121,8 +119,8 @@ public class InputBlock extends InputBase {
} else { } else {
Zone zone = Singletons.getModel().getGame().getZoneOf(card); Zone zone = Singletons.getModel().getGame().getZoneOf(card);
// Make sure this card is valid to even be a blocker // Make sure this card is valid to even be a blocker
if (this.currentAttacker != null && card.isCreature() && card.getController().equals(defender) if (this.currentAttacker != null && card.isCreature() && card.getController().equals(player)
&& zone.is(ZoneType.Battlefield, defender)) { && zone.is(ZoneType.Battlefield, player)) {
// Create a new blockedBy list if it doesn't exist // Create a new blockedBy list if it doesn't exist
if (!this.allBlocking.containsKey(card)) { if (!this.allBlocking.containsKey(card)) {
this.allBlocking.put(card, new ArrayList<Card>()); this.allBlocking.put(card, new ArrayList<Card>());

View File

@@ -24,7 +24,6 @@ import forge.game.GameState;
import forge.game.player.Player; import forge.game.player.Player;
import forge.game.zone.Zone; import forge.game.zone.Zone;
import forge.game.zone.ZoneType; import forge.game.zone.ZoneType;
import forge.gui.match.CMatchUI;
import forge.view.ButtonUtil; import forge.view.ButtonUtil;
/** /**
@@ -44,9 +43,9 @@ public class InputCleanup extends InputBase {
* TODO: Write javadoc for Constructor. * TODO: Write javadoc for Constructor.
* @param game * @param game
*/ */
public InputCleanup(GameState game) { public InputCleanup(Player player) {
super(); super(player);
this.game = game; this.game = player.getGame();
} }
/** {@inheritDoc} */ /** {@inheritDoc} */
@@ -59,7 +58,7 @@ public class InputCleanup extends InputBase {
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 || active != turnOwner) { if (active.isUnlimitedHandSize() || n <= max || n <= 0 || active != turnOwner) {
active.getController().passPriority(); passPriority();
return; return;
} }
ButtonUtil.disableAll(); ButtonUtil.disableAll();
@@ -69,7 +68,7 @@ public class InputCleanup extends InputBase {
final StringBuffer sb = new StringBuffer(); final StringBuffer sb = new StringBuffer();
sb.append("Cleanup Phase: You can only have a maximum of ").append(max); sb.append("Cleanup Phase: You can only have a maximum of ").append(max);
sb.append(" cards, you currently have ").append(n).append(" cards in your hand - select a card to discard"); sb.append(" cards, you currently have ").append(n).append(" cards in your hand - select a card to discard");
CMatchUI.SINGLETON_INSTANCE.showMessage(sb.toString()); showMessage(sb.toString());
} }
/** {@inheritDoc} */ /** {@inheritDoc} */

View File

@@ -19,6 +19,7 @@ package forge.control.input;
import java.util.Stack; import java.util.Stack;
import forge.Singletons;
import forge.game.GameState; import forge.game.GameState;
import forge.game.phase.PhaseHandler; import forge.game.phase.PhaseHandler;
import forge.game.phase.PhaseType; import forge.game.phase.PhaseType;
@@ -115,38 +116,37 @@ public class InputControl extends MyObservable implements java.io.Serializable {
*/ */
public final Input getActualInput(GameState game) { public final Input getActualInput(GameState game) {
if ( !game.hasMulliganned() ) if ( !game.hasMulliganned() )
return new InputMulligan(); return new InputMulligan(Singletons.getModel().getMatch(), Singletons.getControl().getPlayer());
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();
final Player priority = handler.getPriorityPlayer(); final Player priority = handler.getPriorityPlayer();
final MagicStack stack = game.getStack(); if (priority == null)
throw new RuntimeException("No player has priority!");
PlayerController pc = priority.getController();
// TODO this resolving portion needs more work, but fixes Death Cloud
// issues
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 the Phase we're in doesn't allow for Priority, return null to move
// to next phase
// If the Phase we're in doesn't allow for Priority, move to next phase
if (!handler.isPlayerPriorityAllowed()) { if (!handler.isPlayerPriorityAllowed()) {
return null; return pc.getAutoPassPriorityInput();
} }
if (priority == null)
return null;
PlayerController pc = priority.getController();
// Special Inputs needed for the following phases: // Special Inputs needed for the following phases:
final MagicStack stack = game.getStack();
switch (phase) { switch (phase) {
case COMBAT_DECLARE_ATTACKERS: case COMBAT_DECLARE_ATTACKERS:
stack.freezeStack(); stack.freezeStack();
if (playerTurn.isHuman() && !playerTurn.getController().mayAutoPass(phase)) { if (playerTurn.isHuman() && !playerTurn.getController().mayAutoPass(phase)) {
game.getCombat().initiatePossibleDefenders(playerTurn.getOpponents()); game.getCombat().initiatePossibleDefenders(playerTurn.getOpponents());
return new InputAttack(game); return new InputAttack(playerTurn);
} }
break; break;
@@ -158,8 +158,7 @@ public class InputControl extends MyObservable implements java.io.Serializable {
} }
// noone attacks you // noone attacks you
pc.passPriority(); return pc.getAutoPassPriorityInput();
return null;
case CLEANUP: case CLEANUP:
// discard // discard
@@ -176,10 +175,9 @@ 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
boolean prioritySkip = pc.mayAutoPass(phase) || pc.isUiSetToSkipPhase(playerTurn, phase); boolean maySkipPriority = pc.mayAutoPass(phase) || pc.isUiSetToSkipPhase(playerTurn, phase);
if (game.getStack().isEmpty() && prioritySkip) { if (game.getStack().isEmpty() && maySkipPriority) {
pc.passPriority(); return pc.getAutoPassPriorityInput();
return null;
} else } else
pc.autoPassCancel(); // probably cancel, since something has happened pc.autoPassCancel(); // probably cancel, since something has happened

View File

@@ -2,16 +2,18 @@ package forge.control.input;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import forge.Card;
import forge.FThreads; import forge.FThreads;
import forge.Singletons;
import forge.game.player.Player;
import forge.gui.match.CMatchUI;
import forge.view.ButtonUtil; import forge.view.ButtonUtil;
/** /**
* TODO: Write javadoc for this type. * TODO: Write javadoc for this type.
* *
*/ */
public class InputLockUI extends InputBase { public class InputLockUI implements Input {
private static final long serialVersionUID = 5777143577098597374L;
private final AtomicInteger iCall = new AtomicInteger(); private final AtomicInteger iCall = new AtomicInteger();
public void showMessage() { public void showMessage() {
@@ -47,5 +49,18 @@ public class InputLockUI extends InputBase {
showMessage("Waiting for actions..."); showMessage("Waiting for actions...");
} }
}; };
protected final boolean isActive() {
return Singletons.getModel().getMatch().getInput().getInput() == this;
}
protected void showMessage(String message) {
CMatchUI.SINGLETON_INSTANCE.showMessage(message);
}
@Override public void selectCard(Card c) {}
@Override public void selectPlayer(Player player) {}
@Override public void selectButtonOK() {}
@Override public void selectButtonCancel() {}
} }

View File

@@ -24,12 +24,13 @@ import com.google.common.collect.Iterables;
import forge.Card; import forge.Card;
import forge.CardPredicates; import forge.CardPredicates;
import forge.Singletons; import forge.FThreads;
import forge.card.ability.AbilityFactory; import forge.card.ability.AbilityFactory;
import forge.card.spellability.SpellAbility; import forge.card.spellability.SpellAbility;
import forge.game.GameAction; import forge.game.GameAction;
import forge.game.GameState; import forge.game.GameState;
import forge.game.GameType; import forge.game.GameType;
import forge.game.MatchController;
import forge.game.ai.ComputerUtil; import forge.game.ai.ComputerUtil;
import forge.game.player.AIPlayer; import forge.game.player.AIPlayer;
import forge.game.player.Player; import forge.game.player.Player;
@@ -52,22 +53,28 @@ import forge.view.ButtonUtil;
public class InputMulligan extends InputBase { public class InputMulligan extends InputBase {
/** Constant <code>serialVersionUID=-8112954303001155622L</code>. */ /** Constant <code>serialVersionUID=-8112954303001155622L</code>. */
private static final long serialVersionUID = -8112954303001155622L; private static final long serialVersionUID = -8112954303001155622L;
private final MatchController match;
public InputMulligan(MatchController match0, Player humanPlayer) {
super(humanPlayer);
match = match0;
}
/** {@inheritDoc} */ /** {@inheritDoc} */
@Override @Override
public final void showMessage() { public final void showMessage() {
ButtonUtil.setButtonText("No", "Yes"); ButtonUtil.setButtonText("No", "Yes");
ButtonUtil.enableAllFocusOk(); ButtonUtil.enableAllFocusOk();
GameState game = Singletons.getModel().getGame(); GameState game = match.getCurrentGame();
Player startingPlayer = game.getPhaseHandler().getPlayerTurn(); Player startingPlayer = game.getPhaseHandler().getPlayerTurn();
Player localPlayer = Singletons.getControl().getPlayer();
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append(startingPlayer.getName()).append(" is going first. "); sb.append(startingPlayer.getName()).append(" is going first. ");
if (!startingPlayer.equals(localPlayer)) { if (!startingPlayer.equals(player)) {
sb.append("You are going ").append(game.getOrdinalPosition(localPlayer, startingPlayer)).append(". "); sb.append("You are going ").append(game.getOrdinalPosition(player, startingPlayer)).append(". ");
} }
sb.append("Do you want to Mulligan?"); sb.append("Do you want to Mulligan?");
@@ -83,10 +90,9 @@ public class InputMulligan extends InputBase {
/** {@inheritDoc} */ /** {@inheritDoc} */
@Override @Override
public final void selectButtonCancel() { public final void selectButtonCancel() {
final Player humanPlayer = Singletons.getControl().getPlayer(); player.doMulligan();
humanPlayer.doMulligan();
if (humanPlayer.getCardsIn(ZoneType.Hand).isEmpty()) { if (player.getCardsIn(ZoneType.Hand).isEmpty()) {
this.end(); this.end();
} else { } else {
ButtonUtil.enableAllFocusOk(); ButtonUtil.enableAllFocusOk();
@@ -94,9 +100,9 @@ public class InputMulligan extends InputBase {
} }
final void end() { final void end() {
GameState game = Singletons.getModel().getGame();
// Computer mulligan // Computer mulligan
final GameState game = match.getCurrentGame();
for (Player p : game.getPlayers()) { for (Player p : game.getPlayers()) {
if (!(p instanceof AIPlayer)) { if (!(p instanceof AIPlayer)) {
continue; continue;
@@ -173,17 +179,22 @@ public class InputMulligan extends InputBase {
SDisplayUtil.showTab(nextField); SDisplayUtil.showTab(nextField);
game.setMulliganned(true); game.setMulliganned(true);
Singletons.getModel().getMatch().getInput().clearInput(); FThreads.invokeInNewThread( new Runnable() {
@Override
public void run() {
match.getInput().clearInput();
}
});
} }
@Override @Override
public void selectCard(Card c0) { public void selectCard(Card c0) {
Zone z0 = Singletons.getModel().getGame().getZoneOf(c0); Zone z0 = match.getCurrentGame().getZoneOf(c0);
if (c0.getName().equals("Serum Powder") && z0.is(ZoneType.Hand)) { if (c0.getName().equals("Serum Powder") && z0.is(ZoneType.Hand)) {
if (GuiDialog.confirm(c0, "Use " + c0.getName() + "'s ability?")) { if (GuiDialog.confirm(c0, "Use " + c0.getName() + "'s ability?")) {
List<Card> hand = new ArrayList<Card>(c0.getController().getCardsIn(ZoneType.Hand)); List<Card> hand = new ArrayList<Card>(c0.getController().getCardsIn(ZoneType.Hand));
for (Card c : hand) { for (Card c : hand) {
Singletons.getModel().getGame().getAction().exile(c); match.getCurrentGame().getAction().exile(c);
} }
c0.getController().drawCards(hand.size()); c0.getController().drawCards(hand.size());
} }

View File

@@ -19,11 +19,9 @@ package forge.control.input;
import forge.Card; import forge.Card;
import forge.FThreads; import forge.FThreads;
import forge.Singletons;
import forge.card.spellability.SpellAbility; import forge.card.spellability.SpellAbility;
import forge.control.FControl; import forge.game.phase.PhaseHandler;
import forge.game.phase.PhaseType; import forge.game.player.HumanPlayer;
import forge.game.player.Player;
import forge.gui.GuiDisplayUtil; import forge.gui.GuiDisplayUtil;
import forge.gui.framework.SDisplayUtil; import forge.gui.framework.SDisplayUtil;
import forge.gui.match.CMatchUI; import forge.gui.match.CMatchUI;
@@ -42,26 +40,28 @@ public class InputPassPriority extends InputBase {
/** Constant <code>serialVersionUID=-581477682214137181L</code>. */ /** Constant <code>serialVersionUID=-581477682214137181L</code>. */
private static final long serialVersionUID = -581477682214137181L; private static final long serialVersionUID = -581477682214137181L;
/**
* TODO: Write javadoc for Constructor.
* @param player
*/
public InputPassPriority(HumanPlayer human) {
super(human);
}
/** {@inheritDoc} */ /** {@inheritDoc} */
@Override @Override
public final void showMessage() { public final void showMessage() {
GuiDisplayUtil.updateGUI(); GuiDisplayUtil.updateGUI();
ButtonUtil.enableOnlyOk(); ButtonUtil.enableOnlyOk();
final PhaseType phase = Singletons.getModel().getGame().getPhaseHandler().getPhase(); final PhaseHandler ph = player.getGame().getPhaseHandler();
final Player player = Singletons.getModel().getGame().getPhaseHandler().getPriorityPlayer();
if (player.isComputer()) {
System.err.println(phase + ": Computer in passpriority");
}
final StringBuilder sb = new StringBuilder(); final StringBuilder sb = new StringBuilder();
sb.append("Turn : ").append(Singletons.getModel().getGame().getPhaseHandler().getPlayerTurn()).append("\n"); sb.append("Turn : ").append(ph.getPlayerTurn()).append("\n");
sb.append("Phase: ").append(phase.Name).append("\n"); sb.append("Phase: ").append(ph.getPhase().Name).append("\n");
sb.append("Stack: "); sb.append("Stack: ");
if (Singletons.getModel().getGame().getStack().size() != 0) { if (player.getGame().getStack().size() != 0) {
sb.append(Singletons.getModel().getGame().getStack().size()).append(" to Resolve."); sb.append(player.getGame().getStack().size()).append(" to Resolve.");
} else { } else {
sb.append("Empty"); sb.append("Empty");
} }
@@ -71,16 +71,17 @@ public class InputPassPriority extends InputBase {
CMatchUI.SINGLETON_INSTANCE.showMessage(sb.toString()); CMatchUI.SINGLETON_INSTANCE.showMessage(sb.toString());
} }
/** {@inheritDoc} */ /** {@inheritDoc} */
@Override @Override
public final void selectButtonOK() { public final void selectButtonOK() {
FControl.SINGLETON_INSTANCE.getPlayer().getController().passPriority(); ButtonUtil.disableAll();
passPriority();
} }
/** {@inheritDoc} */ /** {@inheritDoc} */
@Override @Override
public final void selectCard(final Card card) { public final void selectCard(final Card card) {
final Player player = Singletons.getControl().getPlayer();
final SpellAbility ab = player.getController().getAbilityToPlay(player.getGame().getAbilitesOfCard(card, player)); final SpellAbility ab = player.getController().getAbilityToPlay(player.getGame().getAbilitesOfCard(card, player));
if ( null != ab) { if ( null != ab) {
Runnable execAbility = new Runnable() { Runnable execAbility = new Runnable() {

View File

@@ -30,16 +30,15 @@ public abstract class InputPayManaBase extends InputSyncronizedBase implements I
protected int phyLifeToLose = 0; protected int phyLifeToLose = 0;
protected final Player whoPays;
protected final GameState game; protected final GameState game;
protected ManaCostBeingPaid manaCost; protected ManaCostBeingPaid manaCost;
protected final SpellAbility saPaidFor; protected final SpellAbility saPaidFor;
boolean bPaid = false; boolean bPaid = false;
protected InputPayManaBase(final GameState game, SpellAbility saToPayFor) { protected InputPayManaBase(SpellAbility saToPayFor) {
this.game = game; super(saToPayFor.getActivatingPlayer());
this.whoPays = saToPayFor.getActivatingPlayer(); this.game = player.getGame();
this.saPaidFor = saToPayFor; this.saPaidFor = saToPayFor;
} }
@@ -115,7 +114,7 @@ public abstract class InputPayManaBase extends InputSyncronizedBase implements I
* @return ManaCost the amount of mana remaining to be paid after the mana is activated * @return ManaCost the amount of mana remaining to be paid after the mana is activated
*/ */
protected void useManaFromPool(String color, ManaCostBeingPaid manaCost) { protected void useManaFromPool(String color, ManaCostBeingPaid manaCost) {
ManaPool mp = whoPays.getManaPool(); ManaPool mp = player.getManaPool();
// Convert Color to short String // Convert Color to short String
String manaStr = "1"; String manaStr = "1";
@@ -144,7 +143,7 @@ public abstract class InputPayManaBase extends InputSyncronizedBase implements I
*/ */
protected void activateManaAbility(final Card card, ManaCostBeingPaid manaCost) { protected void activateManaAbility(final Card card, ManaCostBeingPaid manaCost) {
// make sure computer's lands aren't selected // make sure computer's lands aren't selected
if (card.getController() != whoPays) { if (card.getController() != player) {
return; return;
} }
@@ -168,7 +167,7 @@ public abstract class InputPayManaBase extends InputSyncronizedBase implements I
// you can't remove unneeded abilities inside a for(am:abilities) loop :( // you can't remove unneeded abilities inside a for(am:abilities) loop :(
for (SpellAbility ma : card.getManaAbility()) { for (SpellAbility ma : card.getManaAbility()) {
ma.setActivatingPlayer(whoPays); ma.setActivatingPlayer(player);
AbilityManaPart m = null; AbilityManaPart m = null;
SpellAbility tail = ma; SpellAbility tail = ma;
while(m == null && tail != null) while(m == null && tail != null)
@@ -303,11 +302,11 @@ public abstract class InputPayManaBase extends InputSyncronizedBase implements I
public void onManaAbilityPlayed(final SpellAbility saPaymentSrc) { public void onManaAbilityPlayed(final SpellAbility saPaymentSrc) {
if ( saPaymentSrc != null) // null comes when they've paid from pool if ( saPaymentSrc != null) // null comes when they've paid from pool
this.manaCost = whoPays.getManaPool().payManaFromAbility(saPaidFor, manaCost, saPaymentSrc); this.manaCost = player.getManaPool().payManaFromAbility(saPaidFor, manaCost, saPaymentSrc);
onManaAbilityPaid(); onManaAbilityPaid();
if ( saPaymentSrc != null ) if ( saPaymentSrc != null )
whoPays.getZone(ZoneType.Battlefield).updateObservers(); player.getZone(ZoneType.Battlefield).updateObservers();
} }
protected final void checkIfAlredyPaid() { protected final void checkIfAlredyPaid() {

View File

@@ -62,7 +62,7 @@ public class InputPayManaExecuteCommands extends InputPayManaBase implements Inp
* a {@link forge.Command} object. * a {@link forge.Command} object.
*/ */
public InputPayManaExecuteCommands(final Player p, final String prompt, final ManaCost manaCost2) { public InputPayManaExecuteCommands(final Player p, final String prompt, final ManaCost manaCost2) {
super(p.getGame(), new SpellAbility(null) { super(new SpellAbility(null) {
@Override @Override
public void resolve() {} public void resolve() {}
@@ -90,8 +90,8 @@ public class InputPayManaExecuteCommands extends InputPayManaBase implements Inp
} }
@Override @Override
public void selectPlayer(final Player player) { public void selectPlayer(final Player selectedPlayer) {
if (player == whoPays) { if (player == selectedPlayer) {
if (player.canPayLife(this.phyLifeToLose + 2) && manaCost.payPhyrexian()) { if (player.canPayLife(this.phyLifeToLose + 2) && manaCost.payPhyrexian()) {
this.phyLifeToLose += 2; this.phyLifeToLose += 2;
} }

View File

@@ -12,7 +12,7 @@ import forge.view.ButtonUtil;
public class InputPayManaOfCostPayment extends InputPayManaBase { public class InputPayManaOfCostPayment extends InputPayManaBase {
public InputPayManaOfCostPayment(final GameState game, CostPartMana costMana, SpellAbility spellAbility, int toAdd) { public InputPayManaOfCostPayment(final GameState game, CostPartMana costMana, SpellAbility spellAbility, int toAdd) {
super(game, spellAbility); super(spellAbility);
manaCost = new ManaCostBeingPaid(costMana.getManaToPay()); manaCost = new ManaCostBeingPaid(costMana.getManaToPay());
manaCost.increaseColorlessMana(toAdd); manaCost.increaseColorlessMana(toAdd);
} }
@@ -21,8 +21,8 @@ public class InputPayManaOfCostPayment extends InputPayManaBase {
private int phyLifeToLose = 0; private int phyLifeToLose = 0;
@Override @Override
public void selectPlayer(final Player player) { public void selectPlayer(final Player selectedPlayer) {
if (player == whoPays) { if (player == selectedPlayer) {
if (player.canPayLife(this.phyLifeToLose + 2) && manaCost.payPhyrexian()) { if (player.canPayLife(this.phyLifeToLose + 2) && manaCost.payPhyrexian()) {
this.phyLifeToLose += 2; this.phyLifeToLose += 2;
} }

View File

@@ -37,7 +37,7 @@ public class InputPayManaSimple extends InputPayManaBase {
private final String originalManaCost; private final String originalManaCost;
public InputPayManaSimple(final GameState game, final SpellAbility sa, final ManaCostBeingPaid manaCostToPay) { public InputPayManaSimple(final GameState game, final SpellAbility sa, final ManaCostBeingPaid manaCostToPay) {
super(game, sa); super(sa);
this.originalManaCost = manaCostToPay.toString(); // Change this.originalManaCost = manaCostToPay.toString(); // Change
this.originalCard = sa.getSourceCard(); this.originalCard = sa.getSourceCard();
@@ -68,9 +68,9 @@ public class InputPayManaSimple extends InputPayManaBase {
/** {@inheritDoc} */ /** {@inheritDoc} */
@Override @Override
public final void selectPlayer(final Player player) { public final void selectPlayer(final Player selectedPlayer) {
if (player == whoPays) { if (player == selectedPlayer) {
if (player.canPayLife(this.phyLifeToLose + 2) && manaCost.payPhyrexian()) { if (player.canPayLife(this.phyLifeToLose + 2) && manaCost.payPhyrexian()) {
this.phyLifeToLose += 2; this.phyLifeToLose += 2;
} }
@@ -88,10 +88,10 @@ public class InputPayManaSimple extends InputPayManaBase {
@Override @Override
protected void done() { protected void done() {
if (this.phyLifeToLose > 0) { if (this.phyLifeToLose > 0) {
whoPays.payLife(this.phyLifeToLose, this.originalCard); player.payLife(this.phyLifeToLose, this.originalCard);
} }
if (!this.saPaidFor.getSourceCard().isCopiedSpell()) { if (!this.saPaidFor.getSourceCard().isCopiedSpell()) {
whoPays.getManaPool().clearManaPaid(this.saPaidFor, false); player.getManaPool().clearManaPaid(this.saPaidFor, false);
this.resetManaCost(); this.resetManaCost();
if (this.saPaidFor.isSpell()) { if (this.saPaidFor.isSpell()) {
@@ -110,8 +110,8 @@ public class InputPayManaSimple extends InputPayManaBase {
handleConvokedCards(true); handleConvokedCards(true);
this.resetManaCost(); this.resetManaCost();
whoPays.getManaPool().refundManaPaid(this.saPaidFor, true); player.getManaPool().refundManaPaid(this.saPaidFor, true);
whoPays.getZone(ZoneType.Battlefield).updateObservers(); // DO player.getZone(ZoneType.Battlefield).updateObservers(); // DO
this.stop(); this.stop();
} }

View File

@@ -3,7 +3,6 @@ package forge.control.input;
import forge.Card; import forge.Card;
import forge.card.mana.ManaCostBeingPaid; import forge.card.mana.ManaCostBeingPaid;
import forge.card.spellability.SpellAbility; import forge.card.spellability.SpellAbility;
import forge.game.GameState;
import forge.view.ButtonUtil; import forge.view.ButtonUtil;
public class InputPayManaX extends InputPayManaBase { public class InputPayManaX extends InputPayManaBase {
@@ -15,9 +14,9 @@ public class InputPayManaX extends InputPayManaBase {
private final boolean xCanBe0; private final boolean xCanBe0;
public InputPayManaX(final GameState game, final SpellAbility sa0, final int amountX, final boolean xCanBe0) public InputPayManaX(final SpellAbility sa0, final int amountX, final boolean xCanBe0)
{ {
super(game, sa0); super(sa0);
xPaid = 0; xPaid = 0;
colorX = saPaidFor.hasParam("XColor") ? saPaidFor.getParam("XColor") : ""; colorX = saPaidFor.hasParam("XColor") ? saPaidFor.getParam("XColor") : "";

View File

@@ -5,6 +5,7 @@ import java.util.List;
import forge.Card; import forge.Card;
import forge.GameEntity; import forge.GameEntity;
import forge.Singletons;
import forge.view.ButtonUtil; import forge.view.ButtonUtil;
public abstract class InputSelectManyBase<T extends GameEntity> extends InputSyncronizedBase implements InputSelectMany<T> { public abstract class InputSelectManyBase<T extends GameEntity> extends InputSyncronizedBase implements InputSelectMany<T> {
@@ -23,6 +24,7 @@ public abstract class InputSelectManyBase<T extends GameEntity> extends InputSyn
protected InputSelectManyBase(int min, int max) { protected InputSelectManyBase(int min, int max) {
super(Singletons.getControl().getPlayer());
selected = new ArrayList<T>(); selected = new ArrayList<T>();
if (min > max) { if (min > max) {
throw new IllegalArgumentException("Min must not be greater than Max"); throw new IllegalArgumentException("Min must not be greater than Max");

View File

@@ -4,13 +4,15 @@ import java.util.concurrent.CountDownLatch;
import forge.FThreads; import forge.FThreads;
import forge.error.BugReporter; import forge.error.BugReporter;
import forge.game.player.Player;
public abstract class InputSyncronizedBase extends InputBase implements InputSynchronized { public abstract class InputSyncronizedBase extends InputBase implements InputSynchronized {
private static final long serialVersionUID = 8756177361251703052L; private static final long serialVersionUID = 8756177361251703052L;
private final CountDownLatch cdlDone; private final CountDownLatch cdlDone;
public InputSyncronizedBase() { public InputSyncronizedBase(Player player) {
super(player);
cdlDone = new CountDownLatch(1); cdlDone = new CountDownLatch(1);
} }

View File

@@ -14,21 +14,17 @@ import forge.game.player.Player;
* *
*/ */
public class AiInputBlock extends InputBase { public class AiInputBlock extends InputBase {
private final GameState game; private final GameState game;
/** /**
* TODO: Write javadoc for Constructor. * TODO: Write javadoc for Constructor.
* @param game * @param game
* @param player * @param player
*/ */
public AiInputBlock(GameState game, Player player) { public AiInputBlock(Player human) {
super(); super(human);
this.game = game; this.game = human.getGame();
this.player = player;
} }
private final Player player;
private static final long serialVersionUID = -2253562658069995572L; private static final long serialVersionUID = -2253562658069995572L;
@Override @Override

View File

@@ -43,6 +43,7 @@ public class AiInputCommon extends InputBase implements AiInput {
* a {@link forge.game.player.Computer} object. * a {@link forge.game.player.Computer} object.
*/ */
public AiInputCommon(final AiController iComputer) { public AiInputCommon(final AiController iComputer) {
super(iComputer.getPlayer());
this.computer = iComputer; this.computer = iComputer;
} }

View File

@@ -709,6 +709,7 @@ public class PhaseHandler extends MyObservable implements java.io.Serializable {
* </p> * </p>
*/ */
public final void passPriority() { public final void passPriority() {
FThreads.checkEDT("PhaseHandler.passPriority", false);
// stop game if it's outcome is clear // stop game if it's outcome is clear
if (game.isGameOver()) { if (game.isGameOver()) {
return; return;

View File

@@ -29,13 +29,15 @@ public abstract class PlayerController {
private PhaseType autoPassUntil = null; private PhaseType autoPassUntil = null;
public PlayerController(GameState game0) { public PlayerController(GameState game0) {
game = game0; game = game0;
} }
public abstract Input getDefaultInput(); public abstract Input getDefaultInput();
public abstract Input getBlockInput(); public abstract Input getBlockInput();
public abstract Input getCleanupInput(); public abstract Input getCleanupInput();
public abstract Input getAutoPassPriorityInput();
/** /**

View File

@@ -13,6 +13,7 @@ import forge.GameEntity;
import forge.card.spellability.Spell; import forge.card.spellability.Spell;
import forge.card.spellability.SpellAbility; import forge.card.spellability.SpellAbility;
import forge.control.input.Input; import forge.control.input.Input;
import forge.control.input.InputAutoPassPriority;
import forge.deck.Deck; import forge.deck.Deck;
import forge.game.GameState; import forge.game.GameState;
import forge.game.GameType; import forge.game.GameType;
@@ -36,6 +37,7 @@ public class PlayerControllerAi extends PlayerController {
private Input defaultInput; private Input defaultInput;
private Input blockInput; private Input blockInput;
private Input cleanupInput; private Input cleanupInput;
private Input autoPassPriorityInput;
private final AiController brains; private final AiController brains;
private final AIPlayer player; private final AIPlayer player;
@@ -52,9 +54,9 @@ public class PlayerControllerAi extends PlayerController {
brains = new AiController(p, game); brains = new AiController(p, game);
defaultInput = new AiInputCommon(brains); defaultInput = new AiInputCommon(brains);
blockInput = new AiInputBlock(game, getPlayer()); blockInput = new AiInputBlock(getPlayer());
cleanupInput = getDefaultInput(); cleanupInput = getDefaultInput();
autoPassPriorityInput = new InputAutoPassPriority(getPlayer());
} }
/** /**
@@ -75,6 +77,11 @@ public class PlayerControllerAi extends PlayerController {
return blockInput; return blockInput;
} }
@Override
public Input getAutoPassPriorityInput() {
return autoPassPriorityInput;
}
/** /**
* @return the cleanupInput * @return the cleanupInput
*/ */

View File

@@ -16,6 +16,7 @@ import forge.FThreads;
import forge.GameEntity; import forge.GameEntity;
import forge.card.spellability.SpellAbility; import forge.card.spellability.SpellAbility;
import forge.control.input.Input; import forge.control.input.Input;
import forge.control.input.InputAutoPassPriority;
import forge.control.input.InputBlock; import forge.control.input.InputBlock;
import forge.control.input.InputCleanup; import forge.control.input.InputCleanup;
import forge.control.input.InputPassPriority; import forge.control.input.InputPassPriority;
@@ -45,8 +46,9 @@ public class PlayerControllerHuman extends PlayerController {
private final Input defaultInput; private final Input defaultInput;
private final Input blockInput; private final Input blockInput;
private final Input cleanupInput; private final Input cleanupInput;
private final Input autoPassPriorityInput;
private final HumanPlayer player; private final HumanPlayer player;
public final Input getDefaultInput() { public final Input getDefaultInput() {
return defaultInput; return defaultInput;
} }
@@ -55,9 +57,10 @@ public class PlayerControllerHuman extends PlayerController {
super(game0); super(game0);
player = p; player = p;
defaultInput = new InputPassPriority(); defaultInput = new InputPassPriority(player);
blockInput = new InputBlock(getPlayer()); blockInput = new InputBlock(getPlayer());
cleanupInput = new InputCleanup(game); cleanupInput = new InputCleanup(getPlayer());
autoPassPriorityInput = new InputAutoPassPriority(getPlayer());
} }
@Override @Override
@@ -83,6 +86,11 @@ public class PlayerControllerHuman extends PlayerController {
return blockInput; return blockInput;
} }
@Override
public Input getAutoPassPriorityInput() {
return autoPassPriorityInput;
}
/** /**
* @return the cleanupInput * @return the cleanupInput
*/ */

View File

@@ -391,7 +391,7 @@ public class MagicStack extends MyObservable {
final int xCost = sa.getXManaCost(); final int xCost = sa.getXManaCost();
Player player = sp.getSourceCard().getController(); Player player = sp.getSourceCard().getController();
if (player.isHuman()) { if (player.isHuman()) {
InputSynchronized inp = new InputPayManaX(game, sa, xCost, true); InputSynchronized inp = new InputPayManaX(sa, xCost, true);
FThreads.setInputAndWait(inp); FThreads.setInputAndWait(inp);
MagicStack.this.push(sa); MagicStack.this.push(sa);
} else { } else {

View File

@@ -26,7 +26,6 @@ import forge.FThreads;
import forge.control.input.Input; import forge.control.input.Input;
import forge.game.GameState; import forge.game.GameState;
import forge.game.MatchController; import forge.game.MatchController;
import forge.game.ai.AiInput;
import forge.game.phase.PhaseHandler; import forge.game.phase.PhaseHandler;
import forge.game.player.Player; import forge.game.player.Player;
@@ -50,35 +49,37 @@ public class InputProxy implements Observer {
@Override @Override
public final synchronized void update(final Observable observable, final Object obj) { public final synchronized void update(final Observable observable, final Object obj) {
this.input.set(null);
final GameState game = match.getCurrentGame(); final GameState game = match.getCurrentGame();
final PhaseHandler ph = game.getPhaseHandler(); final PhaseHandler ph = game.getPhaseHandler();
//System.out.printf("%s > InputProxy.update() =>%n", FThreads.debugGetCurrThreadId());
//System.out.print((FThreads.isEDT() ? "EDT > " : "TRD > ") + ph.debugPrintState());
if ( match.getInput().isEmpty() && ph.hasPhaseEffects()) { if ( match.getInput().isEmpty() && ph.hasPhaseEffects()) {
//System.out.println(" handle begin phase"); Runnable rPhase = new Runnable() {
FThreads.invokeInNewThread(new Runnable() { @Override
@Override public void run() { public void run() {
//System.out.printf("\t%s > handle begin phase during %s%n", FThreads.debugGetCurrThreadId(), ph.debugPrintState());
ph.handleBeginPhase(); ph.handleBeginPhase();
update(observable, obj); update(null, null);
} }
}, true); };
FThreads.invokeInNewThread(rPhase);
return; return;
} }
final Input nextInput = match.getInput().getActualInput(game); final Input nextInput = match.getInput().getActualInput(game);
//System.out.printf(" input is %s \t stack = %s%n", nextInput == null ? "null" : nextInput.getClass().getSimpleName(), match.getInput().printInputStack()); //System.out.printf("\tinput is %s during %s, \tstack = %s%n", nextInput == null ? "null" : nextInput.getClass().getSimpleName(), ph.debugPrintState(), match.getInput().printInputStack());
if (nextInput != null) { this.input.set(nextInput);
this.input.set(nextInput); Runnable showMessage = new Runnable() {
Runnable showMessage = new Runnable() { @Override public void run() { nextInput.showMessage(); } }; @Override public void run() {
//System.out.printf("%s > showMessage @ %s during %s%n", FThreads.debugGetCurrThreadId(), nextInput.getClass().getSimpleName(), ph.debugPrintState());
nextInput.showMessage();
}
};
// if( nextInput instanceof AiInput ) // if( nextInput instanceof AiInput )
// FThreads.invokeInNewThread(showMessage, true); // FThreads.invokeInNewThread(showMessage, true);
// else // else
FThreads.invokeInEDT(showMessage); FThreads.invokeInEDT(showMessage);
} else if (!ph.isPlayerPriorityAllowed()) {
ph.getPriorityPlayer().getController().passPriority();
}
} }
/** /**
* <p> * <p>