package chess.controller.commands; import chess.controller.PlayerCommand; import chess.controller.event.GameListener; import chess.model.ChessBoard; import chess.model.Color; import chess.model.Coordinate; import chess.model.Game; import chess.model.Piece; import chess.model.pieces.Bishop; import chess.model.pieces.Knight; import chess.model.pieces.Queen; import chess.model.pieces.Rook; import chess.model.visitor.PawnIdentifier; public class PromoteCommand extends PlayerCommand { public enum PromoteType { Queen, Rook, Bishop, Knight } private final PromoteType promoteType; private Coordinate pieceCoords; private Piece oldPawn; public PromoteCommand(PromoteType promoteType) { this.promoteType = promoteType; assert this.promoteType != null; this.pieceCoords = null; this.oldPawn = null; } @Override public CommandResult execute(Game game, GameListener outputSystem) { final ChessBoard board = game.getBoard(); this.pieceCoords = board.pawnPromotePosition(); if (this.pieceCoords == null) return CommandResult.NotAllowed; Piece pawn = board.pieceAt(this.pieceCoords); if (!new PawnIdentifier(game.getPlayerTurn()).isPawn(pawn)) return CommandResult.NotAllowed; int destY = this.pieceCoords.getY(); int enemyLine = pawn.getColor() == Color.White ? 0 : 7; if (destY != enemyLine) return CommandResult.NotAllowed; this.oldPawn = pawn; board.pieceComes(createPiece(this.promoteType, pawn.getColor()), this.pieceCoords); outputSystem.onPawnPromoted(this.promoteType); // invalidate the last move cache board.setLastMove(null); return CommandResult.Moved; } private Piece createPiece(PromoteType promoteType, Color color) { switch (promoteType) { case Queen: return new Queen(color); case Bishop: return new Bishop(color); case Knight: return new Knight(color); case Rook: return new Rook(color); default: return null; } } @Override protected CommandResult undoImpl(Game game, GameListener outputSystem) { final ChessBoard board = game.getBoard(); Piece promoted = board.pieceAt(this.pieceCoords); assert promoted != null; game.undoTraitPiecesPos(); board.pieceComes(this.oldPawn, this.pieceCoords); game.getLastAction().undo(game, outputSystem); return CommandResult.Moved; } public PromoteType getPromoteType() { return promoteType; } }