mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-17 19:28:01 +00:00
- Update SimulateMatch to handle multiple (>2) players and multiple formats
This commit is contained in:
@@ -1,10 +1,10 @@
|
|||||||
package forge.view;
|
package forge.view;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.ArrayList;
|
import java.util.*;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
|
import forge.util.storage.IStorage;
|
||||||
|
import org.apache.commons.lang3.text.WordUtils;
|
||||||
import org.apache.commons.lang3.time.StopWatch;
|
import org.apache.commons.lang3.time.StopWatch;
|
||||||
|
|
||||||
import forge.deck.Deck;
|
import forge.deck.Deck;
|
||||||
@@ -24,39 +24,95 @@ public class SimulateMatch {
|
|||||||
FModel.initialize(null);
|
FModel.initialize(null);
|
||||||
|
|
||||||
System.out.println("Simulation mode");
|
System.out.println("Simulation mode");
|
||||||
if(args.length < 3 ) {
|
if(args.length < 4) {
|
||||||
System.out.println("Syntax: forge.exe sim <deck1[.dck]> <deck2[.dck]> [N]");
|
argumentHelp();
|
||||||
System.out.println("\tsim - stands for simulation mode");
|
|
||||||
System.out.println("\tdeck1 (or deck2) - constructed deck name or filename (has to be quoted when contains multiple words)");
|
|
||||||
System.out.println("\tdeck is treated as file if it ends with a dot followed by three numbers or letters");
|
|
||||||
System.out.println("\tN - number of games, defaults to 1");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Deck d1 = deckFromCommandLineParameter(args[1]);
|
|
||||||
Deck d2 = deckFromCommandLineParameter(args[2]);
|
final Map<String, List<String>> params = new HashMap<>();
|
||||||
if(d1 == null || d2 == null) {
|
List<String> options = null;
|
||||||
System.out.println("One of decks could not be loaded, match cannot start");
|
|
||||||
return;
|
for (int i = 1; i < args.length; i++) {
|
||||||
|
// "sim" is in the 0th slot
|
||||||
|
final String a = args[i];
|
||||||
|
|
||||||
|
if (a.charAt(0) == '-') {
|
||||||
|
if (a.length() < 2) {
|
||||||
|
System.err.println("Error at argument " + a);
|
||||||
|
argumentHelp();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
options = new ArrayList<>();
|
||||||
|
params.put(a.substring(1), options);
|
||||||
|
}
|
||||||
|
else if (options != null) {
|
||||||
|
options.add(a);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
System.err.println("Illegal parameter usage");
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int nGames = args.length >= 4 ? Integer.parseInt(args[3]) : 1;
|
//final Map<String, List<String>> params = new HashMap<>();
|
||||||
|
|
||||||
System.out.println(String.format("Ai-%s vs Ai_%s - %s", d1.getName(), d2.getName(), Lang.nounWithNumeral(nGames, "game")));
|
int nGames = 1;
|
||||||
|
if (params.containsKey("n")) {
|
||||||
|
// Number of games should only be a single string
|
||||||
|
nGames = Integer.parseInt(params.get("n").get(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
GameType type = GameType.Constructed;
|
||||||
|
if (params.containsKey("f")) {
|
||||||
|
type = GameType.valueOf(WordUtils.capitalize(params.get("f").get(0)));
|
||||||
|
}
|
||||||
|
|
||||||
List<RegisteredPlayer> pp = new ArrayList<RegisteredPlayer>();
|
List<RegisteredPlayer> pp = new ArrayList<RegisteredPlayer>();
|
||||||
pp.add(new RegisteredPlayer(d1).setPlayer(GamePlayerUtil.createAiPlayer("Ai-" + d1.getName(), 0)));
|
|
||||||
pp.add(new RegisteredPlayer(d2).setPlayer(GamePlayerUtil.createAiPlayer("Ai_" + d2.getName(), 1)));
|
StringBuilder sb = new StringBuilder();
|
||||||
GameRules rules = new GameRules(GameType.Constructed);
|
|
||||||
|
int i = 1;
|
||||||
|
for(String deck : params.get("d")) {
|
||||||
|
Deck d = deckFromCommandLineParameter(deck, type);
|
||||||
|
if (d == null) {
|
||||||
|
System.out.println("One of decks could not be loaded, match cannot start");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (i > 1) {
|
||||||
|
sb.append(" vs ");
|
||||||
|
}
|
||||||
|
String name = String.format("Ai(%s)-%s", i, d.getName());
|
||||||
|
sb.append(name);
|
||||||
|
|
||||||
|
pp.add(new RegisteredPlayer(d).setPlayer(GamePlayerUtil.createAiPlayer(name, i-1)));
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
sb.append(" - ").append(Lang.nounWithNumeral(nGames, "game")).append(" of ").append(type);
|
||||||
|
|
||||||
|
System.out.println(sb.toString());
|
||||||
|
|
||||||
|
GameRules rules = new GameRules(type);
|
||||||
Match mc = new Match(rules, pp, "Test");
|
Match mc = new Match(rules, pp, "Test");
|
||||||
for (int iGame = 0; iGame < nGames; iGame++) {
|
for (int iGame = 0; iGame < nGames; iGame++) {
|
||||||
simulateSingleMatch(mc, iGame);
|
simulateSingleMatch(mc, iGame);
|
||||||
}
|
}
|
||||||
System.out.flush();
|
System.out.flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void argumentHelp() {
|
||||||
|
System.out.println("Syntax: forge.exe sim -d <deck1[.dck]> ... <deckX[.dck]> -n [N] -f [F]");
|
||||||
|
System.out.println("\tsim - stands for simulation mode");
|
||||||
|
System.out.println("\tdeck1 (or deck2,...,X) - constructed deck name or filename (has to be quoted when contains multiple words)");
|
||||||
|
System.out.println("\tdeck is treated as file if it ends with a dot followed by three numbers or letters");
|
||||||
|
System.out.println("\tN - number of games, defaults to 1");
|
||||||
|
System.out.println("\tF - format of games, defaults to constructed");
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO: Write javadoc for this method.
|
* TODO: Write javadoc for this method.
|
||||||
* @param sw
|
* @param mc
|
||||||
* @param pp
|
* @param iGame
|
||||||
*/
|
*/
|
||||||
private static void simulateSingleMatch(Match mc, int iGame) {
|
private static void simulateSingleMatch(Match mc, int iGame) {
|
||||||
StopWatch sw = new StopWatch();
|
StopWatch sw = new StopWatch();
|
||||||
@@ -66,22 +122,31 @@ public class SimulateMatch {
|
|||||||
// will run match in the same thread
|
// will run match in the same thread
|
||||||
mc.startGame(g1);
|
mc.startGame(g1);
|
||||||
sw.stop();
|
sw.stop();
|
||||||
|
|
||||||
List<GameLogEntry> log = g1.getGameLog().getLogEntries(null);
|
List<GameLogEntry> log = g1.getGameLog().getLogEntries(null);
|
||||||
Collections.reverse(log);
|
Collections.reverse(log);
|
||||||
|
|
||||||
for(GameLogEntry l : log)
|
for(GameLogEntry l : log)
|
||||||
System.out.println(l);
|
System.out.println(l);
|
||||||
|
|
||||||
System.out.println(String.format("\nGame %d ended in %d ms. %s has won!\n", 1+iGame, sw.getTime(), g1.getOutcome().getWinningLobbyPlayer().getName()));
|
System.out.println(String.format("\nGame %d ended in %d ms. %s has won!\n", 1+iGame, sw.getTime(), g1.getOutcome().getWinningLobbyPlayer().getName()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static Deck deckFromCommandLineParameter(String deckname, GameType type) {
|
||||||
private static Deck deckFromCommandLineParameter(String deckname) {
|
|
||||||
int dotpos = deckname.lastIndexOf('.');
|
int dotpos = deckname.lastIndexOf('.');
|
||||||
if(dotpos > 0 && dotpos == deckname.length()-4)
|
if(dotpos > 0 && dotpos == deckname.length()-4)
|
||||||
return DeckSerializer.fromFile(new File(deckname));
|
return DeckSerializer.fromFile(new File(deckname));
|
||||||
return FModel.getDecks().getConstructed().get(deckname);
|
|
||||||
|
IStorage<Deck> deckStore = null;
|
||||||
|
|
||||||
|
// Add other game types here...
|
||||||
|
if (type.equals(GameType.Commander)) {
|
||||||
|
deckStore = FModel.getDecks().getCommander();
|
||||||
|
} else {
|
||||||
|
deckStore = FModel.getDecks().getConstructed();
|
||||||
|
}
|
||||||
|
|
||||||
|
return deckStore.get(deckname);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user