package chess.controller.commands; import chess.controller.PlayerCommand; import chess.controller.event.GameListener; import chess.model.ChessBoard; import chess.model.Coordinate; import chess.model.Game; import chess.model.Move; import chess.model.Piece; import chess.model.visitor.PiecePathChecker; public class MoveCommand extends PlayerCommand { private final Move move; private Piece deadPiece; public MoveCommand(Move move) { this.move = move; this.deadPiece = null; } public Move getMove() { return move; } public Piece getDeadPiece() { return deadPiece; } @Override public CommandResult execute(Game game, GameListener outputSystem) { CommandResult result = processMove(game, outputSystem); switch (result) { case NotAllowed: outputSystem.onMoveNotAllowed(this.move); return result; case Moved: outputSystem.onMove(this.move); game.saveTraitPiecesPos(); return result; case ActionNeeded: case NotMoved: return result; } return null; } private CommandResult processMove(Game game, GameListener outputSystem) { final ChessBoard board = game.getBoard(); // we must promote the pending pawn before if (board.pawnShouldBePromoted()) return CommandResult.NotAllowed; Piece piece = board.pieceAt(move.getStart()); if (piece == null) return CommandResult.NotAllowed; if (piece.getColor() != game.getPlayerTurn()) return CommandResult.NotAllowed; boolean valid = new PiecePathChecker(board, move).isValid(); if (!valid) return CommandResult.NotAllowed; this.deadPiece = board.pieceAt(move.getDeadPieceCoords()); board.applyMove(move); if (board.isKingInCheck(game.getPlayerTurn())) { board.undoLastMove(); return CommandResult.NotAllowed; } if (tryPromote(game, outputSystem)) { return CommandResult.ActionNeeded; } board.setLastMove(this.move); return CommandResult.Moved; } @Override protected CommandResult undoImpl(Game game, GameListener outputSystem) { final ChessBoard board = game.getBoard(); game.undoTraitPiecesPos(); board.undoMove(move, deadPiece); return CommandResult.Moved; } private boolean tryPromote(Game game, GameListener outputSystem) { Coordinate pawnPos = game.getBoard().pawnPromotePosition(); if (pawnPos == null) return false; outputSystem.onPromotePawn(pawnPos); return true; } }