diff --git a/app/src/main/java/chess/ai/DumbAI.java b/app/src/main/java/chess/ai/DumbAI.java index b6f8f08..df0bbf9 100644 --- a/app/src/main/java/chess/ai/DumbAI.java +++ b/app/src/main/java/chess/ai/DumbAI.java @@ -28,7 +28,7 @@ public class DumbAI extends GameAdaptator { } @Override - public void playerTurn(Color color) { + public void onPlayerTurn(Color color) { if (color != player) return; @@ -40,7 +40,7 @@ public class DumbAI extends GameAdaptator { } @Override - public void promotePawn(Coordinate pieceCoords) { + public void onPromotePawn(Coordinate pieceCoords) { Piece pawn = pieceAt(pieceCoords); if (pawn.getColor() != this.player) return; diff --git a/app/src/main/java/chess/controller/Command.java b/app/src/main/java/chess/controller/Command.java index 2e39bfb..9396eb7 100644 --- a/app/src/main/java/chess/controller/Command.java +++ b/app/src/main/java/chess/controller/Command.java @@ -6,7 +6,9 @@ import chess.model.Game; public abstract class Command { public enum CommandResult { - /** The command was successfull. Should update display and switch player turn. */ + /** + * The command was successfull. Should update display and switch player turn. + */ Moved, /** The command was successfull. Should not update anything */ NotMoved, @@ -18,5 +20,4 @@ public abstract class Command { public abstract CommandResult execute(Game game, GameListener outputSystem); - public void postExec(Game game, GameListener outputSystem) {} } diff --git a/app/src/main/java/chess/controller/CommandExecutor.java b/app/src/main/java/chess/controller/CommandExecutor.java index 7124558..785f968 100644 --- a/app/src/main/java/chess/controller/CommandExecutor.java +++ b/app/src/main/java/chess/controller/CommandExecutor.java @@ -34,7 +34,6 @@ public class CommandExecutor { if (command instanceof PlayerCommand playerCommand && result != CommandResult.NotAllowed) this.game.addAction(playerCommand); - command.postExec(game, dispatcher); return result; } @@ -45,21 +44,23 @@ public class CommandExecutor { return; case ActionNeeded: - this.dispatcher.updateDisplay(); + this.dispatcher.onBoardUpdate(); return; case Moved: - if (checkGameStatus()) + this.dispatcher.onBoardUpdate(); + if (checkGameStatus()) { + this.dispatcher.onGameEnd(); return; + } switchPlayerTurn(); - this.dispatcher.updateDisplay(); return; } } private void switchPlayerTurn() { this.game.switchPlayerTurn(); - this.dispatcher.playerTurn(this.game.getPlayerTurn()); + this.dispatcher.onPlayerTurn(this.game.getPlayerTurn()); } /** @@ -71,19 +72,19 @@ public class CommandExecutor { switch (gameStatus) { case Check: - this.dispatcher.kingIsInCheck(); + this.dispatcher.onKingInCheck(); return false; case CheckMate: - this.dispatcher.kingIsInMat(); - this.dispatcher.winnerIs(this.game.getPlayerTurn()); + this.dispatcher.onKingInMat(); + this.dispatcher.onWin(this.game.getPlayerTurn()); return true; case OnGoing: return false; case Pat: - this.dispatcher.patSituation(); + this.dispatcher.onPatSituation(); return true; } diff --git a/app/src/main/java/chess/controller/commands/MoveCommand.java b/app/src/main/java/chess/controller/commands/MoveCommand.java index fe0773f..5a1b159 100644 --- a/app/src/main/java/chess/controller/commands/MoveCommand.java +++ b/app/src/main/java/chess/controller/commands/MoveCommand.java @@ -25,6 +25,26 @@ public class MoveCommand extends PlayerCommand { @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); + 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 @@ -50,10 +70,12 @@ public class MoveCommand extends PlayerCommand { return CommandResult.NotAllowed; } - if (board.pawnShouldBePromoted()) + if (tryPromote(game, outputSystem)) { return CommandResult.ActionNeeded; + } board.setLastMove(this.move); + return CommandResult.Moved; } @@ -65,18 +87,14 @@ public class MoveCommand extends PlayerCommand { return CommandResult.Moved; } - @Override - public void postExec(Game game, GameListener outputSystem) { - tryPromote(game, outputSystem); - } - - private void tryPromote(Game game, GameListener outputSystem) { + private boolean tryPromote(Game game, GameListener outputSystem) { Coordinate pawnPos = game.getBoard().pawnPromotePosition(); if (pawnPos == null) - return; + return false; - outputSystem.promotePawn(pawnPos); + outputSystem.onPromotePawn(pawnPos); + return true; } } diff --git a/app/src/main/java/chess/controller/commands/NewGameCommand.java b/app/src/main/java/chess/controller/commands/NewGameCommand.java index 96f2f87..51bb373 100644 --- a/app/src/main/java/chess/controller/commands/NewGameCommand.java +++ b/app/src/main/java/chess/controller/commands/NewGameCommand.java @@ -50,8 +50,8 @@ public class NewGameCommand extends Command { game.resetPlayerTurn(); - outputSystem.gameStarted(); - outputSystem.playerTurn(game.getPlayerTurn()); + outputSystem.onGameStart(); + outputSystem.onPlayerTurn(game.getPlayerTurn()); return CommandResult.NotMoved; } diff --git a/app/src/main/java/chess/controller/commands/SurrenderCommand.java b/app/src/main/java/chess/controller/commands/SurrenderCommand.java index 191475a..e8be6dc 100644 --- a/app/src/main/java/chess/controller/commands/SurrenderCommand.java +++ b/app/src/main/java/chess/controller/commands/SurrenderCommand.java @@ -15,8 +15,8 @@ public class SurrenderCommand extends Command { @Override public CommandResult execute(Game game, GameListener outputSystem) { - outputSystem.hasSurrendered(player); - outputSystem.winnerIs(Color.getEnemy(player)); + outputSystem.onSurrender(player); + outputSystem.onWin(Color.getEnemy(player)); return CommandResult.NotMoved; } diff --git a/app/src/main/java/chess/controller/event/GameAdaptator.java b/app/src/main/java/chess/controller/event/GameAdaptator.java index 2191f75..e1b7c43 100644 --- a/app/src/main/java/chess/controller/event/GameAdaptator.java +++ b/app/src/main/java/chess/controller/event/GameAdaptator.java @@ -2,34 +2,44 @@ package chess.controller.event; import chess.model.Color; import chess.model.Coordinate; +import chess.model.Move; public abstract class GameAdaptator implements GameListener { @Override - public void playerTurn(Color color) {} + public void onPlayerTurn(Color color) {} @Override - public void winnerIs(Color color) {} + public void onWin(Color color) {} @Override - public void kingIsInCheck() {} + public void onKingInCheck() {} @Override - public void kingIsInMat() {} + public void onKingInMat() {} @Override - public void patSituation() {} + public void onPatSituation() {} @Override - public void hasSurrendered(Color color) {} + public void onSurrender(Color color) {} @Override - public void gameStarted() {} + public void onGameStart() {} @Override - public void promotePawn(Coordinate pieceCoords) {} + public void onPromotePawn(Coordinate pieceCoords) {} @Override - public void updateDisplay() {} + public void onBoardUpdate() {} + + @Override + public void onGameEnd() {} + + @Override + public void onMove(Move move) {} + + @Override + public void onMoveNotAllowed(Move move) {} } diff --git a/app/src/main/java/chess/controller/event/GameDispatcher.java b/app/src/main/java/chess/controller/event/GameDispatcher.java index 961d507..cec2dfb 100644 --- a/app/src/main/java/chess/controller/event/GameDispatcher.java +++ b/app/src/main/java/chess/controller/event/GameDispatcher.java @@ -8,6 +8,7 @@ import java.util.function.Consumer; import chess.model.Color; import chess.model.Coordinate; +import chess.model.Move; public class GameDispatcher implements GameListener{ @@ -28,48 +29,63 @@ public class GameDispatcher implements GameListener{ } @Override - public void playerTurn(Color color) { - asyncForEachCall((l) -> l.playerTurn(color)); + public void onPlayerTurn(Color color) { + asyncForEachCall((l) -> l.onPlayerTurn(color)); } @Override - public void winnerIs(Color color) { - asyncForEachCall((l) -> l.winnerIs(color)); + public void onWin(Color color) { + asyncForEachCall((l) -> l.onWin(color)); } @Override - public void kingIsInCheck() { - asyncForEachCall((l) -> l.kingIsInCheck()); + public void onKingInCheck() { + asyncForEachCall((l) -> l.onKingInCheck()); } @Override - public void kingIsInMat() { - asyncForEachCall((l) -> l.kingIsInMat()); + public void onKingInMat() { + asyncForEachCall((l) -> l.onKingInMat()); } @Override - public void patSituation() { - asyncForEachCall((l) -> l.patSituation()); + public void onPatSituation() { + asyncForEachCall((l) -> l.onPatSituation()); } @Override - public void hasSurrendered(Color color) { - asyncForEachCall((l) -> l.hasSurrendered(color)); + public void onSurrender(Color color) { + asyncForEachCall((l) -> l.onSurrender(color)); } @Override - public void gameStarted() { - asyncForEachCall((l) -> l.gameStarted()); + public void onGameStart() { + asyncForEachCall((l) -> l.onGameStart()); } @Override - public void promotePawn(Coordinate pieceCoords) { - asyncForEachCall((l) -> l.promotePawn(pieceCoords)); + public void onPromotePawn(Coordinate pieceCoords) { + asyncForEachCall((l) -> l.onPromotePawn(pieceCoords)); } @Override - public void updateDisplay() { - asyncForEachCall((l) -> l.updateDisplay()); + public void onBoardUpdate() { + asyncForEachCall((l) -> l.onBoardUpdate()); + } + + @Override + public void onGameEnd() { + asyncForEachCall((l) -> l.onGameEnd()); + } + + @Override + public void onMove(Move move) { + asyncForEachCall((l) -> l.onMove(move)); + } + + @Override + public void onMoveNotAllowed(Move move) { + asyncForEachCall((l) -> l.onMoveNotAllowed(move)); } public void stopService() { diff --git a/app/src/main/java/chess/controller/event/GameListener.java b/app/src/main/java/chess/controller/event/GameListener.java index a8183c8..9a89938 100644 --- a/app/src/main/java/chess/controller/event/GameListener.java +++ b/app/src/main/java/chess/controller/event/GameListener.java @@ -2,24 +2,74 @@ package chess.controller.event; import chess.model.Color; import chess.model.Coordinate; +import chess.model.Move; public interface GameListener { - void playerTurn(Color color); + /** + * Invoked when the display of the board should be updated + */ + void onBoardUpdate(); + + /** + * Invoked when the game has ended (by a win or a draw) + */ + void onGameEnd(); - void winnerIs(Color color); + /** + * Invoked when the game has started + */ + void onGameStart(); + + /** + * Invoked when a king is in check + */ + void onKingInCheck(); - void kingIsInCheck(); + /** + * Invoked when a checkmate occurs + */ + void onKingInMat(); + + /** + * Invoked when a valid move on the board occurs + * @param move the move to be processed + */ + void onMove(Move move); - void kingIsInMat(); + /** + * Invoked when a sent move is not allowed + * @param move the move to be processed + */ + void onMoveNotAllowed(Move move); + + /** + * Invoked when a pat situation occurs + */ + void onPatSituation(); + + /** + * Invoked when it's the player turn + * @param color the color of the player who should play + */ + void onPlayerTurn(Color color); + + /** + * Invoked when a pawn should be promoted + * @param pieceCoords the coordinates of the pawn + */ + void onPromotePawn(Coordinate pieceCoords); + + /** + * Invoked when a players surrenders + * @param coward the player who gave up + */ + void onSurrender(Color coward); + + /** + * Invoked when a player wins (by checkmate or if the other one surrenders) + * @param winner + */ + void onWin(Color winner); - void patSituation(); - - void hasSurrendered(Color color); - - void gameStarted(); - - void promotePawn(Coordinate pieceCoords); - - void updateDisplay(); } diff --git a/app/src/main/java/chess/view/consolerender/Console.java b/app/src/main/java/chess/view/consolerender/Console.java index c7cdbb7..7fd3762 100644 --- a/app/src/main/java/chess/view/consolerender/Console.java +++ b/app/src/main/java/chess/view/consolerender/Console.java @@ -55,7 +55,7 @@ public class Console implements GameListener { } @Override - public void playerTurn(Color color) { + public void onPlayerTurn(Color color) { System.out.println(Colors.RED + "Player turn: " + color + Colors.RESET); boolean endTurn; do { @@ -73,7 +73,7 @@ public class Console implements GameListener { }; } while (!endTurn); System.out.println(Colors.RED + "Turn ended." + Colors.RESET); - updateDisplay(); + onBoardUpdate(); } private boolean playerPickedSurrender(Color color) { @@ -89,10 +89,9 @@ public class Console implements GameListener { 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."); + case Command.CommandResult.Moved: + case Command.CommandResult.ActionNeeded: return true; + default: return false; } @@ -125,46 +124,45 @@ public class Console implements GameListener { } @Override - public void winnerIs(Color color) { + public void onWin(Color color) { System.out.println(Colors.RED + "Victory of player " + color + Colors.RESET); - gameEnded(); } @Override - public void kingIsInCheck() { + public void onKingInCheck() { System.out.println(Colors.RED + "Check!" + Colors.RESET); // todo } @Override - public void kingIsInMat() { + public void onKingInMat() { System.out.println(Colors.RED + "Checkmate!" + Colors.RESET); } @Override - public void patSituation() { + public void onPatSituation() { // todo - gameEnded(); } @Override - public void hasSurrendered(Color color) { + public void onSurrender(Color color) { System.out.println("The " + color + " player has surrendered!"); } @Override - public void gameStarted() { + public void onGameStart() { System.out.println("Game start!"); - updateDisplay(); + onBoardUpdate(); } - public void gameEnded(){ + @Override + public void onGameEnd() { System.out.println("Thank you for playing!"); this.commandExecutor.close(); } @Override - public void promotePawn(Coordinate pieceCoords) { + public void onPromotePawn(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; @@ -189,7 +187,7 @@ public class Console implements GameListener { } @Override - public void updateDisplay() { + public void onBoardUpdate() { StringBuilder string = new StringBuilder(); string.append(" a b c d e f g h \n"); for (int i = 0; i < Coordinate.VALUE_MAX; i++) { @@ -246,4 +244,12 @@ public class Console implements GameListener { } System.out.println(string); } + + @Override + public void onMove(Move move) {} + + @Override + public void onMoveNotAllowed(Move move) { + System.out.println("Move not allowed."); + } } diff --git a/app/src/main/java/chess/view/simplerender/Window.java b/app/src/main/java/chess/view/simplerender/Window.java index a6e7ed9..ea0fd6a 100644 --- a/app/src/main/java/chess/view/simplerender/Window.java +++ b/app/src/main/java/chess/view/simplerender/Window.java @@ -188,29 +188,25 @@ public class Window extends JFrame implements GameListener { } if (!this.lastClick.equals(new Coordinate(x, y))) { Move move = new Move(lastClick, new Coordinate(x, y)); - - if (sendCommand(new MoveCommand(move)) == CommandResult.NotAllowed) { - drawInvalid(move); - } + sendCommand(new MoveCommand(move)); } this.lastClick = null; } @Override - public void playerTurn(chess.model.Color color) { + public void onPlayerTurn(chess.model.Color color) { this.displayText.setText("Current turn: " + color); } @Override - public void winnerIs(chess.model.Color color) { + public void onWin(chess.model.Color color) { SwingUtilities.invokeLater(() -> { JOptionPane.showMessageDialog(this, "Victory of " + color); - onGameEnd(); }); } @Override - public void kingIsInCheck() { + public void onKingInCheck() { if (!showPopups) return; SwingUtilities.invokeLater(() -> { @@ -219,39 +215,40 @@ public class Window extends JFrame implements GameListener { } @Override - public void kingIsInMat() { + public void onKingInMat() { SwingUtilities.invokeLater(() -> { JOptionPane.showMessageDialog(this, "Checkmate!"); }); } @Override - public void patSituation() { + public void onPatSituation() { SwingUtilities.invokeLater(() -> { JOptionPane.showMessageDialog(this, "Pat. It's a draw!"); - onGameEnd(); }); } @Override - public void hasSurrendered(chess.model.Color color) { + public void onSurrender(chess.model.Color color) { SwingUtilities.invokeLater(() -> { JOptionPane.showMessageDialog(this, color + " has surrendered."); }); } - private void onGameEnd() { + @Override + public void onGameEnd() { + JOptionPane.showMessageDialog(this, "End of the game"); this.dispose(); this.commandExecutor.close(); } @Override - public void gameStarted() { + public void onGameStart() { buildBoard(); } @Override - public void promotePawn(Coordinate pieceCoords) { + public void onPromotePawn(Coordinate pieceCoords) { if (!showPopups) return; SwingUtilities.invokeLater(() -> { @@ -290,8 +287,16 @@ public class Window extends JFrame implements GameListener { } @Override - public void updateDisplay() { + public void onBoardUpdate() { updateBoard(); } + @Override + public void onMove(Move move) {} + + @Override + public void onMoveNotAllowed(Move move) { + drawInvalid(move); + } + }