package net.demilich.metastone.gui.trainingmode;
import net.demilich.metastone.trainingmode.TrainingData;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import net.demilich.nittygrittymvc.Notification;
import net.demilich.nittygrittymvc.SimpleCommand;
import net.demilich.nittygrittymvc.interfaces.INotification;
import net.demilich.metastone.GameNotification;
import net.demilich.metastone.game.GameContext;
import net.demilich.metastone.game.Player;
import net.demilich.metastone.game.behaviour.threat.FeatureVector;
import net.demilich.metastone.game.behaviour.threat.GameStateValueBehaviour;
import net.demilich.metastone.game.behaviour.threat.cuckoo.CuckooLearner;
import net.demilich.metastone.game.cards.CardSet;
import net.demilich.metastone.game.decks.DeckFormat;
import net.demilich.metastone.game.logic.GameLogic;
import net.demilich.metastone.game.statistics.Statistic;
import net.demilich.metastone.game.gameconfig.PlayerConfig;
public class PerformTrainingCommand extends SimpleCommand<GameNotification> {
private static Logger logger = LoggerFactory.getLogger(PerformTrainingCommand.class);
private int gamesCompleted;
private int gamesWon;
@Override
public void execute(INotification<GameNotification> notification) {
final TrainingConfig config = (TrainingConfig) notification.getBody();
if (config.getDecks().isEmpty()) {
logger.error("Deck list is empty!!");
}
gamesCompleted = 0;
gamesWon = 0;
Thread t = new Thread(new Runnable() {
@Override
public void run() {
logger.info("Training started");
CuckooLearner learner = new CuckooLearner(config.getDeckToTrain(), config.getDecks());
// send initial status update
TrainingProgressReport progress = new TrainingProgressReport(gamesCompleted, config.getNumberOfGames(), gamesWon);
getFacade().sendNotification(GameNotification.TRAINING_PROGRESS_UPDATE, progress);
for (int i = 0; i < config.getNumberOfGames(); i++) {
FeatureVector fittest = learner.getFittest();
PlayerConfig learnerConfig = new PlayerConfig(config.getDeckToTrain(),
new GameStateValueBehaviour(fittest, "(fittest)"));
learnerConfig.setName("Learner");
Player player1 = new Player(learnerConfig);
PlayerConfig opponentConfig = new PlayerConfig(config.getRandomDeck(), new GameStateValueBehaviour());
opponentConfig.setName("Opponent");
Player player2 = new Player(opponentConfig);
DeckFormat deckFormat = new DeckFormat();
for (CardSet set : CardSet.values()) {
deckFormat.addSet(set);
}
GameContext newGame = new GameContext(player1, player2, new GameLogic(), deckFormat);
newGame.play();
onGameComplete(config, newGame);
newGame.dispose();
if (i % 10 == 0) {
learner.evolve();
}
}
getFacade().sendNotification(GameNotification.TRAINING_PROGRESS_UPDATE,
new TrainingProgressReport(gamesCompleted, config.getNumberOfGames(), gamesWon));
logger.info("Training ended");
FeatureVector fittest = learner.getFittest();
logger.info("**************Final weights: {}", fittest);
// save training data
getFacade().sendNotification(GameNotification.SAVE_TRAINING_DATA,
new TrainingData(config.getDeckToTrain().getName(), fittest));
}
});
t.setDaemon(true);
t.start();
}
private void onGameComplete(TrainingConfig config, GameContext completedGame) {
gamesCompleted++;
gamesWon += completedGame.getPlayer1().getStatistics().getLong(Statistic.GAMES_WON);
TrainingProgressReport progress = new TrainingProgressReport(gamesCompleted, config.getNumberOfGames(), gamesWon);
Notification<GameNotification> updateNotification = new Notification<>(GameNotification.TRAINING_PROGRESS_UPDATE, progress);
getFacade().notifyObservers(updateNotification);
}
}