diff --git a/src/magic/CardTest.java b/src/magic/CardTest.java new file mode 100644 index 0000000000..4d8a264b3e --- /dev/null +++ b/src/magic/CardTest.java @@ -0,0 +1,219 @@ +package magic; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import magic.ai.MagicAI; +import magic.ai.MagicAIImpl; +import magic.data.CardDefinitions; +import magic.data.DuelConfig; +import magic.exception.handler.ConsoleExceptionHandler; +import magic.headless.HeadlessGameController; +import magic.model.DuelPlayerConfig; +import magic.model.MagicCardDefinition; +import magic.model.MagicDeckProfile; +import magic.model.MagicDuel; +import magic.model.MagicGame; +import magic.model.MagicPlayer; +import magic.model.phase.MagicMainPhase; +import magic.model.player.AiProfile; +import magic.test.TestGameBuilder; +import magic.utility.MagicSystem; +import magic.utility.ProgressReporter; + +/** + * Special kind of headless game, where every implemented + * card and token is used for a very short game in a predefined scenario. + */ +public class CardTest { + private static void parseCommandLine(CommandLineArgs cmdline) { + MagicAI.setMaxThreads(cmdline.getMaxThreads()); + MagicSystem.setIsDevMode(cmdline.isDevMode()); + } + + public static void main(final CommandLineArgs cmdline) { + Thread.setDefaultUncaughtExceptionHandler(new ConsoleExceptionHandler()); + + parseCommandLine(cmdline); + + MagicSystem.initialize(new ProgressReporter()); + + System.out.println("=================== Card test ===================="); + + Collection allC = CardDefinitions.getAllPlayableCardDefs(); + + List cards = new ArrayList<>(); + List tokens = new ArrayList<>(); + + for (MagicCardDefinition def : allC) { + String name = def.getName(); + if (name.isEmpty()) { + // Manifest, morph, or alike ... + System.out.println("Def without name: " + def.getDistinctName()); + continue; + } + if (def.isToken()) tokens.add(def); + else cards.add(name); + } + System.out.println("Cards: " + cards.size()); + System.out.println("Tokens: " + tokens.size()); + + int t = 1; + for (MagicCardDefinition token : tokens) { + System.out.println("Testing token #" + t + ": " + token.getName()); + t++; + MagicGame game = new TokenScenario(token).getGame(); + game.setArtificial(true); + + //5 seconds max for a quick match + final HeadlessGameController controller = new HeadlessGameController( + game, 5 * 1000 + ); + + final long start_time = System.currentTimeMillis(); + controller.runGame(); + final double duration = (double) (System.currentTimeMillis() - start_time) / 1000; + + System.out.printf("Token time: %.2fs : %s\n", duration, token); + } + + + int n = 1; + for (String name : cards) { + System.out.println("Testing card #" + n + ": " + name); + n++; + MagicGame game = new CardScenario(name).getGame(); + game.setArtificial(true); + + //5 seconds max for a quick match + final HeadlessGameController controller = new HeadlessGameController( + game, 5 * 1000 + ); + + final long start_time = System.currentTimeMillis(); + controller.runGame(); + final double duration = (double) (System.currentTimeMillis() - start_time) / 1000; + + System.out.printf("Time: %.2fs : %s\n", duration, name); + } + + } + + /** + * Base scenario, where player starts with two tested cares in hand. + */ + private static class CardScenario extends BaseScenario { + private String testCard; + + public CardScenario(String testCard) { + this.testCard = testCard; + } + + @Override + public void prepareScenario(MagicPlayer player, MagicPlayer opponent) { + addToHand(player, testCard, 2); + + } + } + + /** + * Base scenario, where player starts one tested token in play. + */ + private static class TokenScenario extends BaseScenario { + private MagicCardDefinition testToken; + + public TokenScenario(MagicCardDefinition testToken) { + this.testToken = testToken; + } + + @Override + public void prepareScenario(MagicPlayer player, MagicPlayer opponent) { + createPermanent(player, testToken, false, 1); + } + } + + /** + * Base scenario - player has most likely enough mana to cast anything, + * opponent has at least one permanent of every type, so there would likely be some targets + * for variety of possible spells and effects. + * + * Libraries have only two cards (basic lands) in them, so the game is likely to end quickly. + */ + private static abstract class BaseScenario extends TestGameBuilder { + public abstract void prepareScenario(MagicPlayer player, MagicPlayer opponent); + + public static MagicDuel createAiDuel(final MagicAIImpl aAiType, final int aAiLevel) { + // Set number of games. + final DuelConfig config = new DuelConfig(); + config.setNrOfGames(1); + config.setStartLife(20); + + AiProfile ai = AiProfile.create(aAiType, aAiLevel); + + // Create players + config.setPlayerProfile(0, ai); + config.setPlayerProfile(1, ai); + + final MagicDuel duel = new MagicDuel(config); + + final MagicDeckProfile profile = new MagicDeckProfile("bgruw"); + final DuelPlayerConfig player1 = new DuelPlayerConfig(ai, profile); + final DuelPlayerConfig player2 = new DuelPlayerConfig(ai, profile); + + duel.setPlayers(new DuelPlayerConfig[]{player1, player2}); + duel.setStartPlayer(0); + return duel; + } + + public static MagicDuel createAiDuel() { + return createAiDuel(MagicAIImpl.MMABFast, 2); + } + + @Override + public MagicGame getGame() { + final MagicDuel duel = createAiDuel(); + final MagicGame game = duel.nextGame(); + game.setPhase(MagicMainPhase.getFirstInstance()); + final MagicPlayer player = game.getPlayer(0); + final MagicPlayer opponent = game.getPlayer(1); + + MagicPlayer P = player; + + P.setLife(10); + addToLibrary(P, "Plains", 2); + // 5 mana of every color + createPermanent(P, "Plains", false, 5); + createPermanent(P, "Forest", false, 5); + createPermanent(P, "Island", false, 5); + createPermanent(P, "Swamp", false, 5); + createPermanent(P, "Mountain", false, 5); + // Own artifact creature + createPermanent(P, "Ornithopter", false, 1); + + P = opponent; + + P.setLife(10); + addToLibrary(P, "Plains", 2); + createPermanent(P, "Plains", false, 1); + createPermanent(P, "Forest", false, 1); + createPermanent(P, "Island", false, 1); + createPermanent(P, "Swamp", false, 1); + createPermanent(P, "Mountain", false, 1); + // Creature + createPermanent(P, "Wall of Ice", false, 1); + // Enchantment + createPermanent(P, "Orcish Oriflamme", false, 1); + // Artifact Creature + createPermanent(P, "Omega Myr", false, 1); + // Planeswalker + createPermanent(P, "Ajani Goldmane", false, 1); + // Sorcery + addToHand(P, "Angelic Edict", 1); + // Instant + addToHand(P, "Giant Growth", 1); + prepareScenario(player, opponent); + + return game; + } + } +} diff --git a/src/magic/CommandLineArgs.java b/src/magic/CommandLineArgs.java index d991ce3294..16f875565b 100644 --- a/src/magic/CommandLineArgs.java +++ b/src/magic/CommandLineArgs.java @@ -22,6 +22,7 @@ class CommandLineArgs { private String deck2 = ""; private boolean showFps = false; private boolean headless = false; + private boolean cardTest = false; private int fps; private int duels = 1; @@ -74,6 +75,9 @@ class CommandLineArgs { case "--headless": headless = true; break; + case "--cardtest": + cardTest = true; + break; case "--duels": // the number of duels to play [--duels 1]. duels = Integer.parseInt(args[i + 1].trim()); break; @@ -209,6 +213,10 @@ class CommandLineArgs { return headless; } + boolean isCardTest() { + return cardTest; + } + int getFPS() { return fps; } diff --git a/src/magic/MagicMain.java b/src/magic/MagicMain.java index 3b0194c071..d9ac0d6ed6 100644 --- a/src/magic/MagicMain.java +++ b/src/magic/MagicMain.java @@ -49,6 +49,12 @@ public class MagicMain { return; } + // transfer control to automatic card test + if (cmdline.isCardTest()) { + CardTest.main(cmdline); + return; + } + parseCommandLine(cmdline); Thread.setDefaultUncaughtExceptionHandler(new UiExceptionHandler()); diff --git a/src/magic/test/TestGameBuilder.java b/src/magic/test/TestGameBuilder.java index 0429546a25..bc17bd4df8 100644 --- a/src/magic/test/TestGameBuilder.java +++ b/src/magic/test/TestGameBuilder.java @@ -55,8 +55,13 @@ public abstract class TestGameBuilder { } public static MagicPermanent createPermanent(final MagicPlayer player, final String name, final boolean tapped, final int count) { + final MagicCardDefinition cardDefinition = CardDefinitions.getCard(name); + return createPermanent(player, cardDefinition, tapped, count); + } + + + public static MagicPermanent createPermanent(final MagicPlayer player, final MagicCardDefinition cardDefinition, final boolean tapped, final int count) { final MagicGame game = player.getGame(); - final MagicCardDefinition cardDefinition=CardDefinitions.getCard(name); MagicPermanent lastPermanent= MagicPermanent.NONE; for (int c=count;c>0;c--) { diff --git a/test/magic/model/mstatic/MagicManaCostTest.java b/test/magic/model/mstatic/MagicManaCostTest.java index 8b0041213d..4c84fdec4e 100644 --- a/test/magic/model/mstatic/MagicManaCostTest.java +++ b/test/magic/model/mstatic/MagicManaCostTest.java @@ -52,7 +52,5 @@ public class MagicManaCostTest { MagicManaCost phy = MagicManaCost.create("{R/P}{G/P}{W/P}"); assertEquals("{W/P}", phy.reducedBy(MagicManaCost.create("{R}{G}{U}")).toString()); - - } }