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 4e18cec..efa8323 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), // TODO: Player order matters here, this won't work atm + local ? new LocalFixedRateThreadBehaviour<>(ReversiR) : 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/framework/src/main/java/org/toop/framework/gameFramework/model/game/DeepCopyable.java b/framework/src/main/java/org/toop/framework/gameFramework/model/game/DeepCopyable.java index cf3bfe4..51cb1e2 100644 --- a/framework/src/main/java/org/toop/framework/gameFramework/model/game/DeepCopyable.java +++ b/framework/src/main/java/org/toop/framework/gameFramework/model/game/DeepCopyable.java @@ -1,5 +1,5 @@ package org.toop.framework.gameFramework.model.game; -public interface DeepCopyable> { +public interface DeepCopyable { T deepCopy(); } diff --git a/framework/src/main/java/org/toop/framework/gameFramework/model/player/AI.java b/framework/src/main/java/org/toop/framework/gameFramework/model/player/AI.java new file mode 100644 index 0000000..8377166 --- /dev/null +++ b/framework/src/main/java/org/toop/framework/gameFramework/model/player/AI.java @@ -0,0 +1,7 @@ +package org.toop.framework.gameFramework.model.player; + +import org.toop.framework.gameFramework.model.game.DeepCopyable; +import org.toop.framework.gameFramework.model.game.TurnBasedGame; + +public interface AI> extends MoveProvider, DeepCopyable> { +} 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 ea22859..328132d 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,6 +12,6 @@ import org.toop.framework.gameFramework.model.game.TurnBasedGame; * * @param the specific type of game this AI can play, extending {@link GameR} */ -public abstract class AbstractAI> implements MoveProvider { +public abstract class AbstractAI> implements AI { // Concrete AI implementations should override findBestMove(T game, int depth) } diff --git a/framework/src/main/java/org/toop/framework/gameFramework/model/player/AbstractPlayer.java b/framework/src/main/java/org/toop/framework/gameFramework/model/player/AbstractPlayer.java index 077dee3..bca7a01 100644 --- a/framework/src/main/java/org/toop/framework/gameFramework/model/player/AbstractPlayer.java +++ b/framework/src/main/java/org/toop/framework/gameFramework/model/player/AbstractPlayer.java @@ -16,15 +16,17 @@ import org.toop.framework.gameFramework.model.game.TurnBasedGame; *

