package chess.model; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Stack; import chess.controller.PlayerCommand; import chess.controller.commands.MoveCommand; /** * Game class that represents a chess game. */ public class Game { private final ChessBoard board; private Color playerTurn; private final Stack movesHistory; private final Map traitsPos; private static final int DRAW_REPETITONS = 3; public enum GameStatus { Draw, Check, CheckMate, OnGoing, Pat; } public Game() { this.board = new ChessBoard(); this.movesHistory = new Stack<>(); this.traitsPos = new HashMap<>(); } public ChessBoard getBoard() { return board; } public Color getPlayerTurn() { return playerTurn; } /** * Reset the game */ public void reset() { resetPlayerTurn(); this.traitsPos.clear(); } /** * Reset the player turn. * Aka: white for the win */ public void resetPlayerTurn() { this.playerTurn = Color.White; } /** * Save the current board configuration */ public void saveTraitPiecesPos() { int piecesHash = this.board.hashCode(); Integer count = this.traitsPos.get(piecesHash); this.traitsPos.put(piecesHash, count == null ? 1 : count + 1); } /** * @return whether the game is in a draw situation */ private boolean checkDraw() { return this.traitsPos.containsValue(DRAW_REPETITONS); } /** * Switch player turn */ public void switchPlayerTurn() { playerTurn = Color.getEnemy(playerTurn); } /** * Check the status of the game ofr the specified player * @return a GameStatus enum */ public GameStatus checkGameStatus(Color color) { if (checkDraw()) return GameStatus.Draw; if (this.board.isKingInCheck(color)) if (this.board.hasAllowedMoves(color)) return GameStatus.Check; else return GameStatus.CheckMate; if (!board.hasAllowedMoves(color)) return GameStatus.Pat; return GameStatus.OnGoing; } /** * Check the status of the gamere */ public GameStatus checkGameStatus() { return checkGameStatus(Color.getEnemy(getPlayerTurn())); } /** * Add a player move (basic move, castling, ...) to the game history. */ public void addAction(PlayerCommand command) { this.movesHistory.add(command); } /** * @return the last player action */ public PlayerCommand getLastAction() { if (this.movesHistory.isEmpty()) return null; return this.movesHistory.pop(); } /** * Update the last board move ater an undo. */ public void updateLastMove() { if (this.movesHistory.isEmpty()) return; PlayerCommand last = this.movesHistory.getLast(); if (last instanceof MoveCommand move) { this.board.setLastMove(move.getMove()); } } /** * Remove the board configuration occurence from the game history */ public void undoTraitPiecesPos() { int piecesHash = this.board.hashCode(); Integer count = this.traitsPos.get(piecesHash); if (count != null) this.traitsPos.put(piecesHash, count - 1); } public List getMoves() { return this.movesHistory; } /** * @return wether a pawn should be promoted */ public boolean pawnShouldBePromoted() { return this.board.pawnShouldBePromoted(); } }