package net.ciklum.icfpc11.domain import net.ciklum.icfpc11.domain.greenspoon10.Identity import net.ciklum.icfpc11.controller.AiPlayer /** * @author vic */ @Typed final class Game { int currentTurn = 0 // up to 100000 private int nApplications = 0 boolean nowZombieTime = false Player player0 = new Player('Player 0') Player player1 = new Player('Player 1') private Player currentPlayer /** I don't want to engage into tying every Function to a Game, so let's just make a * global stack of Games. We're single-threaded anyway. */ private static List games = [] static Game getInstance() { if (games.isEmpty()) { push() } games[-1] } static Game push(Player player0, Player player1) { games << new Game(player0, player1) games[-1] } static Game push() { games << new Game() games[-1] } static void pop() { games.remove(games.size()-1) } private Game() { this(new Player('Player 0'), new Player('Player 1')) currentPlayer = player0 } private Game(Player player0, Player player1) { this.player0 = player0 this.player1 = player1 currentPlayer = player0 } boolean isEnded() { // TODO: Probably save the values and don't reevaluate currentTurn >= 100000 || player0.isDead() || player1.isDead() } Player getWinner() { if (!isEnded()) return null int player0Alive = player0.slots.count { Slot it -> it.alive } int player1Alive = player1.slots.count { Slot it -> it.alive } if (player0Alive > player1Alive) { return player0 } else if (player0Alive < player1Alive) { return player1 } else { return null } } boolean isDraw() { if (!isEnded()) return false int player0Alive = player0.slots.count { Slot it -> it.alive } int player1Alive = player1.slots.count { Slot it -> it.alive } return player0Alive == player1Alive } Player getCurrentProponent() { currentPlayer } Player getCurrentOpponent() { currentPlayer == player0 ? player1 : player0 } boolean isMyPlayer() { currentPlayer instanceof AiPlayer } void nextTurn() { if (currentTurn >= 100000) { throw new RuntimeException('Turns ran out') } nApplications = 0 if (currentPlayer == player0) { currentPlayer = player1 } else { currentPlayer = player0 currentTurn++ } zombieApocalypse() } /** Runs "zombie turn" before player's turn */ void zombieApocalypse() { currentPlayer.slots.findAll { it.vitality == -1 }.each { try { nowZombieTime = true it.value.apply(Identity.IDENTITY) } catch (GameError e) { // log.info "Error during zombie turn: $e.message", e } finally { nowZombieTime = false } it.vitality = 0 it.value = Identity.IDENTITY } } void incApplications() throws GameError { nApplications++ if (nApplications > 1000) { throw new GameError('Too many applications this turn') } } }