magarena/src/magic/model/MagicDuel.java

266 lines
7.9 KiB
Java

package magic.model;
import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import java.util.Properties;
import magic.data.DeckGenerators;
import magic.data.DuelConfig;
import magic.data.stats.MagicStats;
import magic.model.phase.MagicDefaultGameplay;
import magic.model.player.PlayerProfile;
import magic.utility.DeckUtils;
import magic.utility.FileIO;
import magic.utility.MagicFileSystem;
import magic.utility.MagicFileSystem.DataPath;
import magic.utility.SortedProperties;
public class MagicDuel {
private static final String GAME = "duel.game";
private static final String PLAYED = "duel.played";
private static final String WON = "duel.won";
private static final String START = "duel.start";
public static MagicDuel instance;
private final DuelConfig duelConfig;
private final int playerIndex = 0;
private final int opponentIndex = 1;
private int gameNr;
private int gamesPlayed;
private int gamesWon;
private int startPlayer;
public MagicDuel(final DuelConfig configuration) {
this.duelConfig=configuration;
restart();
}
public MagicDuel() {
this(new DuelConfig());
}
public DuelConfig getConfiguration() {
return duelConfig;
}
public int getGameNr() {
return gameNr;
}
public int getGamesPlayed() {
return gamesPlayed;
}
public int getGamesTotal() {
return (duelConfig.getPlayerConfigs().length-1)*duelConfig.getNrOfGames();
}
public int getGamesWon() {
return gamesWon;
}
private void determineStartPlayer() {
startPlayer=MagicRandom.nextRNGInt(2);
}
public void setStartPlayer(final int startPlayer) {
this.startPlayer=startPlayer;
}
public boolean isEditable() {
return gameNr==1;
}
public boolean isFinished() {
// if a duel consists of a total of X games, then in an interactive
// game it should be "best of" X games, not first to X.
final int player1GamesWon = getGamesWon();
final int player2GamesWon = getGamesPlayed() - player1GamesWon;
final int gamesRequiredToWin = (int)Math.ceil(getGamesTotal()/2.0);
return (player1GamesWon >= gamesRequiredToWin) || (player2GamesWon >= gamesRequiredToWin);
}
void advance(final boolean won, final MagicGame game) {
gameNr++;
gamesPlayed++;
if (won) {
gamesWon++;
startPlayer = opponentIndex;
} else {
startPlayer = playerIndex;
}
MagicStats.logStats(this, game);
}
public MagicGame nextGame() {
//create players
final MagicPlayer player = new MagicPlayer(duelConfig.getStartingLife(playerIndex), duelConfig.getPlayerConfig(playerIndex), playerIndex);
final MagicPlayer opponent = new MagicPlayer(duelConfig.getStartingLife(opponentIndex), duelConfig.getPlayerConfig(opponentIndex), opponentIndex);
//determine who starts first
final MagicPlayer[] players = new MagicPlayer[]{player,opponent};
final MagicPlayer start = players[startPlayer];
//create game
final MagicGame game = MagicGame.create(
this,
MagicDefaultGameplay.getInstance(),
players,
start
);
//create hand and library
player.createHandAndLibrary(duelConfig.getHandSize());
opponent.createHandAndLibrary(duelConfig.getHandSize());
return game;
}
public int getNrOfPlayers() {
return duelConfig.getPlayerConfigs().length;
}
public DuelPlayerConfig getPlayer(final int index) {
return duelConfig.getPlayerConfig(index);
}
public DuelPlayerConfig[] getPlayers() {
return duelConfig.getPlayerConfigs();
}
// only used by magic.test classes.
public void setPlayers(final DuelPlayerConfig[] aPlayerDefinitions) {
duelConfig.setPlayerConfigs(aPlayerDefinitions);
}
// Used by the "Generate Deck" button in DuelPanel.
public void buildDeck(final DuelPlayerConfig player) {
DeckGenerators.setRandomDeck(player);
}
public void buildDecks() {
for (final DuelPlayerConfig player : duelConfig.getPlayerConfigs()) {
switch (player.getDeckProfile().getDeckType()) {
case Random:
DeckGenerators.setRandomDeck(player);
break;
case Preconstructed:
setDeckFromFile(player, DeckUtils.getPrebuiltDecksFolder());
break;
case Custom:
setDeckFromFile(player, DeckUtils.getDecksFolder());
break;
case Firemind:
setDeckFromFile(player, DeckUtils.getFiremindDecksFolder());
break;
default:
break;
}
}
}
private void setDeckFromFile(DuelPlayerConfig player, Path deckFolder) {
String deckFilename = DeckUtils.getNormalizedFilename(player.getDeckProfile().getDeckValue());
player.setDeck(loadDeck(deckFolder.resolve(deckFilename)));
}
private MagicDeck loadDeck(final Path deckFilePath) {
return DeckUtils.loadDeckFromFile(deckFilePath);
}
public void initialize() {
buildDecks();
}
public static final File getLatestDuelFile() {
return MagicFileSystem.getDataPath(DataPath.DUELS).resolve("latest.duel").toFile();
}
private void save(final Properties properties) {
duelConfig.save(properties);
properties.setProperty(GAME,Integer.toString(gameNr));
properties.setProperty(PLAYED,Integer.toString(gamesPlayed));
properties.setProperty(WON,Integer.toString(gamesWon));
properties.setProperty(START,Integer.toString(startPlayer));
}
public void save(final File file) {
final Properties properties = new SortedProperties();
save(properties);
try {
FileIO.toFile(file, properties, "Duel");
} catch (final IOException ex) {
System.err.println("ERROR! Unable save duel to " + file);
}
}
private void load(final Properties properties) {
duelConfig.load(properties, true);
gameNr=Integer.parseInt(properties.getProperty(GAME,"1"));
gamesPlayed=Integer.parseInt(properties.getProperty(PLAYED,"0"));
gamesWon=Integer.parseInt(properties.getProperty(WON,"0"));
startPlayer=Integer.parseInt(properties.getProperty(START,"0"));
}
public void load(final File file) {
load(FileIO.toProp(file));
}
public void restart() {
gameNr=1;
gamesPlayed=0;
gamesWon=0;
determineStartPlayer();
}
public PlayerProfile getWinningPlayerProfile() {
if (!isFinished()) {
return null;
} else {
final int playerOneGamesWon = getGamesWon();
final int playerTwoGamesWon = getGamesPlayed() - playerOneGamesWon;
if (playerOneGamesWon > playerTwoGamesWon) {
return getConfiguration().getPlayerProfile(0);
} else {
return getConfiguration().getPlayerProfile(1);
}
}
}
public static void restartDuel() {
if (instance != null) {
instance.restart();
}
}
public static void newDuel() {
instance = new MagicDuel(DuelConfig.getInstance());
instance.initialize();
}
public static boolean isDuelReady() {
return instance != null;
}
public boolean isNotFinished() {
return !isFinished();
}
public static void resumeDuel() {
final File duelFile = getLatestDuelFile();
if (duelFile.exists()) {
instance = new MagicDuel(DuelConfig.getInstance());
instance.load(duelFile);
}
}
public boolean hasInvalidDecks() {
return !getPlayer(0).getDeck().isValid()
|| !getPlayer(1).getDeck().isValid();
}
}