*/ public abstract class AbstractPlayer> implements Player { - private int playerIndex = -1; - - private Logger logger = LogManager.getLogger(this.getClass()); + private final Logger logger = LogManager.getLogger(this.getClass()); private final String name; protected AbstractPlayer(String name) { this.name = name; } + + protected AbstractPlayer(AbstractPlayer other) { + this.name = other.name; + } /** * Determines the next move based on the provided game state. *

diff --git a/framework/src/main/java/org/toop/framework/gameFramework/model/player/MoveProvider.java b/framework/src/main/java/org/toop/framework/gameFramework/model/player/MoveProvider.java index 29529e2..5a8555e 100644 --- a/framework/src/main/java/org/toop/framework/gameFramework/model/player/MoveProvider.java +++ b/framework/src/main/java/org/toop/framework/gameFramework/model/player/MoveProvider.java @@ -2,6 +2,6 @@ package org.toop.framework.gameFramework.model.player; import org.toop.framework.gameFramework.model.game.TurnBasedGame; -public interface MoveProvider { +public interface MoveProvider> { int getMove(T game); } diff --git a/framework/src/main/java/org/toop/framework/gameFramework/model/player/Player.java b/framework/src/main/java/org/toop/framework/gameFramework/model/player/Player.java index bf49cd7..e2ff1a8 100644 --- a/framework/src/main/java/org/toop/framework/gameFramework/model/player/Player.java +++ b/framework/src/main/java/org/toop/framework/gameFramework/model/player/Player.java @@ -1,6 +1,7 @@ package org.toop.framework.gameFramework.model.player; +import org.toop.framework.gameFramework.model.game.DeepCopyable; import org.toop.framework.gameFramework.model.game.TurnBasedGame; -public interface Player> extends NameProvider, MoveProvider { +public interface Player> extends NameProvider, MoveProvider, DeepCopyable> { } diff --git a/game/src/main/java/org/toop/game/BitboardGame.java b/game/src/main/java/org/toop/game/BitboardGame.java index 70311b9..d0f1be4 100644 --- a/game/src/main/java/org/toop/game/BitboardGame.java +++ b/game/src/main/java/org/toop/game/BitboardGame.java @@ -60,7 +60,9 @@ public abstract class BitboardGame> implements TurnBas this.playerBitboard = Arrays.copyOf(other.playerBitboard, other.playerBitboard.length); this.currentTurn = other.currentTurn; - this.players = Arrays.copyOf(other.players, other.players.length); // TODO: Make this a deep copy + this.players = Arrays.stream(other.players) + .map(Player::deepCopy) + .toArray(Player[]::new); } public int getColumnSize() { 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 626a367..928f4e8 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 @@ -1,10 +1,11 @@ package org.toop.game.games.reversi; +import org.toop.framework.gameFramework.model.player.AI; import org.toop.framework.gameFramework.model.player.AbstractAI; import java.util.Random; -public final class ReversiAIR extends AbstractAI { +public final class ReversiAIR extends AbstractAI{ public int getMove(BitboardReversi game) { int[] moves = game.getLegalMoves(); if (moves.length == 0) return -1; @@ -12,4 +13,8 @@ public final class ReversiAIR extends AbstractAI { int inty = new Random().nextInt(0, moves.length); return moves[inty]; } + + public ReversiAIR deepCopy() { + return new ReversiAIR(); + } } 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 8a3e105..497a0b8 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 @@ -1,5 +1,6 @@ package org.toop.game.games.tictactoe; +import org.toop.framework.gameFramework.model.player.AI; import org.toop.framework.gameFramework.model.player.AbstractAI; import org.toop.framework.gameFramework.model.game.PlayResult; import org.toop.framework.gameFramework.GameState; @@ -99,4 +100,9 @@ public final class TicTacToeAIR extends AbstractAI { return score; } + + @Override + public AI deepCopy() { + return new TicTacToeAIR(); + } } diff --git a/game/src/main/java/org/toop/game/players/ArtificialPlayer.java b/game/src/main/java/org/toop/game/players/ArtificialPlayer.java index 49fff2d..41883a5 100644 --- a/game/src/main/java/org/toop/game/players/ArtificialPlayer.java +++ b/game/src/main/java/org/toop/game/players/ArtificialPlayer.java @@ -1,8 +1,6 @@ package org.toop.game.players; -import org.toop.framework.gameFramework.model.player.AbstractAI; -import org.toop.framework.gameFramework.model.player.AbstractPlayer; -import org.toop.framework.gameFramework.model.player.MoveProvider; +import org.toop.framework.gameFramework.model.player.*; import org.toop.framework.gameFramework.model.game.TurnBasedGame; /** @@ -17,18 +15,23 @@ import org.toop.framework.gameFramework.model.game.TurnBasedGame; public class ArtificialPlayer> extends AbstractPlayer { /** The AI instance used to calculate moves. */ - private final MoveProvider ai; + private final AI ai; /** * Constructs a new ArtificialPlayer using the specified AI. * * @param ai the AI instance that determines moves for this player */ - public ArtificialPlayer(MoveProvider ai, String name) { + public ArtificialPlayer(AI ai, String name) { super(name); this.ai = ai; } + public ArtificialPlayer(ArtificialPlayer other) { + super(other); + this.ai = other.ai.deepCopy(); + } + /** * Determines the next move for this player using its AI. *

@@ -44,4 +47,9 @@ public class ArtificialPlayer> extends AbstractPlayer public int getMove(T gameCopy) { return ai.getMove(gameCopy); } + + @Override + public ArtificialPlayer deepCopy() { + return new ArtificialPlayer(this); + } } diff --git a/game/src/main/java/org/toop/game/players/LocalPlayer.java b/game/src/main/java/org/toop/game/players/LocalPlayer.java index e83b3f4..200ac3a 100644 --- a/game/src/main/java/org/toop/game/players/LocalPlayer.java +++ b/game/src/main/java/org/toop/game/players/LocalPlayer.java @@ -2,6 +2,7 @@ package org.toop.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 java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; @@ -16,6 +17,10 @@ public class LocalPlayer> extends AbstractPlayer { super(name); } + public LocalPlayer(LocalPlayer other) { + super(other); + } + @Override public int getMove(T gameCopy) { return getValidMove(gameCopy); @@ -57,6 +62,11 @@ public class LocalPlayer> extends AbstractPlayer { return move; } + @Override + public LocalPlayer deepCopy() { + return new LocalPlayer(this.getName()); + } + /*public void register() { // Listening to PlayerAttemptedMove new EventFlow().listen(GUIEvents.PlayerAttemptedMove.class, event -> { diff --git a/game/src/main/java/org/toop/game/players/OnlinePlayer.java b/game/src/main/java/org/toop/game/players/OnlinePlayer.java index 148e19c..9f011c0 100644 --- a/game/src/main/java/org/toop/game/players/OnlinePlayer.java +++ b/game/src/main/java/org/toop/game/players/OnlinePlayer.java @@ -2,6 +2,7 @@ package org.toop.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; /** * Represents a player controlled remotely or over a network. @@ -23,4 +24,13 @@ public class OnlinePlayer> extends AbstractPlayer public OnlinePlayer(String name) { super(name); } + + public OnlinePlayer(OnlinePlayer other) { + super(other); + } + + @Override + public Player deepCopy() { + return new OnlinePlayer<>(this); + } }