mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-20 12:48:00 +00:00
- Started working on the full split card face creation in CardFactory (mostly works, but some parts need modification to work correctly).
- Merge: merge the latest trunk into Splitcards.
This commit is contained in:
@@ -1110,6 +1110,8 @@ public class AbilityUtils {
|
||||
if (paid) {
|
||||
unpaidCommand = paidCommand;
|
||||
}
|
||||
ability.setActivatingPlayer(payer);
|
||||
ability.setTarget(sa.getTarget());
|
||||
GameActionUtil.payCostDuringAbilityResolve(payer, ability, cost, paidCommand, unpaidCommand, sa, game);
|
||||
waitForInput = true; // wait for the human input
|
||||
break; // multiple human players are not supported
|
||||
|
||||
@@ -25,6 +25,7 @@ import forge.card.spellability.SpellAbility;
|
||||
import forge.card.spellability.Target;
|
||||
import forge.card.staticability.StaticAbility;
|
||||
import forge.game.ai.ComputerUtilCard;
|
||||
import forge.game.ai.ComputerUtilCost;
|
||||
import forge.game.ai.ComputerUtilMana;
|
||||
import forge.game.phase.CombatUtil;
|
||||
import forge.game.phase.PhaseHandler;
|
||||
@@ -46,7 +47,13 @@ public class AttachAi extends SpellAbilityAi {
|
||||
final Card source = sa.getSourceCard();
|
||||
|
||||
if (abCost != null) {
|
||||
// No Aura spells have Additional Costs
|
||||
// AI currently disabled for these costs
|
||||
if (!ComputerUtilCost.checkSacrificeCost(ai, abCost, source)) {
|
||||
return false;
|
||||
}
|
||||
if (!ComputerUtilCost.checkLifeCost(ai, abCost, source, 4, null)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// prevent run-away activations - first time will always return true
|
||||
@@ -991,10 +998,12 @@ public class AttachAi extends SpellAbilityAi {
|
||||
if (!CardUtil.isStackingKeyword(keyword) && card.hasKeyword(keyword)) {
|
||||
return false;
|
||||
}
|
||||
final boolean evasive = (keyword.endsWith("Unblockable") || keyword.equals("Fear")
|
||||
final boolean evasive = (keyword.equals("Unblockable") || keyword.equals("Fear")
|
||||
|| keyword.equals("Intimidate") || keyword.equals("Shadow")
|
||||
|| keyword.equals("Flying") || keyword.equals("Horsemanship")
|
||||
|| keyword.endsWith("walk"));
|
||||
|| keyword.endsWith("walk") || keyword.equals("CARDNAME can't be blocked except by Walls.")
|
||||
|| keyword.equals("All creatures able to block CARDNAME do so.")
|
||||
|| keyword.equals("CARDNAME can't be blocked by more than one creature."));
|
||||
// give evasive keywords to creatures that can attack and deal damage
|
||||
if (evasive) {
|
||||
if (card.getNetCombatDamage() <= 0
|
||||
|
||||
@@ -77,6 +77,13 @@ public class ControlGainAi extends SpellAbilityAi {
|
||||
|
||||
// if Defined, then don't worry about targeting
|
||||
if (tgt == null) {
|
||||
if (sa.hasParam("AllValid")) {
|
||||
List<Card> tgtCards = ai.getOpponent().getCardsIn(ZoneType.Battlefield);
|
||||
tgtCards = AbilityUtils.filterListByType(tgtCards, sa.getParam("AllValid"), sa);
|
||||
if (tgtCards.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
tgt.resetTargets();
|
||||
|
||||
@@ -91,7 +91,7 @@ public class DamageAllAi extends SpellAbilityAi {
|
||||
}
|
||||
|
||||
int minGain = 200; // The minimum gain in destroyed creatures
|
||||
if (sa.getPayCosts().isReusuableResource()) {
|
||||
if (sa.getPayCosts() != null && sa.getPayCosts().isReusuableResource()) {
|
||||
minGain = 100;
|
||||
}
|
||||
|
||||
|
||||
@@ -166,7 +166,7 @@ public abstract class PumpAiBase extends SpellAbilityAi {
|
||||
|
||||
final boolean evasive = (keyword.endsWith("Unblockable") || keyword.endsWith("Fear")
|
||||
|| keyword.endsWith("Intimidate") || keyword.endsWith("Shadow")
|
||||
|| keyword.contains("CantBeBlockedBy"));
|
||||
|| keyword.contains("CantBeBlockedBy") || keyword.endsWith("CARDNAME can't be blocked except by Walls."));
|
||||
final boolean combatRelevant = (keyword.endsWith("First Strike") || keyword.contains("Bushido"));
|
||||
// give evasive keywords to creatures that can or do attack
|
||||
if (evasive) {
|
||||
|
||||
@@ -48,7 +48,7 @@ public class RestartGameEffect extends SpellAbilityEffect {
|
||||
playerLibraries.put(p, newLibrary);
|
||||
}
|
||||
|
||||
GameNew.restartGame(game, sa.getActivatingPlayer(), playerLibraries);
|
||||
GameNew.restartGame(Singletons.getModel().getMatch(), game, sa.getActivatingPlayer(), playerLibraries);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
|
||||
@@ -32,6 +32,7 @@ import forge.card.CardRules;
|
||||
import forge.card.CardSplitType;
|
||||
import forge.card.ICardFace;
|
||||
import forge.card.cost.Cost;
|
||||
import forge.card.mana.ManaCost;
|
||||
import forge.card.replacement.ReplacementHandler;
|
||||
import forge.card.spellability.AbilityActivated;
|
||||
import forge.card.spellability.SpellAbility;
|
||||
@@ -359,7 +360,31 @@ public class CardFactory {
|
||||
}
|
||||
if ( st == CardSplitType.Split ) {
|
||||
card.setName(rules.getName());
|
||||
|
||||
// BUILD COMBINED 'Original' SIDE HERE
|
||||
// Combined mana cost
|
||||
ManaCost combinedManaCost = ManaCost.combine(rules.getMainPart().getManaCost(), rules.getOtherPart().getManaCost());
|
||||
card.setManaCost(combinedManaCost);
|
||||
|
||||
// Combined card color
|
||||
CardColor combinedCardColor = new CardColor(card);
|
||||
combinedCardColor.addToCardColor(Color.fromColorSet(rules.getMainPart().getColor()));
|
||||
combinedCardColor.addToCardColor(Color.fromColorSet(rules.getOtherPart().getColor()));
|
||||
ArrayList<CardColor> combinedCardColorArr = new ArrayList<CardColor>();
|
||||
combinedCardColorArr.add(combinedCardColor);
|
||||
card.setColor(combinedCardColorArr);
|
||||
|
||||
// Combined abilities -- DOESN'T WORK AS DESIRED (?)
|
||||
for (String a : rules.getMainPart().getAbilities()) {
|
||||
card.addIntrinsicAbility(a);
|
||||
}
|
||||
for (String a : rules.getOtherPart().getAbilities()) {
|
||||
card.addIntrinsicAbility(a);
|
||||
}
|
||||
|
||||
// Combined text -- CURRENTLY TAKES ORACLE TEXT BECAUSE THE ABILITY TEXT DOESN'T WORK (?)
|
||||
String combinedText = String.format("%s: %s\n%s: %s", rules.getMainPart().getName(), rules.getMainPart().getOracleText(), rules.getOtherPart().getName(), rules.getOtherPart().getOracleText());
|
||||
card.setText(combinedText);
|
||||
}
|
||||
|
||||
return card;
|
||||
|
||||
@@ -3,10 +3,15 @@ package forge.card.cardfactory;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.swing.JOptionPane;
|
||||
|
||||
import forge.Card;
|
||||
import forge.Command;
|
||||
|
||||
import forge.Singletons;
|
||||
import forge.card.cost.Cost;
|
||||
import forge.card.mana.ManaCost;
|
||||
import forge.card.spellability.Ability;
|
||||
import forge.card.spellability.AbilityActivated;
|
||||
import forge.card.spellability.Target;
|
||||
import forge.control.input.Input;
|
||||
@@ -193,5 +198,126 @@ class CardFactoryArtifacts {
|
||||
ability.setStackDescription(sbStack.toString());
|
||||
card.addSpellAbility(ability);
|
||||
} // *************** END ************ END **************************
|
||||
|
||||
|
||||
// *************** START *********** START **************************
|
||||
else if (cardName.equals("Temporal Aperture")) {
|
||||
/*
|
||||
* 5, Tap: Shuffle your library, then reveal the top card. Until end
|
||||
* of turn, for as long as that card remains on top of your library,
|
||||
* play with the top card of your library revealed and you may play
|
||||
* that card without paying its mana cost. (If it has X in its mana
|
||||
* cost, X is 0.)
|
||||
*/
|
||||
final Card[] topCard = new Card[1];
|
||||
|
||||
final Ability freeCast = new Ability(card, ManaCost.ZERO) {
|
||||
|
||||
@Override
|
||||
public boolean canPlay() {
|
||||
final PlayerZone lib = card.getController().getZone(ZoneType.Library);
|
||||
return super.canPlay() && ((lib.size() > 0) && lib.get(0).equals(topCard[0]));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resolve() {
|
||||
final Card freeCard = topCard[0];
|
||||
final Player player = card.getController();
|
||||
if (freeCard != null) {
|
||||
if (freeCard.isLand()) {
|
||||
if (player.canPlayLand(freeCard)) {
|
||||
player.playLand(freeCard);
|
||||
} else {
|
||||
JOptionPane.showMessageDialog(null, "You can't play any more lands this turn.", "",
|
||||
JOptionPane.INFORMATION_MESSAGE);
|
||||
}
|
||||
} else {
|
||||
Singletons.getModel().getGame().getActionPlay().playCardWithoutManaCost(freeCard, player);
|
||||
}
|
||||
} else {
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
sb.append("Error in ").append(cardName).append(". freeCard is null");
|
||||
JOptionPane.showMessageDialog(null, sb.toString(), "", JOptionPane.INFORMATION_MESSAGE);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canPlayAI() {
|
||||
return false;
|
||||
}
|
||||
|
||||
};
|
||||
freeCast.setDescription("Play the previously revealed top card of your library for free.");
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
sb.append(cardName).append(" - play card without paying its mana cost.");
|
||||
freeCast.setStackDescription(sb.toString());
|
||||
|
||||
class AbilityTemporalAperture extends AbilityActivated {
|
||||
public AbilityTemporalAperture(final Card ca, final Cost co, final Target t) {
|
||||
super(ca, co, t);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbilityActivated getCopy() {
|
||||
AbilityActivated res = new AbilityTemporalAperture(getSourceCard(),
|
||||
getPayCosts(), getTarget() == null ? null : new Target(getTarget()));
|
||||
CardFactoryUtil.copySpellAbility(this, res);
|
||||
return res;
|
||||
}
|
||||
|
||||
private static final long serialVersionUID = -7328518969488588777L;
|
||||
|
||||
@Override
|
||||
public void resolve() {
|
||||
final PlayerZone lib = card.getController().getZone(ZoneType.Library);
|
||||
if (lib.size() > 0) {
|
||||
|
||||
// shuffle your library
|
||||
card.getController().shuffle();
|
||||
|
||||
// reveal the top card
|
||||
topCard[0] = lib.get(0);
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
sb.append("Revealed card:\n").append(topCard[0].getName());
|
||||
JOptionPane.showMessageDialog(null, sb.toString(), card.getName(), JOptionPane.PLAIN_MESSAGE);
|
||||
|
||||
card.addSpellAbility(freeCast);
|
||||
card.addExtrinsicKeyword("Play with the top card of your library revealed.");
|
||||
Singletons.getModel().getGame().getEndOfTurn().addUntil(new Command() {
|
||||
private static final long serialVersionUID = -2860753262177388046L;
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
card.removeSpellAbility(freeCast);
|
||||
card.removeExtrinsicKeyword("Play with the top card of your library revealed.");
|
||||
}
|
||||
});
|
||||
}
|
||||
} // resolve
|
||||
|
||||
@Override
|
||||
public boolean canPlayAI() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
final Cost abCost = new Cost(card, "5 T", true);
|
||||
final AbilityActivated ability = new AbilityTemporalAperture(card, abCost, null);
|
||||
|
||||
final StringBuilder sbStack = new StringBuilder();
|
||||
sbStack.append(card).append(" - Shuffle your library, then reveal the top card.");
|
||||
ability.setStackDescription(sbStack.toString());
|
||||
|
||||
final StringBuilder sbDesc = new StringBuilder();
|
||||
sbDesc.append(abCost).append("Shuffle your library, then reveal the top card. ");
|
||||
sbDesc.append("Until end of turn, for as long as that card remains on top of your ");
|
||||
sbDesc.append("library, play with the top card of your library revealed ");
|
||||
sbDesc.append("and you may play that card without paying its mana cost. ");
|
||||
sbDesc.append("(If it has X in its mana cost, X is 0.)");
|
||||
ability.setDescription(sbDesc.toString());
|
||||
|
||||
card.addSpellAbility(ability);
|
||||
} // *************** END ************ END **************************
|
||||
}
|
||||
}
|
||||
|
||||
@@ -373,7 +373,6 @@ public class Cost {
|
||||
}
|
||||
|
||||
public final CostPartMana getCostMana() {
|
||||
// TODO: Change where ChangeCost happens
|
||||
for (final CostPart part : this.costParts) {
|
||||
if (part instanceof CostPartMana) {
|
||||
return (CostPartMana) part;
|
||||
|
||||
@@ -106,7 +106,6 @@ public class InputBlock extends Input {
|
||||
currentAttacker = null;
|
||||
allBlocking.clear();
|
||||
|
||||
stop();
|
||||
FControl.SINGLETON_INSTANCE.getPlayer().getController().passPriority();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,7 +59,6 @@ public class InputCleanup extends Input {
|
||||
// goes to the next phase
|
||||
if (active.isUnlimitedHandSize() || n <= max || n <= 0 || active != turnOwner) {
|
||||
active.getController().passPriority();
|
||||
stop();
|
||||
return;
|
||||
}
|
||||
ButtonUtil.disableAll();
|
||||
|
||||
@@ -25,6 +25,7 @@ import forge.game.phase.PhaseType;
|
||||
import forge.game.player.Player;
|
||||
import forge.game.player.PlayerController;
|
||||
import forge.game.zone.MagicStack;
|
||||
import forge.gui.match.controllers.CMessage;
|
||||
import forge.util.MyObservable;
|
||||
|
||||
/**
|
||||
@@ -65,7 +66,7 @@ public class InputControl extends MyObservable implements java.io.Serializable {
|
||||
*/
|
||||
public final void setInput(final Input in) {
|
||||
boolean isInputEmpty = this.input == null || this.input instanceof InputPassPriority;
|
||||
System.out.println(in.getClass().getName());
|
||||
//System.out.println(in.getClass().getName());
|
||||
if (!this.game.getStack().isResolving() && isInputEmpty) {
|
||||
this.input = in;
|
||||
} else {
|
||||
@@ -134,12 +135,9 @@ public class InputControl extends MyObservable implements java.io.Serializable {
|
||||
* @param update
|
||||
* a boolean.
|
||||
*/
|
||||
public final void resetInput() { resetInput(true); }
|
||||
public final void resetInput(final boolean update) {
|
||||
public final void resetInput() {
|
||||
this.input = null;
|
||||
if (update) {
|
||||
this.updateObservers();
|
||||
}
|
||||
this.updateObservers();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -244,4 +242,19 @@ public class InputControl extends MyObservable implements java.io.Serializable {
|
||||
return pc.getDefaultInput();
|
||||
} // getInput()
|
||||
|
||||
public final void setNewInput(GameState game) {
|
||||
PhaseHandler ph = game.getPhaseHandler();
|
||||
|
||||
final Input tmp = getActualInput();
|
||||
//String message = String.format("%s's %s, priority of %s [%sP] input is %s", ph.getPlayerTurn(), ph.getPhase(), ph.getPriorityPlayer(), ph.isPlayerPriorityAllowed() ? "+" : "-", tmp == null ? "null" : tmp.getClass().getSimpleName());
|
||||
//System.out.println(message);
|
||||
if (tmp != null) {
|
||||
//System.out.println(ph.getPlayerTurn() + "'s " + ph.getPhase() + ", priority of " + ph.getPriorityPlayer() + " @ input is " + tmp.getClass().getName() );
|
||||
CMessage.SINGLETON_INSTANCE.getInputControl().setInput(tmp);
|
||||
} else if (!ph.isPlayerPriorityAllowed()) {
|
||||
// System.out.println("cannot have priority, forced to pass");
|
||||
ph.getPriorityPlayer().getController().passPriority();
|
||||
}
|
||||
}
|
||||
|
||||
} // InputControl
|
||||
|
||||
@@ -174,12 +174,11 @@ public class InputMulligan extends Input {
|
||||
next.initPlane();
|
||||
}
|
||||
|
||||
//Set Field shown to current player.
|
||||
//Set Field shown to current player.
|
||||
VField nextField = CMatchUI.SINGLETON_INSTANCE.getFieldViewFor(next);
|
||||
SDisplayUtil.showTab(nextField);
|
||||
|
||||
game.getPhaseHandler().nextPhase();
|
||||
stop();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -75,7 +75,6 @@ public class InputPassPriority extends Input {
|
||||
@Override
|
||||
public final void selectButtonOK() {
|
||||
FControl.SINGLETON_INSTANCE.getPlayer().getController().passPriority();
|
||||
stop();
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
|
||||
@@ -11,8 +11,6 @@ import java.util.Set;
|
||||
|
||||
import javax.swing.JOptionPane;
|
||||
|
||||
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.base.Predicates;
|
||||
import com.google.common.collect.Iterables;
|
||||
@@ -25,11 +23,13 @@ import forge.CardUtil;
|
||||
import forge.Singletons;
|
||||
import forge.card.trigger.TriggerHandler;
|
||||
import forge.card.trigger.TriggerType;
|
||||
import forge.control.input.Input;
|
||||
import forge.control.input.InputControl;
|
||||
import forge.control.input.InputMulligan;
|
||||
import forge.deck.Deck;
|
||||
import forge.deck.CardPool;
|
||||
import forge.deck.DeckSection;
|
||||
import forge.error.BugReporter;
|
||||
import forge.game.event.FlipCoinEvent;
|
||||
import forge.game.phase.PhaseHandler;
|
||||
import forge.game.phase.PhaseType;
|
||||
@@ -38,9 +38,11 @@ import forge.game.player.LobbyPlayer;
|
||||
import forge.game.player.Player;
|
||||
import forge.game.zone.PlayerZone;
|
||||
import forge.game.zone.ZoneType;
|
||||
import forge.gui.match.controllers.CMessage;
|
||||
import forge.gui.match.views.VAntes;
|
||||
import forge.item.CardPrinted;
|
||||
import forge.item.IPaperCard;
|
||||
import forge.properties.ForgePreferences;
|
||||
import forge.properties.ForgePreferences.FPref;
|
||||
import forge.util.Aggregates;
|
||||
import forge.util.MyRandom;
|
||||
@@ -50,6 +52,45 @@ import forge.util.MyRandom;
|
||||
* All of these methods can and should be static.
|
||||
*/
|
||||
public class GameNew {
|
||||
|
||||
/**
|
||||
* TODO: Write javadoc for this type.
|
||||
*
|
||||
*/
|
||||
public static final class GameInputUpdatesThread extends Thread {
|
||||
private final MatchController match;
|
||||
private final GameState game;
|
||||
private boolean wasChangedRecently;
|
||||
|
||||
/**
|
||||
* TODO: Write javadoc for Constructor.
|
||||
* @param match
|
||||
* @param game
|
||||
*/
|
||||
public GameInputUpdatesThread(MatchController match, GameState game) {
|
||||
this.match = match;
|
||||
this.game = game;
|
||||
}
|
||||
|
||||
public void run(){
|
||||
while(!game.isGameOver()) {
|
||||
boolean needsNewInput = CMessage.SINGLETON_INSTANCE.getInputControl().isValid() == false;
|
||||
if ( needsNewInput ) {
|
||||
match.getInput().setNewInput(game);
|
||||
wasChangedRecently = true;
|
||||
}
|
||||
try {
|
||||
Thread.sleep(wasChangedRecently ? 2 : 40);
|
||||
wasChangedRecently = false;
|
||||
} catch (InterruptedException e) {
|
||||
BugReporter.reportException(e);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static final ForgePreferences preferences = Singletons.getModel().getPreferences();
|
||||
|
||||
private static void preparePlayerLibrary(Player player, final ZoneType zoneType, CardPool secion, boolean canRandomFoil, Random generator) {
|
||||
PlayerZone library = player.getZone(zoneType);
|
||||
@@ -60,7 +101,7 @@ public class GameNew {
|
||||
final Card card = cardPrinted.toForgeCard(player);
|
||||
|
||||
// apply random pictures for cards
|
||||
if (Singletons.getModel().getPreferences().getPrefBoolean(FPref.UI_RANDOM_CARD_ART)) {
|
||||
if (preferences.getPrefBoolean(FPref.UI_RANDOM_CARD_ART)) {
|
||||
final int cntVariants = cardPrinted.getRules().getEditionInfo(cardPrinted.getEdition()).getCopiesCount();
|
||||
if (cntVariants > 1) {
|
||||
card.setRandomPicture(generator.nextInt(cntVariants - 1) + 1);
|
||||
@@ -86,8 +127,8 @@ public class GameNew {
|
||||
* TODO: Accept something like match state as parameter. Match should be aware of players,
|
||||
* their decks and other special starting conditions.
|
||||
*/
|
||||
public static void newGame(final Map<Player, PlayerStartConditions> playersConditions, final GameState game, final boolean canRandomFoil) {
|
||||
Singletons.getModel().getMatch().getInput().clearInput();
|
||||
public static void newGame(final MatchController match, final Map<Player, PlayerStartConditions> playersConditions, final GameState game, final boolean canRandomFoil) {
|
||||
match.getInput().clearInput();
|
||||
|
||||
Card.resetUniqueNumber();
|
||||
// need this code here, otherwise observables fail
|
||||
@@ -97,7 +138,7 @@ public class GameNew {
|
||||
trigHandler.clearDelayedTrigger();
|
||||
|
||||
// friendliness
|
||||
boolean useAnte = Singletons.getModel().getPreferences().getPrefBoolean(FPref.UI_ANTE);
|
||||
boolean useAnte = preferences.getPrefBoolean(FPref.UI_ANTE);
|
||||
final Set<CardPrinted> rAICards = new HashSet<CardPrinted>();
|
||||
|
||||
Map<Player, Set<CardPrinted>> removedAnteCards = new HashMap<Player, Set<CardPrinted>>();
|
||||
@@ -112,8 +153,8 @@ public class GameNew {
|
||||
|
||||
initVariantsZones(player, psc);
|
||||
|
||||
GameType gameType = Singletons.getModel().getMatch().getGameType();
|
||||
boolean isFirstGame = Singletons.getModel().getMatch().getPlayedGames().isEmpty();
|
||||
GameType gameType = match.getGameType();
|
||||
boolean isFirstGame = match.getPlayedGames().isEmpty();
|
||||
boolean hasSideboard = psc.getOriginalDeck().has(DeckSection.Sideboard);
|
||||
boolean canSideBoard = !isFirstGame && gameType.isSideboardingAllowed() && hasSideboard;
|
||||
|
||||
@@ -132,7 +173,7 @@ public class GameNew {
|
||||
preparePlayerLibrary(player, ZoneType.Sideboard, myDeck.get(DeckSection.Sideboard), canRandomFoil, generator);
|
||||
|
||||
// Shuffling
|
||||
if (player instanceof AIPlayer && Singletons.getModel().getPreferences().getPrefBoolean(FPref.UI_SMOOTH_LAND)) {
|
||||
if (player instanceof AIPlayer && preferences.getPrefBoolean(FPref.UI_SMOOTH_LAND)) {
|
||||
// AI may do this instead of shuffling its deck
|
||||
final Iterable<Card> c1 = GameNew.smoothComputerManaCurve(player.getCardsIn(ZoneType.Library));
|
||||
player.getZone(ZoneType.Library).setCards(c1);
|
||||
@@ -174,7 +215,7 @@ public class GameNew {
|
||||
JOptionPane.showMessageDialog(null, ante.toString(), "", JOptionPane.INFORMATION_MESSAGE);
|
||||
}
|
||||
|
||||
GameNew.actuateGame(game, false);
|
||||
GameNew.actuateGame(match, game, false);
|
||||
}
|
||||
|
||||
private static void initVariantsZones(final Player player, final PlayerStartConditions psc) {
|
||||
@@ -243,8 +284,7 @@ public class GameNew {
|
||||
}
|
||||
|
||||
// ultimate of Karn the Liberated
|
||||
public static void restartGame(final GameState game, final Player startingTurn, Map<Player, List<Card>> playerLibraries) {
|
||||
MatchController match = Singletons.getModel().getMatch();
|
||||
public static void restartGame(final MatchController match, final GameState game, final Player startingTurn, Map<Player, List<Card>> playerLibraries) {
|
||||
|
||||
Map<LobbyPlayer, PlayerStartConditions> players = match.getPlayers();
|
||||
Map<Player, PlayerStartConditions> playersConditions = new HashMap<Player, PlayerStartConditions>();
|
||||
@@ -291,7 +331,7 @@ public class GameNew {
|
||||
PhaseHandler phaseHandler = game.getPhaseHandler();
|
||||
phaseHandler.setPlayerTurn(startingTurn);
|
||||
|
||||
GameNew.actuateGame(game, true);
|
||||
GameNew.actuateGame(match, game, true);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -302,10 +342,10 @@ public class GameNew {
|
||||
* newGame, then when all is ready, call this function.
|
||||
* @param isRestartedGame Whether the actuated game is the first start or a restart
|
||||
*/
|
||||
private static void actuateGame(final GameState game, boolean isRestartedGame) {
|
||||
private static void actuateGame(final MatchController match, final GameState game, boolean isRestartedGame) {
|
||||
if (!isRestartedGame) {
|
||||
// Deciding which cards go to ante
|
||||
if (Singletons.getModel().getPreferences().getPrefBoolean(FPref.UI_ANTE)) {
|
||||
if (preferences.getPrefBoolean(FPref.UI_ANTE)) {
|
||||
final String nl = System.getProperty("line.separator");
|
||||
final StringBuilder msg = new StringBuilder();
|
||||
for (final Player p : game.getPlayers()) {
|
||||
@@ -324,15 +364,24 @@ public class GameNew {
|
||||
JOptionPane.showMessageDialog(null, msg, "Ante", JOptionPane.INFORMATION_MESSAGE);
|
||||
}
|
||||
|
||||
GameOutcome lastGameOutcome = Singletons.getModel().getMatch().getLastGameOutcome();
|
||||
GameOutcome lastGameOutcome = match.getLastGameOutcome();
|
||||
// Only cut/coin toss if it's the first game of the match
|
||||
if (lastGameOutcome == null) {
|
||||
GameNew.seeWhoPlaysFirstDice();
|
||||
Player goesFirst;
|
||||
Player humanPlayer = Singletons.getControl().getPlayer();
|
||||
boolean isFirstGame = lastGameOutcome == null;
|
||||
if (isFirstGame) {
|
||||
goesFirst = GameNew.seeWhoPlaysFirstDice(game);
|
||||
} else {
|
||||
Player human = Singletons.getControl().getPlayer();
|
||||
Player goesFirst = lastGameOutcome.isWinner(human.getLobbyPlayer()) ? human.getOpponent() : human;
|
||||
setPlayersFirstTurn(goesFirst, false);
|
||||
|
||||
goesFirst = lastGameOutcome.isWinner(humanPlayer.getLobbyPlayer()) ? humanPlayer.getOpponent() : humanPlayer;
|
||||
}
|
||||
String message = goesFirst + ( isFirstGame ? " has won the coin toss." : " lost the last game.");
|
||||
boolean willPlay = goesFirst.getController().getWillPlayOnFirstTurn(message);
|
||||
if ( goesFirst != humanPlayer ) {
|
||||
JOptionPane.showMessageDialog(null, message + "\nComputer Going First", "You are drawing", JOptionPane.INFORMATION_MESSAGE);
|
||||
}
|
||||
goesFirst = willPlay ? goesFirst : goesFirst.getOpponent();
|
||||
game.getPhaseHandler().setPlayerTurn(goesFirst);
|
||||
}
|
||||
|
||||
// Draw <handsize> cards
|
||||
@@ -340,9 +389,20 @@ public class GameNew {
|
||||
p.drawCards(p.getMaxHandSize());
|
||||
}
|
||||
|
||||
|
||||
|
||||
game.getPhaseHandler().setPhaseState(PhaseType.MULLIGAN);
|
||||
InputControl control = Singletons.getModel().getMatch().getInput();
|
||||
control.setInput(new InputMulligan());
|
||||
|
||||
InputControl control = match.getInput();
|
||||
Input tmp = new InputMulligan();
|
||||
control.setInput(tmp);
|
||||
|
||||
|
||||
Thread thGame = new GameInputUpdatesThread(match, game);
|
||||
|
||||
match.getInput().getInput().showMessage();
|
||||
thGame.setName("Game input updater");
|
||||
thGame.start();
|
||||
} // newGame()
|
||||
|
||||
private static String buildFourColumnList(String firstLine, Iterable<CardPrinted> cAnteRemoved) {
|
||||
@@ -418,49 +478,14 @@ public class GameNew {
|
||||
* <p>
|
||||
* seeWhoPlaysFirstCoinToss.
|
||||
* </p>
|
||||
* @return
|
||||
*/
|
||||
private static void seeWhoPlaysFirstDice() {
|
||||
int playerDie = 0;
|
||||
int computerDie = 0;
|
||||
|
||||
while (playerDie == computerDie) {
|
||||
playerDie = MyRandom.getRandom().nextInt(20);
|
||||
computerDie = MyRandom.getRandom().nextInt(20);
|
||||
}
|
||||
|
||||
private static Player seeWhoPlaysFirstDice(final GameState game) {
|
||||
// Play the Flip Coin sound
|
||||
Singletons.getModel().getGame().getEvents().post(new FlipCoinEvent());
|
||||
game.getEvents().post(new FlipCoinEvent());
|
||||
|
||||
List<Player> allPlayers = Singletons.getModel().getGame().getPlayers();
|
||||
setPlayersFirstTurn(allPlayers.get(MyRandom.getRandom().nextInt(allPlayers.size())), true);
|
||||
List<Player> allPlayers = game.getPlayers();
|
||||
return allPlayers.get(MyRandom.getRandom().nextInt(allPlayers.size()));
|
||||
}
|
||||
|
||||
private static void setPlayersFirstTurn(Player goesFirst, boolean firstGame) {
|
||||
StringBuilder sb = new StringBuilder(goesFirst.toString());
|
||||
if (firstGame) {
|
||||
sb.append(" has won the coin toss.");
|
||||
}
|
||||
else {
|
||||
sb.append(" lost the last game.");
|
||||
}
|
||||
if (goesFirst.isHuman()) {
|
||||
if (!humanPlayOrDraw(sb.toString())) {
|
||||
goesFirst = goesFirst.getOpponent();
|
||||
}
|
||||
} else {
|
||||
sb.append("\nComputer Going First");
|
||||
JOptionPane.showMessageDialog(null, sb.toString(), "Play or Draw?", JOptionPane.INFORMATION_MESSAGE);
|
||||
}
|
||||
Singletons.getModel().getGame().getPhaseHandler().setPlayerTurn(goesFirst);
|
||||
} // seeWhoPlaysFirstDice()
|
||||
|
||||
private static boolean humanPlayOrDraw(String message) {
|
||||
final String[] possibleValues = { "Play", "Draw" };
|
||||
|
||||
final Object playDraw = JOptionPane.showOptionDialog(null, message + "\n\nWould you like to play or draw?",
|
||||
"Play or Draw?", JOptionPane.DEFAULT_OPTION, JOptionPane.INFORMATION_MESSAGE, null,
|
||||
possibleValues, possibleValues[0]);
|
||||
|
||||
return !playDraw.equals(1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ import forge.game.player.Player;
|
||||
import forge.game.player.PlayerStatistics;
|
||||
import forge.game.player.PlayerType;
|
||||
import forge.game.zone.ZoneType;
|
||||
import forge.gui.GuiInput;
|
||||
import forge.gui.InputProxy;
|
||||
import forge.gui.framework.EDocID;
|
||||
import forge.gui.framework.SDisplayUtil;
|
||||
import forge.gui.match.CMatchUI;
|
||||
@@ -149,8 +149,7 @@ public class MatchController {
|
||||
Singletons.getControl().changeState(FControl.Screens.MATCH_SCREEN);
|
||||
SDisplayUtil.showTab(EDocID.REPORT_LOG.getDoc());
|
||||
|
||||
// set all observers
|
||||
GuiInput inputControl = CMessage.SINGLETON_INSTANCE.getInputControl();
|
||||
InputProxy inputControl = CMessage.SINGLETON_INSTANCE.getInputControl();
|
||||
input.addObserver(inputControl);
|
||||
currentGame.getStack().addObserver(inputControl);
|
||||
currentGame.getPhaseHandler().addObserver(inputControl);
|
||||
@@ -159,7 +158,7 @@ public class MatchController {
|
||||
// some observers are set in CMatchUI.initMatch
|
||||
|
||||
final boolean canRandomFoil = Singletons.getModel().getPreferences().getPrefBoolean(FPref.UI_RANDOM_FOIL) && gameType == GameType.Constructed;
|
||||
GameNew.newGame(startConditions, currentGame, canRandomFoil);
|
||||
GameNew.newGame(this, startConditions, currentGame, canRandomFoil);
|
||||
|
||||
// TODO restore this functionality!!!
|
||||
//VMatchUI.SINGLETON_INSTANCE.getViewDevMode().getDocument().setVisible(Preferences.DEV_MODE);
|
||||
|
||||
@@ -108,7 +108,6 @@ public class AiInputCommon extends Input {
|
||||
}
|
||||
}
|
||||
player.getController().passPriority();
|
||||
stop();
|
||||
} // getMessage();
|
||||
|
||||
/**
|
||||
@@ -162,7 +161,9 @@ public class AiInputCommon extends Input {
|
||||
sa = computer.getSpellAbilityToPlay();
|
||||
if ( sa == null ) break;
|
||||
//System.out.println("Playing sa: " + sa);
|
||||
ComputerUtil.handlePlayingSpellAbility(player, sa, game);
|
||||
if (!ComputerUtil.handlePlayingSpellAbility(player, sa, game)) {
|
||||
break;
|
||||
}
|
||||
} while ( sa != null );
|
||||
}
|
||||
|
||||
|
||||
@@ -425,14 +425,16 @@ public class ComputerUtil {
|
||||
int count = 0;
|
||||
|
||||
while (count < amount) {
|
||||
final Card prefCard = ComputerUtil.getCardPreference(ai, source, "SacCost", typeList);
|
||||
if (prefCard != null) {
|
||||
sacList.add(prefCard);
|
||||
typeList.remove(prefCard);
|
||||
count++;
|
||||
} else {
|
||||
Card prefCard = ComputerUtil.getCardPreference(ai, source, "SacCost", typeList);
|
||||
if (prefCard == null) {
|
||||
prefCard = ComputerUtilCard.getWorstAI(typeList);
|
||||
}
|
||||
if (prefCard == null) {
|
||||
return null;
|
||||
}
|
||||
sacList.add(prefCard);
|
||||
typeList.remove(prefCard);
|
||||
count++;
|
||||
}
|
||||
return sacList;
|
||||
}
|
||||
|
||||
@@ -1648,13 +1648,13 @@ public class ComputerUtilCombat {
|
||||
public static Map<Card, Integer> distributeAIDamage(final Card attacker, final List<Card> block, int dmgCanDeal, GameEntity defender) {
|
||||
Map<Card, Integer> damageMap = new HashMap<Card, Integer>();
|
||||
|
||||
if (attacker.hasKeyword("You may have CARDNAME assign its combat damage as though it weren't blocked.")
|
||||
|| attacker.hasKeyword("CARDNAME assigns its combat damage as though it weren't blocked.")) {
|
||||
boolean isAttacking = defender != null;
|
||||
|
||||
if (isAttacking && (attacker.hasKeyword("You may have CARDNAME assign its combat damage as though it weren't blocked.")
|
||||
|| attacker.hasKeyword("CARDNAME assigns its combat damage as though it weren't blocked."))) {
|
||||
damageMap.put(null, dmgCanDeal);
|
||||
return damageMap;
|
||||
}
|
||||
|
||||
boolean isAttacking = defender != null;
|
||||
|
||||
final boolean hasTrample = attacker.hasKeyword("Trample");
|
||||
|
||||
|
||||
@@ -21,9 +21,7 @@ import java.util.Observable;
|
||||
import java.util.Observer;
|
||||
|
||||
import forge.Card;
|
||||
import forge.Singletons;
|
||||
import forge.control.input.Input;
|
||||
import forge.game.phase.PhaseHandler;
|
||||
import forge.game.player.Player;
|
||||
import forge.game.zone.PlayerZone;
|
||||
import forge.util.MyObservable;
|
||||
@@ -36,28 +34,16 @@ import forge.util.MyObservable;
|
||||
* @author Forge
|
||||
* @version $Id$
|
||||
*/
|
||||
public class GuiInput extends MyObservable implements Observer {
|
||||
public class InputProxy extends MyObservable implements Observer {
|
||||
|
||||
/** The input. */
|
||||
private Input input;
|
||||
private volatile boolean valid = false;
|
||||
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public final void update(final Observable observable, final Object obj) {
|
||||
PhaseHandler ph = Singletons.getModel().getGame().getPhaseHandler();
|
||||
|
||||
final Input tmp = Singletons.getModel().getMatch().getInput().getActualInput();
|
||||
// System.out.println(ph.getPlayerTurn() + "'s " + ph.getPhase() + ", priority of " + ph.getPriorityPlayer() + " @ actual input is " + ( tmp == null ? "null" : tmp.getClass().getName()) + "; MHP = " + ph.mayPlayerHavePriority() );
|
||||
if (tmp != null) {
|
||||
// System.out.println(ph.getPlayerTurn() + "'s " + ph.getPhase() + ", priority of " + ph.getPriorityPlayer() + " @ input is " + tmp.getClass().getName() );
|
||||
this.setInput(tmp);
|
||||
} else if (!ph.isPlayerPriorityAllowed()) {
|
||||
//System.out.println("cannot have priority, forced to pass");
|
||||
ph.passPriority();
|
||||
}
|
||||
valid = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Setter for the field <code>input</code>.
|
||||
@@ -66,9 +52,10 @@ public class GuiInput extends MyObservable implements Observer {
|
||||
* @param in
|
||||
* a {@link forge.control.input.Input} object.
|
||||
*/
|
||||
private void setInput(final Input in) {
|
||||
public void setInput(final Input in) {
|
||||
valid = true;
|
||||
this.input = in;
|
||||
this.input.showMessage();
|
||||
this.input.showMessage(); // this call may invalidate the input by the time it returns
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -121,10 +108,13 @@ public class GuiInput extends MyObservable implements Observer {
|
||||
return this.getInput().toString();
|
||||
}
|
||||
|
||||
/** @return {@link forge.gui.GuiInput.Input} */
|
||||
/** @return {@link forge.gui.InputProxy.Input} */
|
||||
public Input getInput() {
|
||||
return this.input;
|
||||
}
|
||||
|
||||
|
||||
public boolean isValid() {
|
||||
return valid;
|
||||
}
|
||||
}
|
||||
@@ -28,7 +28,7 @@ import javax.swing.JButton;
|
||||
|
||||
import forge.Command;
|
||||
import forge.game.MatchController;
|
||||
import forge.gui.GuiInput;
|
||||
import forge.gui.InputProxy;
|
||||
import forge.gui.framework.ICDoc;
|
||||
import forge.gui.framework.SDisplayUtil;
|
||||
import forge.gui.match.views.VMessage;
|
||||
@@ -42,7 +42,7 @@ public enum CMessage implements ICDoc {
|
||||
/** */
|
||||
SINGLETON_INSTANCE;
|
||||
|
||||
private GuiInput inputControl = new GuiInput();
|
||||
private InputProxy inputControl = new InputProxy();
|
||||
private Component lastFocusedButton = null;
|
||||
|
||||
private final ActionListener actCancel = new ActionListener() {
|
||||
@@ -87,7 +87,7 @@ public enum CMessage implements ICDoc {
|
||||
*
|
||||
* @return GuiInput
|
||||
*/
|
||||
public GuiInput getInputControl() {
|
||||
public InputProxy getInputControl() {
|
||||
return this.inputControl;
|
||||
}
|
||||
|
||||
|
||||
@@ -214,6 +214,7 @@ public class PlayArea extends CardPanelContainer implements CardPanelMouseListen
|
||||
|
||||
while (deltaCardWidth > 0) {
|
||||
List<CardStackRow> template = tryArrangePilesOfWidth(lands, tokens, creatures, others);
|
||||
//System.out.println(template == null ? "won't fit" : "Fits @ " + cardWidth + " !!! " + template.toString());
|
||||
|
||||
deltaCardWidth = (getCardWidth() - lastGoodCardWidth) / 2;
|
||||
if (template != null) {
|
||||
@@ -258,6 +259,7 @@ public class PlayArea extends CardPanelContainer implements CardPanelMouseListen
|
||||
int x = 0;
|
||||
int y = PlayArea.GUTTER_Y;
|
||||
|
||||
//System.out.println("-------- " + (mirror ? "^" : "_") + " (Positioning ) Card width = " + cardWidth + ". Playarea = " + playAreaWidth + " x " + playAreaHeight );
|
||||
for (final CardStackRow row : template) {
|
||||
int rowBottom = 0;
|
||||
x = PlayArea.GUTTER_X;
|
||||
@@ -277,10 +279,11 @@ public class PlayArea extends CardPanelContainer implements CardPanelMouseListen
|
||||
this.setComponentZOrder(panel, panelIndex);
|
||||
final int panelX = x + (stackPosition * this.stackSpacingX);
|
||||
final int panelY = y + (stackPosition * this.stackSpacingY);
|
||||
//System.out.println("... placinng " + panel.getCard() + " @ (" + panelX + ", " + panelY + ")" );
|
||||
panel.setCardBounds(panelX, panelY, this.getCardWidth(), this.cardHeight);
|
||||
}
|
||||
rowBottom = Math.max(rowBottom, y + stack.getHeight());
|
||||
x += stack.getWidth() + cardSpacingX;
|
||||
x += stack.getWidth();
|
||||
}
|
||||
y = rowBottom;
|
||||
}
|
||||
@@ -291,6 +294,7 @@ public class PlayArea extends CardPanelContainer implements CardPanelMouseListen
|
||||
|
||||
int afterFirstRow;
|
||||
|
||||
//System.out.println( "======== " + ( mirror ? "^" : "_" ) + " (try arrange) Card width = " + cardWidth + ". PlayArea = " + playAreaWidth + " x " + playAreaHeight + " ========");
|
||||
boolean landsFit, tokensFit, creaturesFit;
|
||||
if (this.mirror) {
|
||||
// Wrap all creatures and lands.
|
||||
@@ -354,13 +358,13 @@ public class PlayArea extends CardPanelContainer implements CardPanelMouseListen
|
||||
// card width.
|
||||
final boolean isMinimalSize = this.getCardWidth() == this.getCardWidthMin();
|
||||
|
||||
// System.err.format("[%d] @ %d - Repaint playarea - %s %n", new Date().getTime(), cntRepaints++, mirror ? "MIRROR" : "DIRECT");
|
||||
|
||||
CardStackRow currentRow = new CardStackRow();
|
||||
for (final CardStack stack : sourceRow) {
|
||||
final int rowWidth = currentRow.getWidth();
|
||||
final int stackWidth = stack.getWidth();
|
||||
//System.out.printf("Adding %s (+%dpx), current row is %dpx and has %s \n", stack, stackWidth, rowWidth, currentRow );
|
||||
// If the row is not empty and this stack doesn't fit, add the row.
|
||||
if (rowWidth + stack.getWidth() > this.playAreaWidth && !currentRow.isEmpty() ) {
|
||||
if (rowWidth + stackWidth > this.playAreaWidth && !currentRow.isEmpty() ) {
|
||||
|
||||
// Stop processing if the row is too wide or tall.
|
||||
if (rowWidth > this.playAreaWidth || this.getRowsHeight(template) + sourceRow.getHeight() > this.playAreaHeight) {
|
||||
@@ -388,6 +392,7 @@ public class PlayArea extends CardPanelContainer implements CardPanelMouseListen
|
||||
template.add(insertIndex, currentRow);
|
||||
} else return false;
|
||||
}
|
||||
//System.out.println("... row complete! " + currentRow.getWidth() + "px");
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -409,6 +414,7 @@ public class PlayArea extends CardPanelContainer implements CardPanelMouseListen
|
||||
private int planOthersRow(final List<CardStack> sourceRow, final int firstPile, final List<CardStackRow> template, final CardStackRow rowToFill) {
|
||||
int rowWidth = rowToFill.getWidth();
|
||||
|
||||
// System.out.println("This row has:" + rowToFill + "; want to add:" + sourceRow );
|
||||
for (int i = firstPile; i < sourceRow.size(); i++ ) {
|
||||
CardStack stack = sourceRow.get(i);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user