diff --git a/framework/src/main/java/org/toop/framework/game/BitboardGame.java b/framework/src/main/java/org/toop/framework/game/BitboardGame.java index f2781cd..3e26d40 100644 --- a/framework/src/main/java/org/toop/framework/game/BitboardGame.java +++ b/framework/src/main/java/org/toop/framework/game/BitboardGame.java @@ -13,20 +13,20 @@ public abstract class BitboardGame implements TurnBasedGame { private Player[] players; // long is 64 bits. Every game has a limit of 64 cells maximum. - private long[] playerBitboard; + private final long[] playerBitboard; private int currentTurn = 0; - private int playerCount; + private final int playerCount; public BitboardGame(int columnSize, int rowSize, int playerCount) { this.columnSize = columnSize; this.rowSize = rowSize; this.playerCount = playerCount; + this.playerBitboard = new long[playerCount]; } @Override public void init(Player[] players) { this.players = players; - this.playerBitboard = new long[playerCount]; Arrays.fill(playerBitboard, 0L); } @@ -34,7 +34,7 @@ public abstract class BitboardGame implements TurnBasedGame { public BitboardGame(BitboardGame other) { this.columnSize = other.columnSize; this.rowSize = other.rowSize; - + this.playerCount = other.playerCount; this.playerBitboard = other.playerBitboard.clone(); this.currentTurn = other.currentTurn; this.players = Arrays.stream(other.players) diff --git a/framework/src/main/java/org/toop/framework/game/gameThreads/ServerThreadBehaviour.java b/framework/src/main/java/org/toop/framework/game/gameThreads/ServerThreadBehaviour.java new file mode 100644 index 0000000..8789e41 --- /dev/null +++ b/framework/src/main/java/org/toop/framework/game/gameThreads/ServerThreadBehaviour.java @@ -0,0 +1,68 @@ +package org.toop.framework.game.gameThreads; + +import org.toop.framework.eventbus.EventFlow; +import org.toop.framework.gameFramework.GameState; +import org.toop.framework.gameFramework.model.game.PlayResult; +import org.toop.framework.gameFramework.model.game.TurnBasedGame; +import org.toop.framework.gameFramework.model.game.threadBehaviour.AbstractThreadBehaviour; +import org.toop.framework.gameFramework.model.player.Player; +import org.toop.framework.gameFramework.view.GUIEvents; + +import java.util.function.Consumer; + +public class ServerThreadBehaviour extends AbstractThreadBehaviour implements Runnable { + private Consumer onPlayerMove; + /** + * Creates a new base behaviour for the specified game. + * + * @param game the turn-based game to control + */ + public ServerThreadBehaviour(TurnBasedGame game, Consumer onPlayerMove) { + super(game); + } + + private void notifyPlayerMove(int player) { + onPlayerMove.accept(player); + } + + /** Starts the game loop in a new thread. */ + @Override + public void start() { + if (isRunning.compareAndSet(false, true)) { + new Thread(this).start(); + } + } + + /** Stops the game loop after the current iteration. */ + @Override + public void stop() { + isRunning.set(false); + } + + @Override + public void run() { + while (isRunning.get()) { + Player currentPlayer = game.getPlayer(game.getCurrentTurn()); + long move = currentPlayer.getMove(game.deepCopy()); + PlayResult result = game.play(move); + + GameState state = result.state(); + switch (state) { + case WIN, DRAW -> { + isRunning.set(false); + new EventFlow().addPostEvent( + GUIEvents.GameEnded.class, + state == GameState.WIN, + result.player() + ).postEvent(); + } + case NORMAL, TURN_SKIPPED -> { /* continue normally */ } + default -> { + logger.error("Unexpected state {}", state); + isRunning.set(false); + throw new RuntimeException("Unknown state: " + state); + } + } + } + } +} diff --git a/framework/src/main/java/org/toop/framework/game/games/reversi/BitboardReversi.java b/framework/src/main/java/org/toop/framework/game/games/reversi/BitboardReversi.java index c36f236..e116c9a 100644 --- a/framework/src/main/java/org/toop/framework/game/games/reversi/BitboardReversi.java +++ b/framework/src/main/java/org/toop/framework/game/games/reversi/BitboardReversi.java @@ -15,17 +15,16 @@ public class BitboardReversi extends BitboardGame { public BitboardReversi() { super(8, 8, 2); - - // Black (player 0) - setPlayerBitboard(0, (1L << (3 + 4 * 8)) | (1L << (4 + 3 * 8))); - - // White (player 1) - setPlayerBitboard(1, (1L << (3 + 3 * 8)) | (1L << (4 + 4 * 8))); } @Override public void init(Player[] players) { super.init(players); + // Black (player 0) + setPlayerBitboard(0, (1L << (3 + 4 * 8)) | (1L << (4 + 3 * 8))); + + // White (player 1) + setPlayerBitboard(1, (1L << (3 + 3 * 8)) | (1L << (4 + 4 * 8))); } public BitboardReversi(BitboardReversi other) { diff --git a/framework/src/main/java/org/toop/framework/game/players/ServerPlayer.java b/framework/src/main/java/org/toop/framework/game/players/ServerPlayer.java new file mode 100644 index 0000000..535a033 --- /dev/null +++ b/framework/src/main/java/org/toop/framework/game/players/ServerPlayer.java @@ -0,0 +1,46 @@ +package org.toop.framework.game.players; + +import org.toop.framework.gameFramework.model.game.TurnBasedGame; +import org.toop.framework.gameFramework.model.player.AbstractPlayer; +import org.toop.framework.gameFramework.model.player.Player; +import org.toop.framework.networking.server.User; + +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; + +public class ServerPlayer extends AbstractPlayer { + private User user; + private CompletableFuture lastMove; + + public ServerPlayer(User user) { + super(user.name()); + this.user = user; + } + + public void setMove(long move) { + lastMove.complete(move); + } + + @Override + public Player deepCopy() { + return null; + } + + @Override + public long getMove(TurnBasedGame game) { + lastMove = new CompletableFuture<>(); + System.out.println("Sending yourturn"); + user.sendMessage("SVR GAME YOURTURN {TURNMESSAGE: \"\"}\n"); + try { + return lastMove.get(); + } catch (InterruptedException | ExecutionException e) { + e.printStackTrace(); + return 0; + } + } + + @Override + public String getName() { + return ""; + } +} diff --git a/framework/src/main/java/org/toop/framework/networking/server/Game.java b/framework/src/main/java/org/toop/framework/networking/server/Game.java index 48f5036..87e24f7 100644 --- a/framework/src/main/java/org/toop/framework/networking/server/Game.java +++ b/framework/src/main/java/org/toop/framework/networking/server/Game.java @@ -1,5 +1,8 @@ package org.toop.framework.networking.server; +import org.toop.framework.game.gameThreads.LocalThreadBehaviour; +import org.toop.framework.game.gameThreads.OnlineThreadBehaviour; +import org.toop.framework.game.gameThreads.ServerThreadBehaviour; import org.toop.framework.gameFramework.model.game.TurnBasedGame; public class Game implements OnlineGame { @@ -7,9 +10,11 @@ public class Game implements OnlineGame { private long id; private User[] users; private TurnBasedGame game; + private ServerThreadBehaviour gameThread; public Game(TurnBasedGame game, User... users) { this.game = game; + this.gameThread = new ServerThreadBehaviour(game, null); this.users = users; } @@ -27,4 +32,9 @@ public class Game implements OnlineGame { public User[] users() { return users; } + + @Override + public void start(){ + this.gameThread.start(); + } } diff --git a/framework/src/main/java/org/toop/framework/networking/server/OnlineGame.java b/framework/src/main/java/org/toop/framework/networking/server/OnlineGame.java index 1b072a9..b82b4b1 100644 --- a/framework/src/main/java/org/toop/framework/networking/server/OnlineGame.java +++ b/framework/src/main/java/org/toop/framework/networking/server/OnlineGame.java @@ -4,4 +4,5 @@ public interface OnlineGame { long id(); T game(); User[] users(); + void start(); } diff --git a/framework/src/main/java/org/toop/framework/networking/server/Server.java b/framework/src/main/java/org/toop/framework/networking/server/Server.java index 4db663c..7f0f71c 100644 --- a/framework/src/main/java/org/toop/framework/networking/server/Server.java +++ b/framework/src/main/java/org/toop/framework/networking/server/Server.java @@ -1,6 +1,9 @@ package org.toop.framework.networking.server; +import org.toop.framework.game.gameThreads.OnlineThreadBehaviour; import org.toop.framework.game.players.LocalPlayer; +import org.toop.framework.game.players.OnlinePlayer; +import org.toop.framework.game.players.ServerPlayer; import org.toop.framework.gameFramework.model.game.TurnBasedGame; import org.toop.framework.gameFramework.model.player.Player; @@ -144,16 +147,23 @@ public class Server implements GameServer { if (!gameTypes.containsKey(gameType)) return; try { - Player[] players = new Player[users.length]; for (int i = 0; i < users.length; i++) { - players[i] = new LocalPlayer(users[i].name()); + players[i] = new ServerPlayer(users[i]); } - + System.out.println("Starting Game"); var game = new Game(gameTypes.get(gameType).getDeclaredConstructor().newInstance(), users); game.game().init(players); games.addLast(game); - + users[0].sendMessage(String.format("SVR GAME MATCH {PLAYERTOMOVE: \"%s\", GAMETYPE: \"%s\", OPPONENT: \"%s\"}\n", + users[0].name(), + gameType, + users[1].name())); + users[1].sendMessage(String.format("SVR GAME MATCH {PLAYERTOMOVE: \"%s\", GAMETYPE: \"%s\", OPPONENT: \"%s\"}\n", + users[0].name(), + gameType, + users[0].name())); + game.start(); } catch (Exception ignored) {} }