diff --git a/.gitattributes b/.gitattributes
index 300309331d6..1b0467cbf2a 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -14096,7 +14096,6 @@ 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
-src/main/java/forge/control/input/InputControl.java svneol=native#text/plain
src/main/java/forge/control/input/InputLockUI.java -text
src/main/java/forge/control/input/InputMulligan.java svneol=native#text/plain
src/main/java/forge/control/input/InputPartialParisMulligan.java -text
@@ -14108,6 +14107,7 @@ src/main/java/forge/control/input/InputPayManaSimple.java svneol=native#text/pla
src/main/java/forge/control/input/InputPayManaX.java -text
src/main/java/forge/control/input/InputPayment.java -text
src/main/java/forge/control/input/InputProliferate.java -text
+src/main/java/forge/control/input/InputQueue.java svneol=native#text/plain
src/main/java/forge/control/input/InputSelectCards.java -text
src/main/java/forge/control/input/InputSelectCardsFromList.java -text
src/main/java/forge/control/input/InputSelectMany.java -text
diff --git a/src/main/java/forge/FThreads.java b/src/main/java/forge/FThreads.java
index 60cfb6e4f5d..c9e4b828778 100644
--- a/src/main/java/forge/FThreads.java
+++ b/src/main/java/forge/FThreads.java
@@ -106,12 +106,12 @@ public class FThreads {
Runnable toRun = proc;
if( lockUI ) {
// checkEDT("FThreads.invokeInNewthread", true)
- Singletons.getModel().getMatch().getInput().lock();
+ Singletons.getControl().getMatch().getInput().lock();
toRun = new Runnable() {
@Override
public void run() {
proc.run();
- Singletons.getModel().getMatch().getInput().unlock();
+ Singletons.getControl().getMatch().getInput().unlock();
}
};
}
@@ -119,7 +119,7 @@ public class FThreads {
}
public static void setInputAndWait(InputSynchronized input) {
- Singletons.getModel().getMatch().getInput().setInput(input);
+ Singletons.getControl().getMatch().getInput().setInput(input);
input.awaitLatchRelease();
}
diff --git a/src/main/java/forge/card/ability/effects/RestartGameEffect.java b/src/main/java/forge/card/ability/effects/RestartGameEffect.java
index 74c3de42b4d..1d0572989c3 100644
--- a/src/main/java/forge/card/ability/effects/RestartGameEffect.java
+++ b/src/main/java/forge/card/ability/effects/RestartGameEffect.java
@@ -49,7 +49,7 @@ public class RestartGameEffect extends SpellAbilityEffect {
playerLibraries.put(p, newLibrary);
}
- GameNew.restartGame(Singletons.getModel().getMatch(), game, sa.getActivatingPlayer(), playerLibraries);
+ GameNew.restartGame(Singletons.getControl().getMatch(), game, sa.getActivatingPlayer(), playerLibraries);
}
/* (non-Javadoc)
diff --git a/src/main/java/forge/card/cardfactory/CardFactoryCreatures.java b/src/main/java/forge/card/cardfactory/CardFactoryCreatures.java
index cc655474576..2f930d63ce4 100644
--- a/src/main/java/forge/card/cardfactory/CardFactoryCreatures.java
+++ b/src/main/java/forge/card/cardfactory/CardFactoryCreatures.java
@@ -31,7 +31,6 @@ import forge.FThreads;
import forge.CardPredicates.Presets;
import forge.Command;
import forge.CounterType;
-import forge.Singletons;
import forge.card.cost.Cost;
import forge.card.mana.ManaCost;
import forge.card.spellability.Ability;
@@ -349,8 +348,6 @@ public class CardFactoryCreatures {
} else {
game.getAction().sacrifice(card, null);
}
-
- Singletons.getModel().getMatch().getInput().setInput(target);
}
} // end resolve
}; // end sacOrSac
diff --git a/src/main/java/forge/control/FControl.java b/src/main/java/forge/control/FControl.java
index 80b114d3617..1e814380851 100644
--- a/src/main/java/forge/control/FControl.java
+++ b/src/main/java/forge/control/FControl.java
@@ -33,6 +33,7 @@ import javax.swing.WindowConstants;
import forge.Singletons;
import forge.control.KeyboardShortcuts.Shortcut;
+import forge.game.MatchController;
import forge.game.ai.AiProfileUtil;
import forge.game.player.HumanPlayer;
import forge.gui.SOverlayUtils;
@@ -112,7 +113,7 @@ public enum FControl {
public void windowClosing(final WindowEvent e) {
Singletons.getView().getFrame().setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
- if (!Singletons.getModel().getMatch().getCurrentGame().isGameOver())
+ if (!getMatch().getCurrentGame().isGameOver())
CDock.SINGLETON_INSTANCE.concede();
else {
Singletons.getControl().changeState(FControl.Screens.HOME_SCREEN);
@@ -326,4 +327,12 @@ public enum FControl {
// TODO Auto-generated method stub
return server;
}
+
+ private MatchController match;
+ public MatchController getMatch() {
+ return match;
+ }
+ public void setMatch(MatchController newMatch) {
+ match = newMatch;
+ }
}
diff --git a/src/main/java/forge/control/input/InputAttack.java b/src/main/java/forge/control/input/InputAttack.java
index ed5557a3b84..13df5c1c5da 100644
--- a/src/main/java/forge/control/input/InputAttack.java
+++ b/src/main/java/forge/control/input/InputAttack.java
@@ -102,7 +102,7 @@ public class InputAttack extends InputBase {
game.getPhaseHandler().setCombat(!game.getCombat().getAttackers().isEmpty());
game.getPhaseHandler().setPlayersPriorityPermission(false);
- Singletons.getModel().getMatch().getInput().updateObservers();
+ Singletons.getControl().getMatch().getInput().updateObservers();
}
@Override
diff --git a/src/main/java/forge/control/input/InputBase.java b/src/main/java/forge/control/input/InputBase.java
index fb917b670b4..f48debe7ec3 100644
--- a/src/main/java/forge/control/input/InputBase.java
+++ b/src/main/java/forge/control/input/InputBase.java
@@ -60,12 +60,12 @@ public abstract class InputBase implements java.io.Serializable, Input {
// Removes this input from the stack and releases any latches (in synchronous imports)
protected final void stop() {
// clears a "temp" Input like Input_PayManaCost if there is one
- Singletons.getModel().getMatch().getInput().removeInput(this);
+ Singletons.getControl().getMatch().getInput().removeInput(this);
afterStop(); // sync inputs will release their latch there
}
protected final boolean isActive() {
- return Singletons.getModel().getMatch().getInput().getInput() == this;
+ return Singletons.getControl().getMatch().getInput().getInput() == this;
}
protected void afterStop() { }
diff --git a/src/main/java/forge/control/input/InputLockUI.java b/src/main/java/forge/control/input/InputLockUI.java
index 404a31659d1..e3a053181c3 100644
--- a/src/main/java/forge/control/input/InputLockUI.java
+++ b/src/main/java/forge/control/input/InputLockUI.java
@@ -51,7 +51,7 @@ public class InputLockUI implements Input {
};
protected final boolean isActive() {
- return Singletons.getModel().getMatch().getInput().getInput() == this;
+ return Singletons.getControl().getMatch().getInput().getInput() == this;
}
protected void showMessage(String message) {
diff --git a/src/main/java/forge/control/input/InputControl.java b/src/main/java/forge/control/input/InputQueue.java
similarity index 97%
rename from src/main/java/forge/control/input/InputControl.java
rename to src/main/java/forge/control/input/InputQueue.java
index 0e67e24e4cc..3d2e269da37 100644
--- a/src/main/java/forge/control/input/InputControl.java
+++ b/src/main/java/forge/control/input/InputQueue.java
@@ -41,14 +41,14 @@ import forge.util.MyObservable;
* @author Forge
* @version $Id$
*/
-public class InputControl extends MyObservable implements java.io.Serializable {
+public class InputQueue extends MyObservable implements java.io.Serializable {
/** Constant serialVersionUID=3955194449319994301L. */
private static final long serialVersionUID = 3955194449319994301L;
private final BlockingDeque inputStack = new LinkedBlockingDeque();
private final MatchController match;
- public InputControl(MatchController matchController) {
+ public InputQueue(MatchController matchController) {
match = matchController;
}
diff --git a/src/main/java/forge/game/GameAction.java b/src/main/java/forge/game/GameAction.java
index 7e3574e4cc0..e2b9b0c2763 100644
--- a/src/main/java/forge/game/GameAction.java
+++ b/src/main/java/forge/game/GameAction.java
@@ -724,24 +724,15 @@ public class GameAction {
*/
public final Card moveTo(final ZoneType name, final Card c, final int libPosition) {
// Call specific functions to set PlayerZone, then move onto moveTo
- if (name.equals(ZoneType.Hand)) {
- return this.moveToHand(c);
- } else if (name.equals(ZoneType.Library)) {
- return this.moveToLibrary(c, libPosition);
- } else if (name.equals(ZoneType.Battlefield)) {
- return this.moveToPlay(c);
- } else if (name.equals(ZoneType.Graveyard)) {
- return this.moveToGraveyard(c);
- } else if (name.equals(ZoneType.Exile)) {
- return this.exile(c);
- } else if (name.equals(ZoneType.Ante)) {
- final PlayerZone ante = c.getOwner().getZone(ZoneType.Ante);
- return this.moveTo(ante, c);
- } else if (name.equals(ZoneType.Command)) {
- final PlayerZone command = c.getOwner().getZone(ZoneType.Command);
- return this.moveTo(command, c);
- } else {
- return this.moveToStack(c);
+ switch(name) {
+ case Hand: return this.moveToHand(c);
+ case Library: return this.moveToLibrary(c, libPosition);
+ case Battlefield: return this.moveToPlay(c);
+ case Graveyard: return this.moveToGraveyard(c);
+ case Exile: return this.exile(c);
+ case Ante: return this.moveTo(c.getOwner().getZone(ZoneType.Ante), c);
+ case Command: return this.moveTo(c.getOwner().getZone(ZoneType.Command), c);
+ default: return this.moveToStack(c);
}
}
diff --git a/src/main/java/forge/game/GameNew.java b/src/main/java/forge/game/GameNew.java
index 96fe0092996..672c351132f 100644
--- a/src/main/java/forge/game/GameNew.java
+++ b/src/main/java/forge/game/GameNew.java
@@ -9,8 +9,6 @@ import java.util.Map.Entry;
import java.util.Random;
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;
@@ -19,20 +17,19 @@ import com.google.common.collect.Lists;
import forge.Card;
import forge.CardLists;
import forge.CardPredicates;
-import forge.Singletons;
+import forge.card.trigger.Trigger;
import forge.card.trigger.TriggerHandler;
import forge.card.trigger.TriggerType;
import forge.deck.CardPool;
import forge.deck.Deck;
import forge.deck.DeckSection;
-import forge.game.event.FlipCoinEvent;
import forge.game.phase.PhaseHandler;
import forge.game.player.AIPlayer;
import forge.game.player.LobbyPlayer;
import forge.game.player.Player;
import forge.game.zone.PlayerZone;
import forge.game.zone.ZoneType;
-import forge.gui.match.views.VAntes;
+import forge.gui.GuiDialog;
import forge.item.CardDb;
import forge.item.CardPrinted;
import forge.item.IPaperCard;
@@ -40,6 +37,7 @@ import forge.properties.ForgePreferences;
import forge.properties.ForgePreferences.FPref;
import forge.util.Aggregates;
import forge.util.MyRandom;
+import forge.util.TextUtil;
/**
* Methods for all things related to starting a new game.
@@ -47,7 +45,59 @@ import forge.util.MyRandom;
*/
public class GameNew {
- public static final ForgePreferences preferences = Singletons.getModel().getPreferences();
+ public static final ForgePreferences preferences = forge.Singletons.getModel().getPreferences();
+
+ private static void putCardsOnBattlefield(Player player, Iterable extends IPaperCard> cards) {
+ PlayerZone bf = player.getZone(ZoneType.Battlefield);
+ if (cards != null) {
+ for (final IPaperCard cp : cards) {
+ Card c = cp.toForgeCard(player);
+ c.setOwner(player);
+ bf.add(c, false);
+ c.setSickness(true);
+ c.setStartsGameInPlay(true);
+ c.refreshUniqueNumber();
+ }
+ }
+
+ }
+
+ private static void initVariantsZones(final Player player, final PlayerStartConditions psc) {
+ PlayerZone com = player.getZone(ZoneType.Command);
+
+ // Mainly for avatar, but might find something else here
+ for (final IPaperCard c : psc.getCardsInCommand(player)) {
+ com.add(c.toForgeCard(player), false);
+ }
+
+ // Schemes
+ List sd = new ArrayList();
+ for(IPaperCard cp : psc.getSchemes(player)) sd.add(cp.toForgeCard(player));
+ if ( !sd.isEmpty()) player.setSchemeDeck(sd);
+
+ // Planes
+ List l = new ArrayList();
+ for(IPaperCard cp : psc.getPlanes(player)) l.add(cp.toForgeCard(player));
+ if ( !l.isEmpty() ) player.setPlanarDeck(l);
+ }
+
+ private static Set getRemovedAnteCards(Deck toUse) {
+ final String keywordToRemove = "Remove CARDNAME from your deck before playing if you're not playing for ante.";
+ Set myRemovedAnteCards = new HashSet();
+ for ( Entry ds : toUse ) {
+ for (Entry cp : ds.getValue()) {
+ if ( Iterables.contains(cp.getKey().getRules().getMainPart().getKeywords(), keywordToRemove) )
+ myRemovedAnteCards.add(cp.getKey());
+ }
+ }
+
+ for(CardPrinted cp: myRemovedAnteCards) {
+ for ( Entry ds : toUse ) {
+ ds.getValue().remove(cp, Integer.MAX_VALUE);
+ }
+ }
+ return myRemovedAnteCards;
+ }
private static void preparePlayerLibrary(Player player, final ZoneType zoneType, CardPool secion, boolean canRandomFoil, Random generator) {
PlayerZone library = player.getZone(zoneType);
@@ -79,6 +129,74 @@ public class GameNew {
}
}
+ // this is where the computer cheats
+ // changes AllZone.getComputerPlayer().getZone(Zone.Library)
+
+ /**
+ *
+ * smoothComputerManaCurve.
+ *
+ *
+ * @param in
+ * an array of {@link forge.Card} objects.
+ * @return an array of {@link forge.Card} objects.
+ */
+ private static Iterable smoothComputerManaCurve(final Iterable in) {
+ final List library = Lists.newArrayList(in);
+ CardLists.shuffle(library);
+
+ // remove all land, keep non-basicland in there, shuffled
+ List land = CardLists.filter(library, CardPredicates.Presets.LANDS);
+ for (Card c : land) {
+ if (c.isLand()) {
+ library.remove(c);
+ }
+ }
+
+ try {
+ // mana weave, total of 7 land
+ // The Following have all been reduced by 1, to account for the
+ // computer starting first.
+ library.add(5, land.get(0));
+ library.add(6, land.get(1));
+ library.add(8, land.get(2));
+ library.add(9, land.get(3));
+ library.add(10, land.get(4));
+
+ library.add(12, land.get(5));
+ library.add(15, land.get(6));
+ } catch (final IndexOutOfBoundsException e) {
+ System.err.println("Error: cannot smooth mana curve, not enough land");
+ return in;
+ }
+
+ // add the rest of land to the end of the deck
+ for (int i = 0; i < land.size(); i++) {
+ if (!library.contains(land.get(i))) {
+ library.add(land.get(i));
+ }
+ }
+
+ // check
+ for (int i = 0; i < library.size(); i++) {
+ System.out.println(library.get(i));
+ }
+
+ return library;
+ } // smoothComputerManaCurve()
+
+ private static List getCardsAiCantPlayWell(final Deck toUse) {
+ List result = new ArrayList();
+
+ for ( Entry ds : toUse ) {
+ for (Entry cp : ds.getValue()) {
+ if ( cp.getKey().getRules().getAiHints().getRemAIDecks() )
+ result.add(cp.getKey());
+ }
+ }
+ return result;
+ }
+
/**
* Constructor for new game allowing card lists to be put into play
* immediately, and life totals to be adjusted, for computer and human.
@@ -86,11 +204,11 @@ 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 MatchController match, final Map playersConditions, final GameState game, final boolean canRandomFoil) {
+ public static void newGame(final GameState game, final boolean canRandomFoil) {
Card.resetUniqueNumber();
// need this code here, otherwise observables fail
- forge.card.trigger.Trigger.resetIDs();
+ Trigger.resetIDs();
TriggerHandler trigHandler = game.getTriggerHandler();
trigHandler.clearDelayedTrigger();
@@ -99,23 +217,23 @@ public class GameNew {
final Set rAICards = new HashSet();
Map> removedAnteCards = new HashMap>();
+
+ GameType gameType = game.getType();
+ boolean isFirstGame = game.getMatch().getPlayedGames().isEmpty();
+ boolean canSideBoard = !isFirstGame && gameType.isSideboardingAllowed();
- for (Entry p : playersConditions.entrySet()) {
- final Player player = p.getKey();
- final PlayerStartConditions psc = p.getValue();
+ final Map playersConditions = game.getMatch().getPlayers();
+ for (Player player : game.getPlayers()) {
+ final PlayerStartConditions psc = playersConditions.get(player.getLobbyPlayer());
player.setStartingLife(psc.getStartingLife());
player.setMaxHandSize(psc.getStartingHand());
player.setStartingHandSize(psc.getStartingHand());
- putCardsOnBattlefield(player, psc.getCardsOnBattlefield(player));
+ putCardsOnBattlefield(player, psc.getCardsOnBattlefield(player));
initVariantsZones(player, psc);
- GameType gameType = match.getGameType();
- boolean isFirstGame = match.getPlayedGames().isEmpty();
boolean hasSideboard = psc.getOriginalDeck().has(DeckSection.Sideboard);
- boolean canSideBoard = !isFirstGame && gameType.isSideboardingAllowed() && hasSideboard;
-
- if (canSideBoard) {
+ if (canSideBoard && hasSideboard) {
Deck sideboarded = player.getController().sideboard(psc.getCurrentDeck(), gameType);
psc.setCurrentDeck(sideboarded);
} else {
@@ -154,23 +272,23 @@ public class GameNew {
}
if (rAICards.size() > 0) {
- String message = buildFourColumnList("AI deck contains the following cards that it can't play or may be buggy:", rAICards);
+ String message = TextUtil.buildFourColumnList("AI deck contains the following cards that it can't play or may be buggy:", rAICards);
if (GameType.Quest == game.getType() || GameType.Sealed == game.getType() || GameType.Draft == game.getType()) {
// log, but do not visually warn. quest decks are supposedly already vetted by the quest creator,
// sealed and draft decks do not get any AI-unplayable picks but may contain several
// received/picked but unplayable cards in the sideboard.
System.err.println(message);
} else {
- JOptionPane.showMessageDialog(null, message, "", JOptionPane.INFORMATION_MESSAGE);
+ GuiDialog.message(message);
}
}
if (!removedAnteCards.isEmpty()) {
StringBuilder ante = new StringBuilder("The following ante cards were removed:\n\n");
for (Entry> ants : removedAnteCards.entrySet()) {
- ante.append(buildFourColumnList("From the " + ants.getKey().getName() + "'s deck:", ants.getValue()));
+ ante.append(TextUtil.buildFourColumnList("From the " + ants.getKey().getName() + "'s deck:", ants.getValue()));
}
- JOptionPane.showMessageDialog(null, ante.toString(), "", JOptionPane.INFORMATION_MESSAGE);
+ GuiDialog.message(ante.toString());
}
// Deciding which cards go to ante
@@ -186,19 +304,18 @@ public class GameNew {
throw new RuntimeException(p + " library is empty.");
}
game.getGameLog().add("Ante", p + " anted " + ante, 0);
- VAntes.SINGLETON_INSTANCE.addAnteCard(p, ante);
game.getAction().moveTo(ZoneType.Ante, ante);
msg.append(p.getName()).append(" ante: ").append(ante).append(nl);
}
- JOptionPane.showMessageDialog(null, msg, "Ante", JOptionPane.INFORMATION_MESSAGE);
+ GuiDialog.message(msg.toString(), "Ante");
}
- determineFirstTurnPlayer(match.getLastGameOutcome(), game);
-
// Draw cards
for (final Player p1 : game.getPlayers()) {
p1.drawCards(p1.getMaxHandSize());
}
+
+
}
// ultimate of Karn the Liberated
@@ -255,176 +372,9 @@ public class GameNew {
}
}
- /**
- * TODO: Write javadoc for this method.
- * @param match
- * @param game
- */
- private static void determineFirstTurnPlayer(final GameOutcome lastGameOutcome, final GameState game) {
- // Only cut/coin toss if it's the first game of the match
- Player goesFirst;
- Player humanPlayer = Singletons.getControl().getPlayer();
- boolean isFirstGame = lastGameOutcome == null;
- if (isFirstGame) {
- goesFirst = GameNew.seeWhoPlaysFirstDice(game);
- } else {
-
- 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);
- }
-
- private static void initVariantsZones(final Player player, final PlayerStartConditions psc) {
- PlayerZone com = player.getZone(ZoneType.Command);
-
- // Mainly for avatar, but might find something else here
- for (final IPaperCard c : psc.getCardsInCommand(player)) {
- com.add(c.toForgeCard(player), false);
- }
-
- // Schemes
- List sd = new ArrayList();
- for(IPaperCard cp : psc.getSchemes(player)) sd.add(cp.toForgeCard(player));
- if ( !sd.isEmpty()) player.setSchemeDeck(sd);
-
- // Planes
- List l = new ArrayList();
- for(IPaperCard cp : psc.getPlanes(player)) l.add(cp.toForgeCard(player));
- if ( !l.isEmpty() ) player.setPlanarDeck(l);
- }
-
- private static List getCardsAiCantPlayWell(final Deck toUse) {
- List result = new ArrayList();
-
- for ( Entry ds : toUse ) {
- for (Entry cp : ds.getValue()) {
- if ( cp.getKey().getRules().getAiHints().getRemAIDecks() )
- result.add(cp.getKey());
- }
- }
- return result;
- }
-
- private static Set getRemovedAnteCards(Deck toUse) {
- final String keywordToRemove = "Remove CARDNAME from your deck before playing if you're not playing for ante.";
- Set myRemovedAnteCards = new HashSet();
- for ( Entry ds : toUse ) {
- for (Entry cp : ds.getValue()) {
- if ( Iterables.contains(cp.getKey().getRules().getMainPart().getKeywords(), keywordToRemove) )
- myRemovedAnteCards.add(cp.getKey());
- }
- }
-
- for(CardPrinted cp: myRemovedAnteCards) {
- for ( Entry ds : toUse ) {
- ds.getValue().remove(cp, Integer.MAX_VALUE);
- }
- }
- return myRemovedAnteCards;
- }
- private static void putCardsOnBattlefield(Player player, Iterable extends IPaperCard> cards) {
- PlayerZone bf = player.getZone(ZoneType.Battlefield);
- if (cards != null) {
- for (final IPaperCard cp : cards) {
- Card c = cp.toForgeCard(player);
- c.setOwner(player);
- bf.add(c, false);
- c.setSickness(true);
- c.setStartsGameInPlay(true);
- c.refreshUniqueNumber();
- }
- }
-
- }
-
- private static String buildFourColumnList(String firstLine, Iterable cAnteRemoved) {
- StringBuilder sb = new StringBuilder(firstLine);
- int i = 0;
- for(CardPrinted cp: cAnteRemoved) {
- if ( i != 0 ) sb.append(", ");
- if ( i % 4 == 0 ) sb.append("\n");
- sb.append(cp);
- i++;
- }
- return sb.toString();
- }
// this is where the computer cheats
// changes AllZone.getComputerPlayer().getZone(Zone.Library)
- /**
- *
- * smoothComputerManaCurve.
- *
- *
- * @param in
- * an array of {@link forge.Card} objects.
- * @return an array of {@link forge.Card} objects.
- */
- private static Iterable smoothComputerManaCurve(final Iterable in) {
- final List library = Lists.newArrayList(in);
- CardLists.shuffle(library);
-
- // remove all land, keep non-basicland in there, shuffled
- List land = CardLists.filter(library, CardPredicates.Presets.LANDS);
- for (Card c : land) {
- if (c.isLand()) {
- library.remove(c);
- }
- }
-
- try {
- // mana weave, total of 7 land
- // The Following have all been reduced by 1, to account for the
- // computer starting first.
- library.add(5, land.get(0));
- library.add(6, land.get(1));
- library.add(8, land.get(2));
- library.add(9, land.get(3));
- library.add(10, land.get(4));
-
- library.add(12, land.get(5));
- library.add(15, land.get(6));
- } catch (final IndexOutOfBoundsException e) {
- System.err.println("Error: cannot smooth mana curve, not enough land");
- return in;
- }
-
- // add the rest of land to the end of the deck
- for (int i = 0; i < land.size(); i++) {
- if (!library.contains(land.get(i))) {
- library.add(land.get(i));
- }
- }
-
- // check
- for (int i = 0; i < library.size(); i++) {
- System.out.println(library.get(i));
- }
-
- return library;
- } // smoothComputerManaCurve()
-
- // decides who goes first when starting another game, used by newGame()
- /**
- *
- * seeWhoPlaysFirstCoinToss.
- *
- * @return
- */
- private static Player seeWhoPlaysFirstDice(final GameState game) {
- // Play the Flip Coin sound
- game.getEvents().post(new FlipCoinEvent());
-
- List allPlayers = game.getPlayers();
- return allPlayers.get(MyRandom.getRandom().nextInt(allPlayers.size()));
- }
-
}
diff --git a/src/main/java/forge/game/GameState.java b/src/main/java/forge/game/GameState.java
index 6a6f21d2867..2fdf3406165 100644
--- a/src/main/java/forge/game/GameState.java
+++ b/src/main/java/forge/game/GameState.java
@@ -94,19 +94,20 @@ public class GameState {
*/
public GameState(Iterable players2, GameType t, MatchController match0) { /* no more zones to map here */
type = t;
+ match = match0;
List players = new ArrayList();
for (LobbyPlayer p : players2) {
Player pl = p.getPlayer(this);
players.add(pl);
ingamePlayers.add(pl);
}
- match = match0;
+
allPlayers = Collections.unmodifiableList(players);
roIngamePlayers = Collections.unmodifiableList(ingamePlayers);
action = new GameAction(this);
stack = new MagicStack(this);
phaseHandler = new PhaseHandler(this);
-
+
untap = new Untap(this);
upkeep = new Upkeep(this);
cleanup = new Cleanup(this);
@@ -116,10 +117,9 @@ public class GameState {
if ( match0.getGameType() == GameType.Quest)
events.register(Singletons.getModel().getQuest()); // this one listens to player's mulligans ATM
- events.register(Singletons.getControl().getSoundSystem());
events.register(gameLog);
-
}
+
/**
* Gets the players who are still fighting to win.
@@ -455,10 +455,14 @@ public class GameState {
return colorChanger;
}
- public GameAction getAction() {
+ public final GameAction getAction() {
return action;
}
+ public final MatchController getMatch() {
+ return match;
+ }
+
/**
* TODO: Write javadoc for this method.
* @param playerTurn
diff --git a/src/main/java/forge/game/MatchController.java b/src/main/java/forge/game/MatchController.java
index 17ece6f21e1..fba720efdfe 100644
--- a/src/main/java/forge/game/MatchController.java
+++ b/src/main/java/forge/game/MatchController.java
@@ -7,22 +7,24 @@ import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
+import javax.swing.JOptionPane;
+
import forge.Constant.Preferences;
import forge.FThreads;
import forge.Singletons;
import forge.card.trigger.TriggerType;
import forge.control.FControl;
-import forge.control.input.InputControl;
+import forge.control.input.InputQueue;
import forge.deck.Deck;
import forge.error.BugReporter;
-import forge.game.ai.AiProfileUtil;
import forge.game.event.DuelOutcomeEvent;
-import forge.game.player.AIPlayer;
+import forge.game.event.FlipCoinEvent;
import forge.game.player.HumanPlayer;
import forge.game.player.LobbyPlayer;
import forge.game.player.LobbyPlayerHuman;
import forge.game.player.Player;
import forge.game.player.PlayerStatistics;
+import forge.game.zone.ZoneType;
import forge.gui.InputProxy;
import forge.gui.framework.EDocID;
import forge.gui.framework.SDisplayUtil;
@@ -37,6 +39,7 @@ import forge.gui.match.controllers.CStack;
import forge.gui.match.nonsingleton.VField;
import forge.gui.match.views.VAntes;
import forge.properties.ForgePreferences.FPref;
+import forge.util.MyRandom;
/**
* TODO: Write javadoc for this type.
@@ -46,7 +49,7 @@ import forge.properties.ForgePreferences.FPref;
public class MatchController {
private final Map players = new HashMap();
- private GameType gameType = GameType.Constructed;
+ private final GameType gameType;
private int gamesPerMatch = 3;
private int gamesToWinMatch = 2;
@@ -56,10 +59,15 @@ public class MatchController {
private final List gamesPlayed = new ArrayList();
private final List gamesPlayedRo;
- private InputControl input;
+ private InputQueue inputQueue;
- public MatchController() {
+ /**
+ * This should become constructor once.
+ */
+ public MatchController(GameType type, Map map) {
gamesPlayedRo = Collections.unmodifiableList(gamesPlayed);
+ players.putAll(map);
+ gameType = type;
}
/**
@@ -133,7 +141,7 @@ public class MatchController {
*/
public void startRound() {
- input = new InputControl(this);
+ inputQueue = new InputQueue(this);
currentGame = new GameState(players.keySet(), gameType, this);
Map startConditions = new HashMap();
@@ -141,83 +149,16 @@ public class MatchController {
startConditions.put(p, players.get(p.getLobbyPlayer()));
}
- // Set the current AI profile.
- for (Player p : currentGame.getPlayers()) {
- if ( !(p instanceof AIPlayer))
- continue;
- AIPlayer ai = (AIPlayer) p;
-
- String currentAiProfile = Singletons.getModel().getPreferences().getPref(FPref.UI_CURRENT_AI_PROFILE);
- String lastProfileChosen = this.getPlayedGames().isEmpty() ? currentAiProfile : ai.getLobbyPlayer().getAiProfile();
-
- // TODO: implement specific AI profiles for quest mode.
- boolean wantRandomProfile = currentAiProfile.equals(AiProfileUtil.AI_PROFILE_RANDOM_DUEL)
- || (this.getPlayedGames().isEmpty() && currentAiProfile.equals(AiProfileUtil.AI_PROFILE_RANDOM_MATCH));
-
- String profileToSet = wantRandomProfile ? AiProfileUtil.getRandomProfile() : lastProfileChosen;
-
- ai.getLobbyPlayer().setAiProfile(profileToSet);
- System.out.println(String.format("AI profile %s was chosen for the lobby player %s.", ai.getLobbyPlayer().getAiProfile(), ai.getLobbyPlayer().getName()));
- }
-
try {
-
- HumanPlayer localHuman = null;
- for(Player p : currentGame.getPlayers()) {
- if ( p.getLobbyPlayer() != FControl.SINGLETON_INSTANCE.getLobby().getGuiPlayer())
- continue;
- localHuman = (HumanPlayer) p;
- break;
- }
- if (null == localHuman)
- throw new IllegalStateException("Cannot start a game without a human yet!");
-
- FControl.SINGLETON_INSTANCE.setPlayer(localHuman);
-
- // The UI controls should use these game data as models
- CMatchUI.SINGLETON_INSTANCE.initMatch(currentGame.getRegisteredPlayers(), localHuman);
- CDock.SINGLETON_INSTANCE.onGameStarts(currentGame, localHuman);
- CStack.SINGLETON_INSTANCE.setModel(currentGame.getStack());
- CLog.SINGLETON_INSTANCE.setModel(currentGame.getGameLog());
- CCombat.SINGLETON_INSTANCE.setModel(currentGame);
-
- Singletons.getModel().getPreferences().actuateMatchPreferences();
- Singletons.getControl().changeState(FControl.Screens.MATCH_SCREEN);
- SDisplayUtil.showTab(EDocID.REPORT_LOG.getDoc());
-
- // black magic still
- InputProxy inputProxy = CMessage.SINGLETON_INSTANCE.getInputControl();
- inputProxy.setMatch(this);
- input.addObserver(inputProxy);
-
- // models shall notify controllers of changes
- currentGame.getStack().addObserver(inputProxy);
- currentGame.getStack().addObserver(CStack.SINGLETON_INSTANCE);
- currentGame.getPhaseHandler().addObserver(inputProxy);
- currentGame.getGameLog().addObserver(CLog.SINGLETON_INSTANCE);
- // some observers are set in CMatchUI.initMatch
-
-
+ attachUiToMatch(this, FControl.SINGLETON_INSTANCE.getLobby().getGuiPlayer());
final boolean canRandomFoil = Singletons.getModel().getPreferences().getPrefBoolean(FPref.UI_RANDOM_FOIL) && gameType == GameType.Constructed;
- GameNew.newGame(this, startConditions, currentGame, canRandomFoil);
-
+ GameNew.newGame(currentGame, canRandomFoil);
+ determineFirstTurnPlayer(getLastGameOutcome(), currentGame);
+
currentGame.setAge(GameAge.Mulligan);
getInput().clearInput();
- // TODO restore this functionality!!!
- //VMatchUI.SINGLETON_INSTANCE.getViewDevMode().getDocument().setVisible(Preferences.DEV_MODE);
- for (final VField field : VMatchUI.SINGLETON_INSTANCE.getFieldViews()) {
- field.getLblLibrary().setHoverable(Preferences.DEV_MODE);
- }
-
- if (this.getPlayedGames().isEmpty()) {
- VAntes.SINGLETON_INSTANCE.clearAnteCards();
- }
-
- // per player observers were set in CMatchUI.SINGLETON_INSTANCE.initMatch
-
- CMessage.SINGLETON_INSTANCE.updateGameInfo(this);
// Update observers
currentGame.getGameLog().updateObservers();
} catch (Exception e) {
@@ -226,14 +167,56 @@ public class MatchController {
}
- /**
- * This should become constructor once.
- */
- public void initMatch(GameType type, Map map) {
- gamesPlayed.clear();
- players.clear();
- players.putAll(map);
- gameType = type;
+ public static void attachUiToMatch(MatchController match, LobbyPlayerHuman humanLobbyPlayer) {
+ FControl.SINGLETON_INSTANCE.setMatch(match);
+
+ GameState currentGame = match.getCurrentGame();
+ currentGame.getEvents().register(Singletons.getControl().getSoundSystem());
+
+ HumanPlayer localHuman = null;
+ for(Player p : currentGame.getPlayers()) {
+ if ( p.getLobbyPlayer() != humanLobbyPlayer)
+ continue;
+ localHuman = (HumanPlayer) p;
+ break;
+ }
+ if (null == localHuman)
+ throw new IllegalStateException("Cannot start a game without a human yet!");
+
+ FControl.SINGLETON_INSTANCE.setPlayer(localHuman);
+
+ // The UI controls should use these game data as models
+ CMatchUI.SINGLETON_INSTANCE.initMatch(currentGame.getRegisteredPlayers(), localHuman);
+ CDock.SINGLETON_INSTANCE.setModel(currentGame, localHuman);
+ CStack.SINGLETON_INSTANCE.setModel(currentGame.getStack());
+ CLog.SINGLETON_INSTANCE.setModel(currentGame.getGameLog());
+ CCombat.SINGLETON_INSTANCE.setModel(currentGame);
+
+ Singletons.getModel().getPreferences().actuateMatchPreferences();
+ Singletons.getControl().changeState(FControl.Screens.MATCH_SCREEN);
+ SDisplayUtil.showTab(EDocID.REPORT_LOG.getDoc());
+
+ InputProxy inputProxy = CMessage.SINGLETON_INSTANCE.getInputControl();
+ inputProxy.setMatch(match);
+
+ // models shall notify controllers of changes
+ currentGame.getStack().addObserver(inputProxy);
+ currentGame.getStack().addObserver(CStack.SINGLETON_INSTANCE);
+ currentGame.getPhaseHandler().addObserver(inputProxy);
+ currentGame.getGameLog().addObserver(CLog.SINGLETON_INSTANCE);
+ // some observers were set in CMatchUI.initMatch
+
+ // black magic still
+ match.getInput().addObserver(inputProxy);
+
+ VAntes.SINGLETON_INSTANCE.setModel(currentGame.getRegisteredPlayers());
+
+ for (final VField field : VMatchUI.SINGLETON_INSTANCE.getFieldViews()) {
+ field.getLblLibrary().setHoverable(Preferences.DEV_MODE);
+ }
+
+ // per player observers were set in CMatchUI.SINGLETON_INSTANCE.initMatch
+ CMessage.SINGLETON_INSTANCE.updateGameInfo(match);
}
/**
@@ -345,8 +328,8 @@ public class MatchController {
return players;
}
- public final InputControl getInput() {
- return input;
+ public final InputQueue getInput() {
+ return inputQueue;
}
/**
@@ -366,4 +349,44 @@ public class MatchController {
currentGame.setAge(GameAge.Play);
getInput().clearInput();
}
+
+ /**
+ * TODO: Write javadoc for this method.
+ * @param match
+ * @param game
+ */
+ private void determineFirstTurnPlayer(final GameOutcome lastGameOutcome, final GameState game) {
+ // Only cut/coin toss if it's the first game of the match
+ Player goesFirst;
+ Player humanPlayer = Singletons.getControl().getPlayer();
+ boolean isFirstGame = lastGameOutcome == null;
+ if (isFirstGame) {
+ goesFirst = seeWhoPlaysFirstDice(game);
+ } else {
+ 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);
+ }
+
+ // decides who goes first when starting another game, used by newGame()
+ /**
+ *
+ * seeWhoPlaysFirstCoinToss.
+ *
+ * @return
+ */
+ private Player seeWhoPlaysFirstDice(final GameState game) {
+ // Play the Flip Coin sound
+ game.getEvents().post(new FlipCoinEvent());
+
+ List allPlayers = game.getPlayers();
+ return allPlayers.get(MyRandom.getRandom().nextInt(allPlayers.size()));
+ }
+
}
diff --git a/src/main/java/forge/game/ai/AiInputBlock.java b/src/main/java/forge/game/ai/AiInputBlock.java
index 90638e7092a..8d65e48a269 100644
--- a/src/main/java/forge/game/ai/AiInputBlock.java
+++ b/src/main/java/forge/game/ai/AiInputBlock.java
@@ -36,6 +36,6 @@ public class AiInputBlock extends InputBase {
game.getPhaseHandler().setPlayersPriorityPermission(false);
// was not added to stack, so will be replaced by plain update
- Singletons.getModel().getMatch().getInput().updateObservers();
+ Singletons.getControl().getMatch().getInput().updateObservers();
}
}
diff --git a/src/main/java/forge/game/limited/GauntletMini.java b/src/main/java/forge/game/limited/GauntletMini.java
index ae4b9a8bdd0..8888724e4c0 100644
--- a/src/main/java/forge/game/limited/GauntletMini.java
+++ b/src/main/java/forge/game/limited/GauntletMini.java
@@ -21,8 +21,8 @@ import java.util.ArrayList;
import java.util.List;
import javax.swing.SwingUtilities;
-import javax.swing.SwingWorker;
+import forge.FThreads;
import forge.Singletons;
import forge.control.Lobby;
import forge.deck.Deck;
@@ -162,28 +162,19 @@ public class GauntletMini {
}
});
- final SwingWorker