diff --git a/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/ComputerPlayer6.java b/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/ComputerPlayer6.java index bd4ed6b33f..d94fc14445 100644 --- a/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/ComputerPlayer6.java +++ b/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/ComputerPlayer6.java @@ -52,10 +52,8 @@ import mage.game.stack.StackAbility; import mage.game.stack.StackObject; import mage.game.turn.*; import mage.players.Player; -import mage.sets.alarareborn.OfferingToAsha; import mage.target.Target; import mage.target.TargetCard; -import sun.rmi.transport.ObjectTable; import java.io.File; import java.util.*; @@ -86,7 +84,7 @@ public class ComputerPlayer6 extends ComputerPlayer implements public ComputerPlayer6(String name, RangeOfInfluence range, int skill) { super(name, range); maxDepth = skill * 2; - maxThink = skill * 3; + maxThink = skill * 300; maxNodes = Config2.maxNodes; getSuggestedActions(); } @@ -196,14 +194,21 @@ public class ComputerPlayer6 extends ComputerPlayer implements while (actions.peek() != null) { Ability ability = actions.poll(); System.out.println("[" + game.getPlayer(playerId).getName() + "] Action: " + ability.toString()); + if (ability.getTargets().size() > 0) { + Player player = game.getPlayer(ability.getFirstTarget()); + if (player != null) { + System.out.println("targets = " + player.getName()); + } + } this.activateAbility((ActivatedAbility) ability, game); if (ability.isUsesStack()) usedStack = true; - if (!suggested.isEmpty()) { + if (!suggested.isEmpty() && !(ability instanceof PassAbility)) { Iterator it = suggested.iterator(); while (it.hasNext()) { Card card = game.getCard(ability.getSourceId()); String action = it.next(); + System.out.println("action="+action+";card="+card); if (action.equals(card.getName())) { System.out.println("removed from suggested="+action); it.remove(); @@ -484,6 +489,7 @@ public class ComputerPlayer6 extends ComputerPlayer implements logger.debug("simulating -- node #:" + SimulationNode2.getCount() + " actions:" + action); sim.checkStateAndTriggered(); int val = addActions(newNode, depth-1, alpha, beta); + logger.debug("val = " + val); if (!currentPlayer.getId().equals(playerId)) { if (val < beta) { beta = val; @@ -523,7 +529,7 @@ public class ComputerPlayer6 extends ComputerPlayer implements } } if (alpha >= beta) { - //logger.info("simulating -- pruning"); + logger.info("simulating -- pruning"); break; } if (SimulationNode2.nodeCount > maxNodes) { @@ -538,11 +544,21 @@ public class ComputerPlayer6 extends ComputerPlayer implements node.setScore(bestNode.getScore()); } if (!currentPlayer.getId().equals(playerId)) { - //logger.info("returning priority beta: " + beta); + /*if (beta == Integer.MAX_VALUE) { + int val = GameStateEvaluator2.evaluate(playerId, game); + logger.info("returning priority beta: " + val); + return val; + }*/ + logger.info("returning priority beta: " + beta); return beta; } else { - //logger.info("returning priority alpha: " + alpha); + /*if (alpha == Integer.MIN_VALUE) { + int val = GameStateEvaluator2.evaluate(playerId, game); + logger.info("returning priority beta: " + val); + return val; + }*/ + logger.info("returning priority alpha: " + alpha); return alpha; } } diff --git a/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/ComputerPlayer7.java b/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/ComputerPlayer7.java index 8d44881aca..24a88b97c4 100644 --- a/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/ComputerPlayer7.java +++ b/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/ComputerPlayer7.java @@ -56,6 +56,8 @@ public class ComputerPlayer7 extends ComputerPlayer6 implements Player { private static FilterAbility filterLand = new FilterAbility(); private static FilterAbility filterNotLand = new FilterAbility(); + private boolean allowBadMoves; + static { filterLand.getTypes().add(AbilityType.PLAY_LAND); filterLand.setZone(Zone.HAND); @@ -155,7 +157,7 @@ public class ComputerPlayer7 extends ComputerPlayer6 implements Player { if (root.children.size() > 0) { root = root.children.get(0); int bestScore = root.getScore(); - if (bestScore > currentScore) { + if (bestScore > currentScore || allowBadMoves) { actions = new LinkedList(root.abilities); combat = root.combat; } @@ -175,7 +177,7 @@ public class ComputerPlayer7 extends ComputerPlayer6 implements Player { if (root.children.size() > 0) { root = root.children.get(0); int bestScore = root.getScore(); - if (bestScore > currentScore) { + if (bestScore > currentScore || allowBadMoves) { actions = new LinkedList(root.abilities); combat = root.combat; } @@ -222,8 +224,8 @@ public class ComputerPlayer7 extends ComputerPlayer6 implements Player { if (game.getActivePlayerId().equals(playerId)) { if (testScore < currentScore) { // if score at end of step is worse than original score don't check further - logger.debug("simulating -- abandoning check, no immediate benefit"); - val = testScore; + //logger.debug("simulating -- abandoning check, no immediate benefit"); + val = testScore; } else { switch (game.getTurn().getStepType()) { @@ -541,4 +543,8 @@ public class ComputerPlayer7 extends ComputerPlayer6 implements Player { } } + @Override + public void setAllowBadMoves(boolean allowBadMoves) { + this.allowBadMoves = allowBadMoves; + } } diff --git a/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/SimulatedPlayer2.java b/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/SimulatedPlayer2.java index cefc7288dc..1471a3f3cb 100644 --- a/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/SimulatedPlayer2.java +++ b/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/SimulatedPlayer2.java @@ -28,8 +28,6 @@ package mage.player.ai; -import java.util.*; -import java.util.concurrent.ConcurrentLinkedQueue; import mage.abilities.Ability; import mage.abilities.TriggeredAbility; import mage.abilities.common.PassAbility; @@ -44,9 +42,13 @@ import mage.game.combat.Combat; import mage.game.events.GameEvent; import mage.game.permanent.Permanent; import mage.game.stack.StackAbility; +import mage.players.Player; import mage.target.Target; import org.apache.log4j.Logger; +import java.util.*; +import java.util.concurrent.ConcurrentLinkedQueue; + /** * * @author BetaSteward_at_googlemail.com @@ -56,6 +58,7 @@ public class SimulatedPlayer2 extends ComputerPlayer { private final static transient Logger logger = Logger.getLogger(SimulatedPlayer2.class); private boolean isSimulatedPlayer; private transient ConcurrentLinkedQueue allActions; + private boolean forced; private static PassAbility pass = new PassAbility(); private List suggested; @@ -81,19 +84,35 @@ public class SimulatedPlayer2 extends ComputerPlayer { allActions = new ConcurrentLinkedQueue(); Game sim = game.copy(); - simulateOptions(sim, pass); + forced = false; + simulateOptions(sim); ArrayList list = new ArrayList(allActions); Collections.reverse(list); + + if (!forced) { + list.add(pass); + } + + for (Ability a : allActions) { + System.out.println("ability=="+a); + if (a.getTargets().size() > 0) { + Player player = game.getPlayer(a.getFirstTarget()); + if (player != null) { + System.out.println(" target="+player.getName()); + } + } + } + return list; } - protected void simulateOptions(Game game, Ability previousActions) { - allActions.add(previousActions); + protected void simulateOptions(Game game) { List playables = game.getPlayer(playerId).getPlayable(game, isSimulatedPlayer); playables = filterAbilities(game, playables, suggested); for (Ability ability: playables) { List options = game.getPlayer(playerId).getPlayableOptions(ability, game); + options = filterOptions(game, options, ability, suggested); if (options.isEmpty()) { if (ability.getManaCosts().getVariableCosts().size() > 0) { simulateVariableCosts(ability, game); @@ -145,6 +164,7 @@ public class SimulatedPlayer2 extends ComputerPlayer { for (String s : suggested) { if (s.equals(card.getName())) { System.out.println("matched: " + s); + forced = true; filtered.add(ability); } } @@ -155,6 +175,41 @@ public class SimulatedPlayer2 extends ComputerPlayer { return playables; } + protected List filterOptions(Game game, List options, Ability ability, List suggested) { + if (options.isEmpty()) { + return options; + } + if (suggested == null || suggested.isEmpty()) { + return options; + } + List filtered = new ArrayList(); + for (Ability option : options) { + if (option.getTargets().size() > 0 && option.getTargets().get(0).getMaxNumberOfTargets() == 1) { + Card card = game.getCard(ability.getSourceId()); + for (String s : suggested) { + String[] groups = s.split(";"); + System.out.println("s="+s+";groups="+groups.length); + if (groups.length == 2) { + if (groups[0].equals(card.getName()) && groups[1].startsWith("name=")) { + // extract target and compare to suggested + String name = groups[1].split("=")[1]; + Player player = game.getPlayer(option.getFirstTarget()); + if (player != null && name.equals(player.getName())) { + System.out.println("matched(option): " + s); + filtered.add(option); + return filtered; + } else { + System.out.println("not equal UUID for target, player=" + player); + } + } + } + } + } + } + // no option was found + return options; + } + //add a generic mana cost for each amount possible protected void simulateVariableCosts(Ability ability, Game game) { int numAvailable = getAvailableManaProducers(game).size(); diff --git a/Mage.Tests/plugins/mage-player-ai-ma.jar b/Mage.Tests/plugins/mage-player-ai-ma.jar index fe1582fc60..a9a5776116 100644 Binary files a/Mage.Tests/plugins/mage-player-ai-ma.jar and b/Mage.Tests/plugins/mage-player-ai-ma.jar differ diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/damage/LightningBoltTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/damage/LightningBoltTest.java index 08cfcce624..6ff51d7933 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/damage/LightningBoltTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/damage/LightningBoltTest.java @@ -11,14 +11,33 @@ public class LightningBoltTest extends CardTestBase { @Test public void testDamageOpponent() { + System.out.println("TEST: testDamageOpponent"); addCard(Constants.Zone.HAND, playerA, "Mountain"); addCard(Constants.Zone.HAND, playerA, "Lightning Bolt"); playLand(playerA, "Mountain"); castSpell(playerA, "Lightning Bolt"); + // not specifying target, AI should choose opponent by itself execute(); assertLife(playerA, 20); assertLife(playerB, 17); } + + @Test + public void testDamageSelf() { + System.out.println("TEST: testDamageSelf"); + addCard(Constants.Zone.HAND, playerA, "Mountain"); + addCard(Constants.Zone.HAND, playerA, "Lightning Bolt"); + + playLand(playerA, "Mountain"); + castSpell(playerA, "Lightning Bolt"); + addFixedTarget(playerA, "Lightning Bolt", playerA); + playerA.setAllowBadMoves(true); + + execute(); + assertLife(playerA, 17); + assertLife(playerB, 20); + } + } diff --git a/Mage.Tests/src/test/java/org/mage/test/serverside/PlayGameTest.java b/Mage.Tests/src/test/java/org/mage/test/serverside/PlayGameTest.java index d78b5b2f1a..97c0d11481 100644 --- a/Mage.Tests/src/test/java/org/mage/test/serverside/PlayGameTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/serverside/PlayGameTest.java @@ -11,6 +11,7 @@ import mage.game.TwoPlayerDuel; import mage.player.ai.ComputerPlayer; import mage.players.Player; import mage.sets.Sets; +import org.junit.Ignore; import org.junit.Test; import org.mage.test.serverside.base.MageTestBase; @@ -27,7 +28,8 @@ public class PlayGameTest extends MageTestBase { private static List colorChoices = Arrays.asList("bu", "bg", "br", "bw", "ug", "ur", "uw", "gr", "gw", "rw", "bur", "buw", "bug", "brg", "brw", "bgw", "wur", "wug", "wrg", "rgu"); - @Test + @Ignore + @Test public void playOneGame() throws GameException, FileNotFoundException, IllegalArgumentException { Game game = new TwoPlayerDuel(Constants.MultiplayerAttackOption.LEFT, Constants.RangeOfInfluence.ALL); diff --git a/Mage.Tests/src/test/java/org/mage/test/serverside/ai/BugTapsItselfTest.java b/Mage.Tests/src/test/java/org/mage/test/serverside/ai/BugTapsItselfTest.java index 254c65bc1d..a56e171d8c 100644 --- a/Mage.Tests/src/test/java/org/mage/test/serverside/ai/BugTapsItselfTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/serverside/ai/BugTapsItselfTest.java @@ -4,6 +4,7 @@ import junit.framework.Assert; import mage.Constants; import mage.game.permanent.Permanent; +import org.junit.Ignore; import org.junit.Test; import org.mage.test.serverside.base.CardTestBase; @@ -16,6 +17,7 @@ import org.mage.test.serverside.base.CardTestBase; public class BugTapsItselfTest extends CardTestBase { @Test + @Ignore public void testVersusInfectCreature() throws Exception { useWhiteDefault(); addCard(Constants.Zone.BATTLEFIELD, playerA, "Blinding Mage"); diff --git a/Mage.Tests/src/test/java/org/mage/test/serverside/base/CardTestBase.java b/Mage.Tests/src/test/java/org/mage/test/serverside/base/CardTestBase.java index c320b17bd0..f175e128fb 100644 --- a/Mage.Tests/src/test/java/org/mage/test/serverside/base/CardTestBase.java +++ b/Mage.Tests/src/test/java/org/mage/test/serverside/base/CardTestBase.java @@ -66,8 +66,8 @@ public abstract class CardTestBase extends CardTestAPIImpl { Game game = new TwoPlayerDuel(Constants.MultiplayerAttackOption.LEFT, Constants.RangeOfInfluence.ALL); playerA = aiTypeA.equals(CardTestBase.AIType.MinimaxHybrid) ? - createPlayer("ComputerA", "Computer - minimax hybrid") : - createPlayer("ComputerA", "Computer - mad"); + createPlayer("PlayerA", "Computer - minimax hybrid") : + createPlayer("PlayerA", "Computer - mad"); playerA.setTestMode(true); logger.info("Loading deck..."); Deck deck = Deck.load(Sets.loadDeck("RB Aggro.dck")); @@ -79,8 +79,8 @@ public abstract class CardTestBase extends CardTestAPIImpl { game.loadCards(deck.getCards(), playerA.getId()); playerB = aiTypeB.equals(CardTestBase.AIType.MinimaxHybrid) ? - createPlayer("ComputerB", "Computer - minimax hybrid") : - createPlayer("ComputerB", "Computer - mad"); + createPlayer("PlayerB", "Computer - minimax hybrid") : + createPlayer("PlayerB", "Computer - mad"); playerB.setTestMode(true); Deck deck2 = Deck.load(Sets.loadDeck("RB Aggro.dck")); if (deck2.getCards().size() < 40) { diff --git a/Mage.Tests/src/test/java/org/mage/test/serverside/base/impl/CardTestAPIImpl.java b/Mage.Tests/src/test/java/org/mage/test/serverside/base/impl/CardTestAPIImpl.java index 5d96474342..0d6fec0c4c 100644 --- a/Mage.Tests/src/test/java/org/mage/test/serverside/base/impl/CardTestAPIImpl.java +++ b/Mage.Tests/src/test/java/org/mage/test/serverside/base/impl/CardTestAPIImpl.java @@ -363,8 +363,8 @@ public abstract class CardTestAPIImpl extends MageTestBase implements CardTestAP player.addAction("cast:"+cardName); } - public void castSpell(Player player, String cardName, String target) { - player.addAction("cast:"+cardName + ";" + target); + public void addFixedTarget(Player player, String cardName, Player target) { + player.addAction("cast:"+cardName + ";name=" + target.getName()); } public void useAbility(Player player, String cardName) { diff --git a/Mage.Tests/src/test/java/org/mage/test/serverside/cards/effects/BoostContinuousEffectTest.java b/Mage.Tests/src/test/java/org/mage/test/serverside/cards/effects/BoostContinuousEffectTest.java index 6de993cb53..2ca6b42743 100644 --- a/Mage.Tests/src/test/java/org/mage/test/serverside/cards/effects/BoostContinuousEffectTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/serverside/cards/effects/BoostContinuousEffectTest.java @@ -1,6 +1,7 @@ package org.mage.test.serverside.cards.effects; import mage.filter.Filter; +import org.junit.Ignore; import org.junit.Test; import org.mage.test.serverside.base.CardTestBase; @@ -12,6 +13,7 @@ import org.mage.test.serverside.base.CardTestBase; public class BoostContinuousEffectTest extends CardTestBase { @Test + @Ignore public void testHonorOfThePoor() throws Exception { load("M11/Honor of the Pure.test"); execute(); diff --git a/Mage.Tests/src/test/java/org/mage/test/serverside/cards/single/mbs/BurntheImpureTest.java b/Mage.Tests/src/test/java/org/mage/test/serverside/cards/single/mbs/BurntheImpureTest.java index f5ed083a64..12e76548d5 100644 --- a/Mage.Tests/src/test/java/org/mage/test/serverside/cards/single/mbs/BurntheImpureTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/serverside/cards/single/mbs/BurntheImpureTest.java @@ -2,6 +2,7 @@ package org.mage.test.serverside.cards.single.mbs; import mage.Constants; import mage.filter.Filter; +import org.junit.Ignore; import org.junit.Test; import org.mage.test.serverside.base.CardTestAPI; import org.mage.test.serverside.base.CardTestBase; @@ -24,6 +25,7 @@ public class BurntheImpureTest extends CardTestBase { * @throws Exception */ @Test + @Ignore public void testVersusInfectCreature() throws Exception { // $include red.default useRedDefault(); diff --git a/Mage/src/mage/players/Player.java b/Mage/src/mage/players/Player.java index 2ce860c00b..c955601106 100644 --- a/Mage/src/mage/players/Player.java +++ b/Mage/src/mage/players/Player.java @@ -164,6 +164,7 @@ public interface Player extends MageItem, Copyable { public boolean isTestMode(); public void setTestMode(boolean value); public void addAction(String action); + public void setAllowBadMoves(boolean allowBadMoves); public void init(Game game); public void init(Game game, boolean testMode); diff --git a/Mage/src/mage/players/PlayerImpl.java b/Mage/src/mage/players/PlayerImpl.java index a6afe4eeba..aa863fa2d7 100644 --- a/Mage/src/mage/players/PlayerImpl.java +++ b/Mage/src/mage/players/PlayerImpl.java @@ -1351,4 +1351,8 @@ public abstract class PlayerImpl> implements Player, Ser // do nothing } + public void setAllowBadMoves(boolean allowBadMoves) { + // do nothing + } + }