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/input/Input.java -text
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/InputBlock.java svneol=native#text/plain
src/main/java/forge/control/input/InputCleanup.java svneol=native#text/plain

View File

@@ -124,4 +124,8 @@ public class FThreads {
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) {
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);
if(!inpPayment.isPaid())
return false;

View File

@@ -23,83 +23,21 @@ import forge.Card;
import forge.CardLists;
import forge.CardPredicates.Presets;
import forge.FThreads;
import forge.Singletons;
import forge.card.ability.AbilityUtils;
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.ai.ComputerUtil;
import forge.game.player.AIPlayer;
import forge.game.player.Player;
import forge.game.zone.Zone;
import forge.game.zone.ZoneType;
import forge.view.ButtonUtil;
/**
* The Class CostTapType.
*/
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;
/**
@@ -214,9 +152,15 @@ public class CostTapType extends CostPartWithList {
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);
return inp.isPaid();
if ( inp.hasCancelled() )
return false;
return executePayment(ability, inp.getSelected());
}
/* (non-Javadoc)

View File

@@ -1,5 +1,6 @@
package forge.card.cost;
import forge.Singletons;
import forge.control.input.InputPayment;
import forge.control.input.InputSyncronizedBase;
@@ -8,6 +9,14 @@ import forge.control.input.InputSyncronizedBase;
*
*/
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;
boolean bPaid = false;

View File

