From 0993abeec76a2f43c8ac2f9fe0f7a9690e96daeb Mon Sep 17 00:00:00 2001 From: Stef Date: Thu, 4 Dec 2025 19:43:03 +0100 Subject: [PATCH] Everything is broken --- app/src/main/java/org/toop/app/Server.java | 33 +++++++++++-------- .../gameControllers/ReversiBitController.java | 26 +++++++++++++++ .../gameControllers/ReversiController.java | 2 +- .../TicTacToeBitController.java | 25 ++++++++++++++ .../gameControllers/TicTacToeController.java | 2 +- .../model/player/AbstractAI.java | 1 - .../handlers/NetworkingGameClientHandler.java | 18 +++++----- .../main/java/org/toop/game/BitboardGame.java | 12 ++++--- .../gameThreads/OnlineThreadBehaviour.java | 15 +++------ .../OnlineWithSleepThreadBehaviour.java | 10 +++--- .../game/games/reversi/BitboardReversi.java | 1 + .../toop/game/games/reversi/ReversiAIR.java | 4 +-- .../game/games/tictactoe/TicTacToeAIR.java | 8 ++--- 13 files changed, 105 insertions(+), 52 deletions(-) create mode 100644 app/src/main/java/org/toop/app/gameControllers/ReversiBitController.java create mode 100644 app/src/main/java/org/toop/app/gameControllers/TicTacToeBitController.java diff --git a/app/src/main/java/org/toop/app/Server.java b/app/src/main/java/org/toop/app/Server.java index 4b149d2..35630a7 100644 --- a/app/src/main/java/org/toop/app/Server.java +++ b/app/src/main/java/org/toop/app/Server.java @@ -2,9 +2,7 @@ package org.toop.app; import javafx.application.Platform; import javafx.geometry.Pos; -import org.toop.app.gameControllers.AbstractGameController; -import org.toop.app.gameControllers.ReversiController; -import org.toop.app.gameControllers.TicTacToeController; +import org.toop.app.gameControllers.*; import org.toop.app.widget.Primitive; import org.toop.app.widget.WidgetContainer; import org.toop.app.widget.complex.LoadingWidget; @@ -13,11 +11,15 @@ import org.toop.app.widget.popup.ErrorPopup; import org.toop.app.widget.popup.SendChallengePopup; import org.toop.app.widget.view.ServerView; import org.toop.framework.eventbus.EventFlow; +import org.toop.framework.gameFramework.controller.GameController; import org.toop.framework.gameFramework.model.player.Player; import org.toop.framework.networking.clients.TournamentNetworkingClient; import org.toop.framework.networking.events.NetworkEvents; import org.toop.framework.networking.types.NetworkingConnector; +import org.toop.game.games.reversi.BitboardReversi; +import org.toop.game.games.tictactoe.BitboardTicTacToe; import org.toop.game.players.ArtificialPlayer; +import org.toop.game.players.LocalPlayer; import org.toop.game.players.OnlinePlayer; import org.toop.game.games.reversi.ReversiAIR; import org.toop.game.games.reversi.ReversiR; @@ -42,7 +44,7 @@ public final class Server { private ServerView primary; private boolean isPolling = true; - private AbstractGameController gameController; + private GameController gameController; private final AtomicBoolean isSingleGame = new AtomicBoolean(false); @@ -195,26 +197,31 @@ public final class Server { information.players[0].computerThinkTime = 1; information.players[1].name = response.opponent(); - Player[] players = new Player[2]; - - players[(myTurn + 1) % 2] = new OnlinePlayer(response.opponent()); - - switch (type){ + /*switch (type){ case TICTACTOE ->{ players[myTurn] = new ArtificialPlayer<>(new TicTacToeAIR(), user); } case REVERSI ->{ players[myTurn] = new ArtificialPlayer<>(new ReversiAIR(), user); } - } + }*/ + + switch (type) { case TICTACTOE ->{ - gameController = new TicTacToeController(players, false); + Player[] players = new Player[2]; + players[(myTurn + 1) % 2] = new OnlinePlayer<>(response.opponent()); + players[myTurn] = new ArtificialPlayer<>(new TicTacToeAIR(), user); + gameController = new TicTacToeBitController(players); } - case REVERSI -> - gameController = new ReversiController(players, false); + case REVERSI -> { + Player[] players = new Player[2]; + players[(myTurn + 1) % 2] = new OnlinePlayer<>(response.opponent()); + players[myTurn] = new ArtificialPlayer<>(new ReversiAIR(), user); + gameController = new ReversiBitController(players);} default -> new ErrorPopup("Unsupported game type."); + } if (gameController != null){ diff --git a/app/src/main/java/org/toop/app/gameControllers/ReversiBitController.java b/app/src/main/java/org/toop/app/gameControllers/ReversiBitController.java new file mode 100644 index 0000000..2bba88f --- /dev/null +++ b/app/src/main/java/org/toop/app/gameControllers/ReversiBitController.java @@ -0,0 +1,26 @@ +package org.toop.app.gameControllers; + +import org.toop.app.canvas.GameCanvas; +import org.toop.app.canvas.ReversiBitCanvas; +import org.toop.framework.gameFramework.model.game.SupportsOnlinePlay; +import org.toop.framework.gameFramework.model.game.threadBehaviour.ThreadBehaviour; +import org.toop.framework.gameFramework.model.player.Player; +import org.toop.game.gameThreads.LocalThreadBehaviour; +import org.toop.game.gameThreads.OnlineThreadBehaviour; +import org.toop.game.gameThreads.OnlineWithSleepThreadBehaviour; +import org.toop.game.games.reversi.BitboardReversi; +import org.toop.game.games.tictactoe.BitboardTicTacToe; +import org.toop.game.players.OnlinePlayer; + +public class ReversiBitController extends GenericGameController { + public ReversiBitController(Player[] players) { + BitboardReversi game = new BitboardReversi(players); + ThreadBehaviour thread = new LocalThreadBehaviour<>(game); + for (Player player : players) { + if (player instanceof OnlinePlayer){ + thread = new OnlineWithSleepThreadBehaviour<>(game); + } + } + super(new ReversiBitCanvas(), game, thread, "Reversi"); + } +} diff --git a/app/src/main/java/org/toop/app/gameControllers/ReversiController.java b/app/src/main/java/org/toop/app/gameControllers/ReversiController.java index 2ea42cd..4e18cec 100644 --- a/app/src/main/java/org/toop/app/gameControllers/ReversiController.java +++ b/app/src/main/java/org/toop/app/gameControllers/ReversiController.java @@ -23,7 +23,7 @@ public class ReversiController extends AbstractGameController { new ReversiCanvas(Color.GRAY, (App.getHeight() / 4) * 3, (App.getHeight() / 4) * 3,(c) -> {new EventFlow().addPostEvent(GUIEvents.PlayerAttemptedMove.class, c).postEvent();}, (c) -> {new EventFlow().addPostEvent(GUIEvents.PlayerMoveHovered.class, c).postEvent();}), players, ReversiR, - local ? new LocalFixedRateThreadBehaviour<>(ReversiR, players) : new OnlineThreadBehaviour<>(ReversiR, players), // TODO: Player order matters here, this won't work atm + local ? new LocalFixedRateThreadBehaviour<>(ReversiR, players) : new OnlineThreadBehaviour<>(ReversiR), // TODO: Player order matters here, this won't work atm "Reversi"); eventFlow.listen(GUIEvents.PlayerAttemptedMove.class, event -> {if (getCurrentPlayer() instanceof LocalPlayer lp){lp.setMove(event.move());}}, false); eventFlow.listen(GUIEvents.PlayerMoveHovered.class, this::onHoverMove, false); diff --git a/app/src/main/java/org/toop/app/gameControllers/TicTacToeBitController.java b/app/src/main/java/org/toop/app/gameControllers/TicTacToeBitController.java new file mode 100644 index 0000000..5347cbf --- /dev/null +++ b/app/src/main/java/org/toop/app/gameControllers/TicTacToeBitController.java @@ -0,0 +1,25 @@ +package org.toop.app.gameControllers; + +import org.toop.app.canvas.GameCanvas; +import org.toop.app.canvas.TicTacToeBitCanvas; +import org.toop.framework.gameFramework.model.game.SupportsOnlinePlay; +import org.toop.framework.gameFramework.model.game.threadBehaviour.ThreadBehaviour; +import org.toop.framework.gameFramework.model.player.Player; +import org.toop.game.gameThreads.LocalThreadBehaviour; +import org.toop.game.gameThreads.OnlineThreadBehaviour; +import org.toop.game.gameThreads.OnlineWithSleepThreadBehaviour; +import org.toop.game.games.tictactoe.BitboardTicTacToe; +import org.toop.game.players.OnlinePlayer; + +public class TicTacToeBitController extends GenericGameController { + public TicTacToeBitController(Player[] players) { + BitboardTicTacToe game = new BitboardTicTacToe(players); + ThreadBehaviour thread = new LocalThreadBehaviour<>(game); + for (Player player : players) { + if (player instanceof OnlinePlayer){ + thread = new OnlineWithSleepThreadBehaviour<>(game); + } + } + super(new TicTacToeBitCanvas(), game, thread , "TicTacToe"); + } +} diff --git a/app/src/main/java/org/toop/app/gameControllers/TicTacToeController.java b/app/src/main/java/org/toop/app/gameControllers/TicTacToeController.java index c49234e..cd7c5fe 100644 --- a/app/src/main/java/org/toop/app/gameControllers/TicTacToeController.java +++ b/app/src/main/java/org/toop/app/gameControllers/TicTacToeController.java @@ -22,7 +22,7 @@ public class TicTacToeController extends AbstractGameController {new EventFlow().addPostEvent(GUIEvents.PlayerAttemptedMove.class, c).postEvent();}), players, BitboardTicTacToe, - local ? new LocalThreadBehaviour(BitboardTicTacToe) : new OnlineThreadBehaviour<>(BitboardTicTacToe, players), // TODO: Player order matters here, this won't work atm + local ? new LocalThreadBehaviour(BitboardTicTacToe) : new OnlineThreadBehaviour<>(BitboardTicTacToe), // TODO: Player order matters here, this won't work atm "TicTacToe"); initUI(); diff --git a/framework/src/main/java/org/toop/framework/gameFramework/model/player/AbstractAI.java b/framework/src/main/java/org/toop/framework/gameFramework/model/player/AbstractAI.java index 00dc9f6..ea22859 100644 --- a/framework/src/main/java/org/toop/framework/gameFramework/model/player/AbstractAI.java +++ b/framework/src/main/java/org/toop/framework/gameFramework/model/player/AbstractAI.java @@ -12,7 +12,6 @@ import org.toop.framework.gameFramework.model.game.TurnBasedGame; * * @param the specific type of game this AI can play, extending {@link GameR} */ -@Deprecated public abstract class AbstractAI> implements MoveProvider { // Concrete AI implementations should override findBestMove(T game, int depth) } diff --git a/framework/src/main/java/org/toop/framework/networking/handlers/NetworkingGameClientHandler.java b/framework/src/main/java/org/toop/framework/networking/handlers/NetworkingGameClientHandler.java index 11acf04..ceabbfc 100644 --- a/framework/src/main/java/org/toop/framework/networking/handlers/NetworkingGameClientHandler.java +++ b/framework/src/main/java/org/toop/framework/networking/handlers/NetworkingGameClientHandler.java @@ -42,7 +42,7 @@ public class NetworkingGameClientHandler extends ChannelInboundHandlerAdapter { msg); new EventFlow() .addPostEvent(new NetworkEvents.ServerResponse(this.connectionId)) - .asyncPostEvent(); + .postEvent(); parseServerReturn(rec); return; } @@ -117,7 +117,7 @@ public class NetworkingGameClientHandler extends ChannelInboundHandlerAdapter { .addPostEvent( new NetworkEvents.GameMoveResponse( this.connectionId, msg[0], msg[1], msg[2])) - .asyncPostEvent(); + .postEvent(); } private void gameWinConditionHandler(String rec) { @@ -130,7 +130,7 @@ public class NetworkingGameClientHandler extends ChannelInboundHandlerAdapter { new EventFlow() .addPostEvent(new NetworkEvents.GameResultResponse(this.connectionId, condition)) - .asyncPostEvent(); + .postEvent(); } private void gameChallengeHandler(String rec) { @@ -149,13 +149,13 @@ public class NetworkingGameClientHandler extends ChannelInboundHandlerAdapter { .addPostEvent( new NetworkEvents.ChallengeCancelledResponse( this.connectionId, msg[0])) - .asyncPostEvent(); + .postEvent(); else new EventFlow() .addPostEvent( new NetworkEvents.ChallengeResponse( this.connectionId, msg[0], msg[1], msg[2])) - .asyncPostEvent(); + .postEvent(); } catch (ArrayIndexOutOfBoundsException e) { logger.error("Array out of bounds for: {}", rec, e); } @@ -175,7 +175,7 @@ public class NetworkingGameClientHandler extends ChannelInboundHandlerAdapter { .addPostEvent( new NetworkEvents.GameMatchResponse( this.connectionId, msg[0], msg[1], msg[2])) - .asyncPostEvent(); + .postEvent(); } catch (ArrayIndexOutOfBoundsException e) { logger.error("Array out of bounds for: {}", rec, e); } @@ -192,7 +192,7 @@ public class NetworkingGameClientHandler extends ChannelInboundHandlerAdapter { new EventFlow() .addPostEvent(new NetworkEvents.YourTurnResponse(this.connectionId, msg)) - .asyncPostEvent(); + .postEvent(); } private void playerlistHandler(String rec) { @@ -205,7 +205,7 @@ public class NetworkingGameClientHandler extends ChannelInboundHandlerAdapter { new EventFlow() .addPostEvent(new NetworkEvents.PlayerlistResponse(this.connectionId, players)) - .asyncPostEvent(); + .postEvent(); } private void gamelistHandler(String rec) { @@ -218,7 +218,7 @@ public class NetworkingGameClientHandler extends ChannelInboundHandlerAdapter { new EventFlow() .addPostEvent(new NetworkEvents.GamelistResponse(this.connectionId, gameTypes)) - .asyncPostEvent(); + .postEvent(); } private void helpHandler(String rec) { diff --git a/game/src/main/java/org/toop/game/BitboardGame.java b/game/src/main/java/org/toop/game/BitboardGame.java index 35b87ab..31ff705 100644 --- a/game/src/main/java/org/toop/game/BitboardGame.java +++ b/game/src/main/java/org/toop/game/BitboardGame.java @@ -4,6 +4,7 @@ import org.toop.framework.gameFramework.model.game.TurnBasedGame; import org.toop.framework.gameFramework.model.player.Player; import java.util.Arrays; +import java.util.concurrent.atomic.AtomicInteger; public abstract class BitboardGame> implements TurnBasedGame { private final int columnSize; @@ -13,14 +14,13 @@ public abstract class BitboardGame> implements TurnBas // long is 64 bits. Every game has a limit of 64 cells maximum. private final long[] playerBitboard; - private int currentTurn; + private AtomicInteger currentTurn = new AtomicInteger(0); public BitboardGame(int columnSize, int rowSize, int playerCount, Player[] players) { this.columnSize = columnSize; this.rowSize = rowSize; this.players = players; this.playerBitboard = new long[playerCount]; - this.currentTurn = 0; Arrays.fill(playerBitboard, 0L); } @@ -91,11 +91,12 @@ public abstract class BitboardGame> implements TurnBas public Player getPlayer(int index) {return players[index];} public int getCurrentPlayerIndex() { - return currentTurn % playerBitboard.length; + System.out.println(currentTurn.get() % playerBitboard.length); + return currentTurn.get() % playerBitboard.length; } public int getNextPlayer() { - return (currentTurn + 1) % playerBitboard.length; + return (currentTurn.get() + 1) % playerBitboard.length; } public Player getCurrentPlayer(){ @@ -103,6 +104,7 @@ public abstract class BitboardGame> implements TurnBas } public void nextTurn() { - currentTurn++; + System.out.println("Incrementing turn"); + currentTurn.incrementAndGet(); } } \ No newline at end of file diff --git a/game/src/main/java/org/toop/game/gameThreads/OnlineThreadBehaviour.java b/game/src/main/java/org/toop/game/gameThreads/OnlineThreadBehaviour.java index fcce936..6fa886a 100644 --- a/game/src/main/java/org/toop/game/gameThreads/OnlineThreadBehaviour.java +++ b/game/src/main/java/org/toop/game/gameThreads/OnlineThreadBehaviour.java @@ -17,19 +17,12 @@ import org.toop.game.players.OnlinePlayer; * for the local player while receiving moves from other players. */ public class OnlineThreadBehaviour> extends AbstractThreadBehaviour implements SupportsOnlinePlay { - - /** The local player controlled by this client. */ - private final Player mainPlayer; - private final int playerTurn; - /** * Creates behaviour and sets the first local player * (non-online player) from the given array. */ - public OnlineThreadBehaviour(T game, Player[] players) { + public OnlineThreadBehaviour(T game) { super(game); - this.playerTurn = getFirstNotOnlinePlayer(players); - this.mainPlayer = players[this.playerTurn]; } /** Finds the first non-online player in the array. */ @@ -61,7 +54,7 @@ public class OnlineThreadBehaviour> extends AbstractT @Override public void onYourTurn(NetworkEvents.YourTurnResponse event) { if (!isRunning.get()) return; - int move = mainPlayer.getMove(game.deepCopy()); + int move = game.getPlayer(game.getCurrentTurn()).getMove(game.deepCopy()); new EventFlow().addPostEvent(NetworkEvents.SendMove.class, event.clientId(), (short) move).postEvent(); } @@ -83,9 +76,9 @@ public class OnlineThreadBehaviour> extends AbstractT @Override public void gameFinished(NetworkEvents.GameResultResponse event) { switch(event.condition().toUpperCase()){ - case "WIN" -> new EventFlow().addPostEvent(GUIEvents.GameEnded.class, true, playerTurn).postEvent(); + case "WIN" -> new EventFlow().addPostEvent(GUIEvents.GameEnded.class, true, game.getCurrentTurn()).postEvent(); case "DRAW" -> new EventFlow().addPostEvent(GUIEvents.GameEnded.class, false, AbstractGame.EMPTY).postEvent(); - case "LOSS" -> new EventFlow().addPostEvent(GUIEvents.GameEnded.class, true, (playerTurn + 1)%2).postEvent(); + case "LOSS" -> new EventFlow().addPostEvent(GUIEvents.GameEnded.class, true, (game.getCurrentTurn() + 1)%2).postEvent(); default -> { logger.error("Invalid condition"); throw new RuntimeException("Unknown condition"); diff --git a/game/src/main/java/org/toop/game/gameThreads/OnlineWithSleepThreadBehaviour.java b/game/src/main/java/org/toop/game/gameThreads/OnlineWithSleepThreadBehaviour.java index f4e2627..f9cc672 100644 --- a/game/src/main/java/org/toop/game/gameThreads/OnlineWithSleepThreadBehaviour.java +++ b/game/src/main/java/org/toop/game/gameThreads/OnlineWithSleepThreadBehaviour.java @@ -1,6 +1,7 @@ package org.toop.game.gameThreads; import org.toop.framework.gameFramework.model.game.AbstractGame; +import org.toop.framework.gameFramework.model.game.TurnBasedGame; import org.toop.framework.networking.events.NetworkEvents; import org.toop.framework.gameFramework.model.player.AbstractPlayer; @@ -11,16 +12,15 @@ import org.toop.framework.gameFramework.model.player.AbstractPlayer; * This is identical to {@link OnlineThreadBehaviour}, but inserts a * short sleep before delegating to the base implementation. */ -public class OnlineWithSleepThreadBehaviour extends OnlineThreadBehaviour { +public class OnlineWithSleepThreadBehaviour> extends OnlineThreadBehaviour { /** * Creates the behaviour and forwards the players to the base class. * * @param game the online-capable turn-based game - * @param players the list of local and remote players */ - public OnlineWithSleepThreadBehaviour(AbstractGame game, AbstractPlayer[] players) { - super(game, players); + public OnlineWithSleepThreadBehaviour(T game) { + super(game); } /** @@ -32,7 +32,7 @@ public class OnlineWithSleepThreadBehaviour extends OnlineThreadBehaviour { public void onYourTurn(NetworkEvents.YourTurnResponse event) { try { - Thread.sleep(1000); + Thread.sleep(50); } catch (InterruptedException e) { e.printStackTrace(); } diff --git a/game/src/main/java/org/toop/game/games/reversi/BitboardReversi.java b/game/src/main/java/org/toop/game/games/reversi/BitboardReversi.java index bb38ed1..e702bfe 100644 --- a/game/src/main/java/org/toop/game/games/reversi/BitboardReversi.java +++ b/game/src/main/java/org/toop/game/games/reversi/BitboardReversi.java @@ -65,6 +65,7 @@ public class BitboardReversi extends BitboardGame { @Override public int[] getLegalMoves(){ System.out.println(Arrays.toString(translateLegalMoves(getLegalMoves2()))); + System.out.println(Long.toBinaryString(getLegalMoves2())); return translateLegalMoves(getLegalMoves2()); } diff --git a/game/src/main/java/org/toop/game/games/reversi/ReversiAIR.java b/game/src/main/java/org/toop/game/games/reversi/ReversiAIR.java index 4a038ab..626a367 100644 --- a/game/src/main/java/org/toop/game/games/reversi/ReversiAIR.java +++ b/game/src/main/java/org/toop/game/games/reversi/ReversiAIR.java @@ -4,8 +4,8 @@ import org.toop.framework.gameFramework.model.player.AbstractAI; import java.util.Random; -public final class ReversiAIR extends AbstractAI { - public int getMove(ReversiR game) { +public final class ReversiAIR extends AbstractAI { + public int getMove(BitboardReversi game) { int[] moves = game.getLegalMoves(); if (moves.length == 0) return -1; diff --git a/game/src/main/java/org/toop/game/games/tictactoe/TicTacToeAIR.java b/game/src/main/java/org/toop/game/games/tictactoe/TicTacToeAIR.java index 07271b1..8a3e105 100644 --- a/game/src/main/java/org/toop/game/games/tictactoe/TicTacToeAIR.java +++ b/game/src/main/java/org/toop/game/games/tictactoe/TicTacToeAIR.java @@ -13,7 +13,7 @@ import org.toop.framework.gameFramework.GameState; * opening or when no clear best move is found. *

*/ -public final class TicTacToeAIR extends AbstractAI { +public final class TicTacToeAIR extends AbstractAI { /** * Determines the best move for the given Tic-Tac-Toe game state. @@ -27,7 +27,7 @@ public final class TicTacToeAIR extends AbstractAI { * @param depth the depth of lookahead for evaluating moves (non-negative) * @return the index of the best move, or -1 if no moves are available */ - public int getMove(TicTacToeR game) { + public int getMove(BitboardTicTacToe game) { int depth = 9; assert game != null; final int[] legalMoves = game.getLegalMoves(); @@ -71,8 +71,8 @@ public final class TicTacToeAIR extends AbstractAI { * @param maximizing true if the AI is to maximize score, false if minimizing * @return the score of the move */ - private int getMoveScore(TicTacToeR game, int depth, int move, boolean maximizing) { - final TicTacToeR copy = game.deepCopy(); + private int getMoveScore(BitboardTicTacToe game, int depth, int move, boolean maximizing) { + final BitboardTicTacToe copy = game.deepCopy(); final PlayResult result = copy.play(move); GameState state = result.state();