From d2485a4d75435115b9970984941f623e57fc2ecd Mon Sep 17 00:00:00 2001 From: Persson-dev Date: Sat, 12 Apr 2025 12:15:58 +0200 Subject: [PATCH] thread pool + ai vs ai --- app/src/main/java/chess/SwingMain.java | 10 ++- app/src/main/java/chess/ai/DumbAI.java | 62 ++++++++++++++++ .../controller/event/GameDispatcher.java | 29 +++++--- .../java/chess/view/simplerender/Window.java | 72 +++++++++---------- 4 files changed, 123 insertions(+), 50 deletions(-) create mode 100644 app/src/main/java/chess/ai/DumbAI.java diff --git a/app/src/main/java/chess/SwingMain.java b/app/src/main/java/chess/SwingMain.java index cff871f..a81bb7a 100644 --- a/app/src/main/java/chess/SwingMain.java +++ b/app/src/main/java/chess/SwingMain.java @@ -1,8 +1,10 @@ package chess; +import chess.ai.DumbAI; import chess.controller.CommandExecutor; import chess.controller.commands.NewGameCommand; import chess.model.ChessBoard; +import chess.model.Color; import chess.model.Game; import chess.view.simplerender.Window; @@ -11,9 +13,15 @@ public class SwingMain { Game game = new Game(new ChessBoard()); CommandExecutor commandExecutor = new CommandExecutor(game); - Window window = new Window(commandExecutor); + Window window = new Window(commandExecutor, false); commandExecutor.addListener(window); + DumbAI ai = new DumbAI(commandExecutor, Color.Black); + commandExecutor.addListener(ai); + + DumbAI ai2 = new DumbAI(commandExecutor, Color.White); + commandExecutor.addListener(ai2); + commandExecutor.executeCommand(new NewGameCommand()); } } diff --git a/app/src/main/java/chess/ai/DumbAI.java b/app/src/main/java/chess/ai/DumbAI.java new file mode 100644 index 0000000..b6f8f08 --- /dev/null +++ b/app/src/main/java/chess/ai/DumbAI.java @@ -0,0 +1,62 @@ +package chess.ai; + +import java.util.List; +import java.util.Random; + +import chess.controller.Command; +import chess.controller.CommandExecutor; +import chess.controller.commands.GetPieceAtCommand; +import chess.controller.commands.GetPlayerMovesCommand; +import chess.controller.commands.MoveCommand; +import chess.controller.commands.PromoteCommand; +import chess.controller.commands.PromoteCommand.PromoteType; +import chess.controller.event.GameAdaptator; +import chess.model.Color; +import chess.model.Coordinate; +import chess.model.Move; +import chess.model.Piece; + +public class DumbAI extends GameAdaptator { + + private final Color player; + private final CommandExecutor commandExecutor; + private final Random random = new Random(); + + public DumbAI(CommandExecutor commandExecutor, Color color) { + this.player = color; + this.commandExecutor = commandExecutor; + } + + @Override + public void playerTurn(Color color) { + if (color != player) + return; + + GetPlayerMovesCommand cmd = new GetPlayerMovesCommand(); + sendCommand(cmd); + List moves = cmd.getMoves(); + int randomMove = this.random.nextInt(moves.size()); + this.commandExecutor.executeCommand(new MoveCommand(moves.get(randomMove))); + } + + @Override + public void promotePawn(Coordinate pieceCoords) { + Piece pawn = pieceAt(pieceCoords); + if (pawn.getColor() != this.player) + return; + + int promote = this.random.nextInt(PromoteType.values().length); + this.commandExecutor.executeCommand(new PromoteCommand(PromoteType.values()[promote])); + } + + private Piece pieceAt(Coordinate coordinate) { + GetPieceAtCommand command = new GetPieceAtCommand(coordinate); + sendCommand(command); + return command.getPiece(); + } + + private void sendCommand(Command command) { + this.commandExecutor.executeCommand(command); + } + +} diff --git a/app/src/main/java/chess/controller/event/GameDispatcher.java b/app/src/main/java/chess/controller/event/GameDispatcher.java index af2fc48..4799b5d 100644 --- a/app/src/main/java/chess/controller/event/GameDispatcher.java +++ b/app/src/main/java/chess/controller/event/GameDispatcher.java @@ -2,6 +2,9 @@ package chess.controller.event; import java.util.ArrayList; import java.util.List; +import java.util.concurrent.Executor; +import java.util.concurrent.Executors; +import java.util.function.Consumer; import chess.model.Color; import chess.model.Coordinate; @@ -9,60 +12,64 @@ import chess.model.Coordinate; public class GameDispatcher implements GameListener{ private final List listeners; + private final Executor executor; public GameDispatcher() { this.listeners = new ArrayList<>(); + this.executor = Executors.newSingleThreadExecutor(); } public void addListener(GameListener listener) { this.listeners.add(listener); } + private void asyncForEachCall(Consumer func) { + this.executor.execute(() -> this.listeners.forEach(func)); + } + @Override public void playerTurn(Color color) { - this.listeners.forEach((l) -> l.playerTurn(color)); + asyncForEachCall((l) -> l.playerTurn(color)); } @Override public void winnerIs(Color color) { - this.listeners.forEach((l) -> l.winnerIs(color)); + asyncForEachCall((l) -> l.winnerIs(color)); } @Override public void kingIsInCheck() { - this.listeners.forEach((l) -> l.kingIsInCheck()); + asyncForEachCall((l) -> l.kingIsInCheck()); } @Override public void kingIsInMat() { - this.listeners.forEach((l) -> l.kingIsInMat()); + asyncForEachCall((l) -> l.kingIsInMat()); } @Override public void patSituation() { - this.listeners.forEach((l) -> l.patSituation()); + asyncForEachCall((l) -> l.patSituation()); } @Override public void hasSurrendered(Color color) { - this.listeners.forEach((l) -> l.hasSurrendered(color)); + asyncForEachCall((l) -> l.hasSurrendered(color)); } @Override public void gameStarted() { - this.listeners.forEach((l) -> l.gameStarted()); + asyncForEachCall((l) -> l.gameStarted()); } @Override public void promotePawn(Coordinate pieceCoords) { - this.listeners.forEach((l) -> l.promotePawn(pieceCoords)); + asyncForEachCall((l) -> l.promotePawn(pieceCoords)); } @Override public void updateDisplay() { - this.listeners.forEach((l) -> l.updateDisplay()); + asyncForEachCall((l) -> l.updateDisplay()); } - - } diff --git a/app/src/main/java/chess/view/simplerender/Window.java b/app/src/main/java/chess/view/simplerender/Window.java index edb34f1..75637fe 100644 --- a/app/src/main/java/chess/view/simplerender/Window.java +++ b/app/src/main/java/chess/view/simplerender/Window.java @@ -44,10 +44,13 @@ public class Window extends JFrame implements GameListener { private final JButton bigCastlingButton = new JButton("Grand Roque"); private final JButton undoButton = new JButton("Annuler le coup précédent"); - public Window(CommandExecutor commandExecutor) { + private final boolean showPopups; + + public Window(CommandExecutor commandExecutor, boolean showPopups) { this.cells = new JLabel[8][8]; this.displayText = new JLabel(); this.commandExecutor = commandExecutor; + this.showPopups = showPopups; setSize(800, 910); setVisible(true); setLocationRelativeTo(null); @@ -198,15 +201,6 @@ public class Window extends JFrame implements GameListener { @Override public void playerTurn(chess.model.Color color) { this.displayText.setText("Current turn: " + color); - - // dumb IA - if (color == chess.model.Color.Black) { - GetPlayerMovesCommand cmd = new GetPlayerMovesCommand(); - sendCommand(cmd); - List moves = cmd.getMoves(); - int random = new Random().nextInt(moves.size()); - sendCommand(new MoveCommand(moves.get(random))); - } } @Override @@ -219,6 +213,8 @@ public class Window extends JFrame implements GameListener { @Override public void kingIsInCheck() { + if (!showPopups) + return; SwingUtilities.invokeLater(() -> { JOptionPane.showMessageDialog(this, "Check!"); }); @@ -252,39 +248,39 @@ public class Window extends JFrame implements GameListener { @Override public void promotePawn(Coordinate pieceCoords) { - SwingUtilities.invokeLater(() -> { - String result = null; + // SwingUtilities.invokeLater(() -> { + // String result = null; - Object[] possibilities = new Object[PromoteType.values().length]; - int i = 0; - for (PromoteType type : PromoteType.values()) { - possibilities[i] = type.name(); - i++; - } + // Object[] possibilities = new Object[PromoteType.values().length]; + // int i = 0; + // for (PromoteType type : PromoteType.values()) { + // possibilities[i] = type.name(); + // i++; + // } - while (result == null || result.isEmpty()) { - result = (String) JOptionPane.showInputDialog( - this, - "Choose the type of piece to upgrade the pawn", - "Promote Dialog", - JOptionPane.PLAIN_MESSAGE, - null, - possibilities, - possibilities[0]); - } + // while (result == null || result.isEmpty()) { + // result = (String) JOptionPane.showInputDialog( + // this, + // "Choose the type of piece to upgrade the pawn", + // "Promote Dialog", + // JOptionPane.PLAIN_MESSAGE, + // null, + // possibilities, + // possibilities[0]); + // } - PromoteType choosedType = null; + // PromoteType choosedType = null; - for (PromoteType type : PromoteType.values()) { - if (type.name().equals(result)) { - choosedType = type; - break; - } - } + // for (PromoteType type : PromoteType.values()) { + // if (type.name().equals(result)) { + // choosedType = type; + // break; + // } + // } - if (choosedType != null) - sendCommand(new PromoteCommand(choosedType)); - }); + // if (choosedType != null) + // sendCommand(new PromoteCommand(choosedType)); + // }); } @Override