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();