From 08b99fcbf75d2be9e19e5bfce4567c96b24e3d6a Mon Sep 17 00:00:00 2001 From: Oleg Agafonov Date: Mon, 15 Jan 2024 03:14:42 +0400 Subject: [PATCH] AI: removed outdated AIMinimax project (#7075), removed some useless player classes, code and config files, improved docs; --- Mage.Client/plugins/AIMinimax.properties | 7 - .../Mage.Player.AI.DraftBot/pom.xml | 2 +- .../mage/player/ai/ComputerDraftPlayer.java | 10 +- .../config/AIMinimax.properties | 7 - Mage.Server.Plugins/Mage.Player.AI.MA/pom.xml | 2 +- .../src/mage/player/ai/ComputerPlayer6.java | 10 +- .../src/mage/player/ai/ComputerPlayer7.java | 2 + .../src/mage/player/ai/Config2.java | 59 - .../src/mage/player/ai/SimulatedPlayer2.java | 4 +- Mage.Server.Plugins/Mage.Player.AI/pom.xml | 2 +- .../java/mage/player/ai/ComputerPlayer.java | 4 +- .../mage/player/ai/ComputerPlayerMCTS.java | 2 +- .../src/mage/player/ai/MCTSPlayer.java | 22 +- .../mage/player/ai/SimulatedPlayerMCTS.java | 23 +- .../config/AIMinimax.properties | 7 - .../Mage.Player.AIMinimax/pom.xml | 57 - .../src/mage/player/ai/Attackers.java | 27 - .../src/mage/player/ai/Config.java | 47 - .../mage/player/ai/GameStateEvaluator.java | 124 -- .../src/mage/player/ai/SimulatedAction.java | 42 - .../src/mage/player/ai/SimulatedPlayer.java | 265 --- .../src/mage/player/ai/SimulationNode.java | 111 -- .../src/mage/player/ai/SimulationWorker.java | 41 - .../src/mage/player/human/HumanPlayer.java | 2 + Mage.Server.Plugins/pom.xml | 1 - Mage.Server/config/config.xml | 1 - Mage.Server/pom.xml | 6 - .../release/plugins/AIMinimax.properties | 7 - .../src/main/assembly/distribution.xml | 2 - .../mage/test/mulligan/MulliganTestBase.java | 10 +- .../mage/test/player/TestComputerPlayer.java | 10 +- .../mage/test/player/TestComputerPlayer7.java | 4 +- .../player/TestComputerPlayerMonteCarlo.java | 4 +- .../java/org/mage/test/player/TestPlayer.java | 2 + .../mage/test/serverside/PlayGameTest.java | 95 -- ...SwissPairingMinimalWeightMatchingTest.java | 54 +- .../java/org/mage/test/stub/PlayerStub.java | 1466 ----------------- .../main/java/mage/game/match/MatchImpl.java | 2 +- .../main/java/mage/players/PlayerType.java | 11 +- .../main/java/mage/players/StubPlayer.java | 11 +- 40 files changed, 103 insertions(+), 2462 deletions(-) delete mode 100644 Mage.Client/plugins/AIMinimax.properties delete mode 100644 Mage.Server.Plugins/Mage.Player.AI.MA/config/AIMinimax.properties delete mode 100644 Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/Config2.java delete mode 100644 Mage.Server.Plugins/Mage.Player.AIMinimax/config/AIMinimax.properties delete mode 100644 Mage.Server.Plugins/Mage.Player.AIMinimax/pom.xml delete mode 100644 Mage.Server.Plugins/Mage.Player.AIMinimax/src/mage/player/ai/Attackers.java delete mode 100644 Mage.Server.Plugins/Mage.Player.AIMinimax/src/mage/player/ai/Config.java delete mode 100644 Mage.Server.Plugins/Mage.Player.AIMinimax/src/mage/player/ai/GameStateEvaluator.java delete mode 100644 Mage.Server.Plugins/Mage.Player.AIMinimax/src/mage/player/ai/SimulatedAction.java delete mode 100644 Mage.Server.Plugins/Mage.Player.AIMinimax/src/mage/player/ai/SimulatedPlayer.java delete mode 100644 Mage.Server.Plugins/Mage.Player.AIMinimax/src/mage/player/ai/SimulationNode.java delete mode 100644 Mage.Server.Plugins/Mage.Player.AIMinimax/src/mage/player/ai/SimulationWorker.java delete mode 100644 Mage.Server/release/plugins/AIMinimax.properties delete mode 100644 Mage.Tests/src/test/java/org/mage/test/serverside/PlayGameTest.java delete mode 100644 Mage.Tests/src/test/java/org/mage/test/stub/PlayerStub.java diff --git a/Mage.Client/plugins/AIMinimax.properties b/Mage.Client/plugins/AIMinimax.properties deleted file mode 100644 index 96b5480294c..00000000000 --- a/Mage.Client/plugins/AIMinimax.properties +++ /dev/null @@ -1,7 +0,0 @@ -maxDepth=10 -maxNodes=5000 -evaluatorLifeFactor=2 -evaluatorPermanentFactor=1 -evaluatorCreatureFactor=1 -evaluatorHandFactor=1 -maxThinkSeconds=30 \ No newline at end of file diff --git a/Mage.Server.Plugins/Mage.Player.AI.DraftBot/pom.xml b/Mage.Server.Plugins/Mage.Player.AI.DraftBot/pom.xml index 4c02450c7fe..1b6d54688bd 100644 --- a/Mage.Server.Plugins/Mage.Player.AI.DraftBot/pom.xml +++ b/Mage.Server.Plugins/Mage.Player.AI.DraftBot/pom.xml @@ -12,7 +12,7 @@ mage-player-ai-draftbot jar - Mage Player AI.DraftBot + Mage Player AI (draft bot) diff --git a/Mage.Server.Plugins/Mage.Player.AI.DraftBot/src/mage/player/ai/ComputerDraftPlayer.java b/Mage.Server.Plugins/Mage.Player.AI.DraftBot/src/mage/player/ai/ComputerDraftPlayer.java index 4d7eedfc092..53fda77b4d0 100644 --- a/Mage.Server.Plugins/Mage.Player.AI.DraftBot/src/mage/player/ai/ComputerDraftPlayer.java +++ b/Mage.Server.Plugins/Mage.Player.AI.DraftBot/src/mage/player/ai/ComputerDraftPlayer.java @@ -1,18 +1,18 @@ - - package mage.player.ai; import mage.constants.RangeOfInfluence; import mage.game.Game; import mage.game.Table; import mage.game.tournament.TournamentType; -import mage.players.Player; /** + * AI: server side bot for drafts (draftbot, the latest version) + *

+ * Can play drafts only, concede/lose on any real game and tourney * * @author nantuko */ -public class ComputerDraftPlayer extends ComputerPlayer implements Player { +public class ComputerDraftPlayer extends ComputerPlayer { public ComputerDraftPlayer(String name, RangeOfInfluence range) { super(name, range); @@ -46,7 +46,7 @@ public class ComputerDraftPlayer extends ComputerPlayer implements Player { public boolean canJoinTable(Table table) { if (table.isTournament()) { TournamentType tournamentType = table.getTournament().getTournamentType(); - if(tournamentType != null && tournamentType.isDraft()) { + if (tournamentType != null && tournamentType.isDraft()) { return true; } } diff --git a/Mage.Server.Plugins/Mage.Player.AI.MA/config/AIMinimax.properties b/Mage.Server.Plugins/Mage.Player.AI.MA/config/AIMinimax.properties deleted file mode 100644 index 219e0264582..00000000000 --- a/Mage.Server.Plugins/Mage.Player.AI.MA/config/AIMinimax.properties +++ /dev/null @@ -1,7 +0,0 @@ -maxDepth=10 -maxNodes=5000 -evaluatorLifeFactor=2 -evaluatorPermanentFactor=1 -evaluatorCreatureFactor=1 -evaluatorHandFactor=1 -maxThinkSeconds=10 \ No newline at end of file diff --git a/Mage.Server.Plugins/Mage.Player.AI.MA/pom.xml b/Mage.Server.Plugins/Mage.Player.AI.MA/pom.xml index 0e3857d37ae..73f91e6dbb8 100644 --- a/Mage.Server.Plugins/Mage.Player.AI.MA/pom.xml +++ b/Mage.Server.Plugins/Mage.Player.AI.MA/pom.xml @@ -12,7 +12,7 @@ mage-player-ai-ma jar - Mage Player AI.MA + Mage Player AI (mad bot) 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 639eb52b134..58eed8958f1 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 @@ -41,12 +41,18 @@ import java.util.concurrent.*; import java.util.stream.Collectors; /** + * AI: server side bot with game simulations (mad bot, part of implementation) + * * @author nantuko */ -public class ComputerPlayer6 extends ComputerPlayer /*implements Player*/ { +public class ComputerPlayer6 extends ComputerPlayer { private static final Logger logger = Logger.getLogger(ComputerPlayer6.class); + // TODO: add and research maxNodes logs, is it good to increase to 50000 for better results? + // TODO: increase maxNodes due AI skill level? + private static final int MAX_SIMULATED_NODES_PER_CALC = 5000; + // same params as Executors.newFixedThreadPool // no needs erorrs check in afterExecute here cause that pool used for FutureTask with result check already private static final ExecutorService threadPoolSimulations = new ThreadPoolExecutor( @@ -97,7 +103,7 @@ public class ComputerPlayer6 extends ComputerPlayer /*implements Player*/ { maxDepth = skill; } maxThink = skill * 3; - maxNodes = Config2.maxNodes; + maxNodes = MAX_SIMULATED_NODES_PER_CALC; getSuggestedActions(); this.actionCache = new HashSet<>(); } 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 6173a8df632..667d64aadb2 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 @@ -9,6 +9,8 @@ import java.util.Date; import java.util.LinkedList; /** + * AI: server side bot with game simulations (mad bot, the latest version) + * * @author ayratn */ public class ComputerPlayer7 extends ComputerPlayer6 { diff --git a/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/Config2.java b/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/Config2.java deleted file mode 100644 index dc528cd0de6..00000000000 --- a/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/Config2.java +++ /dev/null @@ -1,59 +0,0 @@ - - -package mage.player.ai; - -import org.apache.log4j.Logger; - -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.net.URISyntaxException; -import java.util.Properties; - -/** - * - * @author BetaSteward_at_googlemail.com - */ -public final class Config2 { - - private static final Logger logger = Logger.getLogger(Config2.class); - -// public static final int maxDepth; - public static final int maxNodes; - public static final int evaluatorLifeFactor; - public static final int evaluatorPermanentFactor; - public static final int evaluatorCreatureFactor; - public static final int evaluatorHandFactor; -// public static final int maxThinkSeconds; - - static { - Properties p = new Properties(); - try { - File file = new File(Config2.class.getProtectionDomain().getCodeSource().getLocation().toURI().getPath()); - File propertiesFile = new File(file.getParent() + File.separator + "AIMinimax.properties"); - if (propertiesFile.exists()) { - p.load(new FileInputStream(propertiesFile)); - } else { -// p.setProperty("maxDepth", "10"); - p.setProperty("maxNodes", "50000"); - p.setProperty("evaluatorLifeFactor", "2"); - p.setProperty("evaluatorPermanentFactor", "1"); - p.setProperty("evaluatorCreatureFactor", "1"); - p.setProperty("evaluatorHandFactor", "1"); -// p.setProperty("maxThinkSeconds", "30"); - } - } catch (IOException ex) { - logger.error(null, ex); - } catch (URISyntaxException ex) { - logger.error(null, ex); - } -// maxDepth = Integer.parseInt(p.getProperty("maxDepth")); - maxNodes = Integer.parseInt(p.getProperty("maxNodes")); - evaluatorLifeFactor = Integer.parseInt(p.getProperty("evaluatorLifeFactor")); - evaluatorPermanentFactor = Integer.parseInt(p.getProperty("evaluatorPermanentFactor")); - evaluatorCreatureFactor = Integer.parseInt(p.getProperty("evaluatorCreatureFactor")); - evaluatorHandFactor = Integer.parseInt(p.getProperty("evaluatorHandFactor")); -// maxThinkSeconds = Integer.parseInt(p.getProperty("maxThinkSeconds")); - } - -} 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 e8c137dacf8..2a69f9a69c7 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 @@ -27,11 +27,11 @@ import java.util.*; import java.util.concurrent.ConcurrentLinkedQueue; /** - * AI: mock player in simulated games (each player replaced by simulated) + * AI: helper class to simulate games with computer bot (each player replaced by simulated) * * @author BetaSteward_at_googlemail.com */ -public class SimulatedPlayer2 extends ComputerPlayer { +public final class SimulatedPlayer2 extends ComputerPlayer { private static final Logger logger = Logger.getLogger(SimulatedPlayer2.class); diff --git a/Mage.Server.Plugins/Mage.Player.AI/pom.xml b/Mage.Server.Plugins/Mage.Player.AI/pom.xml index f50a620ece1..c3ccebc6803 100644 --- a/Mage.Server.Plugins/Mage.Player.AI/pom.xml +++ b/Mage.Server.Plugins/Mage.Player.AI/pom.xml @@ -12,7 +12,7 @@ mage-player-ai jar - Mage Player AI + Mage Player AI (basic) 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 e6573046e7b..741c0d4e7ff 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 @@ -59,11 +59,11 @@ import java.util.*; import java.util.Map.Entry; /** - * suitable for two player games and some multiplayer games + * AI: basic server side bot with simple actions support (game, draft, construction/sideboarding) * * @author BetaSteward_at_googlemail.com, JayDi85 */ -public class ComputerPlayer extends PlayerImpl implements Player { +public class ComputerPlayer extends PlayerImpl { private static final Logger log = Logger.getLogger(ComputerPlayer.class); private long lastThinkTime = 0; // msecs for last AI actions calc diff --git a/Mage.Server.Plugins/Mage.Player.AIMCTS/src/mage/player/ai/ComputerPlayerMCTS.java b/Mage.Server.Plugins/Mage.Player.AIMCTS/src/mage/player/ai/ComputerPlayerMCTS.java index e34da5d762a..f9319d6d766 100644 --- a/Mage.Server.Plugins/Mage.Player.AIMCTS/src/mage/player/ai/ComputerPlayerMCTS.java +++ b/Mage.Server.Plugins/Mage.Player.AIMCTS/src/mage/player/ai/ComputerPlayerMCTS.java @@ -25,7 +25,7 @@ import java.util.concurrent.TimeUnit; /** * @author BetaSteward_at_googlemail.com */ -public class ComputerPlayerMCTS extends ComputerPlayer implements Player { +public class ComputerPlayerMCTS extends ComputerPlayer { private static final int THINK_MIN_RATIO = 40; private static final int THINK_MAX_RATIO = 100; diff --git a/Mage.Server.Plugins/Mage.Player.AIMCTS/src/mage/player/ai/MCTSPlayer.java b/Mage.Server.Plugins/Mage.Player.AIMCTS/src/mage/player/ai/MCTSPlayer.java index 7e3728bf3ea..a79cc57a104 100644 --- a/Mage.Server.Plugins/Mage.Player.AIMCTS/src/mage/player/ai/MCTSPlayer.java +++ b/Mage.Server.Plugins/Mage.Player.AIMCTS/src/mage/player/ai/MCTSPlayer.java @@ -1,4 +1,3 @@ - package mage.player.ai; import mage.abilities.Ability; @@ -15,6 +14,10 @@ import java.util.List; import java.util.UUID; /** + * AI: server side bot with monte carlo logic (experimental, the latest version) + *

+ * Simple implementation for random play, outdate and do not support, + * see more details here * * @author BetaSteward_at_googlemail.com */ @@ -51,22 +54,19 @@ public class MCTSPlayer extends ComputerPlayer { public List getPlayableOptions(Game game) { List all = new ArrayList<>(); List playables = getPlayableAbilities(game); - for (ActivatedAbility ability: playables) { + for (ActivatedAbility ability : playables) { List options = game.getPlayer(playerId).getPlayableOptions(ability, game); if (options.isEmpty()) { if (!ability.getManaCosts().getVariableCosts().isEmpty()) { simulateVariableCosts(ability, all, game); - } - else { + } else { all.add(ability); } - } - else { - for (Ability option: options) { + } else { + for (Ability option : options) { if (!ability.getManaCosts().getVariableCosts().isEmpty()) { simulateVariableCosts(option, all, game); - } - else { + } else { all.add(option); } } @@ -137,7 +137,7 @@ public class MCTSPlayer extends ComputerPlayer { private List> copyEngagement(List> engagement) { List> newEngagement = new ArrayList<>(); - for (List group: engagement) { + for (List group : engagement) { newEngagement.add(new ArrayList<>(group)); } return newEngagement; @@ -154,7 +154,7 @@ public class MCTSPlayer extends ComputerPlayer { List remaining = remove(blockers, blocker); for (int i = 0; i < numGroups; i++) { if (game.getCombat().getGroups().get(i).canBlock(blocker, game)) { - List>newEngagement = copyEngagement(engagement); + List> newEngagement = copyEngagement(engagement); newEngagement.get(i).add(blocker.getId()); engagements.add(newEngagement); // logger.debug("simulating -- found redundant block combination"); diff --git a/Mage.Server.Plugins/Mage.Player.AIMCTS/src/mage/player/ai/SimulatedPlayerMCTS.java b/Mage.Server.Plugins/Mage.Player.AIMCTS/src/mage/player/ai/SimulatedPlayerMCTS.java index 698c694f96c..09fcfa67339 100644 --- a/Mage.Server.Plugins/Mage.Player.AIMCTS/src/mage/player/ai/SimulatedPlayerMCTS.java +++ b/Mage.Server.Plugins/Mage.Player.AIMCTS/src/mage/player/ai/SimulatedPlayerMCTS.java @@ -24,11 +24,13 @@ import java.io.Serializable; import java.util.*; /** - * plays randomly + * AI: helper class to simulate games with MCTS AI (each player replaced by simulated) + *

+ * Plays randomly * * @author BetaSteward_at_googlemail.com */ -public class SimulatedPlayerMCTS extends MCTSPlayer { +public final class SimulatedPlayerMCTS extends MCTSPlayer { private boolean isSimulatedPlayer; private int actionCount = 0; @@ -98,28 +100,13 @@ public class SimulatedPlayerMCTS extends MCTSPlayer { ability.addManaCostsToPay(new GenericManaCost(RandomUtil.nextInt(amount))); } } - // check if ability kills player, if not then it's ok to play -// if (ability.isUsesStack()) { -// Game testSim = game.copy(); -// activateAbility((ActivatedAbility) ability, testSim); -// StackObject testAbility = testSim.getStack().pop(); -// testAbility.resolve(testSim); -// testSim.applyEffects(); -// testSim.checkStateAndTriggered(); -// if (!testSim.getPlayer(playerId).hasLost()) { -// break; -// } -// } -// else { break; -// } } return ability; } @Override public boolean triggerAbility(TriggeredAbility source, Game game) { -// logger.info("trigger"); if (source != null && source.canChooseTarget(game, playerId)) { Ability ability; List options = getPlayableOptions(source, game); @@ -153,7 +140,6 @@ public class SimulatedPlayerMCTS extends MCTSPlayer { @Override public void selectAttackers(Game game, UUID attackingPlayerId) { //useful only for two player games - will only attack first opponent -// logger.info("select attackers"); UUID defenderId = game.getOpponents(playerId).iterator().next(); List attackersList = super.getAvailableAttackers(defenderId, game); //use binary digits to calculate powerset of attackers @@ -177,7 +163,6 @@ public class SimulatedPlayerMCTS extends MCTSPlayer { @Override public void selectBlockers(Ability source, Game game, UUID defendingPlayerId) { -// logger.info("select blockers"); int numGroups = game.getCombat().getGroups().size(); if (numGroups == 0) { return; diff --git a/Mage.Server.Plugins/Mage.Player.AIMinimax/config/AIMinimax.properties b/Mage.Server.Plugins/Mage.Player.AIMinimax/config/AIMinimax.properties deleted file mode 100644 index 96b5480294c..00000000000 --- a/Mage.Server.Plugins/Mage.Player.AIMinimax/config/AIMinimax.properties +++ /dev/null @@ -1,7 +0,0 @@ -maxDepth=10 -maxNodes=5000 -evaluatorLifeFactor=2 -evaluatorPermanentFactor=1 -evaluatorCreatureFactor=1 -evaluatorHandFactor=1 -maxThinkSeconds=30 \ No newline at end of file diff --git a/Mage.Server.Plugins/Mage.Player.AIMinimax/pom.xml b/Mage.Server.Plugins/Mage.Player.AIMinimax/pom.xml deleted file mode 100644 index 305709ae6b1..00000000000 --- a/Mage.Server.Plugins/Mage.Player.AIMinimax/pom.xml +++ /dev/null @@ -1,57 +0,0 @@ - - - - 4.0.0 - - - org.mage - mage-server-plugins - 1.4.50 - - - mage-player-aiminimax - jar - Mage Player AI Minimax - - - - ${project.groupId} - mage - ${project.version} - - - ${project.groupId} - mage-player-ai - ${project.version} - - - - - src - - - org.apache.maven.plugins - maven-compiler-plugin - - ${java.version} - ${java.version} - - - - maven-resources-plugin - - UTF-8 - - - - - - mage-player-aiminimax - - - - ${project.basedir}/../.. - - - diff --git a/Mage.Server.Plugins/Mage.Player.AIMinimax/src/mage/player/ai/Attackers.java b/Mage.Server.Plugins/Mage.Player.AIMinimax/src/mage/player/ai/Attackers.java deleted file mode 100644 index 45482be1def..00000000000 --- a/Mage.Server.Plugins/Mage.Player.AIMinimax/src/mage/player/ai/Attackers.java +++ /dev/null @@ -1,27 +0,0 @@ - - -package mage.player.ai; - -import mage.game.permanent.Permanent; - -import java.util.ArrayList; -import java.util.List; -import java.util.TreeMap; - -/** - * - * @author BetaSteward_at_googlemail.com - */ -public class Attackers extends TreeMap> { - - public List getAttackers() { - List attackers = new ArrayList<>(); - for (List l: this.values()) { - for (Permanent permanent: l) { - attackers.add(permanent); - } - } - return attackers; - } - -} diff --git a/Mage.Server.Plugins/Mage.Player.AIMinimax/src/mage/player/ai/Config.java b/Mage.Server.Plugins/Mage.Player.AIMinimax/src/mage/player/ai/Config.java deleted file mode 100644 index d239b48ff96..00000000000 --- a/Mage.Server.Plugins/Mage.Player.AIMinimax/src/mage/player/ai/Config.java +++ /dev/null @@ -1,47 +0,0 @@ - - -package mage.player.ai; - -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.net.URISyntaxException; -import java.util.Properties; -import org.apache.log4j.Logger; - -/** - * - * @author BetaSteward_at_googlemail.com - */ -public final class Config { - - private static final Logger logger = Logger.getLogger(Config.class); - -// public static final int maxDepth; - public static final int maxNodes; - public static final int evaluatorLifeFactor; - public static final int evaluatorPermanentFactor; - public static final int evaluatorCreatureFactor; - public static final int evaluatorHandFactor; -// public static final int maxThinkSeconds; - - static { - Properties p = new Properties(); - try { - File file = new File(Config.class.getProtectionDomain().getCodeSource().getLocation().toURI().getPath()); - p.load(new FileInputStream(new File(file.getParent() + File.separator + "AIMinimax.properties"))); - } catch (IOException ex) { - logger.fatal("", ex); - } catch (URISyntaxException ex) { - logger.fatal("", ex); - } -// maxDepth = Integer.parseInt(p.getProperty("maxDepth")); - maxNodes = Integer.parseInt(p.getProperty("maxNodes")); - evaluatorLifeFactor = Integer.parseInt(p.getProperty("evaluatorLifeFactor")); - evaluatorPermanentFactor = Integer.parseInt(p.getProperty("evaluatorPermanentFactor")); - evaluatorCreatureFactor = Integer.parseInt(p.getProperty("evaluatorCreatureFactor")); - evaluatorHandFactor = Integer.parseInt(p.getProperty("evaluatorHandFactor")); -// maxThinkSeconds = Integer.parseInt(p.getProperty("maxThinkSeconds")); - } - -} 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 deleted file mode 100644 index 236bc2e19e1..00000000000 --- a/Mage.Server.Plugins/Mage.Player.AIMinimax/src/mage/player/ai/GameStateEvaluator.java +++ /dev/null @@ -1,124 +0,0 @@ - -package mage.player.ai; - -import java.util.UUID; -import mage.abilities.ActivatedAbility; -import mage.abilities.keyword.DoubleStrikeAbility; -import mage.abilities.keyword.FirstStrikeAbility; -import mage.abilities.keyword.TrampleAbility; -import mage.abilities.mana.ActivatedManaAbilityImpl; -import mage.constants.CardType; -import mage.constants.Zone; -import mage.counters.BoostCounter; -import mage.counters.Counter; -import mage.counters.CounterType; -import mage.game.Game; -import mage.game.permanent.Permanent; -import mage.players.Player; -import org.apache.log4j.Logger; - -/** - * - * @author BetaSteward_at_googlemail.com - * - * this evaluator is only good for two player games - * - */ -public final class GameStateEvaluator { - - private static final Logger logger = Logger.getLogger(GameStateEvaluator.class); - - private static final int LIFE_FACTOR = Config.evaluatorLifeFactor; - private static final int PERMANENT_FACTOR = Config.evaluatorPermanentFactor; - private static final int CREATURE_FACTOR = Config.evaluatorCreatureFactor; - private static final int HAND_FACTOR = Config.evaluatorHandFactor; - - public static final int WIN_SCORE = Integer.MAX_VALUE - 1; - public static final int LOSE_SCORE = Integer.MIN_VALUE + 1; - - public static int evaluate(UUID playerId, Game game) { - return evaluate(playerId, game, false); - } - - public static int evaluate(UUID playerId, Game game, boolean ignoreTapped) { - Player player = game.getPlayer(playerId); - Player opponent = game.getPlayer(game.getOpponents(playerId).stream().findFirst().orElse(null)); - if (opponent == null) { - return WIN_SCORE; - } - - if (game.checkIfGameIsOver()) { - if (player.hasLost() || opponent.hasWon()) { - return LOSE_SCORE; - } - if (opponent.hasLost() || player.hasWon()) { - return WIN_SCORE; - } - } - int lifeScore = (player.getLife() - opponent.getLife()) * LIFE_FACTOR; - int poisonScore = (opponent.getCounters().getCount(CounterType.POISON) - player.getCounters().getCount(CounterType.POISON)) * LIFE_FACTOR * 2; - int permanentScore = 0; - for (Permanent permanent : game.getBattlefield().getAllActivePermanents(playerId)) { - permanentScore += evaluatePermanent(permanent, game, ignoreTapped); - } - for (Permanent permanent : game.getBattlefield().getAllActivePermanents(opponent.getId())) { - permanentScore -= evaluatePermanent(permanent, game, ignoreTapped); - } - permanentScore *= PERMANENT_FACTOR; - - int handScore = 0; - handScore = player.getHand().size() - opponent.getHand().size(); - handScore *= HAND_FACTOR; - - int score = lifeScore + poisonScore + permanentScore + handScore; - if (logger.isDebugEnabled()) { - logger.debug("game state for player " + player.getName() + " evaluated to- lifeScore:" + lifeScore + " permanentScore:" + permanentScore + " handScore:" + handScore + " total:" + score); - } - return score; - } - - public static int evaluatePermanent(Permanent permanent, Game game, boolean ignoreTapped) { - int value = 0; - if (ignoreTapped) { - value = 5; - } else { - value = permanent.isTapped() ? 4 : 5; - } - if (permanent.getCardType(game).contains(CardType.CREATURE)) { - value += evaluateCreature(permanent, game) * CREATURE_FACTOR; - } - value += permanent.getAbilities().getActivatedManaAbilities(Zone.BATTLEFIELD).size(); - for (ActivatedAbility ability : permanent.getAbilities().getActivatedAbilities(Zone.BATTLEFIELD)) { - if (!(ability instanceof ActivatedManaAbilityImpl) && ability.canActivate(ability.getControllerId(), game).canActivate()) { - value += ability.getEffects().size(); - } - } - for (Counter counter : permanent.getCounters(game).values()) { - if (!(counter instanceof BoostCounter)) { - value += counter.getCount(); - } - } - value += permanent.getAbilities().getStaticAbilities(Zone.BATTLEFIELD).size(); - value += permanent.getAbilities().getTriggeredAbilities(Zone.BATTLEFIELD).size(); - value += permanent.getManaCost().manaValue(); - //TODO: add a difficulty to calculation to ManaCost - sort permanents by difficulty for casting when evaluating game states - return value; - } - - public static int evaluateCreature(Permanent creature, Game game) { - int value = 0; - value += creature.getPower().getValue(); - value += creature.getToughness().getValue(); -// if (creature.canAttack(game)) -// value += creature.getPower().getValue(); -// if (!creature.isTapped()) -// value += 2; - value += creature.getAbilities().getEvasionAbilities().size(); - value += creature.getAbilities().getProtectionAbilities().size(); - value += creature.getAbilities().containsKey(FirstStrikeAbility.getInstance().getId()) ? 1 : 0; - value += creature.getAbilities().containsKey(DoubleStrikeAbility.getInstance().getId()) ? 2 : 0; - value += creature.getAbilities().containsKey(TrampleAbility.getInstance().getId()) ? 1 : 0; - return value; - } - -} diff --git a/Mage.Server.Plugins/Mage.Player.AIMinimax/src/mage/player/ai/SimulatedAction.java b/Mage.Server.Plugins/Mage.Player.AIMinimax/src/mage/player/ai/SimulatedAction.java deleted file mode 100644 index a67d383991d..00000000000 --- a/Mage.Server.Plugins/Mage.Player.AIMinimax/src/mage/player/ai/SimulatedAction.java +++ /dev/null @@ -1,42 +0,0 @@ - - -package mage.player.ai; - -import java.util.List; -import mage.abilities.Ability; -import mage.game.Game; - -/** - * - * @author BetaSteward_at_googlemail.com - */ -public class SimulatedAction { - - private Game game; - private List abilities; - - public SimulatedAction(Game game, List abilities) { - this.game = game; - this.abilities = abilities; - } - - public Game getGame() { - return this.game; - } - - public List getAbilities() { - return this.abilities; - } - - @Override - public String toString() { - return this.abilities.toString(); - } - - public boolean usesStack() { - if (abilities != null && !abilities.isEmpty()) { - return abilities.get(abilities.size() -1).isUsesStack(); - } - return true; - } -} 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 deleted file mode 100644 index 3888dad2ecb..00000000000 --- a/Mage.Server.Plugins/Mage.Player.AIMinimax/src/mage/player/ai/SimulatedPlayer.java +++ /dev/null @@ -1,265 +0,0 @@ - - -package mage.player.ai; - -import mage.abilities.Ability; -import mage.abilities.ActivatedAbility; -import mage.abilities.SpellAbility; -import mage.abilities.TriggeredAbility; -import mage.abilities.common.PassAbility; -import mage.abilities.costs.mana.GenericManaCost; -import mage.game.Game; -import mage.game.combat.Combat; -import mage.game.events.GameEvent; -import mage.game.match.MatchPlayer; -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 - */ -public class SimulatedPlayer extends ComputerPlayer { - - private static final Logger logger = Logger.getLogger(SimulatedPlayer.class); - private boolean isSimulatedPlayer; - private transient ConcurrentLinkedQueue allActions; - protected int maxDepth; - - public SimulatedPlayer(Player originalPlayer, boolean isSimulatedPlayer, int maxDepth) { - super(originalPlayer.getId()); - this.maxDepth = maxDepth; - this.isSimulatedPlayer = isSimulatedPlayer; - this.matchPlayer = new MatchPlayer(originalPlayer.getMatchPlayer(), this); - } - - public SimulatedPlayer(final SimulatedPlayer player) { - super(player); - this.isSimulatedPlayer = player.isSimulatedPlayer; - } - - @Override - public SimulatedPlayer copy() { - return new SimulatedPlayer(this); - } - - public List simulatePriority(Game game) { - allActions = new ConcurrentLinkedQueue<>(); - Game sim = game.copy(); - - ActivatedAbility pass = new PassAbility(); - simulateOptions(sim, pass); - - List list = new ArrayList<>(allActions); - //Collections.shuffle(list); - Collections.reverse(list); - return list; - } - - protected void simulateOptions(Game game, ActivatedAbility previousActions) { - allActions.add(previousActions); - List playables = game.getPlayer(playerId).getPlayable(game, isSimulatedPlayer); - for (ActivatedAbility ability: playables) { - List options = game.getPlayer(playerId).getPlayableOptions(ability, game); - if (options.isEmpty()) { - if (!ability.getManaCosts().getVariableCosts().isEmpty()) { - simulateVariableCosts(ability, game); - } - else { - allActions.add(ability); - } -// simulateAction(game, previousActions, ability); - } - else { -// ExecutorService simulationExecutor = Executors.newFixedThreadPool(4); - for (Ability option: options) { - if (!ability.getManaCosts().getVariableCosts().isEmpty()) { - simulateVariableCosts(option, game); - } - else { - allActions.add(option); - } -// SimulationWorker worker = new SimulationWorker(game, this, previousActions, option); -// simulationExecutor.submit(worker); - } -// simulationExecutor.shutdown(); -// while(!simulationExecutor.isTerminated()) {} - } - } - } - -// protected void simulateAction(Game game, SimulatedAction previousActions, Ability action) { -// List actions = new ArrayList(previousActions.getAbilities()); -// actions.add(action); -// Game sim = game.copy(); -// if (sim.getPlayer(playerId).activateAbility((ActivatedAbility) action.copy(), sim)) { -// sim.applyEffects(); -// sim.getPlayers().resetPassed(); -// allActions.add(new SimulatedAction(sim, actions)); -// } -// } - - //add a generic mana cost for each amount possible - protected void simulateVariableCosts(Ability ability, Game game) { - int numAvailable = getAvailableManaProducers(game).size() - ability.getManaCosts().manaValue(); - int start = 0; - if (!(ability instanceof SpellAbility)) { - //only use x=0 on spell abilities - if (numAvailable == 0) - return; - else - start = 1; - } - for (int i = start; i < numAvailable; i++) { - Ability newAbility = ability.copy(); - newAbility.addManaCostsToPay(new GenericManaCost(i)); - allActions.add(newAbility); - } - } - - /*@Override - public boolean playXMana(VariableManaCost cost, ManaCosts costs, Game game) { - //simulateVariableCosts method adds a generic mana cost for each option - for (ManaCost manaCost: costs) { - if (manaCost instanceof GenericManaCost) { - cost.setPayment(manaCost.getPayment()); - logger.debug("simulating -- X = " + cost.getPayment().count()); - break; - } - } - cost.setPaid(); - return true; - }*/ - - public List addAttackers(Game game) { - Map engagements = new HashMap<>(); - //useful only for two player games - will only attack first opponent - UUID defenderId = game.getOpponents(playerId).iterator().next(); - List attackersList = super.getAvailableAttackers(defenderId, game); - //use binary digits to calculate powerset of attackers - int powerElements = (int) Math.pow(2, attackersList.size()); - StringBuilder binary = new StringBuilder(); - for (int i = powerElements - 1; i >= 0; i--) { - Game sim = game.copy(); - binary.setLength(0); - binary.append(Integer.toBinaryString(i)); - while (binary.length() < attackersList.size()) { - binary.insert(0, '0'); - } - for (int j = 0; j < attackersList.size(); j++) { - if (binary.charAt(j) == '1') { - setStoredBookmark(sim.bookmarkState()); // makes it possible to UNDO a declared attacker with costs from e.g. Propaganda - if (!sim.getCombat().declareAttacker(attackersList.get(j).getId(), defenderId, playerId, sim)) { - sim.undo(playerId); - } - } - } - if (engagements.put(sim.getCombat().getValue().hashCode(), sim.getCombat()) != null) { - logger.debug("simulating -- found redundant attack combination"); - } - else if (logger.isDebugEnabled()) { - logger.debug("simulating -- attack:" + sim.getCombat().getGroups().size()); - } - } - return new ArrayList<>(engagements.values()); - } - - public List addBlockers(Game game) { - Map engagements = new HashMap<>(); - int numGroups = game.getCombat().getGroups().size(); - if (numGroups == 0) return new ArrayList<>(); - - //add a node with no blockers - Game sim = game.copy(); - engagements.put(sim.getCombat().getValue().hashCode(), sim.getCombat()); - sim.fireEvent(GameEvent.getEvent(GameEvent.EventType.DECLARED_BLOCKERS, playerId, playerId)); - - List blockers = getAvailableBlockers(game); - addBlocker(game, blockers, engagements); - - return new ArrayList<>(engagements.values()); - } - - protected void addBlocker(Game game, List blockers, Map engagements) { - if (blockers.isEmpty()) - return; - int numGroups = game.getCombat().getGroups().size(); - //try to block each attacker with each potential blocker - Permanent blocker = blockers.get(0); - if (logger.isDebugEnabled()) - logger.debug("simulating -- block:" + blocker); - List remaining = remove(blockers, blocker); - for (int i = 0; i < numGroups; i++) { - if (game.getCombat().getGroups().get(i).canBlock(blocker, game)) { - Game sim = game.copy(); - sim.getCombat().getGroups().get(i).addBlocker(blocker.getId(), playerId, sim); - if (engagements.put(sim.getCombat().getValue().hashCode(), sim.getCombat()) != null) - logger.debug("simulating -- found redundant block combination"); - addBlocker(sim, remaining, engagements); // and recurse minus the used blocker - } - } - addBlocker(game, remaining, engagements); - } - - @Override - public boolean triggerAbility(TriggeredAbility source, Game game) { - Ability ability = source.copy(); - List options = getPlayableOptions(ability, game); - if (options.isEmpty()) { - if (logger.isDebugEnabled()) - logger.debug("simulating -- triggered ability:" + ability); - game.getStack().push(new StackAbility(ability, playerId)); - if (ability.activate(game, false) && ability.isUsesStack()) { - game.fireEvent(new GameEvent(GameEvent.EventType.TRIGGERED_ABILITY, ability.getId(), ability, ability.getControllerId())); - } - game.applyEffects(); - game.getPlayers().resetPassed(); - } - else { - SimulationNode parent = (SimulationNode) game.getCustomData(); - if (parent.getDepth() == maxDepth) return true; - logger.debug(indent(parent.getDepth()) + "simulating -- triggered ability - adding children:" + options.size()); - for (Ability option: options) { - addAbilityNode(parent, option, game); - } - } - return true; - } - - protected void addAbilityNode(SimulationNode parent, Ability ability, Game game) { - Game sim = game.copy(); - sim.getStack().push(new StackAbility(ability, playerId)); - ability.activate(sim, false); - if (ability.activate(sim, false) && ability.isUsesStack()) { - game.fireEvent(new GameEvent(GameEvent.EventType.TRIGGERED_ABILITY, ability.getId(), ability, ability.getControllerId())); - } - sim.applyEffects(); - SimulationNode newNode = new SimulationNode(parent, sim, playerId); - logger.debug(indent(newNode.getDepth()) + "simulating -- node #:" + SimulationNode.getCount() + " triggered ability option"); - for (Target target: ability.getTargets()) { - for (UUID targetId: target.getTargets()) { - newNode.getTargets().add(targetId); - } - } - parent.children.add(newNode); - } - - @Override - public boolean priority(Game game) { - //should never get here - return false; - } - - protected String indent(int num) { - char[] fill = new char[num]; - Arrays.fill(fill, ' '); - return new String(fill); - } - -} 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 deleted file mode 100644 index cac08d4ee16..00000000000 --- a/Mage.Server.Plugins/Mage.Player.AIMinimax/src/mage/player/ai/SimulationNode.java +++ /dev/null @@ -1,111 +0,0 @@ - - -package mage.player.ai; - -import mage.abilities.Ability; -import mage.game.Game; -import mage.game.combat.Combat; - -import java.io.Serializable; -import java.util.ArrayList; -import java.util.List; -import java.util.UUID; - -/** - * - * @author BetaSteward_at_googlemail.com - */ -public class SimulationNode implements Serializable { - - protected static int nodeCount; - - protected Game game; - protected int gameValue; - 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(SimulationNode parent, Game game, UUID playerId) { - this.parent = parent; - this.game = game; - if (parent == null) - this.depth = 1; - else - this.depth = parent.getDepth() + 1; - this.playerId = playerId; - game.setCustomData(this); - nodeCount++; - } - - public SimulationNode(SimulationNode parent, Game game, List abilities, UUID playerId) { - this(parent, game, playerId); - this.abilities = abilities; - } - - public SimulationNode(SimulationNode parent, Game game, Ability ability, UUID playerId) { - this(parent, game, playerId); - this.abilities = new ArrayList<>(); - abilities.add(ability); - } - - public static void resetCount() { - nodeCount = 0; - } - - public static int getCount() { - return nodeCount; - } - - public Game getGame() { - return this.game; - } - - public int getGameValue() { - return this.gameValue; - } - - public void setGameValue(int value) { - this.gameValue = value; - } - - public List getAbilities() { - return this.abilities; - } - - public SimulationNode getParent() { - return this.parent; - } - - public List getChildren() { - return this.children; - } - - public int getDepth() { - return this.depth; - } - - public UUID getPlayerId() { - return this.playerId; - } - - public Combat getCombat() { - return this.combat; - } - - public void setCombat(Combat combat) { - this.combat = combat; - } - - public List getTargets() { - return this.targets; - } - - public List getChoices() { - return this.choices; - } -} diff --git a/Mage.Server.Plugins/Mage.Player.AIMinimax/src/mage/player/ai/SimulationWorker.java b/Mage.Server.Plugins/Mage.Player.AIMinimax/src/mage/player/ai/SimulationWorker.java deleted file mode 100644 index 7af884d5032..00000000000 --- a/Mage.Server.Plugins/Mage.Player.AIMinimax/src/mage/player/ai/SimulationWorker.java +++ /dev/null @@ -1,41 +0,0 @@ - - -package mage.player.ai; - -import java.util.concurrent.Callable; -import mage.abilities.Ability; -import mage.game.Game; -import org.apache.log4j.Logger; - -/** - * - * @author BetaSteward_at_googlemail.com - */ -public class SimulationWorker implements Callable { - - private static final Logger logger = Logger.getLogger(SimulationWorker.class); - - private Game game; - private SimulatedAction previousActions; - private Ability action; - private SimulatedPlayer player; - - public SimulationWorker(Game game, SimulatedPlayer player, SimulatedAction previousActions, Ability action) { - this.game = game; - this.player = player; - this.previousActions = previousActions; - this.action = action; - } - - @Override - public Object call() { - try { -// player.simulateAction(game, previousActions, action); - } catch (Exception ex) { - logger.error(null, ex); - } - return null; - } - -} - diff --git a/Mage.Server.Plugins/Mage.Player.Human/src/mage/player/human/HumanPlayer.java b/Mage.Server.Plugins/Mage.Player.Human/src/mage/player/human/HumanPlayer.java index e6d8bfa2d70..ffe0e1419b8 100644 --- a/Mage.Server.Plugins/Mage.Player.Human/src/mage/player/human/HumanPlayer.java +++ b/Mage.Server.Plugins/Mage.Player.Human/src/mage/player/human/HumanPlayer.java @@ -59,6 +59,8 @@ import static mage.constants.PlayerAction.REQUEST_AUTO_ANSWER_RESET_ALL; import static mage.constants.PlayerAction.TRIGGER_AUTO_ORDER_RESET_ALL; /** + * Human: server side logic to exchange game data between server app and another player's app + * * @author BetaSteward_at_googlemail.com, JayDi85 */ public class HumanPlayer extends PlayerImpl { diff --git a/Mage.Server.Plugins/pom.xml b/Mage.Server.Plugins/pom.xml index f5ff42689c7..778b175b4c2 100644 --- a/Mage.Server.Plugins/pom.xml +++ b/Mage.Server.Plugins/pom.xml @@ -36,7 +36,6 @@ Mage.Game.OathbreakerFreeForAll Mage.Game.TwoPlayerDuel Mage.Player.AI - Mage.Player.AIMinimax Mage.Player.AI.MA Mage.Player.AIMCTS Mage.Player.AI.DraftBot diff --git a/Mage.Server/config/config.xml b/Mage.Server/config/config.xml index 3e31310ac17..6e85074e835 100644 --- a/Mage.Server/config/config.xml +++ b/Mage.Server/config/config.xml @@ -66,7 +66,6 @@ /> - diff --git a/Mage.Server/pom.xml b/Mage.Server/pom.xml index 28e9f587753..eb0d25843b8 100644 --- a/Mage.Server/pom.xml +++ b/Mage.Server/pom.xml @@ -89,12 +89,6 @@ ${project.version} runtime - - ${project.groupId} - mage-player-aiminimax - ${project.version} - runtime - ${project.groupId} mage-player-ai-ma diff --git a/Mage.Server/release/plugins/AIMinimax.properties b/Mage.Server/release/plugins/AIMinimax.properties deleted file mode 100644 index 96b5480294c..00000000000 --- a/Mage.Server/release/plugins/AIMinimax.properties +++ /dev/null @@ -1,7 +0,0 @@ -maxDepth=10 -maxNodes=5000 -evaluatorLifeFactor=2 -evaluatorPermanentFactor=1 -evaluatorCreatureFactor=1 -evaluatorHandFactor=1 -maxThinkSeconds=30 \ No newline at end of file diff --git a/Mage.Server/src/main/assembly/distribution.xml b/Mage.Server/src/main/assembly/distribution.xml index 62ccfe10340..39a0c0bd9af 100644 --- a/Mage.Server/src/main/assembly/distribution.xml +++ b/Mage.Server/src/main/assembly/distribution.xml @@ -23,7 +23,6 @@ org.mage:mage-game-commanderduel org.mage:mage-game-freeforall org.mage:mage-game-twoplayerduel - org.mage:mage-player-aiminimax org.mage:mage-player-ai-ma org.mage:mage-player-human org.mage:mage-tournament-boosterdraft @@ -40,7 +39,6 @@ org.mage:mage-game-commanderduel org.mage:mage-game-freeforall org.mage:mage-game-twoplayerduel - org.mage:mage-player-aiminimax org.mage:mage-player-ai-ma org.mage:mage-player-human org.mage:mage-tournament-boosterdraft diff --git a/Mage.Tests/src/test/java/org/mage/test/mulligan/MulliganTestBase.java b/Mage.Tests/src/test/java/org/mage/test/mulligan/MulliganTestBase.java index bed27a2ff81..40fb1c5a621 100644 --- a/Mage.Tests/src/test/java/org/mage/test/mulligan/MulliganTestBase.java +++ b/Mage.Tests/src/test/java/org/mage/test/mulligan/MulliganTestBase.java @@ -38,7 +38,7 @@ public class MulliganTestBase { private final int freeMulligans; private final List steps = new ArrayList<>(); - private PlayerProxy player1; + private MulliganStubPlayer player1; public MulliganScenarioTest(MulliganType mulliganType, int freeMulligans) { this.mulliganType = mulliganType; @@ -73,13 +73,13 @@ public class MulliganTestBase { options.skipInitShuffling = true; game.setGameOptions(options); - this.player1 = new PlayerProxy("p1", ONE); + this.player1 = new MulliganStubPlayer("p1", ONE); player1.setSteps(steps); Deck deck1 = generateDeck(player1.getId(), 40); game.loadCards(deck1.getCards(), player1.getId()); game.addPlayer(player1, deck1); - PlayerProxy player2 = new PlayerProxy("p2", ONE); + MulliganStubPlayer player2 = new MulliganStubPlayer("p2", ONE); Deck deck2 = generateDeck(player2.getId(), 40); game.loadCards(deck2.getCards(), player2.getId()); game.addPlayer(player2, deck2); @@ -164,12 +164,12 @@ public class MulliganTestBase { List discardBottom(int count); } - static class PlayerProxy extends StubPlayer { + static class MulliganStubPlayer extends StubPlayer { private List steps = null; private int current = 0; - public PlayerProxy(String name, RangeOfInfluence range) { + public MulliganStubPlayer(String name, RangeOfInfluence range) { super(name, range); } diff --git a/Mage.Tests/src/test/java/org/mage/test/player/TestComputerPlayer.java b/Mage.Tests/src/test/java/org/mage/test/player/TestComputerPlayer.java index 3cc1c4b9389..d8bb28d0f08 100644 --- a/Mage.Tests/src/test/java/org/mage/test/player/TestComputerPlayer.java +++ b/Mage.Tests/src/test/java/org/mage/test/player/TestComputerPlayer.java @@ -11,10 +11,8 @@ import mage.target.Target; import mage.target.TargetCard; /** - * @author JayDi85 - */ - -/** + * AI: helper class for tests + *

* Mock class to inject test player support in the inner choice calls, e.g. in PlayerImpl. If you * want to set up inner choices then override it here. *

@@ -29,9 +27,11 @@ import mage.target.TargetCard; *

* If you implement set up of random results for tests (die roll, flip coin, etc) and want to support AI tests * (same random results in simulated games) then override same methods in SimulatedPlayer2 too + * + * @author JayDi85 */ -public class TestComputerPlayer extends ComputerPlayer { +public final class TestComputerPlayer extends ComputerPlayer { private TestPlayer testPlayerLink; diff --git a/Mage.Tests/src/test/java/org/mage/test/player/TestComputerPlayer7.java b/Mage.Tests/src/test/java/org/mage/test/player/TestComputerPlayer7.java index 44a4778c7c3..6934c4ecccd 100644 --- a/Mage.Tests/src/test/java/org/mage/test/player/TestComputerPlayer7.java +++ b/Mage.Tests/src/test/java/org/mage/test/player/TestComputerPlayer7.java @@ -11,12 +11,14 @@ import mage.target.Target; import mage.target.TargetCard; /** + * AI: helper class for tests + *

* Copied-pasted methods from TestComputerPlayer, see docs in there * * @author JayDi85 */ -public class TestComputerPlayer7 extends ComputerPlayer7 { +public final class TestComputerPlayer7 extends ComputerPlayer7 { private TestPlayer testPlayerLink; diff --git a/Mage.Tests/src/test/java/org/mage/test/player/TestComputerPlayerMonteCarlo.java b/Mage.Tests/src/test/java/org/mage/test/player/TestComputerPlayerMonteCarlo.java index 986d362baa2..8c3d3a83527 100644 --- a/Mage.Tests/src/test/java/org/mage/test/player/TestComputerPlayerMonteCarlo.java +++ b/Mage.Tests/src/test/java/org/mage/test/player/TestComputerPlayerMonteCarlo.java @@ -11,12 +11,14 @@ import mage.target.Target; import mage.target.TargetCard; /** + * AI: helper class for tests + *

* Copied-pasted methods from TestComputerPlayer, see docs in there * * @author JayDi85 */ -public class TestComputerPlayerMonteCarlo extends ComputerPlayerMCTS { +public final class TestComputerPlayerMonteCarlo extends ComputerPlayerMCTS { private TestPlayer testPlayerLink; diff --git a/Mage.Tests/src/test/java/org/mage/test/player/TestPlayer.java b/Mage.Tests/src/test/java/org/mage/test/player/TestPlayer.java index 6b5580b7f32..da07ec52407 100644 --- a/Mage.Tests/src/test/java/org/mage/test/player/TestPlayer.java +++ b/Mage.Tests/src/test/java/org/mage/test/player/TestPlayer.java @@ -63,6 +63,8 @@ import java.util.regex.Pattern; import java.util.stream.Collectors; /** + * Basic implementation of testable player + * * @author BetaSteward_at_googlemail.com * @author Simown * @author JayDi85 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 deleted file mode 100644 index 656261dd37f..00000000000 --- a/Mage.Tests/src/test/java/org/mage/test/serverside/PlayGameTest.java +++ /dev/null @@ -1,95 +0,0 @@ -package org.mage.test.serverside; - -import mage.cards.Card; -import mage.cards.Sets; -import mage.cards.decks.Deck; -import mage.constants.ColoredManaSymbol; -import mage.constants.MultiplayerAttackOption; -import mage.constants.RangeOfInfluence; -import mage.game.Game; -import mage.game.GameException; -import mage.game.GameOptions; -import mage.game.TwoPlayerDuel; -import mage.game.mulligan.MulliganType; -import mage.player.ai.ComputerPlayer; -import mage.players.Player; -import mage.players.PlayerType; -import mage.util.RandomUtil; -import org.junit.Ignore; -import org.junit.Test; -import org.mage.test.serverside.base.MageTestBase; - -import java.io.FileNotFoundException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Locale; - -/** - * @author ayratn - */ -public class PlayGameTest extends MageTestBase { - - private static final List colorChoices = new ArrayList<>(Arrays.asList("bu", "bg", "br", "bw", "ug", "ur", "uw", "gr", "gw", "rw", "bur", "buw", "bug", "brg", "brw", "bgw", "wur", "wug", "wrg", "rgu")); - private static final int DECK_SIZE = 40; - - @Ignore - @Test - public void playOneGame() throws GameException, FileNotFoundException, IllegalArgumentException { - Game game = new TwoPlayerDuel(MultiplayerAttackOption.LEFT, RangeOfInfluence.ALL, MulliganType.GAME_DEFAULT.getMulligan(0), 60, 20, 7); - - Player computerA = createPlayer("ComputerA", PlayerType.COMPUTER_MINIMAX_HYBRID); -// Player playerA = createPlayer("ComputerA", "Computer - mad"); -// Deck deck = Deck.load(Sets.loadDeck("RB Aggro.dck")); - Deck deck = generateRandomDeck(); - - if (deck.getMaindeckCards().size() < DECK_SIZE) { - throw new IllegalArgumentException("Couldn't load deck, deck size = " + deck.getMaindeckCards().size() + ", but must be " + DECK_SIZE); - } - game.addPlayer(computerA, deck); - game.loadCards(deck.getCards(), computerA.getId()); - - Player computerB = createPlayer("ComputerB", PlayerType.COMPUTER_MINIMAX_HYBRID); -// Player playerB = createPlayer("ComputerB", "Computer - mad"); -// Deck deck2 = Deck.load(Sets.loadDeck("RB Aggro.dck")); - Deck deck2 = generateRandomDeck(); - if (deck2.getMaindeckCards().size() < DECK_SIZE) { - throw new IllegalArgumentException("Couldn't load deck, deck size = " + deck2.getMaindeckCards().size() + ", but must be " + DECK_SIZE); - } - game.addPlayer(computerB, deck2); - game.loadCards(deck2.getCards(), computerB.getId()); - -// parseScenario("scenario1.txt"); -// game.cheat(playerA.getId(), commandsA); -// game.cheat(playerA.getId(), libraryCardsA, handCardsA, battlefieldCardsA, graveyardCardsA); -// game.cheat(playerB.getId(), commandsB); -// game.cheat(playerB.getId(), libraryCardsB, handCardsB, battlefieldCardsB, graveyardCardsB); - //boolean testMode = false; - boolean testMode = true; - - long t1 = System.nanoTime(); - GameOptions options = new GameOptions(); - options.testMode = true; - game.setGameOptions(options); - game.start(computerA.getId()); - long t2 = System.nanoTime(); - - logger.info("Winner: " + game.getWinner()); - logger.info("Time: " + (t2 - t1) / 1000000 + " ms"); - /*if (!game.getWinner().equals("Player ComputerA is the winner")) { - throw new RuntimeException("Lost :("); - }*/ - } - - private Deck generateRandomDeck() { - String selectedColors = colorChoices.get(RandomUtil.nextInt(colorChoices.size())).toUpperCase(Locale.ENGLISH); - List allowedColors = new ArrayList<>(); - logger.info("Building deck with colors: " + selectedColors); - for (int i = 0; i < selectedColors.length(); i++) { - char c = selectedColors.charAt(i); - allowedColors.add(ColoredManaSymbol.lookup(c)); - } - List cardPool = Sets.generateRandomCardPool(45, allowedColors); - return ComputerPlayer.buildDeck(DECK_SIZE, cardPool, allowedColors); - } -} diff --git a/Mage.Tests/src/test/java/org/mage/test/serverside/tournament/SwissPairingMinimalWeightMatchingTest.java b/Mage.Tests/src/test/java/org/mage/test/serverside/tournament/SwissPairingMinimalWeightMatchingTest.java index b144e00eb04..9ca1e968fb1 100644 --- a/Mage.Tests/src/test/java/org/mage/test/serverside/tournament/SwissPairingMinimalWeightMatchingTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/serverside/tournament/SwissPairingMinimalWeightMatchingTest.java @@ -1,14 +1,16 @@ package org.mage.test.serverside.tournament; +import mage.constants.RangeOfInfluence; import mage.game.tournament.Round; import mage.game.tournament.TournamentPairing; import mage.game.tournament.TournamentPlayer; import mage.game.tournament.pairing.RoundPairings; import mage.game.tournament.pairing.SwissPairingMinimalWeightMatching; +import mage.players.Player; +import mage.players.StubPlayer; import mage.util.RandomUtil; import org.junit.Assert; import org.junit.Test; -import org.mage.test.stub.PlayerStub; import org.mage.test.stub.TournamentStub; import java.util.ArrayList; @@ -21,15 +23,19 @@ import java.util.Set; */ public class SwissPairingMinimalWeightMatchingTest { + private Player createTourneyPlayer(int number) { + return new StubPlayer("Tourney player " + number, RangeOfInfluence.ALL); + } + @Test public void FourPlayersSecondRoundTest() { // 1 > 3 // 2 > 4 - TournamentPlayer player1 = new TournamentPlayer(new PlayerStub(), null); - TournamentPlayer player2 = new TournamentPlayer(new PlayerStub(), null); - TournamentPlayer player3 = new TournamentPlayer(new PlayerStub(), null); - TournamentPlayer player4 = new TournamentPlayer(new PlayerStub(), null); + TournamentPlayer player1 = new TournamentPlayer(createTourneyPlayer(1), null); + TournamentPlayer player2 = new TournamentPlayer(createTourneyPlayer(2), null); + TournamentPlayer player3 = new TournamentPlayer(createTourneyPlayer(3), null); + TournamentPlayer player4 = new TournamentPlayer(createTourneyPlayer(3), null); List players = new ArrayList<>(); players.add(player4); players.add(player2); @@ -68,10 +74,10 @@ public class SwissPairingMinimalWeightMatchingTest { // 1 > 2 // 3 > 4 - TournamentPlayer player3 = new TournamentPlayer(new PlayerStub(), null); - TournamentPlayer player2 = new TournamentPlayer(new PlayerStub(), null); - TournamentPlayer player4 = new TournamentPlayer(new PlayerStub(), null); - TournamentPlayer player1 = new TournamentPlayer(new PlayerStub(), null); + TournamentPlayer player3 = new TournamentPlayer(createTourneyPlayer(3), null); + TournamentPlayer player2 = new TournamentPlayer(createTourneyPlayer(2), null); + TournamentPlayer player4 = new TournamentPlayer(createTourneyPlayer(4), null); + TournamentPlayer player1 = new TournamentPlayer(createTourneyPlayer(1), null); List players = new ArrayList<>(); players.add(player4); players.add(player2); @@ -116,10 +122,10 @@ public class SwissPairingMinimalWeightMatchingTest { // 2 > 4 // 4 left the tournament - TournamentPlayer player1 = new TournamentPlayer(new PlayerStub(), null); - TournamentPlayer player2 = new TournamentPlayer(new PlayerStub(), null); - TournamentPlayer player3 = new TournamentPlayer(new PlayerStub(), null); - TournamentPlayer player4 = new TournamentPlayer(new PlayerStub(), null); + TournamentPlayer player1 = new TournamentPlayer(createTourneyPlayer(1), null); + TournamentPlayer player2 = new TournamentPlayer(createTourneyPlayer(2), null); + TournamentPlayer player3 = new TournamentPlayer(createTourneyPlayer(3), null); + TournamentPlayer player4 = new TournamentPlayer(createTourneyPlayer(4), null); List players = new ArrayList<>(); //players.add(player4); -- player 4 is not active players.add(player2); @@ -159,11 +165,11 @@ public class SwissPairingMinimalWeightMatchingTest { // 2 > 3 // 4 - TournamentPlayer player1 = new TournamentPlayer(new PlayerStub(), null); - TournamentPlayer player2 = new TournamentPlayer(new PlayerStub(), null); - TournamentPlayer player3 = new TournamentPlayer(new PlayerStub(), null); - TournamentPlayer player4 = new TournamentPlayer(new PlayerStub(), null); - TournamentPlayer player5 = new TournamentPlayer(new PlayerStub(), null); + TournamentPlayer player1 = new TournamentPlayer(createTourneyPlayer(1), null); + TournamentPlayer player2 = new TournamentPlayer(createTourneyPlayer(2), null); + TournamentPlayer player3 = new TournamentPlayer(createTourneyPlayer(3), null); + TournamentPlayer player4 = new TournamentPlayer(createTourneyPlayer(4), null); + TournamentPlayer player5 = new TournamentPlayer(createTourneyPlayer(5), null); List players = new ArrayList<>(); players.add(player4); players.add(player2); @@ -214,11 +220,11 @@ public class SwissPairingMinimalWeightMatchingTest { // 5 left the tournament - TournamentPlayer player1 = new TournamentPlayer(new PlayerStub(), null); - TournamentPlayer player2 = new TournamentPlayer(new PlayerStub(), null); - TournamentPlayer player3 = new TournamentPlayer(new PlayerStub(), null); - TournamentPlayer player4 = new TournamentPlayer(new PlayerStub(), null); - TournamentPlayer player5 = new TournamentPlayer(new PlayerStub(), null); + TournamentPlayer player1 = new TournamentPlayer(createTourneyPlayer(1), null); + TournamentPlayer player2 = new TournamentPlayer(createTourneyPlayer(2), null); + TournamentPlayer player3 = new TournamentPlayer(createTourneyPlayer(3), null); + TournamentPlayer player4 = new TournamentPlayer(createTourneyPlayer(4), null); + TournamentPlayer player5 = new TournamentPlayer(createTourneyPlayer(5), null); List players = new ArrayList<>(); //players.add(player5); -- player 5 is not active players.add(player4); @@ -268,7 +274,7 @@ public class SwissPairingMinimalWeightMatchingTest { List players = new ArrayList<>(); for (int i = 0; i < playersCount; i++) { - players.add(new TournamentPlayer(new PlayerStub(), null)); + players.add(new TournamentPlayer(createTourneyPlayer(i + 1), null)); } List playedPairs = new ArrayList<>(); diff --git a/Mage.Tests/src/test/java/org/mage/test/stub/PlayerStub.java b/Mage.Tests/src/test/java/org/mage/test/stub/PlayerStub.java deleted file mode 100644 index 0b92f4f154c..00000000000 --- a/Mage.Tests/src/test/java/org/mage/test/stub/PlayerStub.java +++ /dev/null @@ -1,1466 +0,0 @@ -package org.mage.test.stub; - -import mage.ApprovingObject; -import mage.MageIdentifier; -import mage.MageObject; -import mage.Mana; -import mage.abilities.*; -import mage.abilities.costs.AlternativeSourceCosts; -import mage.abilities.costs.Cost; -import mage.abilities.costs.Costs; -import mage.abilities.costs.VariableCost; -import mage.abilities.costs.mana.ManaCost; -import mage.abilities.costs.mana.ManaCosts; -import mage.abilities.mana.ManaOptions; -import mage.cards.Card; -import mage.cards.Cards; -import mage.cards.decks.Deck; -import mage.choices.Choice; -import mage.constants.*; -import mage.counters.Counter; -import mage.counters.Counters; -import mage.designations.Designation; -import mage.designations.DesignationType; -import mage.filter.FilterCard; -import mage.filter.FilterMana; -import mage.filter.FilterPermanent; -import mage.game.Game; -import mage.game.Graveyard; -import mage.game.Table; -import mage.game.combat.CombatGroup; -import mage.game.draft.Draft; -import mage.game.events.GameEvent; -import mage.game.match.Match; -import mage.game.match.MatchPlayer; -import mage.game.permanent.Permanent; -import mage.game.tournament.Tournament; -import mage.players.Library; -import mage.players.ManaPool; -import mage.players.PlayableObjectsList; -import mage.players.Player; -import mage.players.net.UserData; -import mage.target.Target; -import mage.target.TargetAmount; -import mage.target.TargetCard; -import mage.target.common.TargetCardInLibrary; -import mage.util.MultiAmountMessage; - -import java.io.Serializable; -import java.util.*; - -/** - * @author Quercitron - */ -public class PlayerStub implements Player { - - private final UUID id = UUID.randomUUID(); - - @Override - public UUID getId() { - return id; - } - - @Override - public boolean isHuman() { - return false; - } - - @Override - public String getName() { - return null; - } - - @Override - public String getLogName() { - return null; - } - - @Override - public RangeOfInfluence getRange() { - return null; - } - - @Override - public Library getLibrary() { - return null; - } - - @Override - public Cards getSideboard() { - return null; - } - - @Override - public Graveyard getGraveyard() { - return null; - } - - @Override - public Abilities getAbilities() { - return null; - } - - @Override - public void addAbility(Ability ability) { - - } - - @Override - public Counters getCounters() { - return null; - } - - @Override - public int getLife() { - return 0; - } - - @Override - public void initLife(int life) { - - } - - @Override - public void setLife(int life, Game game, Ability source) { - - } - - @Override - public int loseLife(int amount, Game game, Ability source, boolean atCombat, UUID attackerId) { - return 0; - } - - @Override - public int loseLife(int amount, Game game, Ability source, boolean atCombat) { - return 0; - } - - @Override - public int gainLife(int amount, Game game, Ability source) { - return 0; - } - - @Override - public void exchangeLife(Player player, Ability source, Game game) { - } - - @Override - public int damage(int damage, UUID attackerId, Ability source, Game game) { - return 0; - } - - @Override - public int damage(int damage, Ability source, Game game) { - return 0; - } - - @Override - public int damage(int damage, UUID attackerId, Ability source, Game game, boolean combatDamage, boolean preventable) { - return 0; - } - - @Override - public int damage(int damage, UUID attackerId, Ability source, Game game, boolean combatDamage, boolean preventable, List appliedEffects) { - return 0; - } - - @Override - public boolean isCanLoseLife() { - return false; - } - - @Override - public void setCanLoseLife(boolean canLoseLife) { - - } - - @Override - public void setCanGainLife(boolean canGainLife) { - - } - - @Override - public boolean isCanGainLife() { - return false; - } - - @Override - public void setPayLifeCostLevel(PayLifeCostLevel playLifeCostLevel) { - } - - @Override - public PayLifeCostLevel getPayLifeCostLevel() { - return PayLifeCostLevel.none; - } - - @Override - public boolean canPayLifeCost(Ability ability) { - return false; - } - - @Override - public void setCanPaySacrificeCostFilter(FilterPermanent filter) { - } - - @Override - public FilterPermanent getSacrificeCostFilter() { - return null; - } - - @Override - public boolean canPaySacrificeCost(Permanent permanent, Ability source, UUID controllerId, Game game) { - return false; - } - - @Override - public void setLifeTotalCanChange(boolean lifeTotalCanChange) { - - } - - @Override - public boolean isLifeTotalCanChange() { - return false; - } - - @Override - public void setLoseByZeroOrLessLife(boolean loseByZeroOrLessLife) { - - } - - @Override - public boolean canLoseByZeroOrLessLife() { - return false; - } - - @Override - public void setPlayCardsFromGraveyard(boolean playCardsFromGraveyard) { - - } - - @Override - public boolean canPlayCardsFromGraveyard() { - return false; - } - - @Override - public void setDrawsOnOpponentsTurn(boolean drawsOnOpponentsTurn) { - - } - - @Override - public boolean isDrawsOnOpponentsTurn() { - return false; - } - - @Override - public List getAlternativeSourceCosts() { - return null; - } - - @Override - public Cards getHand() { - return null; - } - - @Override - public void incrementLandsPlayed() { - } - - @Override - public void resetLandsPlayed() { - } - - @Override - public int getLandsPlayed() { - return 0; - } - - @Override - public int getLandsPerTurn() { - return 0; - } - - @Override - public void setLandsPerTurn(int landsPerTurn) { - - } - - @Override - public int getMaxHandSize() { - return 0; - } - - @Override - public void setMaxHandSize(int maxHandSize) { - - } - - @Override - public int getMaxAttackedBy() { - return 0; - } - - @Override - public void setMaxAttackedBy(int maxAttackedBy) { - - } - - @Override - public boolean isPassed() { - return false; - } - - @Override - public void pass(Game game) { - - } - - @Override - public void resetPassed() { - - } - - @Override - public void resetPlayerPassedActions() { - - } - - @Override - public boolean getPassedTurn() { - return false; - } - - @Override - public boolean getPassedUntilEndOfTurn() { - return false; - } - - @Override - public boolean getPassedUntilNextMain() { - return false; - } - - @Override - public boolean getPassedUntilStackResolved() { - return false; - } - - @Override - public boolean getPassedAllTurns() { - return false; - } - - @Override - public boolean getPassedUntilEndStepBeforeMyTurn() { - return false; - } - - @Override - public AbilityType getJustActivatedType() { - return null; - } - - @Override - public void setJustActivatedType(AbilityType abilityType) { - - } - - @Override - public boolean hasLost() { - return false; - } - - @Override - public boolean hasWon() { - return false; - } - - @Override - public boolean hasQuit() { - return false; - } - - @Override - public void quit(Game game) { - - } - - @Override - public boolean hasTimerTimeout() { - return false; - } - - @Override - public void timerTimeout(Game game) { - - } - - @Override - public boolean hasIdleTimeout() { - return false; - } - - @Override - public void idleTimeout(Game game) { - - } - - @Override - public boolean hasLeft() { - return false; - } - - @Override - public boolean isInGame() { - return false; - } - - @Override - public boolean canRespond() { - return false; - } - - @Override - public ManaPool getManaPool() { - return null; - } - - @Override - public Set getInRange() { - return null; - } - - @Override - public boolean isTopCardRevealed() { - return false; - } - - @Override - public void setTopCardRevealed(boolean topCardRevealed) { - - } - - @Override - public UserData getUserData() { - return null; - } - - @Override - public void setUserData(UserData userData) { - - } - - @Override - public boolean canLose(Game game) { - return false; - } - - @Override - public boolean autoLoseGame() { - return false; - } - - @Override - public Set getPlayersUnderYourControl() { - return null; - } - - @Override - public void controlPlayersTurn(Game game, UUID playerUnderControlId, String info) { - - } - - @Override - public void setTurnControlledBy(UUID playerId) { - - } - - @Override - public UUID getTurnControlledBy() { - return null; - } - - @Override - public void resetOtherTurnsControlled() { - - } - - @Override - public boolean isGameUnderControl() { - return false; - } - - @Override - public void setGameUnderYourControl(boolean value) { - - } - - @Override - public boolean isTestsMode() { - return false; - } - - @Override - public void setTestMode(boolean value) { - - } - - @Override - public void addAction(String action) { - - } - - @Override - public int getActionCount() { - return 0; - } - - @Override - public void setAllowBadMoves(boolean allowBadMoves) { - - } - - @Override - public void init(Game game) { - - } - - @Override - public void useDeck(Deck deck, Game game) { - - } - - @Override - public void reset() { - - } - - @Override - public void shuffleLibrary(Ability source, Game game) { - - } - - @Override - public int drawCards(int num, Ability source, Game game) { - return 0; - } - - @Override - public int drawCards(int num, Ability source, Game game, GameEvent event) { - return 0; - } - - @Override - public boolean cast(SpellAbility ability, Game game, boolean noMana, ApprovingObject approvingObject) { - return false; - } - - @Override - public boolean removeFromHand(Card card, Game game) { - return false; - } - - @Override - public boolean removeFromBattlefield(Permanent permanent, Ability source, Game game) { - return false; - } - - @Override - public boolean putInGraveyard(Card card, Game game) { - return false; - } - - @Override - public boolean removeFromGraveyard(Card card, Game game) { - return false; - } - - @Override - public boolean removeFromLibrary(Card card, Game game) { - return false; - } - - @Override - public boolean searchLibrary(TargetCardInLibrary target, Ability source, Game game) { - return false; - } - - @Override - public boolean searchLibrary(TargetCardInLibrary target, Ability source, Game game, UUID targetPlayerId) { - return false; - } - - @Override - public boolean seekCard(FilterCard filter, Ability source, Game game) { - return false; - } - - @Override - public void lookAtAllLibraries(Ability source, Game game) { - } - - @Override - public boolean canPlayLand() { - return false; - } - - @Override - public boolean playCard(Card card, Game game, boolean noMana, ApprovingObject approvingObject) { - return false; - } - - @Override - public boolean playLand(Card card, Game game, boolean ignoreTiming) { - return false; - } - - @Override - public boolean activateAbility(ActivatedAbility ability, Game game) { - return false; - } - - @Override - public boolean triggerAbility(TriggeredAbility ability, Game game) { - return false; - } - - @Override - public boolean canBeTargetedBy(MageObject source, UUID sourceControllerId, Game game) { - return false; - } - - @Override - public boolean hasProtectionFrom(MageObject source, Game game) { - return false; - } - - @Override - public boolean flipCoin(Ability source, Game game, boolean winnable) { - return false; - } - - @Override - public boolean flipCoinResult(Game game) { - return false; - } - - @Override - public List rollDice(Outcome outcome, Ability source, Game game, int numSides, int numDice, int ignoreLowestAmount) { - return null; - } - - @Override - public int rollDieResult(int sides, Game game) { - return 1; - } - - @Override - public Cards discard(Cards cards, boolean payForCost, Ability source, Game game) { - return null; - } - - @Override - public Card discardOne(boolean random, boolean payForCost, Ability source, Game game) { - return null; - } - - @Override - public Cards discard(int amount, boolean random, boolean payForCost, Ability source, Game game) { - return null; - } - - @Override - public Cards discard(int minAmount, int maxAmount, boolean payForCost, Ability source, Game game) { - return null; - } - - @Override - public void discardToMax(Game game) { - - } - - @Override - public boolean discard(Card card, boolean payForCost, Ability source, Game game) { - return false; - } - - @Override - public void lost(Game game) { - - } - - @Override - public void lostForced(Game game) { - - } - - @Override - public void won(Game game) { - - } - - @Override - public void leave() { - - } - - @Override - public void concede(Game game) { - - } - - @Override - public void abort() { - - } - - @Override - public void signalPlayerConcede() { - - } - - @Override - public void signalPlayerCheat() { - - } - - @Override - public void abortReset() { - - } - - @Override - public void skip() { - - } - - @Override - public void sendPlayerAction(PlayerAction passPriorityAction, Game game, Object data) { - - } - - @Override - public int getStoredBookmark() { - return 0; - } - - @Override - public void setStoredBookmark(int bookmark) { - - } - - @Override - public void resetStoredBookmark(Game game) { - - } - - @Override - public void revealCards(Ability source, Cards cards, Game game) { - - } - - @Override - public void revealCards(String name, Cards cards, Game game) { - - } - - @Override - public void revealCards(Ability source, String name, Cards cards, Game game) { - - } - - @Override - public void revealCards(String name, Cards cards, Game game, boolean postToLog) { - - } - - @Override - public void revealCards(Ability source, String name, Cards cards, Game game, boolean postToLog) { - - } - - @Override - public void lookAtCards(String name, Card card, Game game) { - - } - - @Override - public void lookAtCards(String name, Cards cards, Game game) { - - } - - @Override - public void lookAtCards(Ability source, String name, Cards cards, Game game) { - - } - - @Override - public Player copy() { - return null; - } - - @Override - public void restore(Player player) { - - } - - @Override - public void setResponseString(String responseString) { - - } - - @Override - public void setResponseUUID(UUID responseUUID) { - - } - - @Override - public void setResponseBoolean(Boolean responseBoolean) { - - } - - @Override - public void setResponseInteger(Integer data) { - - } - - @Override - public void setResponseManaType(UUID manaTypePlayerId, ManaType responseManaType) { - - } - - @Override - public boolean priority(Game game) { - return false; - } - - @Override - public boolean choose(Outcome outcome, Target target, Ability source, Game game) { - return false; - } - - @Override - public boolean choose(Outcome outcome, Target target, Ability source, Game game, Map options) { - return false; - } - - @Override - public boolean choose(Outcome outcome, Cards cards, TargetCard target, Ability source, Game game) { - return false; - } - - @Override - public boolean chooseTarget(Outcome outcome, Target target, Ability source, Game game) { - return false; - } - - @Override - public boolean chooseTarget(Outcome outcome, Cards cards, TargetCard target, Ability source, Game game) { - return false; - } - - @Override - public boolean chooseTargetAmount(Outcome outcome, TargetAmount target, Ability source, Game game) { - return false; - } - - @Override - public boolean chooseMulligan(Game game) { - return false; - } - - @Override - public boolean chooseUse(Outcome outcome, String message, Ability source, Game game) { - return false; - } - - @Override - public boolean chooseUse(Outcome outcome, String message, String secondMessage, String trueText, String falseText, Ability source, Game game) { - return false; - } - - @Override - public boolean choose(Outcome outcome, Choice choice, Game game) { - return false; - } - - @Override - public boolean choosePile(Outcome outcome, String message, List pile1, List pile2, Game game) { - return false; - } - - @Override - public boolean playMana(Ability ability, ManaCost unpaid, String promptText, Game game) { - return false; - } - - @Override - public boolean putCardsOnBottomOfLibrary(Card card, Game game, Ability source, boolean anyOrder) { - return false; - } - - @Override - public boolean putCardsOnBottomOfLibrary(Cards cards, Game game, Ability source, boolean anyOrder) { - return false; - } - - @Override - public boolean putCardsOnTopOfLibrary(Cards cards, Game game, Ability source, boolean anyOrder) { - return false; - } - - @Override - public boolean putCardsOnTopOfLibrary(Card card, Game game, Ability source, boolean anyOrder) { - return false; - } - - @Override - public boolean shuffleCardsToLibrary(Cards cards, Game game, Ability source) { - return false; - } - - @Override - public boolean shuffleCardsToLibrary(Card card, Game game, Ability source) { - return false; - } - - @Override - public boolean putCardOnTopXOfLibrary(Card card, Game game, Ability source, int xFromTheTop, boolean withName) { - return true; - } - - @Override - public int announceXMana(int min, int max, int multiplier, String message, Game game, Ability ability) { - return min; - } - - @Override - public int announceXCost(int min, int max, String message, Game game, Ability ability, VariableCost variableCost) { - return min; - } - - @Override - public int chooseReplacementEffect(Map abilityMap, Game game) { - return 0; - } - - @Override - public TriggeredAbility chooseTriggeredAbility(List abilities, Game game) { - return null; - } - - @Override - public Mode chooseMode(Modes modes, Ability source, Game game) { - return null; - } - - @Override - public void selectAttackers(Game game, UUID attackingPlayerId) { - - } - - @Override - public void selectBlockers(Ability source, Game game, UUID defendingPlayerId) { - - } - - @Override - public UUID chooseAttackerOrder(List attacker, Game game) { - return null; - } - - @Override - public UUID chooseBlockerOrder(List blockers, CombatGroup combatGroup, List blockerOrder, Game game) { - return null; - } - - @Override - public void assignDamage(int damage, List targets, String singleTargetName, UUID attackerId, Ability source, Game game) { - - } - - @Override - public int getAmount(int min, int max, String message, Game game) { - return 0; - } - - @Override - public List getMultiAmountWithIndividualConstraints(Outcome outcome, List messages, - int min, int max, MultiAmountType type, Game game) { - return null; - } - - @Override - public void sideboard(Match match, Deck deck) { - - } - - @Override - public void construct(Tournament tournament, Deck deck) { - - } - - @Override - public void pickCard(List cards, Deck deck, Draft draft) { - - } - - @Override - public void declareAttacker(UUID attackerId, UUID defenderId, Game game, boolean allowUndo) { - - } - - @Override - public void declareBlocker(UUID defenderId, UUID blockerId, UUID attackerId, Game game) { - - } - - @Override - public void declareBlocker(UUID defenderId, UUID blockerId, UUID attackerId, Game game, boolean allowUndo) { - - } - - @Override - public List getAvailableAttackers(Game game) { - return null; - } - - @Override - public List getAvailableAttackers(UUID defenderId, Game game) { - return null; - } - - @Override - public List getAvailableBlockers(Game game) { - return null; - } - - @Override - public void beginTurn(Game game) { - - } - - @Override - public void endOfTurn(Game game) { - - } - - @Override - public void phasing(Game game) { - - } - - @Override - public void untap(Game game) { - - } - - @Override - public void updateRange(Game game) { - - } - - @Override - public ManaOptions getManaAvailable(Game game) { - return null; - } - - @Override - public void addAvailableTriggeredMana(List availableTriggeredMan) { - - } - - @Override - public List> getAvailableTriggeredMana() { - return null; - } - - @Override - public int announceXMana(int min, int max, String message, Game game, Ability ability) { - return 0; - } - - @Override - public List getPlayable(Game game, boolean hidden) { - return null; - } - - @Override - public List getPlayableOptions(Ability ability, Game game) { - return null; - } - - @Override - public PlayableObjectsList getPlayableObjects(Game game, Zone zone) { - return null; - } - - @Override - public LinkedHashMap getPlayableActivatedAbilities(MageObject object, Zone zone, Game game) { - return null; - } - - @Override - public boolean addCounters(Counter counter, UUID playerAddingCounters, Ability source, Game game) { - return true; - } - - @Override - public void removeCounters(String name, int amount, Ability source, Game game) { - - } - - @Override - public List getAttachments() { - return null; - } - - @Override - public boolean addAttachment(UUID permanentId, Ability source, Game game) { - return false; - } - - @Override - public boolean removeAttachment(Permanent permanent, Ability source, Game game) { - return false; - } - - @Override - public void becomesActivePlayer() { - - } - - @Override - public int getTurns() { - return 0; - } - - @Override - public boolean lookAtFaceDownCard(Card card, Game game, int abilitiesToActivate) { - return false; - } - - @Override - public void setPriorityTimeLeft(int timeLeft) { - - } - - @Override - public int getPriorityTimeLeft() { - return 0; - } - - @Override - public void setBufferTimeLeft(int timeLeft) { - - } - - @Override - public int getBufferTimeLeft() { - return 0; - } - - @Override - public void setReachedNextTurnAfterLeaving(boolean reachedNextTurnAfterLeaving) { - - } - - @Override - public boolean hasReachedNextTurnAfterLeaving() { - return false; - } - - @Override - public boolean canJoinTable(Table table) { - return false; - } - - @Override - public void addCommanderId(UUID commanderId) { - - } - - @Override - public Set getCommandersIds() { - return null; - } - - @Override - public boolean moveCards(Card card, Zone toZone, Ability source, Game game) { - return false; - } - - @Override - public boolean moveCards(Card card, Zone toZone, Ability source, Game game, boolean tapped, boolean faceDown, boolean byOwner, List appliedEffects) { - return false; - } - - @Override - public boolean moveCards(Cards cards, Zone toZone, Ability source, Game game) { - return false; - } - - @Override - public boolean moveCards(Set cards, Zone toZone, Ability source, Game game) { - return false; - } - - @Override - public boolean moveCards(Set cards, Zone toZone, Ability source, Game game, boolean tapped, boolean faceDown, boolean byOwner, List appliedEffects) { - return false; - } - - @Override - public boolean moveCardsToExile(Card card, Ability source, Game game, boolean withName, UUID exileId, String exileZoneName) { - return false; - } - - @Override - public boolean moveCardsToExile(Set cards, Ability source, Game game, boolean withName, UUID exileId, String exileZoneName) { - return false; - } - - @Override - public boolean moveCardToHandWithInfo(Card card, Ability source, Game game, boolean withName) { - return false; - } - - @Override - public boolean moveCardsToHandWithInfo(Cards cards, Ability source, Game game, boolean withName) { - return false; - } - - @Override - public boolean moveCardToExileWithInfo(Card card, UUID exileId, String exileName, Ability source, Game game, Zone fromZone, boolean withName) { - return false; - } - - @Override - public boolean moveCardToGraveyardWithInfo(Card card, Ability source, Game game, Zone fromZone) { - return false; - } - - @Override - public Set moveCardsToGraveyardWithInfo(Set cards, Ability source, Game game, Zone fromZone) { - return null; - } - - @Override - public boolean moveCardToLibraryWithInfo(Card card, Ability source, Game game, Zone fromZone, boolean toTop, boolean withName) { - return false; - } - - @Override - public boolean moveCardToCommandWithInfo(Card card, Ability source, Game game, Zone fromZone) { - return false; - } - - @Override - public Cards millCards(int toMill, Ability source, Game game) { - return null; - } - - @Override - public boolean hasOpponent(UUID playerToCheckId, Game game) { - return false; - } - - @Override - public void cleanUpOnMatchEnd() { - - } - - @Override - public Map> getCastSourceIdWithAlternateMana() { - return null; - } - - @Override - public void setCastSourceIdWithAlternateMana(UUID sourceId, ManaCosts manaCosts, Costs costs, MageIdentifier identifier) { - - } - - @Override - public Map>> getCastSourceIdCosts() { - return null; - } - - @Override - public Map>> getCastSourceIdManaCosts() { - return null; - } - - @Override - public void clearCastSourceIdManaCosts() { - - } - - @Override - public void addPermissionToShowHandCards(UUID watcherUserId) { - - } - - @Override - public boolean hasUserPermissionToSeeHand(UUID userId) { - return false; - } - - @Override - public void revokePermissionToSeeHandCards() { - - } - - @Override - public boolean isPlayerAllowedToRequestHand(UUID gameId, UUID requesterPlayerId) { - return false; - } - - @Override - public void addPlayerToRequestedHandList(UUID gameId, UUID requesterPlayerId) { - // - } - - @Override - public Set getUsersAllowedToSeeHandCards() { - return null; - } - - @Override - public boolean isInPayManaMode() { - return false; - } - - @Override - public void setMatchPlayer(MatchPlayer matchPlayer) { - - } - - @Override - public MatchPlayer getMatchPlayer() { - return null; - } - - @Override - public boolean scry(int value, Ability source, Game game) { - return false; - } - - @Override - public SurveilResult doSurveil(int value, Ability source, Game game) { - return SurveilResult.noSurveil(); - } - - @Override - public boolean addTargets(Ability ability, Game game) { - return false; - } - - @Override - public String getHistory() { - return ""; - } - - @Override - public boolean hasDrew() { - return false; - } - - @Override - public void drew(Game game) { - - } - - @Override - public boolean hasDesignation(DesignationType designationName) { - return false; - } - - @Override - public void addDesignation(Designation designation) { - - } - - @Override - public List getDesignations() { - return null; - } - - @Override - public PlanarDieRollResult rollPlanarDie(Outcome outcome, Ability source, Game game, int numberChaosSides, int numberPlanarSides) { - throw new UnsupportedOperationException("Not supported yet."); - } - - @Override - public List getTurnControllers() { - throw new UnsupportedOperationException("Not supported yet."); - } - - @Override - public void setGameUnderYourControl(boolean value, boolean fullRestore) { - - } - - @Override - public void setPayManaMode(boolean payManaMode) { - - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - - if (o == null || getClass() != o.getClass()) { - return false; - } - - Player obj = (Player) o; - if (this.getId() == null || obj.getId() == null) { - return false; - } - - return this.getId().equals(obj.getId()); - } - - @Override - public int hashCode() { - int hash = 5; - hash = 41 * hash + Objects.hashCode(this.id); - return hash; - } - - @Override - public void addPhyrexianToColors(FilterMana colors) { - - } - - @Override - public FilterMana getPhyrexianColors() { - return (new FilterMana()); - } - - @Override - public Permanent getRingBearer(Game game) { - return null; - } - - @Override - public void chooseRingBearer(Game game) { - } - - @Override - public UserData getControllingPlayersUserData(Game game) { - return null; - } - - @Override - public SpellAbility chooseAbilityForCast(Card card, Game game, boolean noMana) { - return card.getSpellAbility(); - } - - @Override - public ActivatedAbility chooseLandOrSpellAbility(Card card, Game game, boolean noMana) { - return card.getSpellAbility(); - } -} diff --git a/Mage/src/main/java/mage/game/match/MatchImpl.java b/Mage/src/main/java/mage/game/match/MatchImpl.java index 6deb8f1d1e1..98ae8b21dd9 100644 --- a/Mage/src/main/java/mage/game/match/MatchImpl.java +++ b/Mage/src/main/java/mage/game/match/MatchImpl.java @@ -199,7 +199,7 @@ public abstract class MatchImpl implements Match { matchPlayer.getPlayer().init(game); game.loadCards(matchPlayer.getDeck().getCards(), matchPlayer.getPlayer().getId()); game.loadCards(matchPlayer.getDeck().getSideboard(), matchPlayer.getPlayer().getId()); - game.addPlayer(matchPlayer.getPlayer(), matchPlayer.getDeck()); + game.addPlayer(matchPlayer.getPlayer(), matchPlayer.getDeck()); // TODO: keeps old player?! // time limits matchPlayer.getPlayer().setBufferTimeLeft(options.getMatchBufferTime().getBufferSecs()); if (games.isEmpty()) { diff --git a/Mage/src/main/java/mage/players/PlayerType.java b/Mage/src/main/java/mage/players/PlayerType.java index 2f8c36e6106..75bd6058227 100644 --- a/Mage/src/main/java/mage/players/PlayerType.java +++ b/Mage/src/main/java/mage/players/PlayerType.java @@ -1,16 +1,19 @@ package mage.players; /** - * Created by IGOUDT on 2-4-2017. + * Server: all possible player types + *

+ * Warning, do not change description - it must be same with config.xml file + * + * @author IGOUDT */ public enum PlayerType { HUMAN("Human"), COMPUTER_DRAFT_BOT("Computer - draftbot"), - COMPUTER_MINIMAX_HYBRID("Computer - minimax hybrid"), COMPUTER_MONTE_CARLO("Computer - monte carlo"), COMPUTER_MAD("Computer - mad"); - String description; + final String description; PlayerType(String description) { this.description = description; @@ -27,6 +30,6 @@ public enum PlayerType { return type; } } - throw new IllegalArgumentException(String.format("PlayerType (%s) is not configured", description)); + throw new IllegalArgumentException(String.format("PlayerType (%s) is not configured in server's config.xml", description)); } } diff --git a/Mage/src/main/java/mage/players/StubPlayer.java b/Mage/src/main/java/mage/players/StubPlayer.java index 0cef8efa61b..67af4945a16 100644 --- a/Mage/src/main/java/mage/players/StubPlayer.java +++ b/Mage/src/main/java/mage/players/StubPlayer.java @@ -35,7 +35,10 @@ import java.util.UUID; import static com.google.common.collect.Iterables.getOnlyElement; -public class StubPlayer extends PlayerImpl implements Player { +/** + * Empty player, do nothing, used for tests only + */ +public class StubPlayer extends PlayerImpl { @Override public boolean choose(Outcome outcome, Target target, Ability source, Game game) { @@ -209,7 +212,7 @@ public class StubPlayer extends PlayerImpl implements Player { @Override public List getMultiAmountWithIndividualConstraints(Outcome outcome, List messages, - int min, int max, MultiAmountType type, Game game) { + int min, int max, MultiAmountType type, Game game) { return null; } @@ -227,10 +230,10 @@ public class StubPlayer extends PlayerImpl implements Player { public void pickCard(List cards, Deck deck, Draft draft) { } - + @Override public void addPhyrexianToColors(FilterMana colors) { - + } @Override