package chess.view.consolerender; import chess.controller.Command; import chess.controller.CommandExecutor; import chess.controller.commands.*; import chess.controller.event.GameListener; import chess.model.Color; import chess.model.Coordinate; import chess.model.Move; import chess.model.Piece; import java.util.List; import java.util.Objects; import java.util.Scanner; public class Console implements GameListener { private final Scanner scanner = new Scanner(System.in); private final CommandExecutor commandExecutor; private final ConsolePieceName consolePieceName = new ConsolePieceName(); public Console(CommandExecutor commandExecutor) { this.commandExecutor = commandExecutor; } private Piece pieceAt(int x, int y) { return pieceAt(new Coordinate(x, y)); } private Command.CommandResult sendCommand(Command command) { return this.commandExecutor.executeCommand(command); } private Piece pieceAt(Coordinate coordinate) { GetPieceAtCommand command = new GetPieceAtCommand(coordinate); sendCommand(command); return command.getPiece(); } public Coordinate stringToCoordinate(String coordinates) throws Exception { char xPos = coordinates.charAt(0); char yPos = coordinates.charAt(1); int x; if (xPos >= 'A' && xPos <= 'Z') { x = xPos - 'A'; } else if (xPos >= 'a' && xPos <= 'z') { x = xPos - 'a'; } else { throw new Exception("Invalid input"); } if (!(yPos >= '1' && yPos <= '9')) { throw new Exception("Invalid input"); } int y = Coordinate.VALUE_MAX - 1 - (yPos - '1'); return new Coordinate(x, y); } @Override public void playerTurn(Color color) { System.out.println(Colors.RED + "Player turn: " + color + Colors.RESET); boolean endTurn; do { System.out.println(""" Pick your choice: 1 - Move 2 - Show potential moves 3 - Surrender """); endTurn = switch (scanner.nextLine()) { case "1" -> playerPickedMove(); case "2" -> playerPickedShowMoves(); case "3" -> playerPickedSurrender(color); default -> false; }; } while (!endTurn); System.out.println(Colors.RED + "Turn ended." + Colors.RESET); updateDisplay(); } private boolean playerPickedSurrender(Color color) { sendCommand(new SurrenderCommand(color)); return true; } public boolean playerPickedMove() { try { System.out.println("Piece to move: "); Coordinate start = stringToCoordinate(scanner.nextLine()); System.out.println("New position: "); Coordinate end = stringToCoordinate(scanner.nextLine()); Command.CommandResult result = sendCommand(new MoveCommand(new Move(start, end))); switch (Objects.requireNonNull(result)) { case Command.CommandResult.Moved: return true; case Command.CommandResult.ActionNeeded: updateDisplay(); promotePawn(end); return true; default: System.out.println(result); System.out.println("Move not allowed."); return false; } } catch (Exception e) { System.out.println(e.getMessage()); return false; } } private boolean playerPickedShowMoves() { try { System.out.println("Piece to examine: "); Coordinate piece = stringToCoordinate(scanner.nextLine()); GetAllowedMovesPieceCommand movesCommand = new GetAllowedMovesPieceCommand(piece); if (sendCommand(movesCommand) == Command.CommandResult.NotAllowed) { System.out.println("Not allowed."); return false; } List allowedMoves = movesCommand.getDestinations(); if (allowedMoves.isEmpty()) { System.out.println("No moves allowed for this piece."); return false; } displayMoves(piece, allowedMoves); return false; } catch (Exception e) { System.out.println(e.getMessage()); return false; } } @Override public void winnerIs(Color color) { System.out.println(Colors.RED + "Victory of player " + color + Colors.RESET); gameEnded(); } @Override public void kingIsInCheck() { System.out.println(Colors.RED + "Check!" + Colors.RESET); // todo } @Override public void kingIsInMat() { System.out.println(Colors.RED + "Checkmate!" + Colors.RESET); } @Override public void patSituation() { // todo gameEnded(); } @Override public void hasSurrendered(Color color) { System.out.println("The " + color + " player has surrendered!"); } @Override public void gameStarted() { System.out.println("Game start!"); updateDisplay(); } public void gameEnded(){ System.out.println("Thank you for playing!"); this.commandExecutor.close(); } @Override public void promotePawn(Coordinate pieceCoords) { System.out.println("The pawn on the " + pieceCoords + " coordinates needs to be promoted."); System.out.println("Enter 'B' to promote it into a Bishop, 'N' for a Knight, 'Q' for a Queen, 'R' for a Rook."); boolean valid = false; PromoteCommand.PromoteType newPiece; do { try { String promotion = scanner.next(); newPiece = switch (promotion) { case ("B") -> PromoteCommand.PromoteType.Bishop; case ("N") -> PromoteCommand.PromoteType.Knight; case ("Q") -> PromoteCommand.PromoteType.Queen; case ("R") -> PromoteCommand.PromoteType.Rook; default -> throw new Exception(); }; valid = true; sendCommand(new PromoteCommand(newPiece)); } catch (Exception e) { System.out.println("Invalid input!"); } } while (!valid); } @Override public void updateDisplay() { StringBuilder string = new StringBuilder(); string.append(" a b c d e f g h \n"); for (int i = 0; i < Coordinate.VALUE_MAX; i++) { string.append(8 - i).append(" "); for (int j = 0; j < Coordinate.VALUE_MAX; j++) { Piece p = pieceAt(j, i); if ((i+j)%2==0) { string.append(Colors.LIGHT_GRAY_BACKGROUND); } else { string.append(Colors.DARK_GRAY_BACKGROUND); } if (p == null) { string.append(" " + Colors.RESET); } else { string.append(" ").append(consolePieceName.getString(p)).append(" ").append(Colors.RESET); } } string.append("\n"); } System.out.println(string); } public void displayMoves(Coordinate piece, List moves) { StringBuilder string = new StringBuilder(); string.append(" a b c d e f g h \n"); for (int i = 0; i < Coordinate.VALUE_MAX; i++) { string.append(8 - i).append(" "); for (int j = 0; j < Coordinate.VALUE_MAX; j++) { Coordinate currentCell = new Coordinate(j, i); Piece p = pieceAt(j, i); if (moves.contains(currentCell)){ string.append(Colors.YELLOW_BACKGROUND); } else { if ((i + j) % 2 == 0) { string.append(Colors.LIGHT_GRAY_BACKGROUND); } else { string.append(Colors.DARK_GRAY_BACKGROUND); } } if (p == null) { string.append(" " + Colors.RESET); } else { if (currentCell.equals(piece)) { string.append(Colors.RED_BACKGROUND).append(" ").append(consolePieceName.getString(p)).append(" ").append(Colors.RESET); } else { string.append(" ").append(consolePieceName.getString(p)).append(" ").append(Colors.RESET); } } } string.append("\n"); } System.out.println(string); } }