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; 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; } public void reset() { resetPlayerTurn(); this.traitsPos.clear(); } public void resetPlayerTurn() { this.playerTurn = Color.White; } /** * * @param color the current player turn * @return true if a draw should be declared */ 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); } /** * * @return true if a draw should occur */ public void switchPlayerTurn() { playerTurn = Color.getEnemy(playerTurn); } public GameStatus checkGameStatus() { final Color enemy = Color.getEnemy(getPlayerTurn()); if (checkDraw()) return GameStatus.Draw; if (this.board.isKingInCheck(enemy)) if (this.board.hasAllowedMoves(enemy)) return GameStatus.Check; else return GameStatus.CheckMate; if (!board.hasAllowedMoves(enemy)) return GameStatus.Pat; return GameStatus.OnGoing; } public void addAction(PlayerCommand command) { this.movesHistory.add(command); } public PlayerCommand getLastAction() { if (this.movesHistory.isEmpty()) return null; return this.movesHistory.pop(); } public void updateLastMove() { if (this.movesHistory.isEmpty()) return; PlayerCommand last = this.movesHistory.getLast(); if (last instanceof MoveCommand move) { this.board.setLastMove(move.getMove()); } } 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; } }