magarena/src/magic/CardTest.java

245 lines
8.4 KiB
Java

package magic;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
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<MagicCardDefinition> allC = CardDefinitions.getAllPlayableCardDefs();
double totalTime = 0;
int totalCards = 0;
Set<String> skip = new HashSet<>();
String skipList = cmdline.getSkipList();
if (skipList != null) {
try (Stream<String> lines = Files.lines(Paths.get(skipList))) {
skip = lines.collect(Collectors.toSet());
System.out.println("Skipping " + skip.size() + " cards from file: " + skipList);
} catch (IOException e) {
throw new IllegalArgumentException("Unable to load skiplist from file " + skipList, e);
}
}
List<String> cards = new ArrayList<>();
List<MagicCardDefinition> 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 (skip.contains(name)) 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++;
totalCards++;
MagicGame game = new TokenScenario(token).getGame();
final double duration = runGame(game);
totalTime += duration;
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++;
totalCards++;
MagicGame game = new CardScenario(name).getGame();
final double duration = runGame(game);
totalTime += duration;
System.out.printf("Time: %.2fs : %s\n", duration, name);
}
System.out.println("Tested " + totalCards + " cards/tokens.");
System.out.println("Total time: " + totalTime);
System.out.println("Time per card: " + totalTime / totalCards);
}
private static double runGame(MagicGame game) {
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();
return (double) (System.currentTimeMillis() - start_time) / 1000;
}
/**
* 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.
* <p>
* 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;
}
}
}