mirror of
https://github.com/2OOP/pism.git
synced 2026-02-04 02:44:50 +00:00
...
This commit is contained in:
@@ -18,4 +18,4 @@ public final class Main {
|
|||||||
new Thread(NetworkingClientManager::new).start();
|
new Thread(NetworkingClientManager::new).start();
|
||||||
new Thread(SoundManager::new).start();
|
new Thread(SoundManager::new).start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
package org.toop.app;
|
package org.toop.app;
|
||||||
|
|
||||||
public record GameInformation(String[] playerName, boolean[] isPlayerHuman, int[] computerDifficulty, int[] computerThinkTime,
|
public record GameInformation(String[] playerName, boolean[] isPlayerHuman,
|
||||||
|
int[] computerDifficulty, int[] computerThinkTime,
|
||||||
boolean isConnectionLocal, String serverIP, String serverPort) {
|
boolean isConnectionLocal, String serverIP, String serverPort) {
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,40 +1,114 @@
|
|||||||
package org.toop.app.layer.layers;
|
package org.toop.app.layer.layers;
|
||||||
|
|
||||||
import javafx.application.Platform;
|
import javafx.application.Platform;
|
||||||
|
import org.toop.app.App;
|
||||||
|
import org.toop.app.GameInformation;
|
||||||
import org.toop.app.layer.Container;
|
import org.toop.app.layer.Container;
|
||||||
import org.toop.app.layer.Layer;
|
import org.toop.app.layer.Layer;
|
||||||
import org.toop.app.layer.NodeBuilder;
|
import org.toop.app.layer.NodeBuilder;
|
||||||
|
import org.toop.app.layer.Popup;
|
||||||
|
import org.toop.app.layer.containers.HorizontalContainer;
|
||||||
import org.toop.app.layer.containers.VerticalContainer;
|
import org.toop.app.layer.containers.VerticalContainer;
|
||||||
|
import org.toop.app.layer.layers.game.TicTacToeLayer;
|
||||||
import org.toop.framework.eventbus.EventFlow;
|
import org.toop.framework.eventbus.EventFlow;
|
||||||
import org.toop.framework.networking.events.NetworkEvents;
|
import org.toop.framework.networking.events.NetworkEvents;
|
||||||
|
|
||||||
import javafx.geometry.Pos;
|
import javafx.geometry.Pos;
|
||||||
import javafx.scene.control.Label;
|
import javafx.scene.control.Label;
|
||||||
import javafx.scene.control.ListView;
|
import javafx.scene.control.ListView;
|
||||||
|
import org.toop.local.AppContext;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Timer;
|
import java.util.Timer;
|
||||||
import java.util.TimerTask;
|
import java.util.TimerTask;
|
||||||
import java.util.concurrent.CopyOnWriteArrayList;
|
import java.util.concurrent.CopyOnWriteArrayList;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
public final class ConnectedLayer extends Layer {
|
public final class ConnectedLayer extends Layer {
|
||||||
|
private static Timer pollTimer = new Timer();
|
||||||
|
|
||||||
|
private static class ChallengePopup extends Popup {
|
||||||
|
private final GameInformation information;
|
||||||
|
|
||||||
|
private final String challenger;
|
||||||
|
private final String game;
|
||||||
|
|
||||||
|
private final long clientID;
|
||||||
|
private final int challengeID;
|
||||||
|
|
||||||
|
public ChallengePopup(GameInformation information, String challenger, String game, long clientID, String challengeID) {
|
||||||
|
super(false, "bg-popup");
|
||||||
|
|
||||||
|
this.information = information;
|
||||||
|
|
||||||
|
this.challenger = challenger;
|
||||||
|
this.game = game;
|
||||||
|
|
||||||
|
this.clientID = clientID;
|
||||||
|
this.challengeID = Integer.parseInt(challengeID.substring(18, challengeID.length() - 2));
|
||||||
|
|
||||||
|
reload();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void reload() {
|
||||||
|
popAll();
|
||||||
|
|
||||||
|
final var challengeText = NodeBuilder.header(AppContext.getString("challengeText"));
|
||||||
|
final var challengerNameText = NodeBuilder.header(challenger);
|
||||||
|
|
||||||
|
final var gameText = NodeBuilder.text(AppContext.getString("gameIsText"));
|
||||||
|
final var gameNameText = NodeBuilder.text(game);
|
||||||
|
|
||||||
|
final var acceptButton = NodeBuilder.button(AppContext.getString("accept"), () -> {
|
||||||
|
pollTimer.cancel();
|
||||||
|
|
||||||
|
new EventFlow().addPostEvent(new NetworkEvents.SendAcceptChallenge(clientID, challengeID)).postEvent();
|
||||||
|
App.activate(new TicTacToeLayer(information, clientID));
|
||||||
|
});
|
||||||
|
|
||||||
|
final var denyButton = NodeBuilder.button(AppContext.getString("deny"), () -> {
|
||||||
|
App.pop();
|
||||||
|
});
|
||||||
|
|
||||||
|
final Container controlContainer = new HorizontalContainer(30);
|
||||||
|
controlContainer.addNodes(acceptButton, denyButton);
|
||||||
|
|
||||||
|
final Container mainContainer = new VerticalContainer(30);
|
||||||
|
mainContainer.addNodes(challengeText, challengerNameText);
|
||||||
|
mainContainer.addNodes(gameText, gameNameText);
|
||||||
|
|
||||||
|
mainContainer.addContainer(controlContainer, false);
|
||||||
|
|
||||||
|
addContainer(mainContainer, Pos.CENTER, 0, 0, 30, 30);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GameInformation information;
|
||||||
long clientId;
|
long clientId;
|
||||||
String user;
|
String user;
|
||||||
List<String> onlinePlayers = new CopyOnWriteArrayList<>();
|
List<String> onlinePlayers = new CopyOnWriteArrayList<>();
|
||||||
|
|
||||||
public ConnectedLayer(long clientId, String user) {
|
public ConnectedLayer(GameInformation information) {
|
||||||
super("bg-primary");
|
super("bg-primary");
|
||||||
|
|
||||||
this.clientId = clientId;
|
this.information = information;
|
||||||
this.user = user;
|
|
||||||
|
new EventFlow()
|
||||||
|
.addPostEvent(NetworkEvents.StartClient.class, information.serverIP(), Integer.parseInt(information.serverPort()))
|
||||||
|
.onResponse(NetworkEvents.StartClientResponse.class, e -> {
|
||||||
|
clientId = e.clientId();
|
||||||
|
user = information.playerName()[0].replaceAll("\\s+", "");
|
||||||
|
|
||||||
|
new EventFlow().addPostEvent(new NetworkEvents.SendLogin(this.clientId, this.user)).postEvent();
|
||||||
|
|
||||||
|
Thread popThread = new Thread(this::populatePlayerList);
|
||||||
|
popThread.setDaemon(false);
|
||||||
|
popThread.start();
|
||||||
|
}).postEvent();
|
||||||
|
|
||||||
new EventFlow().addPostEvent(new NetworkEvents.SendLogin(this.clientId, this.user)).postEvent();
|
|
||||||
new EventFlow().listen(this::handleReceivedChallenge);
|
new EventFlow().listen(this::handleReceivedChallenge);
|
||||||
|
|
||||||
Thread popThread = new Thread(this::populatePlayerList);
|
|
||||||
popThread.setDaemon(false);
|
|
||||||
popThread.start();
|
|
||||||
|
|
||||||
reload();
|
reload();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -58,19 +132,32 @@ public final class ConnectedLayer extends Layer {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Timer pollTimer = new Timer();
|
|
||||||
pollTimer.schedule(task, 0L, 5000L); // TODO: Block app exit, fix later
|
pollTimer.schedule(task, 0L, 5000L); // TODO: Block app exit, fix later
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sendChallenge(String oppUsername, String gameType) {
|
private void sendChallenge(String oppUsername, String gameType) {
|
||||||
|
final AtomicInteger challengeId = new AtomicInteger(-1);
|
||||||
|
|
||||||
if (onlinePlayers.contains(oppUsername)) {
|
if (onlinePlayers.contains(oppUsername)) {
|
||||||
new EventFlow().addPostEvent(new NetworkEvents.SendChallenge(this.clientId, oppUsername, gameType))
|
new EventFlow().addPostEvent(new NetworkEvents.SendChallenge(this.clientId, oppUsername, gameType))
|
||||||
.postEvent();
|
.listen(NetworkEvents.ChallengeResponse.class, e -> {
|
||||||
|
challengeId.set(Integer.parseInt(e.challengeId().substring(18, e.challengeId().length() - 2)));
|
||||||
|
})
|
||||||
|
.listen(NetworkEvents.GameMatchResponse.class, e -> {
|
||||||
|
if (e.clientId() == this.clientId) {
|
||||||
|
pollTimer.cancel();
|
||||||
|
App.activate(new TicTacToeLayer(information, this.clientId));
|
||||||
|
}
|
||||||
|
}, false).postEvent();
|
||||||
|
// ^
|
||||||
|
// |
|
||||||
|
// |
|
||||||
|
// |
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleReceivedChallenge(NetworkEvents.ChallengeResponse response) {
|
private void handleReceivedChallenge(NetworkEvents.ChallengeResponse response) {
|
||||||
// TODO: Popup? Idk what this actually sends back.
|
App.push(new ChallengePopup(information, response.challengerName(), response.gameType(), clientId, response.challengeId()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
package org.toop.app.layer.layers;
|
package org.toop.app.layer.layers;
|
||||||
|
|
||||||
import javafx.application.Platform;
|
|
||||||
import javafx.geometry.Pos;
|
|
||||||
import org.toop.app.App;
|
import org.toop.app.App;
|
||||||
import org.toop.app.GameInformation;
|
import org.toop.app.GameInformation;
|
||||||
import org.toop.app.layer.Container;
|
import org.toop.app.layer.Container;
|
||||||
@@ -10,10 +8,10 @@ import org.toop.app.layer.NodeBuilder;
|
|||||||
import org.toop.app.layer.containers.HorizontalContainer;
|
import org.toop.app.layer.containers.HorizontalContainer;
|
||||||
import org.toop.app.layer.containers.VerticalContainer;
|
import org.toop.app.layer.containers.VerticalContainer;
|
||||||
import org.toop.app.layer.layers.game.TicTacToeLayer;
|
import org.toop.app.layer.layers.game.TicTacToeLayer;
|
||||||
import org.toop.framework.eventbus.EventFlow;
|
|
||||||
import org.toop.framework.networking.events.NetworkEvents;
|
|
||||||
import org.toop.local.AppContext;
|
import org.toop.local.AppContext;
|
||||||
|
|
||||||
|
import javafx.geometry.Pos;
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
public final class MultiplayerLayer extends Layer {
|
public final class MultiplayerLayer extends Layer {
|
||||||
@@ -59,7 +57,7 @@ public final class MultiplayerLayer extends Layer {
|
|||||||
|
|
||||||
player1Container.addNodes(playerNameText, playerNameInput);
|
player1Container.addNodes(playerNameText, playerNameInput);
|
||||||
} else {
|
} else {
|
||||||
player1Name = "Pism Bot #" + LocalDateTime.now().getSecond();
|
player1Name = "Pism Bot V" + LocalDateTime.now().getSecond();
|
||||||
|
|
||||||
final var computerNameText = NodeBuilder.text(player1Name);
|
final var computerNameText = NodeBuilder.text(player1Name);
|
||||||
final var computerNameSeparator = NodeBuilder.separator();
|
final var computerNameSeparator = NodeBuilder.separator();
|
||||||
@@ -94,7 +92,7 @@ public final class MultiplayerLayer extends Layer {
|
|||||||
|
|
||||||
player2Container.addNodes(playerNameText, playerNameInput);
|
player2Container.addNodes(playerNameText, playerNameInput);
|
||||||
} else {
|
} else {
|
||||||
player2Name = "Pism Bot #" + LocalDateTime.now().getSecond();
|
player2Name = "Pism Bot V" + LocalDateTime.now().getSecond();
|
||||||
|
|
||||||
final var computerNameText = NodeBuilder.text(player2Name);
|
final var computerNameText = NodeBuilder.text(player2Name);
|
||||||
final var computerNameSeparator = NodeBuilder.separator();
|
final var computerNameSeparator = NodeBuilder.separator();
|
||||||
@@ -137,21 +135,17 @@ public final class MultiplayerLayer extends Layer {
|
|||||||
});
|
});
|
||||||
|
|
||||||
final var playButton = NodeBuilder.button(isConnectionLocal ? AppContext.getString("start") : AppContext.getString("connect"), () -> {
|
final var playButton = NodeBuilder.button(isConnectionLocal ? AppContext.getString("start") : AppContext.getString("connect"), () -> {
|
||||||
|
final var information = new GameInformation(
|
||||||
|
new String[]{player1Name, player2Name},
|
||||||
|
new boolean[]{isPlayer1Human, isPlayer2Human},
|
||||||
|
new int[]{computer1Difficulty, computer2Difficulty},
|
||||||
|
new int[]{computer1ThinkTime, computer2ThinkTime},
|
||||||
|
isConnectionLocal, serverIP, serverPort);
|
||||||
|
|
||||||
if (isConnectionLocal) {
|
if (isConnectionLocal) {
|
||||||
App.activate(new TicTacToeLayer(new GameInformation(
|
App.activate(new TicTacToeLayer(information));
|
||||||
new String[]{player1Name, player2Name},
|
|
||||||
new boolean[]{isPlayer1Human, isPlayer2Human},
|
|
||||||
new int[]{computer1Difficulty, computer2Difficulty},
|
|
||||||
new int[]{computer1ThinkTime, computer2ThinkTime},
|
|
||||||
isConnectionLocal, serverIP, serverPort)));
|
|
||||||
} else {
|
} else {
|
||||||
new EventFlow()
|
App.activate(new ConnectedLayer(information));
|
||||||
.addPostEvent(NetworkEvents.StartClient.class, serverIP, Integer.parseInt(serverPort))
|
|
||||||
.onResponse(NetworkEvents.StartClientResponse.class,
|
|
||||||
e -> Platform.runLater(
|
|
||||||
() -> App.activate(new ConnectedLayer(e.clientId(), player1Name))
|
|
||||||
))
|
|
||||||
.postEvent();
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
package org.toop.app.layer.layers.game;
|
package org.toop.app.layer.layers.game;
|
||||||
|
|
||||||
import javafx.geometry.Pos;
|
|
||||||
import org.toop.app.App;
|
import org.toop.app.App;
|
||||||
import org.toop.app.layer.Container;
|
import org.toop.app.layer.Container;
|
||||||
import org.toop.app.layer.NodeBuilder;
|
import org.toop.app.layer.NodeBuilder;
|
||||||
@@ -9,6 +8,8 @@ import org.toop.app.layer.containers.VerticalContainer;
|
|||||||
import org.toop.app.layer.layers.MainLayer;
|
import org.toop.app.layer.layers.MainLayer;
|
||||||
import org.toop.local.AppContext;
|
import org.toop.local.AppContext;
|
||||||
|
|
||||||
|
import javafx.geometry.Pos;
|
||||||
|
|
||||||
public class GameFinishedPopup extends Popup {
|
public class GameFinishedPopup extends Popup {
|
||||||
private final boolean isDraw;
|
private final boolean isDraw;
|
||||||
private final String winner;
|
private final String winner;
|
||||||
|
|||||||
@@ -20,15 +20,15 @@ import org.toop.local.AppContext;
|
|||||||
import javafx.geometry.Pos;
|
import javafx.geometry.Pos;
|
||||||
import javafx.scene.paint.Color;
|
import javafx.scene.paint.Color;
|
||||||
|
|
||||||
import java.time.Duration;
|
|
||||||
import java.util.concurrent.BlockingQueue;
|
import java.util.concurrent.BlockingQueue;
|
||||||
import java.util.concurrent.LinkedBlockingQueue;
|
import java.util.concurrent.LinkedBlockingQueue;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
|
||||||
public final class TicTacToeLayer extends Layer {
|
public final class TicTacToeLayer extends Layer {
|
||||||
private TicTacToeCanvas canvas;
|
private TicTacToeCanvas canvas;
|
||||||
|
|
||||||
private TicTacToe ticTacToe;
|
private AtomicReference<TicTacToe> ticTacToe;
|
||||||
private TicTacToeAI ticTacToeAI;
|
private TicTacToeAI ticTacToeAI;
|
||||||
|
|
||||||
private GameInformation information;
|
private GameInformation information;
|
||||||
@@ -42,45 +42,34 @@ public final class TicTacToeLayer extends Layer {
|
|||||||
private char currentPlayerMove = Game.EMPTY;
|
private char currentPlayerMove = Game.EMPTY;
|
||||||
private String player2Name = "";
|
private String player2Name = "";
|
||||||
|
|
||||||
|
final AtomicBoolean firstPlayerIsMe = new AtomicBoolean(true);
|
||||||
|
|
||||||
public TicTacToeLayer(GameInformation information) {
|
public TicTacToeLayer(GameInformation information) {
|
||||||
super("bg-primary");
|
super("bg-primary");
|
||||||
|
|
||||||
canvas = new TicTacToeCanvas(Color.LIME, (App.getHeight() / 100) * 75, (App.getHeight() / 100) * 75, (cell) -> {
|
canvas = new TicTacToeCanvas(Color.LIME, (App.getHeight() / 100) * 75, (App.getHeight() / 100) * 75, (cell) -> {
|
||||||
try {
|
try {
|
||||||
if (information.isConnectionLocal()) {
|
if (information.isConnectionLocal()) {
|
||||||
if (ticTacToe.getCurrentTurn() == 0) {
|
if (ticTacToe.get().getCurrentTurn() == 0) {
|
||||||
playerMoveQueue.put(new Game.Move(cell, 'X'));
|
playerMoveQueue.put(new Game.Move(cell, 'X'));
|
||||||
} else {
|
} else {
|
||||||
playerMoveQueue.put(new Game.Move(cell, 'O'));
|
playerMoveQueue.put(new Game.Move(cell, 'O'));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (information.isPlayerHuman()[0] && currentPlayerMove != Game.EMPTY) {
|
if (information.isPlayerHuman()[0] && currentPlayerMove != Game.EMPTY) {
|
||||||
playerMoveQueue.put(new Game.Move(cell, currentPlayerMove));
|
playerMoveQueue.put(new Game.Move(cell, firstPlayerIsMe.get()? 'X' : 'O'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException _) {}
|
||||||
return;
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
ticTacToe = new TicTacToe();
|
ticTacToe = new AtomicReference<>(new TicTacToe());
|
||||||
ticTacToeAI = new TicTacToeAI();
|
ticTacToeAI = new TicTacToeAI();
|
||||||
|
|
||||||
this.information = information;
|
this.information = information;
|
||||||
|
|
||||||
if (information.isConnectionLocal()) {
|
if (information.isConnectionLocal()) {
|
||||||
new Thread(this::localGameThread).start();
|
new Thread(this::localGameThread).start();
|
||||||
} else {
|
|
||||||
new EventFlow()
|
|
||||||
.addPostEvent(NetworkEvents.StartClient.class,
|
|
||||||
information.serverIP(),
|
|
||||||
Integer.parseInt(information.serverPort()))
|
|
||||||
.onResponse(NetworkEvents.StartClientResponse.class, event -> {
|
|
||||||
Thread a = new Thread(() -> serverGameThread(event));
|
|
||||||
a.setDaemon(false);
|
|
||||||
a.start();
|
|
||||||
})
|
|
||||||
.postEvent();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
currentPlayerNameText = NodeBuilder.header("");
|
currentPlayerNameText = NodeBuilder.header("");
|
||||||
@@ -89,14 +78,24 @@ public final class TicTacToeLayer extends Layer {
|
|||||||
reload();
|
reload();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public TicTacToeLayer(GameInformation information, long clientID) {
|
||||||
|
this(information);
|
||||||
|
|
||||||
|
Thread a = new Thread(this::serverGameThread);
|
||||||
|
a.setDaemon(false);
|
||||||
|
a.start();
|
||||||
|
|
||||||
|
reload();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void reload() {
|
public void reload() {
|
||||||
popAll();
|
popAll();
|
||||||
|
|
||||||
canvas.resize((App.getHeight() / 100) * 75, (App.getHeight() / 100) * 75);
|
canvas.resize((App.getHeight() / 100) * 75, (App.getHeight() / 100) * 75);
|
||||||
|
|
||||||
for (int i = 0; i < ticTacToe.board.length; i++) {
|
for (int i = 0; i < ticTacToe.get().board.length; i++) {
|
||||||
final char value = ticTacToe.board[i];
|
final char value = ticTacToe.get().board[i];
|
||||||
|
|
||||||
if (value == 'X') {
|
if (value == 'X') {
|
||||||
canvas.drawX(Color.RED, i);
|
canvas.drawX(Color.RED, i);
|
||||||
@@ -128,30 +127,28 @@ public final class TicTacToeLayer extends Layer {
|
|||||||
boolean running = true;
|
boolean running = true;
|
||||||
|
|
||||||
while (running) {
|
while (running) {
|
||||||
final int currentPlayer = ticTacToe.getCurrentTurn();
|
final int currentPlayer = ticTacToe.get().getCurrentTurn();
|
||||||
|
|
||||||
currentPlayerNameText.setText(information.playerName()[currentPlayer]);
|
currentPlayerNameText.setText(information.playerName()[currentPlayer]);
|
||||||
currentPlayerMoveText.setText(ticTacToe.getCurrentTurn() == 0? "X" : "O");
|
currentPlayerMoveText.setText(ticTacToe.get().getCurrentTurn() == 0? "X" : "O");
|
||||||
|
|
||||||
Game.Move move = null;
|
Game.Move move = null;
|
||||||
|
|
||||||
if (information.isPlayerHuman()[currentPlayer]) {
|
if (information.isPlayerHuman()[currentPlayer]) {
|
||||||
try {
|
try {
|
||||||
final Game.Move wants = playerMoveQueue.take();
|
final Game.Move wants = playerMoveQueue.take();
|
||||||
final Game.Move[] legalMoves = ticTacToe.getLegalMoves();
|
final Game.Move[] legalMoves = ticTacToe.get().getLegalMoves();
|
||||||
|
|
||||||
for (final Game.Move legalMove : legalMoves) {
|
for (final Game.Move legalMove : legalMoves) {
|
||||||
if (legalMove.position() == wants.position() && legalMove.value() == wants.value()) {
|
if (legalMove.position() == wants.position() && legalMove.value() == wants.value()) {
|
||||||
move = wants;
|
move = wants;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (InterruptedException exception) {
|
} catch (InterruptedException _) {}
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
final long start = System.currentTimeMillis();
|
final long start = System.currentTimeMillis();
|
||||||
|
|
||||||
move = ticTacToeAI.findBestMove(ticTacToe, compurterDifficultyToDepth(10,
|
move = ticTacToeAI.findBestMove(ticTacToe.get(), compurterDifficultyToDepth(10,
|
||||||
information.computerDifficulty()[currentPlayer]));
|
information.computerDifficulty()[currentPlayer]));
|
||||||
|
|
||||||
if (information.computerThinkTime()[currentPlayer] > 0) {
|
if (information.computerThinkTime()[currentPlayer] > 0) {
|
||||||
@@ -168,7 +165,7 @@ public final class TicTacToeLayer extends Layer {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
final Game.State state = ticTacToe.play(move);
|
final Game.State state = ticTacToe.get().play(move);
|
||||||
|
|
||||||
if (move.value() == 'X') {
|
if (move.value() == 'X') {
|
||||||
canvas.drawX(Color.RED, move.position());
|
canvas.drawX(Color.RED, move.position());
|
||||||
@@ -178,7 +175,7 @@ public final class TicTacToeLayer extends Layer {
|
|||||||
|
|
||||||
if (state != Game.State.NORMAL) {
|
if (state != Game.State.NORMAL) {
|
||||||
if (state == Game.State.WIN) {
|
if (state == Game.State.WIN) {
|
||||||
App.push(new GameFinishedPopup(false, information.playerName()[ticTacToe.getCurrentTurn()]));
|
App.push(new GameFinishedPopup(false, information.playerName()[ticTacToe.get().getCurrentTurn()]));
|
||||||
} else if (state == Game.State.DRAW) {
|
} else if (state == Game.State.DRAW) {
|
||||||
App.push(new GameFinishedPopup(true, ""));
|
App.push(new GameFinishedPopup(true, ""));
|
||||||
}
|
}
|
||||||
@@ -188,125 +185,112 @@ public final class TicTacToeLayer extends Layer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class OnlineGameState {
|
private void serverGameThread() {
|
||||||
public long clientId = -1;
|
new EventFlow()
|
||||||
public long receivedMove = -1;
|
.listen(this::handleServerGameStart) // <-----------
|
||||||
public boolean firstPlayerIsMe = true;
|
.listen(this::yourTurnResponse)
|
||||||
|
.listen(this::onMoveResponse)
|
||||||
|
.listen(this::handleReceivedMessage);
|
||||||
}
|
}
|
||||||
AtomicBoolean firstPlayerIsMe = new AtomicBoolean(true);
|
|
||||||
AtomicBoolean gameHasStarted = new AtomicBoolean(false);
|
|
||||||
private void serverGameThread(NetworkEvents.StartClientResponse event) {
|
|
||||||
boolean running = true;
|
|
||||||
final long clientId = event.clientId();
|
|
||||||
final OnlineGameState onlineGameState = new OnlineGameState();
|
|
||||||
onlineGameState.clientId = clientId;
|
|
||||||
|
|
||||||
//new EventFlow()
|
private void handleServerGameStart(NetworkEvents.GameMatchResponse resp) {
|
||||||
// .listen(NetworkEvents.GameMoveResponse.class,respEvent -> onMoveResponse(onlineGameState, respEvent));
|
// Meneer Bas de Jong. Dit functie wordt niet aangeroepen als je de challenger bent.
|
||||||
|
// Ik heb veel dingen geprobeert. FUCKING veel dingen. Hij doet het niet.
|
||||||
|
// Ik heb zelfs in jou code gekeken en unsubscribeAfterSuccess op false gezet. (zie ConnectedLayer).
|
||||||
|
// Alle andere functies worden wel gecalt. Behalve dit.
|
||||||
|
|
||||||
new EventFlow()
|
// Ben jij gehandicapt of ik? Want het moet 1 van de 2 zijn. Ik ben dit al 2 uur aan het debuggen.
|
||||||
.listen(this::yourTurnResponse)
|
// Ik ga nu slapen (04:46).
|
||||||
.listen(this::handleChallengeResponse)
|
|
||||||
.listen(this::handleServerGameStart)
|
|
||||||
.listen(this::handleReceivedMessage)
|
|
||||||
.listen(this::onMoveResponse);
|
|
||||||
|
|
||||||
while (running) {
|
// ⠀⠀⠀⠀⠀⠀⣀⣀⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||||
try {
|
// ⠀⠀⠀⢀⣴⣿⣿⠿⣟⢷⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||||
Thread.sleep(250);
|
// ⠀⠀⠀⢸⣏⡏⠀⠀⠀⢣⢻⣆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||||
} catch (InterruptedException exception) {}
|
// ⠀⠀⠀⢸⣟⠧⠤⠤⠔⠋⠀⢿⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||||
boolean hasStarted = gameHasStarted.get();
|
// ⠀⠀⠀⠀⣿⡆⠀⠀⠀⠀⠀⠸⣷⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||||
if (hasStarted) {
|
// ⠀⠀⠀⠀⠘⣿⡀⢀⣶⠤⠒⠀⢻⣇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||||
onlineGameState.firstPlayerIsMe = firstPlayerIsMe.get();
|
// ⠀⠀⠀⠀⠀⢹⣧⠀⠀⠀⠀⠀⠈⢿⣆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||||
if (onlineGameState.firstPlayerIsMe) {
|
// ⠀⠀⠀⠀⠀⠀⣿⡆⠀⠀⠀⠀⠀⠈⢿⣆⣠⣤⣤⣤⣤⣴⣦⣄⡀⠀⠀⠀⠀⠀⠀⠀
|
||||||
currentPlayerMove = 'X';
|
// ⠀⠀⠀⠀⢀⣾⢿⢿⠀⠀⠀⢀⣀⣀⠘⣿⠋⠁⠀⠙⢇⠀⠀⠙⢿⣦⡀⠀⠀⠀⠀⠀
|
||||||
}
|
// ⠀⠀⠀⢀⣾⢇⡞⠘⣧⠀⢖⡭⠞⢛⡄⠘⣆⠀⠀⠀⠈⢧⠀⠀⠀⠙⢿⣄⠀⠀⠀⠀
|
||||||
else {
|
// ⠀⠀⣠⣿⣛⣥⠤⠤⢿⡄⠀⠀⠈⠉⠀⠀⠹⡄⠀⠀⠀⠈⢧⠀⠀⠀⠈⠻⣦⠀⠀⠀
|
||||||
currentPlayerMove = 'O';
|
// ⠀⣼⡟⡱⠛⠙⠀⠀⠘⢷⡀⠀⠀⠀⠀⠀⠀⠹⡀⠀⠀⠀⠈⣧⠀⠀⠀⠀⠹⣧⡀⠀
|
||||||
}
|
// ⢸⡏⢠⠃⠀⠀⠀⠀⠀⠀⢳⡀⠀⠀⠀⠀⠀⠀⢳⡀⠀⠀⠀⠘⣧⠀⠀⠀⠀⠸⣷⡀
|
||||||
if(!information.isPlayerHuman()[0]){
|
// ⠸⣧⠘⡇⠀⠀⠀⠀⠀⠀⠀⢳⡀⠀⠀⠀⠀⠀⠀⢣⠀⠀⠀⠀⢹⡇⠀⠀⠀⠀⣿⠇
|
||||||
boolean myTurn = (onlineGameState.firstPlayerIsMe && ticTacToe.getCurrentTurn() % 2 == 0)
|
// ⠀⣿⡄⢳⠀⠀⠀⠀⠀⠀⠀⠈⣷⠀⠀⠀⠀⠀⠀⠈⠆⠀⠀⠀⠀⠀⠀⠀⠀⣼⡟⠀
|
||||||
|| (!onlineGameState.firstPlayerIsMe && ticTacToe.getCurrentTurn() % 2 == 1);
|
// ⠀⢹⡇⠘⣇⠀⠀⠀⠀⠀⠀⠰⣿⡆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡄⠀⣼⡟⠀⠀
|
||||||
if (myTurn) {
|
// ⠀⢸⡇⠀⢹⡆⠀⠀⠀⠀⠀⠀⠙⠁⠀⠀⠀⠀⠀⠀⠀⠀⡀⠀⠀⠀⢳⣼⠟⠀⠀⠀
|
||||||
Game.Move move;
|
// ⠀⠸⣧⣀⠀⢳⡀⠀⠀⠀⠀⠀⠀⠀⡄⠀⠀⠀⠀⠀⠀⠀⢃⠀⢀⣴⡿⠁⠀⠀⠀⠀
|
||||||
move = ticTacToeAI.findBestMove(ticTacToe, compurterDifficultyToDepth(10, 10));
|
// ⠀⠀⠈⠙⢷⣄⢳⡀⠀⠀⠀⠀⠀⠀⢳⡀⠀⠀⠀⠀⠀⣠⡿⠟⠛⠉⠀⠀⠀⠀⠀⠀
|
||||||
new EventFlow().addPostEvent(new NetworkEvents.SendMove(clientId, (short) move.position()))
|
// ⠀⠀⠀⠀⠈⠻⢿⣷⣦⣄⣀⣀⣠⣤⠾⠷⣦⣤⣤⡶⠟⠋⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||||
.postEvent();
|
// ⠀⠀⠀⠀⠀⠀⠀⠈⠉⠛⠛⠉⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||||
}
|
|
||||||
}
|
player2Name = resp.opponent();
|
||||||
else {
|
System.out.println(player2Name);
|
||||||
try {
|
|
||||||
final Game.Move wants = playerMoveQueue.take();
|
currentPlayerMoveText.setText("X");
|
||||||
final Game.Move[] legalMoves = ticTacToe.getLegalMoves();
|
|
||||||
for (final Game.Move legalMove : legalMoves) {
|
if(!resp.playerToMove().equalsIgnoreCase(resp.opponent())) {
|
||||||
if (legalMove.position() == wants.position() && legalMove.value() == wants.value()) {
|
currentPlayerNameText.setText(information.playerName()[0]);
|
||||||
new EventFlow().addPostEvent(new NetworkEvents.SendMove(clientId, (short) wants.position()))
|
firstPlayerIsMe.set(true);
|
||||||
.postEvent();
|
|
||||||
break;
|
System.out.printf("I am starting: My client id is %d\n", resp.clientId());
|
||||||
}
|
} else {
|
||||||
}
|
currentPlayerNameText.setText(player2Name);
|
||||||
} catch (InterruptedException exception) {
|
firstPlayerIsMe.set(false);
|
||||||
System.out.println(exception.getMessage());
|
|
||||||
return;
|
System.out.printf("I am NOT starting: My client id is %d\n", resp.clientId());
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void drawSymbol(Game.Move move) {
|
|
||||||
if (move.value() == 'X') {
|
|
||||||
canvas.drawX(Color.RED, move.position());
|
|
||||||
} else if (move.value() == 'O') {
|
|
||||||
canvas.drawO(Color.BLUE, move.position());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void handleServerGameStart(NetworkEvents.GameMatchResponse resp) {
|
|
||||||
if(resp.playerToMove().equals(resp.opponent())){
|
|
||||||
firstPlayerIsMe.set(false);
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
firstPlayerIsMe.set(true);
|
|
||||||
}
|
|
||||||
gameHasStarted.set(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void onMoveResponse(NetworkEvents.GameMoveResponse resp) {
|
private void onMoveResponse(NetworkEvents.GameMoveResponse resp) {
|
||||||
char playerChar;
|
char playerChar;
|
||||||
if (resp.player().equals(information.playerName()[0]) && firstPlayerIsMe.get()
|
|
||||||
|| !resp.player().equals(information.playerName()[0]) && !firstPlayerIsMe.get()) {
|
if (!resp.player().equalsIgnoreCase(player2Name)) {
|
||||||
playerChar = 'X';
|
playerChar = firstPlayerIsMe.get()? 'X' : 'O';
|
||||||
}
|
} else {
|
||||||
else {
|
playerChar = firstPlayerIsMe.get()? 'O' : 'X';
|
||||||
playerChar = 'O';
|
}
|
||||||
}
|
|
||||||
Game.Move move =new Game.Move(Integer.parseInt(resp.move()),playerChar);
|
final Game.Move move = new Game.Move(Integer.parseInt(resp.move()), playerChar);
|
||||||
Game.State state = ticTacToe.play(move);
|
final Game.State state = ticTacToe.get().play(move);
|
||||||
if (state != Game.State.NORMAL) { //todo differentiate between future draw guaranteed and is currently a draw
|
|
||||||
gameHasStarted.set(false);
|
if (state != Game.State.NORMAL) { //todo differentiate between future draw guaranteed and is currently a draw
|
||||||
}
|
if (state == Game.State.WIN) {
|
||||||
drawSymbol(move);
|
App.push(new GameFinishedPopup(false, information.playerName()[ticTacToe.get().getCurrentTurn()]));
|
||||||
|
} else if (state == Game.State.DRAW) {
|
||||||
|
App.push(new GameFinishedPopup(true, ""));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (move.value() == 'X') {
|
||||||
|
canvas.drawX(Color.RED, move.position());
|
||||||
|
} else if (move.value() == 'O') {
|
||||||
|
canvas.drawO(Color.BLUE, move.position());
|
||||||
|
}
|
||||||
|
|
||||||
|
currentPlayerNameText.setText(ticTacToe.get().getCurrentTurn() == (firstPlayerIsMe.get()? 0 : 1)? information.playerName()[0] : player2Name);
|
||||||
|
currentPlayerMoveText.setText(ticTacToe.get().getCurrentTurn() == 0? "X" : "O");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleChallengeResponse(NetworkEvents.ChallengeResponse resp) {
|
private void yourTurnResponse(NetworkEvents.YourTurnResponse response) {
|
||||||
new EventFlow().addPostEvent(new NetworkEvents.SendAcceptChallenge(resp.clientId(),Integer.parseInt(resp.challengeId())))
|
int position = -1;
|
||||||
.postEvent();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void yourTurnResponse(NetworkEvents.YourTurnResponse response) {
|
if (information.isPlayerHuman()[0]) {
|
||||||
|
try {
|
||||||
|
position = playerMoveQueue.take().position();
|
||||||
|
} catch (InterruptedException _) {}
|
||||||
|
} else {
|
||||||
|
final Game.Move move = ticTacToeAI.findBestMove(ticTacToe.get(), compurterDifficultyToDepth(10,
|
||||||
|
information.computerDifficulty()[0]));
|
||||||
|
|
||||||
//new EventFlow().addPostEvent(new NetworkEvents.SendCommand(response.clientId(),"CHALLENGE banaan tic-tac-toe")).postEvent();
|
position = move.position();
|
||||||
//new EventFlow().addPostEvent(new NetworkEvents.SendMove(response.clientId(),(short)2))
|
}
|
||||||
// .postEvent();
|
|
||||||
}
|
|
||||||
private void handleReceivedMessage(NetworkEvents.ReceivedMessage msg) {
|
|
||||||
System.out.println("Received Message: " + msg.message()); //todo add chat window
|
|
||||||
}
|
|
||||||
|
|
||||||
private void serverGameThreadResponseHandler(OnlineGameState ogs, NetworkEvents.ChallengeResponse msg) {
|
new EventFlow().addPostEvent(new NetworkEvents.SendMove(response.clientId(), (short)position))
|
||||||
if (msg.clientId() != ogs.clientId) return;
|
.postEvent();
|
||||||
IO.println("Client ID: " + ogs.clientId + " Received Message: " + msg);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void handleReceivedMessage(NetworkEvents.ReceivedMessage msg) {
|
||||||
|
System.out.println("Received Message: " + msg.message()); //todo add chat window
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -25,4 +25,4 @@ public class AppContext {
|
|||||||
assert localization != null;
|
assert localization != null;
|
||||||
return localization.getString(key, locale);
|
return localization.getString(key, locale);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,9 @@
|
|||||||
|
accept=Accept
|
||||||
ai=Artificial Intelligence
|
ai=Artificial Intelligence
|
||||||
appTitle=ISY Games Selector
|
appTitle=ISY Games Selector
|
||||||
back=Back
|
back=Back
|
||||||
backToMainMenu=Back to main menu
|
backToMainMenu=Back to main menu
|
||||||
|
challengeText=You were challenged by
|
||||||
computer=Computer
|
computer=Computer
|
||||||
computerDifficulty=Computer Difficulty
|
computerDifficulty=Computer Difficulty
|
||||||
computerThinkTime=Computer Think Time
|
computerThinkTime=Computer Think Time
|
||||||
@@ -11,10 +13,12 @@ connectionType=Connection Type
|
|||||||
credits=Credits
|
credits=Credits
|
||||||
dark=Dark
|
dark=Dark
|
||||||
dark-hc=Dark (High Contrast)
|
dark-hc=Dark (High Contrast)
|
||||||
|
deny=Deny
|
||||||
developers=Developers
|
developers=Developers
|
||||||
drawText=The game ended in a draw
|
drawText=The game ended in a draw
|
||||||
effectsVolume=Effects Volume
|
effectsVolume=Effects Volume
|
||||||
fullscreen=Fullscreen
|
fullscreen=Fullscreen
|
||||||
|
gameIsText=To a game of
|
||||||
goodGameText=Good game. Well played.
|
goodGameText=Good game. Well played.
|
||||||
human=Human
|
human=Human
|
||||||
language=Language
|
language=Language
|
||||||
|
|||||||
Reference in New Issue
Block a user