@@ -71,6 +71,7 @@ public class TargetSelection {
* @param 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.choices = choices;
this.alreadyTargeted = alreadyTargeted;

View File

@@ -47,8 +47,9 @@ public class InputAttack extends InputBase {
private static final long serialVersionUID = 7849903731842214245L;
private final GameState game;
public InputAttack(GameState game0) {
game = game0;
public InputAttack(Player human) {
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;
import forge.Card;
import forge.FThreads;
import forge.Singletons;
import forge.game.player.Player;
import forge.gui.match.CMatchUI;
@@ -33,6 +34,10 @@ import forge.gui.match.CMatchUI;
public abstract class InputBase implements java.io.Serializable, Input {
/** Constant <code>serialVersionUID=-6539552513871194081L</code>. */
private static final long serialVersionUID = -6539552513871194081L;
protected final Player player;
public InputBase(Player player) {
this.player = player;
}
// showMessage() is always the first method called
@Override
@@ -64,4 +69,18 @@ public abstract class InputBase implements java.io.Serializable, Input {
}
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.Singletons;
import forge.control.FControl;
import forge.game.GameState;
import forge.game.phase.CombatUtil;
import forge.game.player.Player;
@@ -48,14 +47,13 @@ public class InputBlock extends InputBase {
private Card currentAttacker = null;
private final HashMap<Card, List<Card>> allBlocking = new HashMap<Card, List<Card>>();
private final Player defender;
/**
* TODO: Write javadoc for Constructor.
* @param priority
*/
public InputBlock(Player priority) {
defender = priority;
public InputBlock(Player human) {
super(human);
}
/**
@@ -98,14 +96,14 @@ public class InputBlock extends InputBase {
@Override
public final void selectButtonOK() {
final GameState game = Singletons.getModel().getGame();
if (CombatUtil.finishedMandatoryBlocks(game.getCombat(), defender)) {
if (CombatUtil.finishedMandatoryBlocks(game.getCombat(), player)) {
// Done blocking
ButtonUtil.reset();
CombatUtil.orderMultipleCombatants(game.getCombat());
currentAttacker = null;
allBlocking.clear();
FControl.SINGLETON_INSTANCE.getPlayer().getController().passPriority();
passPriority();
}
}
@@ -121,8 +119,8 @@ public class InputBlock extends InputBase {
} else {
Zone zone = Singletons.getModel().getGame().getZoneOf(card);
// Make sure this card is valid to even be a blocker
if (this.currentAttacker != null && card.isCreature() && card.getController().equals(defender)
&& zone.is(ZoneType.Battlefield, defender)) {
if (this.currentAttacker != null && card.isCreature() && card.getController().equals(player)
&& zone.is(ZoneType.Battlefield, player)) {
// Create a new blockedBy list if it doesn't exist
if (!this.allBlocking.containsKey(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.zone.Zone;
import forge.game.zone.ZoneType;
import forge.gui.match.CMatchUI;
import forge.view.ButtonUtil;
/**
@@ -44,9 +43,9 @@ public class InputCleanup extends InputBase {
* TODO: Write javadoc for Constructor.
* @param game
*/
public InputCleanup(GameState game) {
super();
this.game = game;
public InputCleanup(Player player) {
super(player);
this.game = player.getGame();
}
/** {@inheritDoc} */
@@ -59,7 +58,7 @@ public class InputCleanup extends InputBase {
final int max = active.getMaxHandSize();
// goes to the next phase
if (active.isUnlimitedHandSize() || n <= max || n <= 0 || active != turnOwner) {
active.getController().passPriority();
passPriority();
return;
}
ButtonUtil.disableAll();
@@ -69,7 +68,7 @@ public class InputCleanup extends InputBase {
final StringBuffer sb = new StringBuffer();
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");
CMatchUI.SINGLETON_INSTANCE.showMessage(sb.toString());
showMessage(sb.toString());
}
/** {@inheritDoc} */

View File

@@ -19,6 +19,7 @@ package forge.control.input;
import java.util.Stack;
import forge.Singletons;
import forge.game.GameState;
import forge.game.phase.PhaseHandler;
import forge.game.phase.PhaseType;
@@ -115,38 +116,37 @@ public class InputControl extends MyObservable implements java.io.Serializable {
*/
public final Input getActualInput(GameState game) {
if ( !game.hasMulliganned() )
return new InputMulligan();
return new InputMulligan(Singletons.getModel().getMatch(), Singletons.getControl().getPlayer());
final PhaseHandler handler = game.getPhaseHandler();
final PhaseType phase = handler.getPhase();
final Player playerTurn = handler.getPlayerTurn();
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
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()) {
return null;
return pc.getAutoPassPriorityInput();
}
if (priority == null)
return null;
PlayerController pc = priority.getController();
// Special Inputs needed for the following phases:
final MagicStack stack = game.getStack();
switch (phase) {
case COMBAT_DECLARE_ATTACKERS:
stack.freezeStack();
if (playerTurn.isHuman() && !playerTurn.getController().mayAutoPass(phase)) {
game.getCombat().initiatePossibleDefenders(playerTurn.getOpponents());
return new InputAttack(game);
return new InputAttack(playerTurn);
}
break;
@@ -158,8 +158,7 @@ public class InputControl extends MyObservable implements java.io.Serializable {
}
// noone attacks you
pc.passPriority();
return null;
return pc.getAutoPassPriorityInput();
case CLEANUP:
// discard
@@ -176,10 +175,9 @@ public class InputControl extends MyObservable implements java.io.Serializable {
// Special phases handled above, everything else is handled simply by
// priority
boolean prioritySkip = pc.mayAutoPass(phase) || pc.isUiSetToSkipPhase(playerTurn, phase);
if (game.getStack().isEmpty() && prioritySkip) {
pc.passPriority();
return null;
boolean maySkipPriority = pc.mayAutoPass(phase) || pc.isUiSetToSkipPhase(playerTurn, phase);
if (game.getStack().isEmpty() && maySkipPriority) {
return pc.getAutoPassPriorityInput();
} else
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 forge.Card;
import forge.FThreads;
import forge.Singletons;
import forge.game.player.Player;
import forge.gui.match.CMatchUI;
import forge.view.ButtonUtil;
/**
* TODO: Write javadoc for this type.
*
*/
public class InputLockUI extends InputBase {
private static final long serialVersionUID = 5777143577098597374L;
public class InputLockUI implements Input {
private final AtomicInteger iCall = new AtomicInteger();
public void showMessage() {
@@ -48,4 +50,17 @@ public class InputLockUI extends InputBase {
}
};
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.CardPredicates;
import forge.Singletons;
import forge.FThreads;
import forge.card.ability.AbilityFactory;
import forge.card.spellability.SpellAbility;
import forge.game.GameAction;
import forge.game.GameState;
import forge.game.GameType;
import forge.game.MatchController;
import forge.game.ai.ComputerUtil;
import forge.game.player.AIPlayer;
import forge.game.player.Player;
@@ -53,21 +54,27 @@ public class InputMulligan extends InputBase {
/** Constant <code>serialVersionUID=-8112954303001155622L</code>. */
private static final long serialVersionUID = -8112954303001155622L;
private final MatchController match;
public InputMulligan(MatchController match0, Player humanPlayer) {
super(humanPlayer);
match = match0;
}
/** {@inheritDoc} */
@Override
public final void showMessage() {
ButtonUtil.setButtonText("No", "Yes");
ButtonUtil.enableAllFocusOk();
GameState game = Singletons.getModel().getGame();
GameState game = match.getCurrentGame();
Player startingPlayer = game.getPhaseHandler().getPlayerTurn();
Player localPlayer = Singletons.getControl().getPlayer();
StringBuilder sb = new StringBuilder();
sb.append(startingPlayer.getName()).append(" is going first. ");
if (!startingPlayer.equals(localPlayer)) {
sb.append("You are going ").append(game.getOrdinalPosition(localPlayer, startingPlayer)).append(". ");
if (!startingPlayer.equals(player)) {
sb.append("You are going ").append(game.getOrdinalPosition(player, startingPlayer)).append(". ");
}
sb.append("Do you want to Mulligan?");
@@ -83,10 +90,9 @@ public class InputMulligan extends InputBase {
/** {@inheritDoc} */
@Override
public final void selectButtonCancel() {
final Player humanPlayer = Singletons.getControl().getPlayer();
humanPlayer.doMulligan();
player.doMulligan();
if (humanPlayer.getCardsIn(ZoneType.Hand).isEmpty()) {
if (player.getCardsIn(ZoneType.Hand).isEmpty()) {
this.end();
} else {
ButtonUtil.enableAllFocusOk();
@@ -94,9 +100,9 @@ public class InputMulligan extends InputBase {
}
final void end() {
GameState game = Singletons.getModel().getGame();
// Computer mulligan
final GameState game = match.getCurrentGame();
for (Player p : game.getPlayers()) {
if (!(p instanceof AIPlayer)) {
continue;
@@ -173,17 +179,22 @@ public class InputMulligan extends InputBase {
SDisplayUtil.showTab(nextField);
game.setMulliganned(true);
Singletons.getModel().getMatch().getInput().clearInput();
FThreads.invokeInNewThread( new Runnable() {
@Override
public void run() {
match.getInput().clearInput();
}
});
}
@Override
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 (GuiDialog.confirm(c0, "Use " + c0.getName() + "'s ability?")) {
List<Card> hand = new ArrayList<Card>(c0.getController().getCardsIn(ZoneType.Hand));
for (Card c : hand) {
Singletons.getModel().getGame().getAction().exile(c);
match.getCurrentGame().getAction().exile(c);
}
c0.getController().drawCards(hand.size());
}

View File

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

View File

@@ -30,16 +30,15 @@ public abstract class InputPayManaBase extends InputSyncronizedBase implements I
protected int phyLifeToLose = 0;
protected final Player whoPays;
protected final GameState game;
protected ManaCostBeingPaid manaCost;
protected final SpellAbility saPaidFor;
boolean bPaid = false;
protected InputPayManaBase(final GameState game, SpellAbility saToPayFor) {
this.game = game;
this.whoPays = saToPayFor.getActivatingPlayer();
protected InputPayManaBase(SpellAbility saToPayFor) {
super(saToPayFor.getActivatingPlayer());
this.game = player.getGame();
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
*/
protected void useManaFromPool(String color, ManaCostBeingPaid manaCost) {
ManaPool mp = whoPays.getManaPool();
ManaPool mp = player.getManaPool();
// Convert Color to short String
String manaStr = "1";
@@ -144,7 +143,7 @@ public abstract class InputPayManaBase extends InputSyncronizedBase implements I
*/
protected void activateManaAbility(final Card card, ManaCostBeingPaid manaCost) {
// make sure computer's lands aren't selected
if (card.getController() != whoPays) {
if (card.getController() != player) {
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 :(
for (SpellAbility ma : card.getManaAbility()) {
ma.setActivatingPlayer(whoPays);
ma.setActivatingPlayer(player);
AbilityManaPart m = null;
SpellAbility tail = ma;
while(m == null && tail != null)
@@ -303,11 +302,11 @@ public abstract class InputPayManaBase extends InputSyncronizedBase implements I
public void onManaAbilityPlayed(final SpellAbility saPaymentSrc) {
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();
if ( saPaymentSrc != null )
whoPays.getZone(ZoneType.Battlefield).updateObservers();
player.getZone(ZoneType.Battlefield).updateObservers();
}
protected final void checkIfAlredyPaid() {

View File

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

View File

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

View File

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

View File

@@ -3,7 +3,6 @@ package forge.control.input;
import forge.Card;
import forge.card.mana.ManaCostBeingPaid;
import forge.card.spellability.SpellAbility;
import forge.game.GameState;
import forge.view.ButtonUtil;
public class InputPayManaX extends InputPayManaBase {
@@ -15,9 +14,9 @@ public class InputPayManaX extends InputPayManaBase {
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;
colorX = saPaidFor.hasParam("XColor") ? saPaidFor.getParam("XColor") : "";

View File

@@ -5,6 +5,7 @@ import java.util.List;
import forge.Card;
import forge.GameEntity;
import forge.Singletons;
import forge.view.ButtonUtil;
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) {
super(Singletons.getControl().getPlayer());
selected = new ArrayList<T>();
if (min > 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.error.BugReporter;
import forge.game.player.Player;
public abstract class InputSyncronizedBase extends InputBase implements InputSynchronized {
private static final long serialVersionUID = 8756177361251703052L;
private final CountDownLatch cdlDone;
public InputSyncronizedBase() {
public InputSyncronizedBase(Player player) {
super(player);
cdlDone = new CountDownLatch(1);
}

View File

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

View File

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

View File

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

View File

@@ -29,13 +29,15 @@ public abstract class PlayerController {
private PhaseType autoPassUntil = null;
public PlayerController(GameState game0) {
game = game0;
}
public abstract Input getDefaultInput();
public abstract Input getBlockInput();
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.SpellAbility;
import forge.control.input.Input;
import forge.control.input.InputAutoPassPriority;
import forge.deck.Deck;
import forge.game.GameState;
import forge.game.GameType;
@@ -36,6 +37,7 @@ public class PlayerControllerAi extends PlayerController {
private Input defaultInput;
private Input blockInput;
private Input cleanupInput;
private Input autoPassPriorityInput;
private final AiController brains;
private final AIPlayer player;
@@ -52,9 +54,9 @@ public class PlayerControllerAi extends PlayerController {
brains = new AiController(p, game);
defaultInput = new AiInputCommon(brains);
blockInput = new AiInputBlock(game, getPlayer());
blockInput = new AiInputBlock(getPlayer());
cleanupInput = getDefaultInput();
autoPassPriorityInput = new InputAutoPassPriority(getPlayer());
}
/**
@@ -75,6 +77,11 @@ public class PlayerControllerAi extends PlayerController {
return blockInput;
}
@Override
public Input getAutoPassPriorityInput() {
return autoPassPriorityInput;
}
/**
* @return the cleanupInput
*/

View File

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

View File

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

View File

@@ -26,7 +26,6 @@ import forge.FThreads;
import forge.control.input.Input;
import forge.game.GameState;
import forge.game.MatchController;
import forge.game.ai.AiInput;
import forge.game.phase.PhaseHandler;
import forge.game.player.Player;
@@ -50,35 +49,37 @@ public class InputProxy implements Observer {
@Override
public final synchronized void update(final Observable observable, final Object obj) {
this.input.set(null);
final GameState game = match.getCurrentGame();
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()) {
//System.out.println(" handle begin phase");
FThreads.invokeInNewThread(new Runnable() {
@Override public void run() {
Runnable rPhase = new Runnable() {
@Override
public void run() {
//System.out.printf("\t%s > handle begin phase during %s%n", FThreads.debugGetCurrThreadId(), ph.debugPrintState());
ph.handleBeginPhase();
update(observable, obj);
update(null, null);
}
}, true);
};
FThreads.invokeInNewThread(rPhase);
return;
}
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);
Runnable showMessage = new Runnable() { @Override public void run() { nextInput.showMessage(); } };
this.input.set(nextInput);
Runnable showMessage = new Runnable() {
@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 )
// FThreads.invokeInNewThread(showMessage, true);
// else
FThreads.invokeInEDT(showMessage);
} else if (!ph.isPlayerPriorityAllowed()) {
ph.getPriorityPlayer().getController().passPriority();
}
FThreads.invokeInEDT(showMessage);
}
/**
* <p>