From 21b489bbe7a1f24f423dc29986ff04f0cb0267ab Mon Sep 17 00:00:00 2001 From: Stef Date: Thu, 4 Dec 2025 14:19:48 +0100 Subject: [PATCH] Almost done with implementing bitboards. Reversi is broken and artifical players don't work yet. --- .../org/toop/app/canvas/BaseGameCanvas.java | 237 +++++++++++++++++ .../org/toop/app/canvas/BitGameCanvas.java | 239 ++++++++++++++++++ .../org/toop/app/canvas/Connect4Canvas.java | 17 -- .../java/org/toop/app/canvas/GameCanvas.java | 236 +---------------- .../java/org/toop/app/canvas/GameDrawer.java | 7 + .../org/toop/app/canvas/ReversiBitCanvas.java | 53 ++++ .../org/toop/app/canvas/ReversiCanvas.java | 4 +- .../toop/app/canvas/TicTacToeBitCanvas.java | 76 ++++++ .../org/toop/app/canvas/TicTacToeCanvas.java | 4 +- .../AbstractGameController.java | 15 +- .../GenericGameController.java | 134 ++++++++++ .../gameControllers/ReversiController.java | 2 +- .../gameControllers/TicTacToeController.java | 4 +- .../app/widget/view/LocalMultiplayerView.java | 34 ++- .../controller/GameController.java | 7 + .../AbstractThreadBehaviour.java | 2 +- .../game/threadBehaviour/ThreadBehaviour.java | 2 +- .../model/player/AbstractAI.java | 3 +- .../main/java/org/toop/game/BitboardGame.java | 8 +- .../gameThreads/LocalThreadBehaviour.java | 3 +- .../game/games/reversi/BitboardReversi.java | 3 + 21 files changed, 804 insertions(+), 286 deletions(-) create mode 100644 app/src/main/java/org/toop/app/canvas/BaseGameCanvas.java create mode 100644 app/src/main/java/org/toop/app/canvas/BitGameCanvas.java delete mode 100644 app/src/main/java/org/toop/app/canvas/Connect4Canvas.java create mode 100644 app/src/main/java/org/toop/app/canvas/GameDrawer.java create mode 100644 app/src/main/java/org/toop/app/canvas/ReversiBitCanvas.java create mode 100644 app/src/main/java/org/toop/app/canvas/TicTacToeBitCanvas.java create mode 100644 app/src/main/java/org/toop/app/gameControllers/GenericGameController.java create mode 100644 framework/src/main/java/org/toop/framework/gameFramework/controller/GameController.java diff --git a/app/src/main/java/org/toop/app/canvas/BaseGameCanvas.java b/app/src/main/java/org/toop/app/canvas/BaseGameCanvas.java new file mode 100644 index 0000000..b645142 --- /dev/null +++ b/app/src/main/java/org/toop/app/canvas/BaseGameCanvas.java @@ -0,0 +1,237 @@ +package org.toop.app.canvas; + +import javafx.animation.KeyFrame; +import javafx.animation.Timeline; +import javafx.scene.canvas.Canvas; +import javafx.scene.canvas.GraphicsContext; +import javafx.scene.input.MouseButton; +import javafx.scene.paint.Color; +import javafx.scene.text.Font; +import javafx.util.Duration; +import org.toop.framework.gameFramework.model.game.TurnBasedGame; + +import java.util.function.Consumer; +@Deprecated +public abstract class BaseGameCanvas> implements DrawPlayerMove, DrawPlayerHover { + protected record Cell(float x, float y, float width, float height) { + public boolean isInside(double x, double y) { + return x >= this.x && x <= this.x + width && + y >= this.y && y <= this.y + height; + } + } + + protected final Canvas canvas; + protected final GraphicsContext graphics; + + protected final Color color; + protected final Color backgroundColor; + + protected final int width; + protected final int height; + + protected final int rowSize; + protected final int columnSize; + + protected final int gapSize; + protected final boolean edges; + + protected final Cell[] cells; + + private Consumer onCellCLicked; + + public void setOnCellClicked(Consumer onClick) { + this.onCellCLicked = onClick; + } + + protected BaseGameCanvas(Color color, Color backgroundColor, int width, int height, int rowSize, int columnSize, int gapSize, boolean edges, Consumer onCellClicked, Consumer newCellEntered) { + canvas = new Canvas(width, height); + graphics = canvas.getGraphicsContext2D(); + + this.onCellCLicked = onCellClicked; + + this.color = color; + this.backgroundColor = backgroundColor; + + this.width = width; + this.height = height; + + this.rowSize = rowSize; + this.columnSize = columnSize; + + this.gapSize = gapSize; + this.edges = edges; + + cells = new Cell[rowSize * columnSize]; + + final float cellWidth = ((float) width - gapSize * rowSize - gapSize) / rowSize; + final float cellHeight = ((float) height - gapSize * columnSize - gapSize) / columnSize; + + for (int y = 0; y < columnSize; y++) { + final float startY = y * cellHeight + y * gapSize + gapSize; + + for (int x = 0; x < rowSize; x++) { + final float startX = x * cellWidth + x * gapSize + gapSize; + cells[x + y * rowSize] = new Cell(startX, startY, cellWidth, cellHeight); + } + } + + canvas.setOnMouseClicked(event -> { + if (event.getButton() != MouseButton.PRIMARY) { + return; + } + + final int column = (int) ((event.getX() / this.width) * rowSize); + final int row = (int) ((event.getY() / this.height) * columnSize); + + final Cell cell = cells[column + row * rowSize]; + + if (cell.isInside(event.getX(), event.getY())) { + event.consume(); + this.onCellCLicked.accept(column + row * rowSize); + } + }); + + + + + render(); + } + + private void render() { + graphics.setFill(backgroundColor); + graphics.fillRect(0, 0, width, height); + + graphics.setFill(color); + + for (int x = 0; x < rowSize - 1; x++) { + final float start = cells[x].x + cells[x].width; + graphics.fillRect(start, gapSize, gapSize, height - gapSize * 2); + } + + for (int y = 0; y < columnSize - 1; y++) { + final float start = cells[y * rowSize].y + cells[y * rowSize].height; + graphics.fillRect(gapSize, start, width - gapSize * 2, gapSize); + } + + if (edges) { + graphics.fillRect(0, 0, width, gapSize); + graphics.fillRect(0, 0, gapSize, height); + + graphics.fillRect(width - gapSize, 0, gapSize, height); + graphics.fillRect(0, height - gapSize, width, gapSize); + } + } + + public void fill(Color color, int cell) { + final float x = cells[cell].x(); + final float y = cells[cell].y(); + + final float width = cells[cell].width(); + final float height = cells[cell].height(); + + graphics.setFill(color); + graphics.fillRect(x, y, width, height); + } + + public void clear(int cell) { + final float x = cells[cell].x(); + final float y = cells[cell].y(); + + final float width = cells[cell].width(); + final float height = cells[cell].height(); + + graphics.clearRect(x, y, width, height); + + graphics.setFill(backgroundColor); + graphics.fillRect(x, y, width, height); + } + + public void clearAll() { + for (int i = 0; i < cells.length; i++) { + clear(i); + } + } + + @Override + public void drawPlayerMove(int player, int move) { + final float x = cells[move].x() + gapSize; + final float y = cells[move].y() + gapSize; + + final float width = cells[move].width() - gapSize * 2; + final float height = cells[move].height() - gapSize * 2; + + graphics.setFill(color); + graphics.setFont(Font.font("Arial", 40)); // TODO different font and size + graphics.fillText(String.valueOf(player), x + width, y + height); + } + + public void drawDot(Color color, int cell) { + final float x = cells[cell].x() + gapSize; + final float y = cells[cell].y() + gapSize; + + final float width = cells[cell].width() - gapSize * 2; + final float height = cells[cell].height() - gapSize * 2; + + graphics.setFill(color); + graphics.fillOval(x, y, width, height); + } + + public void drawInnerDot(Color color, int cell, boolean slightlyBigger) { + final float x = cells[cell].x() + gapSize; + final float y = cells[cell].y() + gapSize; + + float multiplier = slightlyBigger?1.4f:1.5f; + + final float width = (cells[cell].width() - gapSize * 2)/multiplier; + final float height = (cells[cell].height() - gapSize * 2)/multiplier; + + float offset = slightlyBigger?5f:4f; + + graphics.setFill(color); + graphics.fillOval(x + width/offset, y + height/offset, width, height); + } + + private void drawDotScaled(Color color, int cell, double scale) { + final float cx = cells[cell].x() + gapSize; + final float cy = cells[cell].y() + gapSize; + + final float fullWidth = cells[cell].width() - gapSize * 2; + final float height = cells[cell].height() - gapSize * 2; + + final float scaledWidth = (float)(fullWidth * scale); + final float offsetX = (fullWidth - scaledWidth) / 2; + + graphics.setFill(color); + graphics.fillOval(cx + offsetX, cy, scaledWidth, height); + } + + public Timeline flipDot(Color fromColor, Color toColor, int cell) { + final int steps = 60; + final long duration = 250; + final double interval = duration / (double) steps; + + final Timeline timeline = new Timeline(); + + for (int i = 0; i <= steps; i++) { + final double t = i / (double) steps; + final KeyFrame keyFrame = new KeyFrame(Duration.millis(i * interval), + _ -> { + clear(cell); + + final double scale = t <= 0.5 ? 1 - 2 * t : 2 * t - 1; + final Color currentColor = t < 0.5 ? fromColor : toColor; + + drawDotScaled(currentColor, cell, scale); + } + ); + + timeline.getKeyFrames().add(keyFrame); + } + + return timeline; + } + + public Canvas getCanvas() { + return canvas; + } +} \ No newline at end of file diff --git a/app/src/main/java/org/toop/app/canvas/BitGameCanvas.java b/app/src/main/java/org/toop/app/canvas/BitGameCanvas.java new file mode 100644 index 0000000..03d29f6 --- /dev/null +++ b/app/src/main/java/org/toop/app/canvas/BitGameCanvas.java @@ -0,0 +1,239 @@ +package org.toop.app.canvas; + +import javafx.animation.KeyFrame; +import javafx.animation.Timeline; +import javafx.scene.canvas.Canvas; +import javafx.scene.canvas.GraphicsContext; +import javafx.scene.input.MouseButton; +import javafx.scene.paint.Color; +import javafx.scene.text.Font; +import javafx.util.Duration; +import org.toop.framework.eventbus.EventFlow; +import org.toop.framework.gameFramework.model.game.TurnBasedGame; +import org.toop.framework.gameFramework.view.GUIEvents; +import org.toop.game.BitboardGame; + +import java.util.function.Consumer; + +public abstract class BitGameCanvas> implements GameCanvas { + protected record Cell(float x, float y, float width, float height) { + public boolean isInside(double x, double y) { + return x >= this.x && x <= this.x + width && + y >= this.y && y <= this.y + height; + } + } + + protected final Canvas canvas; + protected final GraphicsContext graphics; + + protected final Color color; + protected final Color backgroundColor; + + protected final int width; + protected final int height; + + protected final int rowSize; + protected final int columnSize; + + protected final int gapSize; + protected final boolean edges; + + protected final Cell[] cells; + + private Consumer onCellCLicked; + + public void setOnCellClicked(Consumer onClick) { + this.onCellCLicked = onClick; + } + + protected BitGameCanvas(Color color, Color backgroundColor, int width, int height, int rowSize, int columnSize, int gapSize, boolean edges) { + canvas = new Canvas(width, height); + graphics = canvas.getGraphicsContext2D(); + + this.onCellCLicked = (c) -> new EventFlow().addPostEvent(GUIEvents.PlayerAttemptedMove.class, c).postEvent(); + + this.color = color; + this.backgroundColor = backgroundColor; + + this.width = width; + this.height = height; + + this.rowSize = rowSize; + this.columnSize = columnSize; + + this.gapSize = gapSize; + this.edges = edges; + + cells = new Cell[rowSize * columnSize]; + + final float cellWidth = ((float) width - gapSize * rowSize - gapSize) / rowSize; + final float cellHeight = ((float) height - gapSize * columnSize - gapSize) / columnSize; + + for (int y = 0; y < columnSize; y++) { + final float startY = y * cellHeight + y * gapSize + gapSize; + + for (int x = 0; x < rowSize; x++) { + final float startX = x * cellWidth + x * gapSize + gapSize; + cells[x + y * rowSize] = new Cell(startX, startY, cellWidth, cellHeight); + } + } + + canvas.setOnMouseClicked(event -> { + if (event.getButton() != MouseButton.PRIMARY) { + return; + } + + final int column = (int) ((event.getX() / this.width) * rowSize); + final int row = (int) ((event.getY() / this.height) * columnSize); + + final Cell cell = cells[column + row * rowSize]; + + if (cell.isInside(event.getX(), event.getY())) { + event.consume(); + this.onCellCLicked.accept(column + row * rowSize); + } + }); + + + + + render(); + } + + private void render() { + graphics.setFill(backgroundColor); + graphics.fillRect(0, 0, width, height); + + graphics.setFill(color); + + for (int x = 0; x < rowSize - 1; x++) { + final float start = cells[x].x + cells[x].width; + graphics.fillRect(start, gapSize, gapSize, height - gapSize * 2); + } + + for (int y = 0; y < columnSize - 1; y++) { + final float start = cells[y * rowSize].y + cells[y * rowSize].height; + graphics.fillRect(gapSize, start, width - gapSize * 2, gapSize); + } + + if (edges) { + graphics.fillRect(0, 0, width, gapSize); + graphics.fillRect(0, 0, gapSize, height); + + graphics.fillRect(width - gapSize, 0, gapSize, height); + graphics.fillRect(0, height - gapSize, width, gapSize); + } + } + + public void fill(Color color, int cell) { + final float x = cells[cell].x(); + final float y = cells[cell].y(); + + final float width = cells[cell].width(); + final float height = cells[cell].height(); + + graphics.setFill(color); + graphics.fillRect(x, y, width, height); + } + + public void clear(int cell) { + final float x = cells[cell].x(); + final float y = cells[cell].y(); + + final float width = cells[cell].width(); + final float height = cells[cell].height(); + + graphics.clearRect(x, y, width, height); + + graphics.setFill(backgroundColor); + graphics.fillRect(x, y, width, height); + } + + public void clearAll() { + for (int i = 0; i < cells.length; i++) { + clear(i); + } + } + + public void drawPlayerMove(int player, int move) { + final float x = cells[move].x() + gapSize; + final float y = cells[move].y() + gapSize; + + final float width = cells[move].width() - gapSize * 2; + final float height = cells[move].height() - gapSize * 2; + + graphics.setFill(color); + graphics.setFont(Font.font("Arial", 40)); // TODO different font and size + graphics.fillText(String.valueOf(player), x + width, y + height); + } + + public void drawDot(Color color, int cell) { + final float x = cells[cell].x() + gapSize; + final float y = cells[cell].y() + gapSize; + + final float width = cells[cell].width() - gapSize * 2; + final float height = cells[cell].height() - gapSize * 2; + + graphics.setFill(color); + graphics.fillOval(x, y, width, height); + } + + public void drawInnerDot(Color color, int cell, boolean slightlyBigger) { + final float x = cells[cell].x() + gapSize; + final float y = cells[cell].y() + gapSize; + + float multiplier = slightlyBigger?1.4f:1.5f; + + final float width = (cells[cell].width() - gapSize * 2)/multiplier; + final float height = (cells[cell].height() - gapSize * 2)/multiplier; + + float offset = slightlyBigger?5f:4f; + + graphics.setFill(color); + graphics.fillOval(x + width/offset, y + height/offset, width, height); + } + + private void drawDotScaled(Color color, int cell, double scale) { + final float cx = cells[cell].x() + gapSize; + final float cy = cells[cell].y() + gapSize; + + final float fullWidth = cells[cell].width() - gapSize * 2; + final float height = cells[cell].height() - gapSize * 2; + + final float scaledWidth = (float)(fullWidth * scale); + final float offsetX = (fullWidth - scaledWidth) / 2; + + graphics.setFill(color); + graphics.fillOval(cx + offsetX, cy, scaledWidth, height); + } + + public Timeline flipDot(Color fromColor, Color toColor, int cell) { + final int steps = 60; + final long duration = 250; + final double interval = duration / (double) steps; + + final Timeline timeline = new Timeline(); + + for (int i = 0; i <= steps; i++) { + final double t = i / (double) steps; + final KeyFrame keyFrame = new KeyFrame(Duration.millis(i * interval), + _ -> { + clear(cell); + + final double scale = t <= 0.5 ? 1 - 2 * t : 2 * t - 1; + final Color currentColor = t < 0.5 ? fromColor : toColor; + + drawDotScaled(currentColor, cell, scale); + } + ); + + timeline.getKeyFrames().add(keyFrame); + } + + return timeline; + } + + public Canvas getCanvas() { + return canvas; + } +} \ No newline at end of file diff --git a/app/src/main/java/org/toop/app/canvas/Connect4Canvas.java b/app/src/main/java/org/toop/app/canvas/Connect4Canvas.java deleted file mode 100644 index 4a8c7a2..0000000 --- a/app/src/main/java/org/toop/app/canvas/Connect4Canvas.java +++ /dev/null @@ -1,17 +0,0 @@ -package org.toop.app.canvas; - -import javafx.scene.paint.Color; -import org.toop.framework.gameFramework.model.game.AbstractGame; - -import java.util.function.Consumer; - -public class Connect4Canvas extends GameCanvas { - public Connect4Canvas(Color color, int width, int height, Consumer onCellClicked) { - super(color, Color.TRANSPARENT, width, height, 7, 6, 10, true, onCellClicked,null); - } - - @Override - public void drawPlayerHover(int player, int move, AbstractGame game) { - - } -} \ No newline at end of file diff --git a/app/src/main/java/org/toop/app/canvas/GameCanvas.java b/app/src/main/java/org/toop/app/canvas/GameCanvas.java index 5453b82..d1361c5 100644 --- a/app/src/main/java/org/toop/app/canvas/GameCanvas.java +++ b/app/src/main/java/org/toop/app/canvas/GameCanvas.java @@ -1,238 +1,8 @@ package org.toop.app.canvas; -import javafx.animation.KeyFrame; -import javafx.animation.Timeline; import javafx.scene.canvas.Canvas; -import javafx.scene.canvas.GraphicsContext; -import javafx.scene.input.MouseButton; -import javafx.scene.paint.Color; -import javafx.scene.text.Font; -import javafx.util.Duration; -import org.toop.framework.gameFramework.model.game.AbstractGame; import org.toop.framework.gameFramework.model.game.TurnBasedGame; -import java.util.function.Consumer; - -public abstract class GameCanvas> implements DrawPlayerMove, DrawPlayerHover { - protected record Cell(float x, float y, float width, float height) { - public boolean isInside(double x, double y) { - return x >= this.x && x <= this.x + width && - y >= this.y && y <= this.y + height; - } - } - - protected final Canvas canvas; - protected final GraphicsContext graphics; - - protected final Color color; - protected final Color backgroundColor; - - protected final int width; - protected final int height; - - protected final int rowSize; - protected final int columnSize; - - protected final int gapSize; - protected final boolean edges; - - protected final Cell[] cells; - - private Consumer onCellCLicked; - - public void setOnCellClicked(Consumer onClick) { - this.onCellCLicked = onClick; - } - - protected GameCanvas(Color color, Color backgroundColor, int width, int height, int rowSize, int columnSize, int gapSize, boolean edges, Consumer onCellClicked, Consumer newCellEntered) { - canvas = new Canvas(width, height); - graphics = canvas.getGraphicsContext2D(); - - this.onCellCLicked = onCellClicked; - - this.color = color; - this.backgroundColor = backgroundColor; - - this.width = width; - this.height = height; - - this.rowSize = rowSize; - this.columnSize = columnSize; - - this.gapSize = gapSize; - this.edges = edges; - - cells = new Cell[rowSize * columnSize]; - - final float cellWidth = ((float) width - gapSize * rowSize - gapSize) / rowSize; - final float cellHeight = ((float) height - gapSize * columnSize - gapSize) / columnSize; - - for (int y = 0; y < columnSize; y++) { - final float startY = y * cellHeight + y * gapSize + gapSize; - - for (int x = 0; x < rowSize; x++) { - final float startX = x * cellWidth + x * gapSize + gapSize; - cells[x + y * rowSize] = new Cell(startX, startY, cellWidth, cellHeight); - } - } - - canvas.setOnMouseClicked(event -> { - if (event.getButton() != MouseButton.PRIMARY) { - return; - } - - final int column = (int) ((event.getX() / this.width) * rowSize); - final int row = (int) ((event.getY() / this.height) * columnSize); - - final Cell cell = cells[column + row * rowSize]; - - if (cell.isInside(event.getX(), event.getY())) { - event.consume(); - this.onCellCLicked.accept(column + row * rowSize); - } - }); - - - - - render(); - } - - private void render() { - graphics.setFill(backgroundColor); - graphics.fillRect(0, 0, width, height); - - graphics.setFill(color); - - for (int x = 0; x < rowSize - 1; x++) { - final float start = cells[x].x + cells[x].width; - graphics.fillRect(start, gapSize, gapSize, height - gapSize * 2); - } - - for (int y = 0; y < columnSize - 1; y++) { - final float start = cells[y * rowSize].y + cells[y * rowSize].height; - graphics.fillRect(gapSize, start, width - gapSize * 2, gapSize); - } - - if (edges) { - graphics.fillRect(0, 0, width, gapSize); - graphics.fillRect(0, 0, gapSize, height); - - graphics.fillRect(width - gapSize, 0, gapSize, height); - graphics.fillRect(0, height - gapSize, width, gapSize); - } - } - - public void fill(Color color, int cell) { - final float x = cells[cell].x(); - final float y = cells[cell].y(); - - final float width = cells[cell].width(); - final float height = cells[cell].height(); - - graphics.setFill(color); - graphics.fillRect(x, y, width, height); - } - - public void clear(int cell) { - final float x = cells[cell].x(); - final float y = cells[cell].y(); - - final float width = cells[cell].width(); - final float height = cells[cell].height(); - - graphics.clearRect(x, y, width, height); - - graphics.setFill(backgroundColor); - graphics.fillRect(x, y, width, height); - } - - public void clearAll() { - for (int i = 0; i < cells.length; i++) { - clear(i); - } - } - - @Override - public void drawPlayerMove(int player, int move) { - final float x = cells[move].x() + gapSize; - final float y = cells[move].y() + gapSize; - - final float width = cells[move].width() - gapSize * 2; - final float height = cells[move].height() - gapSize * 2; - - graphics.setFill(color); - graphics.setFont(Font.font("Arial", 40)); // TODO different font and size - graphics.fillText(String.valueOf(player), x + width, y + height); - } - - public void drawDot(Color color, int cell) { - final float x = cells[cell].x() + gapSize; - final float y = cells[cell].y() + gapSize; - - final float width = cells[cell].width() - gapSize * 2; - final float height = cells[cell].height() - gapSize * 2; - - graphics.setFill(color); - graphics.fillOval(x, y, width, height); - } - - public void drawInnerDot(Color color, int cell, boolean slightlyBigger) { - final float x = cells[cell].x() + gapSize; - final float y = cells[cell].y() + gapSize; - - float multiplier = slightlyBigger?1.4f:1.5f; - - final float width = (cells[cell].width() - gapSize * 2)/multiplier; - final float height = (cells[cell].height() - gapSize * 2)/multiplier; - - float offset = slightlyBigger?5f:4f; - - graphics.setFill(color); - graphics.fillOval(x + width/offset, y + height/offset, width, height); - } - - private void drawDotScaled(Color color, int cell, double scale) { - final float cx = cells[cell].x() + gapSize; - final float cy = cells[cell].y() + gapSize; - - final float fullWidth = cells[cell].width() - gapSize * 2; - final float height = cells[cell].height() - gapSize * 2; - - final float scaledWidth = (float)(fullWidth * scale); - final float offsetX = (fullWidth - scaledWidth) / 2; - - graphics.setFill(color); - graphics.fillOval(cx + offsetX, cy, scaledWidth, height); - } - - public Timeline flipDot(Color fromColor, Color toColor, int cell) { - final int steps = 60; - final long duration = 250; - final double interval = duration / (double) steps; - - final Timeline timeline = new Timeline(); - - for (int i = 0; i <= steps; i++) { - final double t = i / (double) steps; - final KeyFrame keyFrame = new KeyFrame(Duration.millis(i * interval), - _ -> { - clear(cell); - - final double scale = t <= 0.5 ? 1 - 2 * t : 2 * t - 1; - final Color currentColor = t < 0.5 ? fromColor : toColor; - - drawDotScaled(currentColor, cell, scale); - } - ); - - timeline.getKeyFrames().add(keyFrame); - } - - return timeline; - } - - public Canvas getCanvas() { - return canvas; - } -} \ No newline at end of file +public interface GameCanvas> extends GameDrawer{ + Canvas getCanvas(); +} diff --git a/app/src/main/java/org/toop/app/canvas/GameDrawer.java b/app/src/main/java/org/toop/app/canvas/GameDrawer.java new file mode 100644 index 0000000..261334c --- /dev/null +++ b/app/src/main/java/org/toop/app/canvas/GameDrawer.java @@ -0,0 +1,7 @@ +package org.toop.app.canvas; + +import org.toop.framework.gameFramework.model.game.TurnBasedGame; + +public interface GameDrawer> { + void redraw(T gameCopy); +} diff --git a/app/src/main/java/org/toop/app/canvas/ReversiBitCanvas.java b/app/src/main/java/org/toop/app/canvas/ReversiBitCanvas.java new file mode 100644 index 0000000..30ea6e9 --- /dev/null +++ b/app/src/main/java/org/toop/app/canvas/ReversiBitCanvas.java @@ -0,0 +1,53 @@ +package org.toop.app.canvas; + +import javafx.scene.paint.Color; +import org.toop.app.App; +import org.toop.game.games.reversi.BitboardReversi; + +import java.util.function.Consumer; + +public class ReversiBitCanvas extends BitGameCanvas{ + public ReversiBitCanvas() { + super(Color.GRAY, new Color(0f,0.4f,0.2f,1f), (App.getHeight() / 4) * 3, (App.getHeight() / 4) * 3, 8, 8, 5, true); + canvas.setOnMouseMoved(event -> { + double mouseX = event.getX(); + double mouseY = event.getY(); + int cellId = -1; + + BitGameCanvas.Cell hovered = null; + for (BitGameCanvas.Cell cell : cells) { + if (cell.isInside(mouseX, mouseY)) { + hovered = cell; + cellId = turnCoordsIntoCellId(mouseX, mouseY); + break; + } + } + }); + } + + private int turnCoordsIntoCellId(double x, double y) { + final int column = (int) ((x / this.width) * rowSize); + final int row = (int) ((y / this.height) * columnSize); + return column + row * rowSize; + } + + public void drawStartingDots() { + drawDot(Color.BLACK, 28); + drawDot(Color.WHITE, 36); + drawDot(Color.BLACK, 35); + drawDot(Color.WHITE, 27); + } + + @Override + public void redraw(BitboardReversi gameCopy) { + clearAll(); + drawStartingDots(); + for (int i = 0; i < gameCopy.getBoard().length; i++) { + if (gameCopy.getBoard()[i] == 0) { + drawDot(Color.WHITE, i); + } else if (gameCopy.getBoard()[i] == 1) { + drawDot(Color.BLACK, i); + } + } + } +} diff --git a/app/src/main/java/org/toop/app/canvas/ReversiCanvas.java b/app/src/main/java/org/toop/app/canvas/ReversiCanvas.java index 090df29..10ad24c 100644 --- a/app/src/main/java/org/toop/app/canvas/ReversiCanvas.java +++ b/app/src/main/java/org/toop/app/canvas/ReversiCanvas.java @@ -7,8 +7,8 @@ import org.toop.game.games.reversi.ReversiR; import java.util.concurrent.atomic.AtomicReference; import java.util.function.Consumer; - -public final class ReversiCanvas extends GameCanvas { +@Deprecated +public final class ReversiCanvas extends BaseGameCanvas { private Move[] currentlyHighlightedMoves = null; public ReversiCanvas(Color color, int width, int height, Consumer onCellClicked, Consumer newCellEntered) { super(color, new Color(0f,0.4f,0.2f,1f), width, height, 8, 8, 5, true, onCellClicked, newCellEntered); diff --git a/app/src/main/java/org/toop/app/canvas/TicTacToeBitCanvas.java b/app/src/main/java/org/toop/app/canvas/TicTacToeBitCanvas.java new file mode 100644 index 0000000..9c5464c --- /dev/null +++ b/app/src/main/java/org/toop/app/canvas/TicTacToeBitCanvas.java @@ -0,0 +1,76 @@ +package org.toop.app.canvas; + +import javafx.scene.paint.Color; +import org.toop.app.App; +import org.toop.framework.eventbus.EventFlow; +import org.toop.framework.gameFramework.model.game.AbstractGame; +import org.toop.framework.gameFramework.view.GUIEvents; +import org.toop.game.games.tictactoe.BitboardTicTacToe; + +import java.util.function.Consumer; + +public class TicTacToeBitCanvas extends BitGameCanvas{ + public TicTacToeBitCanvas() { + super( + Color.GRAY, + Color.TRANSPARENT, + (App.getHeight() / 4) * 3, + (App.getHeight() / 4) * 3, + 3, + 3, + 30, + false + ); + } + + @Override + public void redraw(BitboardTicTacToe gameCopy) { + clearAll(); + drawMoves(gameCopy.getBoard()); + } + + private void drawMoves(int[] gameBoard){ + // Draw each square + for (int i = 0; i < 9; i++){ + // If square isn't empty, draw player move + if (gameBoard[i] != AbstractGame.EMPTY){ + drawPlayerMove(gameBoard[i], i); + } + } + } + + public void drawPlayerMove(int player, int move) { + switch (player) { + case 0 -> drawX(Color.RED, move); + case 1 -> drawO(Color.BLUE, move); + default -> super.drawPlayerMove(player, move); + } + } + + public void drawX(Color color, int cell) { + graphics.setStroke(color); + graphics.setLineWidth(gapSize); + + final float x = cells[cell].x() + gapSize; + final float y = cells[cell].y() + gapSize; + + final float width = cells[cell].width() - gapSize * 2; + final float height = cells[cell].height() - gapSize * 2; + + graphics.strokeLine(x, y, x + width, y + height); + graphics.strokeLine(x + width, y, x, y + height); + } + + public void drawO(Color color, int cell) { + graphics.setStroke(color); + graphics.setLineWidth(gapSize); + + final float x = cells[cell].x() + gapSize; + final float y = cells[cell].y() + gapSize; + + final float width = cells[cell].width() - gapSize * 2; + final float height = cells[cell].height() - gapSize * 2; + + graphics.strokeOval(x, y, width, height); + } +} diff --git a/app/src/main/java/org/toop/app/canvas/TicTacToeCanvas.java b/app/src/main/java/org/toop/app/canvas/TicTacToeCanvas.java index 090fefc..b84f9b3 100644 --- a/app/src/main/java/org/toop/app/canvas/TicTacToeCanvas.java +++ b/app/src/main/java/org/toop/app/canvas/TicTacToeCanvas.java @@ -5,8 +5,8 @@ import org.toop.framework.gameFramework.model.game.AbstractGame; import org.toop.game.games.tictactoe.BitboardTicTacToe; import java.util.function.Consumer; - -public final class TicTacToeCanvas extends GameCanvas { +@Deprecated +public final class TicTacToeCanvas extends BaseGameCanvas { public TicTacToeCanvas(Color color, int width, int height, Consumer onCellClicked) { super(color, Color.TRANSPARENT, width, height, 3, 3, 30, false, onCellClicked,null); } diff --git a/app/src/main/java/org/toop/app/gameControllers/AbstractGameController.java b/app/src/main/java/org/toop/app/gameControllers/AbstractGameController.java index cd7e3cd..b12062e 100644 --- a/app/src/main/java/org/toop/app/gameControllers/AbstractGameController.java +++ b/app/src/main/java/org/toop/app/gameControllers/AbstractGameController.java @@ -5,21 +5,20 @@ import org.apache.logging.log4j.Logger; import org.toop.framework.gameFramework.controller.UpdatesGameUI; import org.toop.framework.gameFramework.model.game.TurnBasedGame; import org.toop.framework.gameFramework.view.GUIEvents; -import org.toop.app.canvas.GameCanvas; +import org.toop.app.canvas.BaseGameCanvas; import org.toop.framework.networking.events.NetworkEvents; import org.toop.framework.gameFramework.model.game.threadBehaviour.ThreadBehaviour; import org.toop.app.widget.view.GameView; import org.toop.framework.eventbus.EventFlow; import org.toop.game.gameThreads.OnlineThreadBehaviour; -import org.toop.framework.gameFramework.model.game.AbstractGame; import org.toop.framework.gameFramework.model.game.SupportsOnlinePlay; import org.toop.framework.gameFramework.model.player.Player; import java.util.ArrayList; import java.util.List; import java.util.function.Consumer; - -public abstract class AbstractGameController> implements UpdatesGameUI, ThreadBehaviour { +@Deprecated +public abstract class AbstractGameController> implements UpdatesGameUI, ThreadBehaviour { protected final EventFlow eventFlow = new EventFlow(); protected final List> listeners = new ArrayList<>(); @@ -27,19 +26,19 @@ public abstract class AbstractGameController> impleme // Logger for logging ofcourse protected final Logger logger = LogManager.getLogger(this.getClass()); - // Reference to primary view + // Reference to gameView view protected final GameView primary; // Reference to game canvas - protected final GameCanvas canvas; + protected final BaseGameCanvas canvas; private final Player[] players; // List of players, can't be changed. protected final TurnBasedGame game; // Reference to game instance - private final ThreadBehaviour gameThreadBehaviour; + private final ThreadBehaviour gameThreadBehaviour; // TODO: Change gameType to automatically happen with either dependency injection or something else. // TODO: Make visualisation of moves a behaviour. - protected AbstractGameController(GameCanvas canvas, Player[] players, T game, ThreadBehaviour gameThreadBehaviour, String gameType) { + protected AbstractGameController(BaseGameCanvas canvas, Player[] players, T game, ThreadBehaviour gameThreadBehaviour, String gameType) { logger.info("Creating AbstractGameController"); this.canvas = canvas; diff --git a/app/src/main/java/org/toop/app/gameControllers/GenericGameController.java b/app/src/main/java/org/toop/app/gameControllers/GenericGameController.java new file mode 100644 index 0000000..c959dda --- /dev/null +++ b/app/src/main/java/org/toop/app/gameControllers/GenericGameController.java @@ -0,0 +1,134 @@ +package org.toop.app.gameControllers; + +import javafx.geometry.Pos; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.toop.app.canvas.GameCanvas; +import org.toop.app.widget.WidgetContainer; +import org.toop.app.widget.view.GameView; +import org.toop.framework.eventbus.EventFlow; +import org.toop.framework.gameFramework.controller.GameController; +import org.toop.framework.gameFramework.controller.UpdatesGameUI; +import org.toop.framework.gameFramework.model.game.SupportsOnlinePlay; +import org.toop.framework.gameFramework.model.game.TurnBasedGame; +import org.toop.framework.gameFramework.model.game.threadBehaviour.ThreadBehaviour; +import org.toop.framework.gameFramework.model.player.Player; +import org.toop.framework.gameFramework.view.GUIEvents; +import org.toop.framework.networking.events.NetworkEvents; +import org.toop.game.gameThreads.OnlineThreadBehaviour; +import org.toop.game.players.LocalPlayer; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Consumer; + +public class GenericGameController> implements GameController { + protected final EventFlow eventFlow = new EventFlow(); + + protected final List> listeners = new ArrayList<>(); + + // Logger for logging ofcourse + protected final Logger logger = LogManager.getLogger(this.getClass()); + + // Reference to gameView view + protected final GameView gameView; + + // Reference to game canvas + protected final GameCanvas canvas; + + protected final TurnBasedGame game; // Reference to game instance + private final ThreadBehaviour gameThreadBehaviour; + + // TODO: Change gameType to automatically happen with either dependency injection or something else. + // TODO: Make visualisation of moves a behaviour. + public GenericGameController(GameCanvas canvas, T game, ThreadBehaviour gameThreadBehaviour, String gameType) { + logger.info("Creating: " + this.getClass()); + + this.canvas = canvas; + this.game = game; + this.gameThreadBehaviour = gameThreadBehaviour; + + + gameView = new GameView(null, null, null, gameType); + gameView.add(Pos.CENTER, canvas.getCanvas()); + WidgetContainer.getCurrentView().transitionNext(gameView, true); + addListeners(); + } + + public void start(){ + logger.info("Starting GameManager"); + updateUI(); + gameThreadBehaviour.start(); + } + + public void stop(){ + logger.info("Stopping GameManager"); + removeListeners(); + gameThreadBehaviour.stop(); + } + + public Player getCurrentPlayer(){ + return game.getPlayer(getCurrentPlayerIndex()); + }; + + public int getCurrentPlayerIndex(){ + return game.getCurrentTurn(); + } + + private void addListeners(){ + eventFlow + .listen(GUIEvents.RefreshGameCanvas.class, this::onUpdateGameUI, false) + .listen(GUIEvents.GameEnded.class, this::onGameFinish, false) + .listen(GUIEvents.PlayerAttemptedMove.class, event -> {if (getCurrentPlayer() instanceof LocalPlayer lp){lp.setMove(event.move());}}, false); + } + + private void removeListeners(){ + eventFlow.unsubscribeAll(); + } + + private void onUpdateGameUI(GUIEvents.RefreshGameCanvas event){ + this.updateUI(); + } + + private void onGameFinish(GUIEvents.GameEnded event){ + logger.info("Game Finished"); + String name = event.winner() == -1 ? null : getPlayer(event.winner()).getName(); + gameView.gameOver(event.winOrTie(), name); + stop(); + } + + public Player getPlayer(int player){ + if (player < 0 || player >= 2){ // TODO: Make game turn player count + logger.error("Invalid player index"); + throw new IllegalArgumentException("player out of range"); + } + return game.getPlayer(player); + } + + private boolean isOnline(){ + return this.gameThreadBehaviour instanceof SupportsOnlinePlay; + } + + public void onYourTurn(NetworkEvents.YourTurnResponse event){ + if (isOnline()){ + ((OnlineThreadBehaviour) this.gameThreadBehaviour).onYourTurn(event); + } + } + + public void onMoveReceived(NetworkEvents.GameMoveResponse event){ + if (isOnline()){ + ((OnlineThreadBehaviour) this.gameThreadBehaviour).onMoveReceived(event); + } + } + + public void gameFinished(NetworkEvents.GameResultResponse event){ + if (isOnline()){ + ((OnlineThreadBehaviour) this.gameThreadBehaviour).gameFinished(event); + } + } + + @Override + public void updateUI() { + canvas.redraw(game.deepCopy()); + } +} 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 95ce463..2ea42cd 100644 --- a/app/src/main/java/org/toop/app/gameControllers/ReversiController.java +++ b/app/src/main/java/org/toop/app/gameControllers/ReversiController.java @@ -14,7 +14,7 @@ import org.toop.game.gameThreads.OnlineThreadBehaviour; import org.toop.game.players.LocalPlayer; import org.toop.framework.gameFramework.model.player.Player; import org.toop.game.games.reversi.ReversiR; - +@Deprecated public class ReversiController extends AbstractGameController { // TODO: Refactor GUI update methods to follow designed system public ReversiController(Player[] players, boolean local) { 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 2003604..c49234e 100644 --- a/app/src/main/java/org/toop/app/gameControllers/TicTacToeController.java +++ b/app/src/main/java/org/toop/app/gameControllers/TicTacToeController.java @@ -13,7 +13,7 @@ import org.toop.game.gameThreads.OnlineThreadBehaviour; import org.toop.game.players.LocalPlayer; import org.toop.app.widget.WidgetContainer; import org.toop.game.games.tictactoe.BitboardTicTacToe; - +@Deprecated public class TicTacToeController extends AbstractGameController { public TicTacToeController(Player[] players, boolean local) { @@ -22,7 +22,7 @@ public class TicTacToeController extends AbstractGameController {new EventFlow().addPostEvent(GUIEvents.PlayerAttemptedMove.class, c).postEvent();}), players, BitboardTicTacToe, - local ? new LocalThreadBehaviour(BitboardTicTacToe, players) : new OnlineThreadBehaviour<>(BitboardTicTacToe, players), // TODO: Player order matters here, this won't work atm + local ? new LocalThreadBehaviour(BitboardTicTacToe) : new OnlineThreadBehaviour<>(BitboardTicTacToe, players), // TODO: Player order matters here, this won't work atm "TicTacToe"); initUI(); diff --git a/app/src/main/java/org/toop/app/widget/view/LocalMultiplayerView.java b/app/src/main/java/org/toop/app/widget/view/LocalMultiplayerView.java index cbbf702..20d33ad 100644 --- a/app/src/main/java/org/toop/app/widget/view/LocalMultiplayerView.java +++ b/app/src/main/java/org/toop/app/widget/view/LocalMultiplayerView.java @@ -2,10 +2,14 @@ package org.toop.app.widget.view; import javafx.application.Platform; import org.toop.app.GameInformation; -import org.toop.app.gameControllers.AbstractGameController; -import org.toop.app.gameControllers.ReversiController; -import org.toop.app.gameControllers.TicTacToeController; +import org.toop.app.canvas.ReversiBitCanvas; +import org.toop.app.canvas.TicTacToeBitCanvas; +import org.toop.app.gameControllers.GenericGameController; +import org.toop.framework.gameFramework.controller.GameController; import org.toop.framework.gameFramework.model.player.Player; +import org.toop.game.gameThreads.LocalThreadBehaviour; +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.app.widget.Primitive; @@ -22,10 +26,12 @@ import javafx.scene.control.ScrollPane; import javafx.scene.layout.VBox; import org.toop.local.AppSettings; +import java.util.Arrays; + public class LocalMultiplayerView extends ViewWidget { private final GameInformation information; - private AbstractGameController gameController; + private GameController gameController; public LocalMultiplayerView(GameInformation.Type type) { this(new GameInformation(type)); @@ -49,6 +55,7 @@ public class LocalMultiplayerView extends ViewWidget { switch (information.type) { case TICTACTOE: + System.out.println("TicTacToe"); if (information.players[0].isHuman) { players[0] = new LocalPlayer<>(information.players[0].name); } else { @@ -59,20 +66,24 @@ public class LocalMultiplayerView extends ViewWidget { } else { players[1] = new ArtificialPlayer<>(new TicTacToeAIR(), information.players[1].name); } + System.out.println(Arrays.toString(players)); if (AppSettings.getSettings().getTutorialFlag() && AppSettings.getSettings().getFirstTTT()) { new ShowEnableTutorialWidget( () -> new TicTacToeTutorialWidget(() -> { - gameController = new TicTacToeController(players); + BitboardTicTacToe game = new BitboardTicTacToe(players); // TODO: ThreadBehaviour might need to be created by game idk + gameController = new GenericGameController(new TicTacToeBitCanvas(), game, new LocalThreadBehaviour(game), "TicTacToe"); gameController.start(); }), () -> Platform.runLater(() -> { - gameController = new TicTacToeController(players); + BitboardTicTacToe game = new BitboardTicTacToe(players); // TODO: ThreadBehaviour might need to be created by game idk + gameController = new GenericGameController(new TicTacToeBitCanvas(), game, new LocalThreadBehaviour(game), "TicTacToe"); gameController.start(); }), () -> AppSettings.getSettings().setFirstTTT(false) ); } else { - gameController = new TicTacToeController(players); + BitboardTicTacToe game = new BitboardTicTacToe(players); // TODO: ThreadBehaviour might need to be created by game idk + gameController = new GenericGameController(new TicTacToeBitCanvas(), game, new LocalThreadBehaviour(game), "TicTacToe"); gameController.start(); } break; @@ -90,17 +101,20 @@ public class LocalMultiplayerView extends ViewWidget { if (AppSettings.getSettings().getTutorialFlag() && AppSettings.getSettings().getFirstReversi()) { new ShowEnableTutorialWidget( () -> new ReversiTutorialWidget(() -> { - gameController = new ReversiController(players); + BitboardReversi game = new BitboardReversi(players); + gameController = new GenericGameController<>(new ReversiBitCanvas(), game, new LocalThreadBehaviour<>(game), "Reversi"); gameController.start(); }), () -> Platform.runLater(() -> { - gameController = new ReversiController(players); + BitboardReversi game = new BitboardReversi(players); + gameController = new GenericGameController<>(new ReversiBitCanvas(), game, new LocalThreadBehaviour<>(game), "Reversi"); gameController.start(); }), () -> AppSettings.getSettings().setFirstReversi(false) ); } else { - gameController = new ReversiController(players); + BitboardReversi game = new BitboardReversi(players); + gameController = new GenericGameController<>(new ReversiBitCanvas(), game, new LocalThreadBehaviour<>(game), "Reversi"); gameController.start(); } break; diff --git a/framework/src/main/java/org/toop/framework/gameFramework/controller/GameController.java b/framework/src/main/java/org/toop/framework/gameFramework/controller/GameController.java new file mode 100644 index 0000000..6a91e2d --- /dev/null +++ b/framework/src/main/java/org/toop/framework/gameFramework/controller/GameController.java @@ -0,0 +1,7 @@ +package org.toop.framework.gameFramework.controller; + +import org.toop.framework.gameFramework.model.game.SupportsOnlinePlay; +import org.toop.framework.gameFramework.model.game.threadBehaviour.Controllable; + +public interface GameController extends Controllable, SupportsOnlinePlay, UpdatesGameUI { +} diff --git a/framework/src/main/java/org/toop/framework/gameFramework/model/game/threadBehaviour/AbstractThreadBehaviour.java b/framework/src/main/java/org/toop/framework/gameFramework/model/game/threadBehaviour/AbstractThreadBehaviour.java index 46a6e6f..e059292 100644 --- a/framework/src/main/java/org/toop/framework/gameFramework/model/game/threadBehaviour/AbstractThreadBehaviour.java +++ b/framework/src/main/java/org/toop/framework/gameFramework/model/game/threadBehaviour/AbstractThreadBehaviour.java @@ -14,7 +14,7 @@ import java.util.concurrent.atomic.AtomicBoolean; * a running flag, a game reference, and a logger. * Subclasses implement the actual game-loop logic. */ -public abstract class AbstractThreadBehaviour> implements ThreadBehaviour { +public abstract class AbstractThreadBehaviour> implements ThreadBehaviour { /** Indicates whether the game loop or event processing is active. */ protected final AtomicBoolean isRunning = new AtomicBoolean(); diff --git a/framework/src/main/java/org/toop/framework/gameFramework/model/game/threadBehaviour/ThreadBehaviour.java b/framework/src/main/java/org/toop/framework/gameFramework/model/game/threadBehaviour/ThreadBehaviour.java index 9ec6736..42b667d 100644 --- a/framework/src/main/java/org/toop/framework/gameFramework/model/game/threadBehaviour/ThreadBehaviour.java +++ b/framework/src/main/java/org/toop/framework/gameFramework/model/game/threadBehaviour/ThreadBehaviour.java @@ -9,5 +9,5 @@ import org.toop.framework.gameFramework.model.player.Player; *

* Defines how a game's execution is started, stopped, and which player is active. */ -public interface ThreadBehaviour> extends Controllable { +public interface ThreadBehaviour extends Controllable { } 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 ebeab4c..00dc9f6 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,7 @@ 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 { +@Deprecated +public abstract class AbstractAI> implements MoveProvider { // Concrete AI implementations should override findBestMove(T game, int depth) } diff --git a/game/src/main/java/org/toop/game/BitboardGame.java b/game/src/main/java/org/toop/game/BitboardGame.java index e312279..35b87ab 100644 --- a/game/src/main/java/org/toop/game/BitboardGame.java +++ b/game/src/main/java/org/toop/game/BitboardGame.java @@ -1,12 +1,9 @@ package org.toop.game; -import org.toop.framework.gameFramework.GameState; import org.toop.framework.gameFramework.model.game.TurnBasedGame; import org.toop.framework.gameFramework.model.player.Player; -import java.util.ArrayList; import java.util.Arrays; -import java.util.List; public abstract class BitboardGame> implements TurnBasedGame { private final int columnSize; @@ -21,9 +18,7 @@ public abstract class BitboardGame> implements TurnBas 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; @@ -60,12 +55,13 @@ public abstract class BitboardGame> implements TurnBas return output; } - public BitboardGame(BitboardGame other) { + public BitboardGame(BitboardGame other) { this.columnSize = other.columnSize; this.rowSize = other.rowSize; 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 } public int getColumnSize() { diff --git a/game/src/main/java/org/toop/game/gameThreads/LocalThreadBehaviour.java b/game/src/main/java/org/toop/game/gameThreads/LocalThreadBehaviour.java index 82ac0ca..5a5c54d 100644 --- a/game/src/main/java/org/toop/game/gameThreads/LocalThreadBehaviour.java +++ b/game/src/main/java/org/toop/game/gameThreads/LocalThreadBehaviour.java @@ -20,9 +20,8 @@ public class LocalThreadBehaviour> extends AbstractTh * Creates a new behaviour for a local turn-based game. * * @param game the game instance - * @param players the list of players in turn order */ - public LocalThreadBehaviour(T game, Player[] players) { + public LocalThreadBehaviour(T game) { super(game); } 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 a898557..c3480e3 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 @@ -5,6 +5,8 @@ import org.toop.framework.gameFramework.model.game.PlayResult; import org.toop.framework.gameFramework.model.player.Player; import org.toop.game.BitboardGame; +import java.util.Arrays; + public class BitboardReversi extends BitboardGame { @Override @@ -62,6 +64,7 @@ public class BitboardReversi extends BitboardGame { @Override public int[] getLegalMoves(){ + System.out.println(Arrays.toString(translateLegalMoves(getLegalMoves2()))); return translateLegalMoves(getLegalMoves2()); }