Removed Generics, pray nothing breaks.

This commit is contained in:
2025-12-12 15:53:24 +01:00
parent 0132981d94
commit fa9c2ce32b
30 changed files with 116 additions and 113 deletions

View File

@@ -7,17 +7,17 @@ import java.util.Arrays;
import java.util.concurrent.atomic.AtomicInteger;
// There is AI performance to be gained by getting rid of non-primitives and thus speeding up deepCopy
public abstract class BitboardGame<T extends BitboardGame<T>> implements TurnBasedGame<T> {
public abstract class BitboardGame implements TurnBasedGame {
private final int columnSize;
private final int rowSize;
private Player<T>[] players;
private Player[] players;
// long is 64 bits. Every game has a limit of 64 cells maximum.
private final long[] playerBitboard;
private int currentTurn = 0;
public BitboardGame(int columnSize, int rowSize, int playerCount, Player<T>[] players) {
public BitboardGame(int columnSize, int rowSize, int playerCount, Player[] players) {
this.columnSize = columnSize;
this.rowSize = rowSize;
this.players = players;
@@ -26,14 +26,14 @@ public abstract class BitboardGame<T extends BitboardGame<T>> implements TurnBas
Arrays.fill(playerBitboard, 0L);
}
public BitboardGame(BitboardGame<T> other) {
public BitboardGame(BitboardGame other) {
this.columnSize = other.columnSize;
this.rowSize = other.rowSize;
this.playerBitboard = other.playerBitboard.clone();
this.currentTurn = other.currentTurn;
this.players = Arrays.stream(other.players)
.map(Player<T>::deepCopy)
.map(Player::deepCopy)
.toArray(Player[]::new);
}
@@ -61,7 +61,7 @@ public abstract class BitboardGame<T extends BitboardGame<T>> implements TurnBas
return getCurrentPlayerIndex();
}
public Player<T> getPlayer(int index) {return players[index];}
public Player getPlayer(int index) {return players[index];}
public int getCurrentPlayerIndex() {
return currentTurn % playerBitboard.length;
@@ -71,7 +71,7 @@ public abstract class BitboardGame<T extends BitboardGame<T>> implements TurnBas
return (currentTurn + 1) % playerBitboard.length;
}
public Player<T> getCurrentPlayer(){
public Player getCurrentPlayer(){
return players[getCurrentPlayerIndex()];
}

View File

@@ -16,7 +16,7 @@ import java.util.function.Consumer;
* Runs a separate thread that executes game turns at a fixed frequency (default 60 updates/sec),
* applying player moves, updating the game state, and dispatching UI events.
*/
public class LocalFixedRateThreadBehaviour<T extends TurnBasedGame<T>> extends AbstractThreadBehaviour<T> implements Runnable {
public class LocalFixedRateThreadBehaviour extends AbstractThreadBehaviour implements Runnable {
/**
@@ -24,7 +24,7 @@ public class LocalFixedRateThreadBehaviour<T extends TurnBasedGame<T>> extends A
*
* @param game the game instance
*/
public LocalFixedRateThreadBehaviour(T game) {
public LocalFixedRateThreadBehaviour(TurnBasedGame game) {
super(game);
}
@@ -59,7 +59,7 @@ public class LocalFixedRateThreadBehaviour<T extends TurnBasedGame<T>> extends A
if (now >= nextUpdate) {
nextUpdate += UPDATE_INTERVAL;
Player<T> currentPlayer = game.getPlayer(game.getCurrentTurn());
Player currentPlayer = game.getPlayer(game.getCurrentTurn());
long move = currentPlayer.getMove(game.deepCopy());
PlayResult result = game.play(move);

View File

@@ -16,14 +16,14 @@ import java.util.function.Consumer;
* Repeatedly gets the current player's move, applies it to the game,
* updates the UI, and stops when the game ends or {@link #stop()} is called.
*/
public class LocalThreadBehaviour<T extends TurnBasedGame<T>> extends AbstractThreadBehaviour<T> implements Runnable {
public class LocalThreadBehaviour extends AbstractThreadBehaviour implements Runnable {
/**
* Creates a new behaviour for a local turn-based game.
*
* @param game the game instance
*/
public LocalThreadBehaviour(T game) {
public LocalThreadBehaviour(TurnBasedGame game) {
super(game);
}
@@ -48,7 +48,7 @@ public class LocalThreadBehaviour<T extends TurnBasedGame<T>> extends AbstractTh
@Override
public void run() {
while (isRunning.get()) {
Player<T> currentPlayer = game.getPlayer(game.getCurrentTurn());
Player currentPlayer = game.getPlayer(game.getCurrentTurn());
long move = currentPlayer.getMove(game.deepCopy());
PlayResult result = game.play(move);

View File

@@ -14,17 +14,17 @@ import org.toop.game.players.OnlinePlayer;
* Reacts to server events, sending moves and updating the game state
* for the local player while receiving moves from other players.
*/
public class OnlineThreadBehaviour<T extends TurnBasedGame<T>> extends AbstractThreadBehaviour<T> implements SupportsOnlinePlay {
public class OnlineThreadBehaviour extends AbstractThreadBehaviour implements SupportsOnlinePlay {
/**
* Creates behaviour and sets the first local player
* (non-online player) from the given array.
*/
public OnlineThreadBehaviour(T game) {
public OnlineThreadBehaviour(TurnBasedGame game) {
super(game);
}
/** Finds the first non-online player in the array. */
private int getFirstNotOnlinePlayer(Player<T>[] players) {
private int getFirstNotOnlinePlayer(Player[] players) {
for (int i = 0; i < players.length; i++) {
if (!(players[i] instanceof OnlinePlayer)) {
return i;

View File

@@ -10,14 +10,14 @@ import org.toop.framework.networking.events.NetworkEvents;
* This is identical to {@link OnlineThreadBehaviour}, but inserts a
* short sleep before delegating to the base implementation.
*/
public class OnlineWithSleepThreadBehaviour<T extends TurnBasedGame<T>> extends OnlineThreadBehaviour<T> {
public class OnlineWithSleepThreadBehaviour extends OnlineThreadBehaviour {
/**
* Creates the behaviour and forwards the players to the base class.
*
* @param game the online-capable turn-based game
*/
public OnlineWithSleepThreadBehaviour(T game) {
public OnlineWithSleepThreadBehaviour(TurnBasedGame game) {
super(game);
}

View File

@@ -5,14 +5,14 @@ import org.toop.framework.gameFramework.model.game.PlayResult;
import org.toop.framework.gameFramework.model.player.Player;
import org.toop.game.BitboardGame;
public class BitboardReversi extends BitboardGame<BitboardReversi> {
public class BitboardReversi extends BitboardGame {
public record Score(int black, int white) {}
private final long notAFile = 0xfefefefefefefefeL;
private final long notHFile = 0x7f7f7f7f7f7f7f7fL;
public BitboardReversi(Player<BitboardReversi>[] players) {
public BitboardReversi(Player[] players) {
super(8, 8, 2, players);
// Black (player 0)

View File

@@ -5,7 +5,7 @@ import org.toop.framework.gameFramework.model.game.PlayResult;
import org.toop.framework.gameFramework.model.player.Player;
import org.toop.game.BitboardGame;
public class BitboardTicTacToe extends BitboardGame<BitboardTicTacToe> {
public class BitboardTicTacToe extends BitboardGame {
private final long[] winningLines = {
0b111000000L, // top row
0b000111000L, // middle row
@@ -17,7 +17,7 @@ public class BitboardTicTacToe extends BitboardGame<BitboardTicTacToe> {
0b001010100L // anti-diagonal
};
public BitboardTicTacToe(Player<BitboardTicTacToe>[] players) {
public BitboardTicTacToe(Player[] players) {
super(3, 3, 2, players);
}
public BitboardTicTacToe(BitboardTicTacToe other) {

View File

@@ -12,22 +12,22 @@ import org.toop.framework.gameFramework.model.game.TurnBasedGame;
*
* @param <T> the specific type of game this AI player can play
*/
public class ArtificialPlayer<T extends TurnBasedGame<T>> extends AbstractPlayer<T> {
public class ArtificialPlayer extends AbstractPlayer {
/** The AI instance used to calculate moves. */
private final AI<T> 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(AI<T> ai, String name) {
public ArtificialPlayer(AI ai, String name) {
super(name);
this.ai = ai;
}
public ArtificialPlayer(ArtificialPlayer<T> other) {
public ArtificialPlayer(ArtificialPlayer other) {
super(other);
this.ai = other.ai.deepCopy();
}
@@ -44,12 +44,12 @@ public class ArtificialPlayer<T extends TurnBasedGame<T>> extends AbstractPlayer
* @return the integer representing the chosen move
* @throws ClassCastException if {@code gameCopy} is not of type {@code T}
*/
public long getMove(T gameCopy) {
public long getMove(TurnBasedGame gameCopy) {
return ai.getMove(gameCopy);
}
@Override
public ArtificialPlayer<T> deepCopy() {
return new ArtificialPlayer<T>(this);
public ArtificialPlayer deepCopy() {
return new ArtificialPlayer(this);
}
}

View File

@@ -7,7 +7,7 @@ import org.toop.framework.gameFramework.model.player.Player;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
public class LocalPlayer<T extends TurnBasedGame<T>> extends AbstractPlayer<T> {
public class LocalPlayer extends AbstractPlayer {
// Future can be used with event system, IF unsubscribeAfterSuccess works...
// private CompletableFuture<Integer> LastMove = new CompletableFuture<>();
@@ -17,12 +17,12 @@ public class LocalPlayer<T extends TurnBasedGame<T>> extends AbstractPlayer<T> {
super(name);
}
public LocalPlayer(LocalPlayer<T> other) {
public LocalPlayer(LocalPlayer other) {
super(other);
}
@Override
public long getMove(T gameCopy) {
public long getMove(TurnBasedGame gameCopy) {
return getValidMove(gameCopy);
}
@@ -36,7 +36,7 @@ public class LocalPlayer<T extends TurnBasedGame<T>> extends AbstractPlayer<T> {
return false;
}
private long getMove2(T gameCopy) {
private long getMove2(TurnBasedGame gameCopy) {
LastMove = new CompletableFuture<>();
long move = 0;
try {
@@ -49,7 +49,7 @@ public class LocalPlayer<T extends TurnBasedGame<T>> extends AbstractPlayer<T> {
return move;
}
protected long getValidMove(T gameCopy){
protected long getValidMove(TurnBasedGame gameCopy){
// Get this player's valid moves
long validMoves = gameCopy.getLegalMoves();
// Make sure provided move is valid
@@ -64,8 +64,8 @@ public class LocalPlayer<T extends TurnBasedGame<T>> extends AbstractPlayer<T> {
}
@Override
public LocalPlayer<T> deepCopy() {
return new LocalPlayer<T>(this.getName());
public LocalPlayer deepCopy() {
return new LocalPlayer(this.getName());
}
/*public void register() {

View File

@@ -9,7 +9,7 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class MiniMaxAI<T extends TurnBasedGame<T>> extends AbstractAI<T> {
public class MiniMaxAI extends AbstractAI {
private final int maxDepth;
private final Random random = new Random();
@@ -18,17 +18,17 @@ public class MiniMaxAI<T extends TurnBasedGame<T>> extends AbstractAI<T> {
this.maxDepth = depth;
}
public MiniMaxAI(MiniMaxAI<T> other) {
public MiniMaxAI(MiniMaxAI other) {
this.maxDepth = other.maxDepth;
}
@Override
public MiniMaxAI<T> deepCopy() {
return new MiniMaxAI<>(this);
public MiniMaxAI deepCopy() {
return new MiniMaxAI(this);
}
@Override
public long getMove(T game) {
public long getMove(TurnBasedGame game) {
long legalMoves = game.getLegalMoves();
if (legalMoves == 0) return 0;
@@ -39,7 +39,7 @@ public class MiniMaxAI<T extends TurnBasedGame<T>> extends AbstractAI<T> {
long movesLoop = legalMoves;
while (movesLoop != 0) {
long move = 1L << Long.numberOfTrailingZeros(movesLoop);
T copy = game.deepCopy();
TurnBasedGame copy = game.deepCopy();
PlayResult result = copy.play(move);
int score;
@@ -75,7 +75,7 @@ public class MiniMaxAI<T extends TurnBasedGame<T>> extends AbstractAI<T> {
* @param beta Beta value
* @return score of the position
*/
private int getMoveScore(T game, int depth, boolean maximizing, int aiPlayer, int alpha, int beta) {
private int getMoveScore(TurnBasedGame game, int depth, boolean maximizing, int aiPlayer, int alpha, int beta) {
long legalMoves = game.getLegalMoves();
// Terminal state
@@ -95,7 +95,7 @@ public class MiniMaxAI<T extends TurnBasedGame<T>> extends AbstractAI<T> {
while (movesLoop != 0) {
long move = 1L << Long.numberOfTrailingZeros(movesLoop);
T copy = game.deepCopy();
TurnBasedGame copy = game.deepCopy();
PlayResult result = copy.play(move);
int score;
@@ -130,7 +130,7 @@ public class MiniMaxAI<T extends TurnBasedGame<T>> extends AbstractAI<T> {
* @param aiPlayer AI's player index
* @return heuristic score
*/
private int evaluateBoard(T game, int aiPlayer) {
private int evaluateBoard(TurnBasedGame game, int aiPlayer) {
long[] board = game.getBoard();
int aiCount = 0;
int opponentCount = 0;

View File

@@ -12,7 +12,7 @@ import org.toop.framework.gameFramework.model.player.Player;
* Currently, this class is a placeholder and does not implement move logic.
* </p>
*/
public class OnlinePlayer<T extends TurnBasedGame<T>> extends AbstractPlayer<T> {
public class OnlinePlayer extends AbstractPlayer {
/**
* Constructs a new OnlinePlayer.
@@ -25,12 +25,12 @@ public class OnlinePlayer<T extends TurnBasedGame<T>> extends AbstractPlayer<T>
super(name);
}
public OnlinePlayer(OnlinePlayer<T> other) {
public OnlinePlayer(OnlinePlayer other) {
super(other);
}
@Override
public Player<T> deepCopy() {
return new OnlinePlayer<>(this);
public Player deepCopy() {
return new OnlinePlayer(this);
}
}

View File

@@ -6,19 +6,19 @@ import org.toop.framework.gameFramework.model.player.AbstractAI;
import java.util.Random;
public class RandomAI<T extends TurnBasedGame<T>> extends AbstractAI<T> {
public class RandomAI extends AbstractAI {
public RandomAI() {
super();
}
@Override
public RandomAI<T> deepCopy() {
return new RandomAI<T>();
public RandomAI deepCopy() {
return new RandomAI();
}
@Override
public long getMove(T game) {
public long getMove(TurnBasedGame game) {
long legalMoves = game.getLegalMoves();
int move = new Random().nextInt(Long.bitCount(legalMoves));
return nthBitIndex(legalMoves, move);