diff --git a/Mage.Client/src/main/java/mage/client/cards/CardsList.form b/Mage.Client/src/main/java/mage/client/cards/CardsList.form
index 38981bdff1..85696ffe74 100644
--- a/Mage.Client/src/main/java/mage/client/cards/CardsList.form
+++ b/Mage.Client/src/main/java/mage/client/cards/CardsList.form
@@ -27,7 +27,7 @@
-
+
@@ -35,7 +35,7 @@
-
+
@@ -57,13 +57,13 @@
-
+
-
-
-
-
-
+
+
+
+
+
diff --git a/Mage.Client/src/main/java/mage/client/cards/CardsList.java b/Mage.Client/src/main/java/mage/client/cards/CardsList.java
index 60556eafef..413b1b5201 100644
--- a/Mage.Client/src/main/java/mage/client/cards/CardsList.java
+++ b/Mage.Client/src/main/java/mage/client/cards/CardsList.java
@@ -200,13 +200,13 @@ public class CardsList extends javax.swing.JPanel implements MouseListener {
jPanel1Layout.setHorizontalGroup(
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup()
- .addComponent(lblCount, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ .addComponent(lblCount, javax.swing.GroupLayout.PREFERRED_SIZE, 81, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
- .addComponent(lblCreatureCount, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ .addComponent(lblCreatureCount, javax.swing.GroupLayout.PREFERRED_SIZE, 100, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
- .addComponent(lblLandCount)
+ .addComponent(lblLandCount, javax.swing.GroupLayout.PREFERRED_SIZE, 75, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
- .addComponent(cbSortBy, javax.swing.GroupLayout.PREFERRED_SIZE, 338, javax.swing.GroupLayout.PREFERRED_SIZE))
+ .addComponent(cbSortBy, 0, 353, Short.MAX_VALUE))
);
jPanel1Layout.setVerticalGroup(
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
@@ -222,14 +222,14 @@ public class CardsList extends javax.swing.JPanel implements MouseListener {
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
- .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 553, Short.MAX_VALUE)
+ .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 639, Short.MAX_VALUE)
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(0, 0, 0)
- .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 321, Short.MAX_VALUE))
+ .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 397, Short.MAX_VALUE))
);
}// //GEN-END:initComponents
diff --git a/Mage.Server.Plugins/Mage.Player.AI/pom.xml b/Mage.Server.Plugins/Mage.Player.AI/pom.xml
index c7b14f1288..e489b8ebb9 100644
--- a/Mage.Server.Plugins/Mage.Player.AI/pom.xml
+++ b/Mage.Server.Plugins/Mage.Player.AI/pom.xml
@@ -15,11 +15,22 @@
Mage Player AI
+
+ log4j
+ log4j
+ 1.2.14
+ jar
+
${project.groupId}
Mage
${project.version}
+
+ ${project.groupId}
+ Mage-Sets
+ ${project.version}
+
diff --git a/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/ComputerPlayer.java b/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/ComputerPlayer.java
index 399f7348d5..f9237e902a 100644
--- a/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/ComputerPlayer.java
+++ b/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/ComputerPlayer.java
@@ -33,11 +33,10 @@ import java.io.IOException;
import java.io.Serializable;
import java.util.*;
import java.util.Map.Entry;
-import java.util.logging.Level;
-import java.util.logging.Logger;
import mage.Constants;
import mage.Constants.CardType;
+import mage.Constants.ColoredManaSymbol;
import mage.Constants.Outcome;
import mage.Constants.RangeOfInfluence;
import mage.Constants.Zone;
@@ -83,6 +82,7 @@ import mage.game.tournament.Tournament;
import mage.player.ai.utils.RateCard;
import mage.players.Player;
import mage.players.PlayerImpl;
+import mage.sets.Sets;
import mage.target.Target;
import mage.target.TargetAmount;
import mage.target.TargetCard;
@@ -93,8 +93,8 @@ import mage.target.common.TargetDiscard;
import mage.target.common.TargetControlledPermanent;
import mage.target.common.TargetCreatureOrPlayerAmount;
import mage.util.Copier;
-import mage.util.Logging;
import mage.util.TreeNode;
+import org.apache.log4j.Logger;
/**
*
@@ -104,7 +104,7 @@ import mage.util.TreeNode;
*/
public class ComputerPlayer> extends PlayerImpl implements Player {
- private final static transient Logger logger = Logging.getLogger(ComputerPlayer.class.getName());
+ private final static transient Logger logger = Logger.getLogger(ComputerPlayer.class);
private transient Map unplayable = new TreeMap();
private transient List playableNonInstant = new ArrayList();
private transient List playableInstant = new ArrayList();
@@ -127,7 +127,7 @@ public class ComputerPlayer> extends PlayerImpl i
@Override
public boolean chooseMulligan(Game game) {
- logger.fine("chooseMulligan");
+ logger.debug("chooseMulligan");
if (hand.size() < 6)
return false;
Set lands = hand.getCards(new FilterLandCard(), game);
@@ -143,8 +143,8 @@ public class ComputerPlayer> extends PlayerImpl i
@Override
public boolean choose(Outcome outcome, Target target, Game game, Map options) {
- if (logger.isLoggable(Level.FINE))
- logger.fine("chooseTarget: " + outcome.toString() + ":" + target.toString());
+ if (logger.isDebugEnabled())
+ logger.debug("chooseTarget: " + outcome.toString() + ":" + target.toString());
UUID opponentId = game.getOpponents(playerId).iterator().next();
if (target instanceof TargetPlayer) {
if (outcome.isGood()) {
@@ -209,8 +209,8 @@ public class ComputerPlayer> extends PlayerImpl i
@Override
public boolean chooseTarget(Outcome outcome, Target target, Ability source, Game game) {
- if (logger.isLoggable(Level.FINE))
- logger.fine("chooseTarget: " + outcome.toString() + ":" + target.toString());
+ if (logger.isDebugEnabled())
+ logger.debug("chooseTarget: " + outcome.toString() + ":" + target.toString());
UUID opponentId = game.getOpponents(playerId).iterator().next();
if (target instanceof TargetPlayer) {
if (outcome.isGood()) {
@@ -303,8 +303,8 @@ public class ComputerPlayer> extends PlayerImpl i
@Override
public boolean chooseTargetAmount(Outcome outcome, TargetAmount target, Ability source, Game game) {
- if (logger.isLoggable(Level.FINE))
- logger.fine("chooseTarget: " + outcome.toString() + ":" + target.toString());
+ if (logger.isDebugEnabled())
+ logger.debug("chooseTarget: " + outcome.toString() + ":" + target.toString());
UUID opponentId = game.getOpponents(playerId).iterator().next();
if (target instanceof TargetCreatureOrPlayerAmount) {
if (game.getPlayer(opponentId).getLife() <= target.getAmountRemaining()) {
@@ -332,7 +332,7 @@ public class ComputerPlayer> extends PlayerImpl i
@Override
public void priority(Game game) {
- logger.fine("priority");
+ logger.debug("priority");
UUID opponentId = game.getOpponents(playerId).iterator().next();
if (game.getActivePlayerId().equals(playerId)) {
if (game.isMainPhase() && game.getStack().isEmpty()) {
@@ -418,7 +418,7 @@ public class ComputerPlayer> extends PlayerImpl i
}
protected void playLand(Game game) {
- logger.fine("playLand");
+ logger.debug("playLand");
Set lands = hand.getCards(new FilterLandCard(), game);
while (lands.size() > 0 && this.landsPlayed < this.landsPerTurn) {
if (lands.size() == 1)
@@ -430,7 +430,7 @@ public class ComputerPlayer> extends PlayerImpl i
}
protected void playALand(Set lands, Game game) {
- logger.fine("playALand");
+ logger.debug("playALand");
//play a land that will allow us to play an unplayable
for (Mana mana: unplayable.keySet()) {
for (Card card: lands) {
@@ -538,19 +538,19 @@ public class ComputerPlayer> extends PlayerImpl i
}
}
}
- if (logger.isLoggable(Level.FINE))
- logger.fine("findPlayables: " + playableInstant.toString() + "---" + playableNonInstant.toString() + "---" + playableAbilities.toString() );
+ if (logger.isDebugEnabled())
+ logger.debug("findPlayables: " + playableInstant.toString() + "---" + playableNonInstant.toString() + "---" + playableAbilities.toString() );
}
@Override
protected ManaOptions getManaAvailable(Game game) {
-// logger.fine("getManaAvailable");
+// logger.debug("getManaAvailable");
return super.getManaAvailable(game);
}
@Override
public boolean playMana(ManaCost unpaid, Game game) {
-// logger.fine("playMana");
+// logger.debug("playMana");
ManaCost cost;
List producers;
if (unpaid instanceof ManaCosts) {
@@ -627,8 +627,14 @@ public class ComputerPlayer> extends PlayerImpl i
}
}
}
- if (score > 0) // score mana producers that produce other types higher
+ if (score > 0) { // score mana producers that produce other mana types and have other uses higher
score += permanent.getAbilities().getManaAbilities(Zone.BATTLEFIELD).size();
+ score += permanent.getAbilities().getActivatedAbilities(Zone.BATTLEFIELD).size();
+ if (!permanent.getCardType().contains(CardType.LAND))
+ score+=2;
+ else if(permanent.getCardType().contains(CardType.CREATURE))
+ score+=2;
+ }
scored.put(permanent, score);
}
return sortByValue(scored);
@@ -652,7 +658,7 @@ public class ComputerPlayer> extends PlayerImpl i
@Override
public boolean playXMana(VariableManaCost cost, Game game) {
- logger.fine("playXMana");
+ logger.debug("playXMana");
//put everything into X
for (Permanent perm: this.getAvailableManaProducers(game)) {
for (ManaAbility ability: perm.getAbilities().getManaAbilities(Zone.BATTLEFIELD)) {
@@ -671,14 +677,14 @@ public class ComputerPlayer> extends PlayerImpl i
@Override
public boolean chooseUse(Outcome outcome, String message, Game game) {
- logger.fine("chooseUse");
+ logger.debug("chooseUse");
//TODO: improve this
return outcome.isGood();
}
@Override
public boolean choose(Outcome outcome, Choice choice, Game game) {
- logger.fine("choose");
+ logger.debug("choose");
//TODO: improve this
choice.setChoice(choice.getChoices().iterator().next());
return true;
@@ -686,7 +692,7 @@ public class ComputerPlayer> extends PlayerImpl i
@Override
public boolean chooseTarget(Cards cards, TargetCard target, Ability source, Game game) {
- logger.fine("chooseTarget");
+ logger.debug("chooseTarget");
//TODO: improve this
//return first match
if (!target.doneChosing()) {
@@ -702,7 +708,7 @@ public class ComputerPlayer> extends PlayerImpl i
@Override
public boolean choose(Cards cards, TargetCard target, Game game) {
- logger.fine("choose");
+ logger.debug("choose");
//TODO: improve this
//return first match
if (!target.doneChosing()) {
@@ -718,7 +724,7 @@ public class ComputerPlayer> extends PlayerImpl i
@Override
public void selectAttackers(Game game) {
- logger.fine("selectAttackers");
+ logger.debug("selectAttackers");
UUID opponentId = game.getCombat().getDefenders().iterator().next();
Attackers attackers = getPotentialAttackers(game);
List blockers = getOpponentBlockers(opponentId, game);
@@ -745,7 +751,7 @@ public class ComputerPlayer> extends PlayerImpl i
@Override
public void selectBlockers(Game game) {
- logger.fine("selectBlockers");
+ logger.debug("selectBlockers");
List blockers = getAvailableBlockers(game);
@@ -761,14 +767,14 @@ public class ComputerPlayer> extends PlayerImpl i
@Override
public int chooseEffect(List rEffects, Game game) {
- logger.fine("chooseEffect");
+ logger.debug("chooseEffect");
//TODO: implement this
return 0;
}
@Override
public TriggeredAbility chooseTriggeredAbility(TriggeredAbilities abilities, Game game) {
- logger.fine("chooseTriggeredAbility");
+ logger.debug("chooseTriggeredAbility");
//TODO: improve this
if (abilities.size() > 0)
return abilities.get(0);
@@ -777,21 +783,21 @@ public class ComputerPlayer> extends PlayerImpl i
@Override
public void assignDamage(int damage, List targets, UUID sourceId, Game game) {
- logger.fine("assignDamage");
+ logger.debug("assignDamage");
//TODO: improve this
game.getPermanent(targets.get(0)).damage(damage, sourceId, game, true, false);
}
@Override
public int getAmount(int min, int max, String message, Game game) {
- logger.fine("getAmount");
+ logger.debug("getAmount");
//TODO: improve this
return min;
}
@Override
protected List getAvailableManaProducers(Game game) {
-// logger.fine("getAvailableManaProducers");
+// logger.debug("getAvailableManaProducers");
return super.getAvailableManaProducers(game);
}
@@ -803,12 +809,73 @@ public class ComputerPlayer> extends PlayerImpl i
@Override
public void construct(Tournament tournament, Deck deck) {
- //TODO: improve this
if (deck.getCards().size() < 40) {
- while (deck.getCards().size() < 40) {
- Card card = deck.getSideboard().iterator().next();
- deck.getCards().add(card);
- deck.getSideboard().remove(card);
+ //pick the top 23 cards
+ if (chosenColors == null) {
+ for (Card card: deck.getSideboard()) {
+ rememberPick(card, RateCard.rateCard(card, null));
+ }
+ chosenColors = chooseDeckColorsIfPossible();
+ }
+ List sortedCards = new ArrayList(deck.getSideboard());
+ Collections.sort(sortedCards, new Comparator() {
+ @Override
+ public int compare(Card o1, Card o2) {
+ Integer score1 = RateCard.rateCard(o1, chosenColors);
+ Integer score2 = RateCard.rateCard(o2, chosenColors);
+ return score2.compareTo(score1);
+ }
+ });
+ int cardNum = 0;
+ while (deck.getCards().size() < 23 && sortedCards.size() > cardNum) {
+ Card card = sortedCards.get(cardNum);
+ if (!card.getSupertype().contains("Basic")) {
+ deck.getCards().add(card);
+ deck.getSideboard().remove(card);
+ }
+ cardNum++;
+ }
+ // add basic lands
+ // TODO: compensate for non basic lands
+ Mana mana = new Mana();
+ for (Card card: deck.getCards()) {
+ mana.add(card.getManaCost().getMana());
+ }
+ double total = mana.getBlack() + mana.getBlue() + mana.getGreen() + mana.getRed() + mana.getWhite();
+ if (mana.getGreen() > 0) {
+ int numGreen = (int) Math.round(mana.getGreen() / total * 17);
+ for (int i = 0; i < numGreen; i++) {
+ Card land = Sets.findCard("Forest", true);
+ deck.getCards().add(land);
+ }
+ }
+ if (mana.getBlack() > 0) {
+ int numBlack = (int) Math.round(mana.getBlack() / total * 17);
+ for (int i = 0; i < numBlack; i++) {
+ Card land = Sets.findCard("Swamp", true);
+ deck.getCards().add(land);
+ }
+ }
+ if (mana.getBlue() > 0) {
+ int numBlue = (int) Math.round(mana.getBlue() / total * 17);
+ for (int i = 0; i < numBlue; i++) {
+ Card land = Sets.findCard("Island", true);
+ deck.getCards().add(land);
+ }
+ }
+ if (mana.getWhite() > 0) {
+ int numWhite = (int) Math.round(mana.getWhite() / total * 17);
+ for (int i = 0; i < numWhite; i++) {
+ Card land = Sets.findCard("Plains", true);
+ deck.getCards().add(land);
+ }
+ }
+ if (mana.getRed() > 0) {
+ int numRed = (int) Math.round(mana.getRed() / total * 17);
+ for (int i = 0; i < numRed; i++) {
+ Card land = Sets.findCard("Mountain", true);
+ deck.getCards().add(land);
+ }
}
}
tournament.submitDeck(playerId, deck);
@@ -926,7 +993,7 @@ public class ComputerPlayer> extends PlayerImpl i
}
protected Attackers getPotentialAttackers(Game game) {
- logger.fine("getAvailableAttackers");
+ logger.debug("getAvailableAttackers");
Attackers attackers = new Attackers();
List creatures = super.getAvailableAttackers(game);
for (Permanent creature: creatures) {
@@ -942,7 +1009,7 @@ public class ComputerPlayer> extends PlayerImpl i
}
protected int combatPotential(Permanent creature, Game game) {
- logger.fine("combatPotential");
+ logger.debug("combatPotential");
if (!creature.canAttack(game))
return 0;
int potential = creature.getPower().getValue();
@@ -955,21 +1022,21 @@ public class ComputerPlayer> extends PlayerImpl i
}
// protected List getAvailableBlockers(Game game) {
-// logger.fine("getAvailableBlockers");
+// logger.debug("getAvailableBlockers");
// FilterCreatureForCombat blockFilter = new FilterCreatureForCombat();
// List blockers = game.getBattlefield().getAllActivePermanents(blockFilter, playerId);
// return blockers;
// }
protected List getOpponentBlockers(UUID opponentId, Game game) {
- logger.fine("getOpponentBlockers");
+ logger.debug("getOpponentBlockers");
FilterCreatureForCombat blockFilter = new FilterCreatureForCombat();
List blockers = game.getBattlefield().getAllActivePermanents(blockFilter, opponentId);
return blockers;
}
protected CombatSimulator simulateAttack(Attackers attackers, List blockers, UUID opponentId, Game game) {
- logger.fine("simulateAttack");
+ logger.debug("simulateAttack");
List attackersList = attackers.getAttackers();
CombatSimulator best = new CombatSimulator();
int bestResult = 0;
@@ -1000,7 +1067,7 @@ public class ComputerPlayer> extends PlayerImpl i
}
protected CombatSimulator simulateBlock(CombatSimulator combat, List blockers, Game game) {
- logger.fine("simulateBlock");
+ logger.debug("simulateBlock");
TreeNode simulations;
@@ -1073,8 +1140,8 @@ public class ComputerPlayer> extends PlayerImpl i
}
protected void logState(Game game) {
- if (logger.isLoggable(Level.FINE))
- logList("computer player hand: ", new ArrayList(hand.getCards(game)));
+ if (logger.isDebugEnabled())
+ logList("computer player " + name + " hand: ", new ArrayList(hand.getCards(game)));
}
protected void logList(String message, List list) {
@@ -1083,7 +1150,7 @@ public class ComputerPlayer> extends PlayerImpl i
for (MageObject object: list) {
sb.append(object.getName()).append(",");
}
- logger.fine(sb.toString());
+ logger.debug(sb.toString());
}
protected void logAbilityList(String message, List list) {
@@ -1092,7 +1159,7 @@ public class ComputerPlayer> extends PlayerImpl i
for (Ability ability: list) {
sb.append(ability.getRule()).append(",");
}
- logger.fine(sb.toString());
+ logger.debug(sb.toString());
}
private void playRemoval(List creatures, Game game) {
@@ -1146,4 +1213,3 @@ public class ComputerPlayer> extends PlayerImpl i
}
}
-
diff --git a/Mage.Server.Plugins/Mage.Player.AIMinimax/src/mage/player/ai/ComputerPlayer2.java b/Mage.Server.Plugins/Mage.Player.AIMinimax/src/mage/player/ai/ComputerPlayer2.java
index ab15d6f8da..7ced3b867f 100644
--- a/Mage.Server.Plugins/Mage.Player.AIMinimax/src/mage/player/ai/ComputerPlayer2.java
+++ b/Mage.Server.Plugins/Mage.Player.AIMinimax/src/mage/player/ai/ComputerPlayer2.java
@@ -44,6 +44,7 @@ import mage.Constants.PhaseStep;
import mage.Constants.RangeOfInfluence;
import mage.abilities.Ability;
import mage.abilities.ActivatedAbility;
+import mage.abilities.common.PassAbility;
import mage.abilities.effects.Effect;
import mage.abilities.effects.SearchEffect;
import mage.cards.Cards;
@@ -161,6 +162,8 @@ public class ComputerPlayer2 extends ComputerPlayer implements
while (actions.peek() != null) {
Ability ability = actions.poll();
this.activateAbility((ActivatedAbility) ability, game);
+ if (logger.isDebugEnabled())
+ logger.debug("activating: " + ability);
if (ability.isUsesStack())
usedStack = true;
}
@@ -174,7 +177,7 @@ public class ComputerPlayer2 extends ComputerPlayer implements
if (!getNextAction(game)) {
Game sim = createSimulation(game);
SimulationNode.resetCount();
- root = new SimulationNode(sim, maxDepth, playerId);
+ root = new SimulationNode(null, sim, maxDepth, playerId);
logger.debug("simulating actions");
addActionsTimed(new FilterAbility());
if (root.children.size() > 0) {
@@ -224,7 +227,7 @@ public class ComputerPlayer2 extends ComputerPlayer implements
if (val < beta) {
beta = val;
bestChild = child;
- if (node.getCombat() == null)
+// if (node.getCombat() == null)
node.setCombat(child.getCombat());
}
}
@@ -232,7 +235,7 @@ public class ComputerPlayer2 extends ComputerPlayer implements
if (val > alpha) {
alpha = val;
bestChild = child;
- if (node.getCombat() == null)
+// if (node.getCombat() == null)
node.setCombat(child.getCombat());
}
}
@@ -272,7 +275,7 @@ public class ComputerPlayer2 extends ComputerPlayer implements
SearchEffect newEffect = getSearchEffect((StackAbility) newAbility);
newEffect.getTarget().addTarget(targetId, newAbility, sim);
sim.getStack().push(newAbility);
- SimulationNode newNode = new SimulationNode(sim, depth, ability.getControllerId());
+ SimulationNode newNode = new SimulationNode(node, sim, depth, ability.getControllerId());
node.children.add(newNode);
newNode.getTargets().add(targetId);
logger.debug("simulating search -- node#: " + SimulationNode.getCount() + "for player: " + sim.getPlayer(ability.getControllerId()).getName());
@@ -381,12 +384,14 @@ public class ComputerPlayer2 extends ComputerPlayer implements
Game sim = game.copy();
if (sim.getPlayer(currentPlayer.getId()).activateAbility((ActivatedAbility) action.copy(), sim)) {
sim.applyEffects();
+ if (checkForRepeatedAction(sim, node, action, currentPlayer.getId()))
+ continue;
if (!sim.isGameOver() && action.isUsesStack()) {
// only pass if the last action uses the stack
sim.getPlayer(currentPlayer.getId()).pass();
sim.getPlayerList().getNext();
}
- SimulationNode newNode = new SimulationNode(sim, action, depth, currentPlayer.getId());
+ SimulationNode newNode = new SimulationNode(node, sim, action, depth, currentPlayer.getId());
if (logger.isDebugEnabled())
logger.debug("simulating -- node #:" + SimulationNode.getCount() + " actions:" + action);
sim.checkStateAndTriggered();
@@ -561,7 +566,7 @@ public class ComputerPlayer2 extends ComputerPlayer implements
}
}
sim.fireEvent(GameEvent.getEvent(GameEvent.EventType.DECLARED_ATTACKERS, playerId, playerId));
- SimulationNode newNode = new SimulationNode(sim, node.getDepth()-1, activePlayerId);
+ SimulationNode newNode = new SimulationNode(node, sim, node.getDepth()-1, activePlayerId);
logger.debug("simulating -- node #:" + SimulationNode.getCount() + " declare attakers");
newNode.setCombat(sim.getCombat());
node.children.add(newNode);
@@ -582,7 +587,7 @@ public class ComputerPlayer2 extends ComputerPlayer implements
}
}
sim.fireEvent(GameEvent.getEvent(GameEvent.EventType.DECLARED_BLOCKERS, playerId, playerId));
- SimulationNode newNode = new SimulationNode(sim, node.getDepth()-1, defenderId);
+ SimulationNode newNode = new SimulationNode(node, sim, node.getDepth()-1, defenderId);
logger.debug("simulating -- node #:" + SimulationNode.getCount() + " declare blockers");
newNode.setCombat(sim.getCombat());
node.children.add(newNode);
@@ -648,4 +653,22 @@ public class ComputerPlayer2 extends ComputerPlayer implements
return sim;
}
+ private boolean checkForRepeatedAction(Game sim, SimulationNode node, Ability action, UUID playerId) {
+ if (action instanceof PassAbility)
+ return false;
+ int val = GameStateEvaluator.evaluate(playerId, sim);
+ SimulationNode test = node.getParent();
+ while (test != null && !test.getPlayerId().equals(playerId)) {
+ test = test.getParent();
+ }
+ if (test != null && test.getAbilities() != null && test.getAbilities().size() == 1) {
+ if (action.toString().equals(test.getAbilities().get(0).toString()) && GameStateEvaluator.evaluate(playerId, sim) == val) {
+ if (logger.isDebugEnabled())
+ logger.debug("found repeated action " + action);
+ return true;
+ }
+ }
+ return false;
+ }
+
}
diff --git a/Mage.Server.Plugins/Mage.Player.AIMinimax/src/mage/player/ai/ComputerPlayer3.java b/Mage.Server.Plugins/Mage.Player.AIMinimax/src/mage/player/ai/ComputerPlayer3.java
index 2e8a2b2dad..5400751b70 100644
--- a/Mage.Server.Plugins/Mage.Player.AIMinimax/src/mage/player/ai/ComputerPlayer3.java
+++ b/Mage.Server.Plugins/Mage.Player.AIMinimax/src/mage/player/ai/ComputerPlayer3.java
@@ -98,6 +98,8 @@ public class ComputerPlayer3 extends ComputerPlayer2 implements Player {
@Override
public void priority(Game game) {
logState(game);
+ if (logger.isDebugEnabled())
+ logger.debug("Game State: Turn-" + game.getTurnNum() + " Step-" + game.getTurn().getStepType() + " ActivePlayer-" + game.getPlayer(game.getActivePlayerId()).getName() + " PriorityPlayer-" + name);
game.firePriorityEvent(playerId);
switch (game.getTurn().getStepType()) {
case UPKEEP:
@@ -154,7 +156,7 @@ public class ComputerPlayer3 extends ComputerPlayer2 implements Player {
currentScore = GameStateEvaluator.evaluate(playerId, game);
Game sim = createSimulation(game);
SimulationNode.resetCount();
- root = new SimulationNode(sim, maxDepth, playerId);
+ root = new SimulationNode(null, sim, maxDepth, playerId);
logger.debug("simulating pre combat actions -----------------------------------------------------------------------------------------");
addActionsTimed(new FilterAbility());
@@ -171,7 +173,7 @@ public class ComputerPlayer3 extends ComputerPlayer2 implements Player {
currentScore = GameStateEvaluator.evaluate(playerId, game);
Game sim = createSimulation(game);
SimulationNode.resetCount();
- root = new SimulationNode(sim, maxDepth, playerId);
+ root = new SimulationNode(null, sim, maxDepth, playerId);
logger.debug("simulating post combat actions ----------------------------------------------------------------------------------------");
addActionsTimed(new FilterAbility());
if (root.children.size() > 0) {
@@ -227,13 +229,13 @@ public class ComputerPlayer3 extends ComputerPlayer2 implements Player {
else {
switch (game.getTurn().getStepType()) {
case PRECOMBAT_MAIN:
- val = -simulateCombat(game, node, depth-1, alpha, beta, false);
+ val = simulateCombat(game, node, depth-1, alpha, beta, false);
break;
case POSTCOMBAT_MAIN:
- val = -simulateCounterAttack(game, node, depth-1, alpha, beta);
+ val = simulateCounterAttack(game, node, depth-1, alpha, beta);
break;
default:
- val = -GameStateEvaluator.evaluate(playerId, game);
+ val = GameStateEvaluator.evaluate(playerId, game);
break;
}
}
@@ -316,6 +318,8 @@ public class ComputerPlayer3 extends ComputerPlayer2 implements Player {
SimulationNode bestNode = null;
SimulatedPlayer attacker = (SimulatedPlayer) game.getPlayer(attackerId);
+ if (logger.isDebugEnabled())
+ logger.debug(attacker.getName() + "'s possible attackers: " + attacker.getAvailableAttackers(game));
for (Combat engagement: attacker.addAttackers(game)) {
if (alpha >= beta) {
logger.debug("simulating -- pruning attackers");
@@ -329,9 +333,9 @@ public class ComputerPlayer3 extends ComputerPlayer2 implements Player {
}
}
sim.fireEvent(GameEvent.getEvent(GameEvent.EventType.DECLARED_ATTACKERS, playerId, playerId));
- SimulationNode newNode = new SimulationNode(sim, depth, game.getActivePlayerId());
+ SimulationNode newNode = new SimulationNode(node, sim, depth, attackerId);
if (logger.isDebugEnabled())
- logger.debug("simulating attack -- node#: " + SimulationNode.getCount());
+ logger.debug("simulating attack for player:" + game.getPlayer(newNode.getPlayerId()).getName());
sim.checkStateAndTriggered();
while (!sim.getStack().isEmpty()) {
sim.getStack().resolve(sim);
@@ -379,6 +383,8 @@ public class ComputerPlayer3 extends ComputerPlayer2 implements Player {
//check if defender is being attacked
if (game.getCombat().isAttacked(defenderId, game)) {
SimulatedPlayer defender = (SimulatedPlayer) game.getPlayer(defenderId);
+ if (logger.isDebugEnabled())
+ logger.debug(defender.getName() + "'s possible blockers: " + defender.getAvailableBlockers(game));
for (Combat engagement: defender.addBlockers(game)) {
if (alpha >= beta) {
logger.debug("simulating -- pruning blockers");
@@ -394,9 +400,9 @@ public class ComputerPlayer3 extends ComputerPlayer2 implements Player {
}
}
sim.fireEvent(GameEvent.getEvent(GameEvent.EventType.DECLARED_BLOCKERS, playerId, playerId));
- SimulationNode newNode = new SimulationNode(sim, depth, defenderId);
+ SimulationNode newNode = new SimulationNode(node, sim, depth, defenderId);
if (logger.isDebugEnabled())
- logger.debug("simulating block -- node#: " + SimulationNode.getCount());
+ logger.debug("simulating block for player:" + game.getPlayer(newNode.getPlayerId()).getName());
sim.checkStateAndTriggered();
while (!sim.getStack().isEmpty()) {
sim.getStack().resolve(sim);
diff --git a/Mage.Server.Plugins/Mage.Player.AIMinimax/src/mage/player/ai/GameStateEvaluator.java b/Mage.Server.Plugins/Mage.Player.AIMinimax/src/mage/player/ai/GameStateEvaluator.java
index f4734f9bbc..90a8b0ec58 100644
--- a/Mage.Server.Plugins/Mage.Player.AIMinimax/src/mage/player/ai/GameStateEvaluator.java
+++ b/Mage.Server.Plugins/Mage.Player.AIMinimax/src/mage/player/ai/GameStateEvaluator.java
@@ -6,8 +6,6 @@
package mage.player.ai;
import java.util.UUID;
-import java.util.logging.Level;
-import java.util.logging.Logger;
import mage.Constants.CardType;
import mage.Constants.Zone;
import mage.abilities.ActivatedAbility;
@@ -18,7 +16,7 @@ import mage.abilities.mana.ManaAbility;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
-import mage.util.Logging;
+import org.apache.log4j.Logger;
/**
*
@@ -29,7 +27,7 @@ import mage.util.Logging;
*/
public class GameStateEvaluator {
- private final static transient Logger logger = Logging.getLogger(GameStateEvaluator.class.getName());
+ private final static transient Logger logger = Logger.getLogger(GameStateEvaluator.class);
private static final int LIFE_FACTOR = Config.evaluatorLifeFactor;
private static final int PERMANENT_FACTOR = Config.evaluatorPermanentFactor;
@@ -56,13 +54,12 @@ public class GameStateEvaluator {
permanentScore *= PERMANENT_FACTOR;
int handScore = 0;
- handScore = 7 - opponent.getHand().size();
- handScore += Math.min(7, player.getHand().size());
+ handScore = player.getHand().size() - opponent.getHand().size();
handScore *= HAND_FACTOR;
int score = lifeScore + permanentScore + handScore;
- if (logger.isLoggable(Level.FINE))
- logger.fine("game state evaluated to- lifeScore:" + lifeScore + " permanentScore:" + permanentScore + " handScore:" + handScore + " total:" + score);
+ if (logger.isDebugEnabled())
+ logger.debug("game state evaluated to- lifeScore:" + lifeScore + " permanentScore:" + permanentScore + " handScore:" + handScore + " total:" + score);
return score;
}
diff --git a/Mage.Server.Plugins/Mage.Player.AIMinimax/src/mage/player/ai/SimulatedPlayer.java b/Mage.Server.Plugins/Mage.Player.AIMinimax/src/mage/player/ai/SimulatedPlayer.java
index 48d4c97903..0bd6533cdf 100644
--- a/Mage.Server.Plugins/Mage.Player.AIMinimax/src/mage/player/ai/SimulatedPlayer.java
+++ b/Mage.Server.Plugins/Mage.Player.AIMinimax/src/mage/player/ai/SimulatedPlayer.java
@@ -221,7 +221,7 @@ public class SimulatedPlayer extends ComputerPlayer {
sim.getStack().push(new StackAbility(ability, playerId));
ability.activate(sim, false);
sim.applyEffects();
- SimulationNode newNode = new SimulationNode(sim, depth, playerId);
+ SimulationNode newNode = new SimulationNode(parent, sim, depth, playerId);
logger.debug("simulating -- node #:" + SimulationNode.getCount() + " triggered ability option");
for (Target target: ability.getTargets()) {
for (UUID targetId: target.getTargets()) {
diff --git a/Mage.Server.Plugins/Mage.Player.AIMinimax/src/mage/player/ai/SimulationNode.java b/Mage.Server.Plugins/Mage.Player.AIMinimax/src/mage/player/ai/SimulationNode.java
index 954e4c7097..002ce922ab 100644
--- a/Mage.Server.Plugins/Mage.Player.AIMinimax/src/mage/player/ai/SimulationNode.java
+++ b/Mage.Server.Plugins/Mage.Player.AIMinimax/src/mage/player/ai/SimulationNode.java
@@ -49,12 +49,14 @@ public class SimulationNode implements Serializable {
protected List abilities;
protected int depth;
protected List children = new ArrayList();
+ protected SimulationNode parent;
protected List targets = new ArrayList();
protected List choices = new ArrayList();
protected UUID playerId;
protected Combat combat;
- public SimulationNode(Game game, int depth, UUID playerId) {
+ public SimulationNode(SimulationNode parent, Game game, int depth, UUID playerId) {
+ this.parent = parent;
this.game = game;
this.depth = depth;
this.playerId = playerId;
@@ -62,13 +64,13 @@ public class SimulationNode implements Serializable {
nodeCount++;
}
- public SimulationNode(Game game, List abilities, int depth, UUID playerId) {
- this(game, depth, playerId);
+ public SimulationNode(SimulationNode parent, Game game, List abilities, int depth, UUID playerId) {
+ this(parent, game, depth, playerId);
this.abilities = abilities;
}
- public SimulationNode(Game game, Ability ability, int depth, UUID playerId) {
- this(game, depth, playerId);
+ public SimulationNode(SimulationNode parent, Game game, Ability ability, int depth, UUID playerId) {
+ this(parent, game, depth, playerId);
this.abilities = new ArrayList();
abilities.add(ability);
}
@@ -97,6 +99,10 @@ public class SimulationNode implements Serializable {
return this.abilities;
}
+ public SimulationNode getParent() {
+ return this.parent;
+ }
+
public List getChildren() {
return this.children;
}
diff --git a/Mage.Server/plugins/mage-player-ai.jar b/Mage.Server/plugins/mage-player-ai.jar
index 4e151620eb..45016d5014 100644
Binary files a/Mage.Server/plugins/mage-player-ai.jar and b/Mage.Server/plugins/mage-player-ai.jar differ
diff --git a/Mage.Server/plugins/mage-player-aiminimax.jar b/Mage.Server/plugins/mage-player-aiminimax.jar
index 6f0d28c6ed..72624ad402 100644
Binary files a/Mage.Server/plugins/mage-player-aiminimax.jar and b/Mage.Server/plugins/mage-player-aiminimax.jar differ
diff --git a/Mage.Server/plugins/mage-tournament-sealed.jar b/Mage.Server/plugins/mage-tournament-sealed.jar
new file mode 100644
index 0000000000..e4a8584a98
Binary files /dev/null and b/Mage.Server/plugins/mage-tournament-sealed.jar differ
diff --git a/Mage.Server/src/main/java/mage/server/tournament/TournamentController.java b/Mage.Server/src/main/java/mage/server/tournament/TournamentController.java
index 9c18fefe56..b01511d9de 100644
--- a/Mage.Server/src/main/java/mage/server/tournament/TournamentController.java
+++ b/Mage.Server/src/main/java/mage/server/tournament/TournamentController.java
@@ -191,7 +191,7 @@ public class TournamentController {
TableManager.getInstance().construct(tableId);
}
- private synchronized void construct(UUID sessionId, Deck deck, int timeout) {
+ private void construct(UUID sessionId, Deck deck, int timeout) {
if (tournamentSessions.containsKey(sessionId))
tournamentSessions.get(sessionId).construct(deck, timeout);
}
diff --git a/Mage/src/mage/Mana.java b/Mage/src/mage/Mana.java
index 2ba46f9fa6..4b31e628dc 100644
--- a/Mage/src/mage/Mana.java
+++ b/Mage/src/mage/Mana.java
@@ -66,6 +66,26 @@ public class Mana implements Comparable, Serializable, Copyable {
any = mana.any;
}
+ public Mana(ColoredManaSymbol color) {
+ switch (color) {
+ case G:
+ green = 1;
+ break;
+ case R:
+ red = 1;
+ break;
+ case B:
+ black = 1;
+ break;
+ case U:
+ blue = 1;
+ break;
+ case W:
+ white = 1;
+ break;
+ }
+ }
+
public static Mana RedMana(int num) {
return new Mana(num, 0, 0, 0, 0, 0, 0);
}
diff --git a/Mage/src/mage/abilities/costs/mana/ColoredManaCost.java b/Mage/src/mage/abilities/costs/mana/ColoredManaCost.java
index ba9d31cc10..155ad4bb7b 100644
--- a/Mage/src/mage/abilities/costs/mana/ColoredManaCost.java
+++ b/Mage/src/mage/abilities/costs/mana/ColoredManaCost.java
@@ -38,6 +38,7 @@ public class ColoredManaCost extends ManaCostImpl {
public ColoredManaCost(ColoredManaSymbol mana) {
this.mana = mana;
+ this.cost = new Mana(mana);
addColoredOption(mana);
}
@@ -46,10 +47,6 @@ public class ColoredManaCost extends ManaCostImpl {
this.mana = cost.mana;
}
- public ColoredManaSymbol getMana() {
- return mana;
- }
-
@Override
public int convertedManaCost() {
return 1;
diff --git a/Mage/src/mage/abilities/costs/mana/GenericManaCost.java b/Mage/src/mage/abilities/costs/mana/GenericManaCost.java
index f4f95d3976..0e1e7aae9b 100644
--- a/Mage/src/mage/abilities/costs/mana/GenericManaCost.java
+++ b/Mage/src/mage/abilities/costs/mana/GenericManaCost.java
@@ -37,6 +37,7 @@ public class GenericManaCost extends ManaCostImpl {
public GenericManaCost(int mana) {
this.mana = mana;
+ this.cost = Mana.ColorlessMana(mana);
this.options.addMana(Mana.ColorlessMana(mana));
}
@@ -45,10 +46,6 @@ public class GenericManaCost extends ManaCostImpl {
this.mana = cost.mana;
}
- public int getMana() {
- return mana;
- }
-
public void setMana(int mana) {
this.mana = mana;
}
diff --git a/Mage/src/mage/abilities/costs/mana/HybridManaCost.java b/Mage/src/mage/abilities/costs/mana/HybridManaCost.java
index 3176a3515b..306466efdf 100644
--- a/Mage/src/mage/abilities/costs/mana/HybridManaCost.java
+++ b/Mage/src/mage/abilities/costs/mana/HybridManaCost.java
@@ -39,6 +39,8 @@ public class HybridManaCost extends ManaCostImpl {
public HybridManaCost(ColoredManaSymbol mana1, ColoredManaSymbol mana2) {
this.mana1 = mana1;
this.mana2 = mana2;
+ this.cost = new Mana(mana1);
+ this.cost.add(new Mana(mana2));
addColoredOption(mana1);
addColoredOption(mana2);
}
@@ -54,14 +56,6 @@ public class HybridManaCost extends ManaCostImpl {
return 1;
}
- public ColoredManaSymbol getMana1() {
- return mana1;
- }
-
- public ColoredManaSymbol getMana2() {
- return mana2;
- }
-
@Override
public boolean isPaid() {
if (paid || isColoredPaid(this.mana1) || isColoredPaid(this.mana2))
diff --git a/Mage/src/mage/abilities/costs/mana/ManaCost.java b/Mage/src/mage/abilities/costs/mana/ManaCost.java
index 8aa0ccc298..31291b1629 100644
--- a/Mage/src/mage/abilities/costs/mana/ManaCost.java
+++ b/Mage/src/mage/abilities/costs/mana/ManaCost.java
@@ -36,6 +36,7 @@ import mage.players.ManaPool;
public interface ManaCost extends Cost {
public int convertedManaCost();
+ public Mana getMana();
public Mana getPayment();
public void assignPayment(ManaPool pool);
@Override
@@ -46,4 +47,5 @@ public interface ManaCost extends Cost {
@Override
public ManaCost copy();
+
}
diff --git a/Mage/src/mage/abilities/costs/mana/ManaCostImpl.java b/Mage/src/mage/abilities/costs/mana/ManaCostImpl.java
index 671092ac60..3729aaeddf 100644
--- a/Mage/src/mage/abilities/costs/mana/ManaCostImpl.java
+++ b/Mage/src/mage/abilities/costs/mana/ManaCostImpl.java
@@ -31,7 +31,6 @@ package mage.abilities.costs.mana;
import java.util.UUID;
import mage.Constants.ColoredManaSymbol;
import mage.Mana;
-import mage.abilities.Ability;
import mage.abilities.costs.CostImpl;
import mage.abilities.mana.ManaOptions;
import mage.game.Game;
@@ -41,6 +40,7 @@ import mage.players.Player;
public abstract class ManaCostImpl> extends CostImpl implements ManaCost {
protected Mana payment;
+ protected Mana cost;
protected ManaOptions options;
@Override
@@ -62,6 +62,11 @@ public abstract class ManaCostImpl> extends CostImpl extends List, ManaCost {
public List getVariableCosts();
public void load(String mana);
public List getSymbols();
+ public Mana getMana();
@Override
public ManaCosts copy();
diff --git a/Mage/src/mage/abilities/costs/mana/ManaCostsImpl.java b/Mage/src/mage/abilities/costs/mana/ManaCostsImpl.java
index eba66b665a..c396e45190 100644
--- a/Mage/src/mage/abilities/costs/mana/ManaCostsImpl.java
+++ b/Mage/src/mage/abilities/costs/mana/ManaCostsImpl.java
@@ -81,6 +81,15 @@ public class ManaCostsImpl extends ArrayList implements M
return total;
}
+ @Override
+ public Mana getMana() {
+ Mana mana = new Mana();
+ for (ManaCost cost: this) {
+ mana.add(cost.getMana());
+ }
+ return mana;
+ }
+
@Override
public Mana getPayment() {
Mana manaTotal = new Mana();
diff --git a/Mage/src/mage/abilities/costs/mana/MonoHybridManaCost.java b/Mage/src/mage/abilities/costs/mana/MonoHybridManaCost.java
index 732007a5cf..e6c1624c9c 100644
--- a/Mage/src/mage/abilities/costs/mana/MonoHybridManaCost.java
+++ b/Mage/src/mage/abilities/costs/mana/MonoHybridManaCost.java
@@ -39,6 +39,8 @@ public class MonoHybridManaCost extends ManaCostImpl {
public MonoHybridManaCost(ColoredManaSymbol mana) {
this.mana = mana;
+ this.cost = new Mana(mana);
+ this.cost.add(Mana.ColorlessMana(2));
addColoredOption(mana);
options.add(Mana.ColorlessMana(2));
}
@@ -54,10 +56,6 @@ public class MonoHybridManaCost extends ManaCostImpl {
return 2;
}
- public ColoredManaSymbol getMana() {
- return mana;
- }
-
@Override
public boolean isPaid() {
if (paid || isColoredPaid(this.mana))
diff --git a/Mage/src/mage/abilities/costs/mana/VariableManaCost.java b/Mage/src/mage/abilities/costs/mana/VariableManaCost.java
index 80e9fb6438..94aece97b4 100644
--- a/Mage/src/mage/abilities/costs/mana/VariableManaCost.java
+++ b/Mage/src/mage/abilities/costs/mana/VariableManaCost.java
@@ -43,6 +43,7 @@ public class VariableManaCost extends ManaCostImpl implements
public VariableManaCost() {
this(1);
+ this.cost = new Mana();
options.add(new Mana());
}
diff --git a/Mage/src/mage/game/draft/DraftImpl.java b/Mage/src/mage/game/draft/DraftImpl.java
index 64bcece061..a1804fddb6 100644
--- a/Mage/src/mage/game/draft/DraftImpl.java
+++ b/Mage/src/mage/game/draft/DraftImpl.java
@@ -58,7 +58,7 @@ public abstract class DraftImpl> implements Draft {
protected int boosterNum = 0;
protected int cardNum = 0;
protected TimingOption timing;
- protected int[] times = {40, 40, 35, 30, 25, 25, 20, 20, 15, 10, 10, 5, 5, 5, 5};
+ protected int[] times = {75, 70, 65, 60, 55, 50, 45, 40, 35, 30, 25, 20, 15, 10, 5};
protected transient TableEventSource tableEventSource = new TableEventSource();
protected transient PlayerQueryEventSource playerQueryEventSource = new PlayerQueryEventSource();
diff --git a/Mage/src/mage/game/draft/DraftPlayer.java b/Mage/src/mage/game/draft/DraftPlayer.java
index 0e7bbbb9c2..671d262fa5 100644
--- a/Mage/src/mage/game/draft/DraftPlayer.java
+++ b/Mage/src/mage/game/draft/DraftPlayer.java
@@ -28,6 +28,7 @@
package mage.game.draft;
+import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import mage.cards.Card;
@@ -68,12 +69,16 @@ public class DraftPlayer {
public void addPick(Card card) {
deck.getSideboard().add(card);
- booster.remove(card);
+ synchronized(booster) {
+ booster.remove(card);
+ }
picking = false;
}
public void openBooster(ExpansionSet set) {
- booster = set.createBooster();
+ synchronized(booster) {
+ booster = set.createBooster();
+ }
}
public void setBooster(List booster) {
@@ -81,7 +86,9 @@ public class DraftPlayer {
}
public List getBooster() {
- return booster;
+ synchronized(booster) {
+ return new ArrayList(booster);
+ }
}
public void setPicking() {
diff --git a/Mage/src/mage/game/permanent/PermanentImpl.java b/Mage/src/mage/game/permanent/PermanentImpl.java
index ad7e09c8c7..44856bd24a 100644
--- a/Mage/src/mage/game/permanent/PermanentImpl.java
+++ b/Mage/src/mage/game/permanent/PermanentImpl.java
@@ -104,6 +104,11 @@ public abstract class PermanentImpl> extends CardImpl
this.attachedTo = permanent.attachedTo;
}
+ @Override
+ public String toString() {
+ return this.name + "-" + this.expansionSetCode;
+ }
+
@Override
public void reset(Game game) {
// this.controllerId = ownerId;
diff --git a/Mage/src/mage/game/tournament/TournamentImpl.java b/Mage/src/mage/game/tournament/TournamentImpl.java
index fd75633b11..6c48e4ebee 100644
--- a/Mage/src/mage/game/tournament/TournamentImpl.java
+++ b/Mage/src/mage/game/tournament/TournamentImpl.java
@@ -228,9 +228,15 @@ public abstract class TournamentImpl implements Tournament {
public void construct() {
tableEventSource.fireTableEvent(EventType.CONSTRUCT);
- for (TournamentPlayer player: players.values()) {
+ for (final TournamentPlayer player: players.values()) {
player.setConstructing();
- player.getPlayer().construct(this, player.getDeck());
+ new Thread(
+ new Runnable() {
+ public void run() {
+ player.getPlayer().construct(TournamentImpl.this, player.getDeck());
+ }
+ }
+ ).start();
}
synchronized(this) {
while (!isDoneConstructing()) {