mirror of
https://github.com/2OOP/pism.git
synced 2026-02-04 10:54:51 +00:00
Compare commits
2 Commits
0132981d94
...
1ae79daef0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1ae79daef0 | ||
|
|
cd8eb99559 |
@@ -21,7 +21,7 @@ import org.toop.game.games.reversi.BitboardReversi;
|
|||||||
import org.toop.game.games.tictactoe.BitboardTicTacToe;
|
import org.toop.game.games.tictactoe.BitboardTicTacToe;
|
||||||
import org.toop.game.players.ArtificialPlayer;
|
import org.toop.game.players.ArtificialPlayer;
|
||||||
import org.toop.game.players.OnlinePlayer;
|
import org.toop.game.players.OnlinePlayer;
|
||||||
import org.toop.game.players.RandomAI;
|
import org.toop.game.players.ai.RandomAI;
|
||||||
import org.toop.local.AppContext;
|
import org.toop.local.AppContext;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ public class GenericGameController<T extends TurnBasedGame<T>> implements GameCo
|
|||||||
// Listen to updates
|
// Listen to updates
|
||||||
eventFlow
|
eventFlow
|
||||||
.listen(GUIEvents.GameEnded.class, this::onGameFinish, false)
|
.listen(GUIEvents.GameEnded.class, this::onGameFinish, false)
|
||||||
.listen(GUIEvents.PlayerAttemptedMove.class, event -> {if (getCurrentPlayer() instanceof LocalPlayer<T> lp){lp.setMove(event.move());}}, false);
|
.listen(GUIEvents.PlayerAttemptedMove.class, event -> {if (getCurrentPlayer() instanceof LocalPlayer<T> lp){lp.setLastMove(event.move());}}, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void start(){
|
public void start(){
|
||||||
|
|||||||
@@ -2,9 +2,6 @@ package org.toop.app.widget.view;
|
|||||||
|
|
||||||
import javafx.application.Platform;
|
import javafx.application.Platform;
|
||||||
import org.toop.app.GameInformation;
|
import org.toop.app.GameInformation;
|
||||||
import org.toop.app.canvas.ReversiBitCanvas;
|
|
||||||
import org.toop.app.canvas.TicTacToeBitCanvas;
|
|
||||||
import org.toop.app.gameControllers.GenericGameController;
|
|
||||||
import org.toop.app.gameControllers.ReversiBitController;
|
import org.toop.app.gameControllers.ReversiBitController;
|
||||||
import org.toop.app.gameControllers.TicTacToeBitController;
|
import org.toop.app.gameControllers.TicTacToeBitController;
|
||||||
import org.toop.framework.gameFramework.controller.GameController;
|
import org.toop.framework.gameFramework.controller.GameController;
|
||||||
@@ -18,8 +15,8 @@ import org.toop.app.widget.complex.PlayerInfoWidget;
|
|||||||
import org.toop.app.widget.complex.ViewWidget;
|
import org.toop.app.widget.complex.ViewWidget;
|
||||||
import org.toop.app.widget.popup.ErrorPopup;
|
import org.toop.app.widget.popup.ErrorPopup;
|
||||||
import org.toop.app.widget.tutorial.*;
|
import org.toop.app.widget.tutorial.*;
|
||||||
import org.toop.game.players.MiniMaxAI;
|
import org.toop.game.players.ai.MiniMaxAI;
|
||||||
import org.toop.game.players.RandomAI;
|
import org.toop.game.players.ai.RandomAI;
|
||||||
import org.toop.local.AppContext;
|
import org.toop.local.AppContext;
|
||||||
|
|
||||||
import javafx.geometry.Pos;
|
import javafx.geometry.Pos;
|
||||||
@@ -27,9 +24,6 @@ import javafx.scene.control.ScrollPane;
|
|||||||
import javafx.scene.layout.VBox;
|
import javafx.scene.layout.VBox;
|
||||||
import org.toop.local.AppSettings;
|
import org.toop.local.AppSettings;
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Random;
|
|
||||||
|
|
||||||
public class LocalMultiplayerView extends ViewWidget {
|
public class LocalMultiplayerView extends ViewWidget {
|
||||||
private final GameInformation information;
|
private final GameInformation information;
|
||||||
|
|
||||||
|
|||||||
@@ -5,46 +5,66 @@ import org.apache.logging.log4j.Logger;
|
|||||||
import org.toop.framework.gameFramework.model.game.TurnBasedGame;
|
import org.toop.framework.gameFramework.model.game.TurnBasedGame;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Abstract class representing a player in a game.
|
* Base class for players in a turn-based game.
|
||||||
* <p>
|
*
|
||||||
* Players are entities that can make moves based on the current state of a game.
|
* @param <T> the game type
|
||||||
* player types, such as human players or AI players.
|
|
||||||
* </p>
|
|
||||||
* <p>
|
|
||||||
* Subclasses should override the {@link #getMove(GameR)} method to provide
|
|
||||||
* specific move logic.
|
|
||||||
* </p>
|
|
||||||
*/
|
*/
|
||||||
public abstract class AbstractPlayer<T extends TurnBasedGame<T>> implements Player<T> {
|
public abstract class AbstractPlayer<T extends TurnBasedGame<T>> implements Player<T> {
|
||||||
private final Logger logger = LogManager.getLogger(this.getClass());
|
|
||||||
|
|
||||||
|
private final Logger logger = LogManager.getLogger(this.getClass());
|
||||||
private final String name;
|
private final String name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new player with the given name.
|
||||||
|
*
|
||||||
|
* @param name the player name
|
||||||
|
*/
|
||||||
protected AbstractPlayer(String name) {
|
protected AbstractPlayer(String name) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a copy of another player.
|
||||||
|
*
|
||||||
|
* @param other the player to copy
|
||||||
|
*/
|
||||||
protected AbstractPlayer(AbstractPlayer<T> other) {
|
protected AbstractPlayer(AbstractPlayer<T> other) {
|
||||||
this.name = other.name;
|
this.name = other.name;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determines the next move based on the provided game state.
|
* Gets the player's move for the given game state.
|
||||||
|
* A deep copy is provided so the player cannot modify the real state.
|
||||||
* <p>
|
* <p>
|
||||||
* The default implementation throws an {@link UnsupportedOperationException},
|
* This method uses the Template Method Pattern: it defines the fixed
|
||||||
* indicating that concrete subclasses must override this method to provide
|
* algorithm and delegates the variable part to {@link #determineMove(T)}.
|
||||||
* actual move logic.
|
|
||||||
* </p>
|
|
||||||
*
|
*
|
||||||
* @param gameCopy a snapshot of the current game state
|
* @param game the current game
|
||||||
* @return an integer representing the chosen move
|
* @return the chosen move
|
||||||
* @throws UnsupportedOperationException if the method is not overridden
|
|
||||||
*/
|
*/
|
||||||
public long getMove(T gameCopy) {
|
public final long getMove(T game) {
|
||||||
logger.error("Method getMove not implemented.");
|
return determineMove(game.deepCopy());
|
||||||
throw new UnsupportedOperationException("Not supported yet.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getName(){
|
|
||||||
|
/**
|
||||||
|
* Determines the player's move using a safe copy of the game.
|
||||||
|
* <p>
|
||||||
|
* This method is called by {@link #getMove(T)} and should contain
|
||||||
|
* the player's strategy for choosing a move.
|
||||||
|
*
|
||||||
|
* @param gameCopy a deep copy of the game
|
||||||
|
* @return the chosen move
|
||||||
|
*/
|
||||||
|
protected abstract long determineMove(T gameCopy);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the player's name.
|
||||||
|
*
|
||||||
|
* @return the name
|
||||||
|
*/
|
||||||
|
public String getName() {
|
||||||
return this.name;
|
return this.name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,52 +4,52 @@ import org.toop.framework.gameFramework.model.player.*;
|
|||||||
import org.toop.framework.gameFramework.model.game.TurnBasedGame;
|
import org.toop.framework.gameFramework.model.game.TurnBasedGame;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a player controlled by an AI in a game.
|
* Represents a player controlled by an AI.
|
||||||
* <p>
|
|
||||||
* This player uses an {@link AbstractAI} instance to determine its moves. The generic
|
|
||||||
* parameter {@code T} specifies the type of {@link GameR} the AI can handle.
|
|
||||||
* </p>
|
|
||||||
*
|
*
|
||||||
* @param <T> the specific type of game this AI player can play
|
* @param <T> the type of turn-based game
|
||||||
*/
|
*/
|
||||||
public class ArtificialPlayer<T extends TurnBasedGame<T>> extends AbstractPlayer<T> {
|
public class ArtificialPlayer<T extends TurnBasedGame<T>> extends AbstractPlayer<T> {
|
||||||
|
|
||||||
/** The AI instance used to calculate moves. */
|
|
||||||
private final AI<T> ai;
|
private final AI<T> ai;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a new ArtificialPlayer using the specified AI.
|
* Creates a new AI-controlled player.
|
||||||
*
|
*
|
||||||
* @param ai the AI instance that determines moves for this player
|
* @param ai the AI controlling this player
|
||||||
|
* @param name the player's name
|
||||||
*/
|
*/
|
||||||
public ArtificialPlayer(AI<T> ai, String name) {
|
public ArtificialPlayer(AI<T> ai, String name) {
|
||||||
super(name);
|
super(name);
|
||||||
this.ai = ai;
|
this.ai = ai;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a copy of another AI-controlled player.
|
||||||
|
*
|
||||||
|
* @param other the player to copy
|
||||||
|
*/
|
||||||
public ArtificialPlayer(ArtificialPlayer<T> other) {
|
public ArtificialPlayer(ArtificialPlayer<T> other) {
|
||||||
super(other);
|
super(other);
|
||||||
this.ai = other.ai.deepCopy();
|
this.ai = other.ai.deepCopy();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determines the next move for this player using its AI.
|
* Determines the player's move using the AI.
|
||||||
* <p>
|
|
||||||
* This method overrides {@link AbstractPlayer#getMove(GameR)}. Because the AI is
|
|
||||||
* typed to {@code T}, a runtime cast is required. It is the caller's
|
|
||||||
* responsibility to ensure that {@code gameCopy} is of type {@code T}.
|
|
||||||
* </p>
|
|
||||||
*
|
*
|
||||||
* @param gameCopy a copy of the current game state
|
* @param gameCopy a copy of the current game
|
||||||
* @return the integer representing the chosen move
|
* @return the move chosen by the AI
|
||||||
* @throws ClassCastException if {@code gameCopy} is not of type {@code T}
|
|
||||||
*/
|
*/
|
||||||
public long getMove(T gameCopy) {
|
protected long determineMove(T gameCopy) {
|
||||||
return ai.getMove(gameCopy);
|
return ai.getMove(gameCopy);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a deep copy of this AI player.
|
||||||
|
*
|
||||||
|
* @return a copy of this player
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public ArtificialPlayer<T> deepCopy() {
|
public ArtificialPlayer<T> deepCopy() {
|
||||||
return new ArtificialPlayer<T>(this);
|
return new ArtificialPlayer<>(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,85 +2,86 @@ package org.toop.game.players;
|
|||||||
|
|
||||||
import org.toop.framework.gameFramework.model.game.TurnBasedGame;
|
import org.toop.framework.gameFramework.model.game.TurnBasedGame;
|
||||||
import org.toop.framework.gameFramework.model.player.AbstractPlayer;
|
import org.toop.framework.gameFramework.model.player.AbstractPlayer;
|
||||||
import org.toop.framework.gameFramework.model.player.Player;
|
|
||||||
|
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a local player who provides moves manually.
|
||||||
|
*
|
||||||
|
* @param <T> the type of turn-based game
|
||||||
|
*/
|
||||||
public class LocalPlayer<T extends TurnBasedGame<T>> extends AbstractPlayer<T> {
|
public class LocalPlayer<T extends TurnBasedGame<T>> extends AbstractPlayer<T> {
|
||||||
// Future can be used with event system, IF unsubscribeAfterSuccess works...
|
|
||||||
// private CompletableFuture<Integer> LastMove = new CompletableFuture<>();
|
|
||||||
|
|
||||||
private CompletableFuture<Long> LastMove;
|
private CompletableFuture<Long> LastMove = new CompletableFuture<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new local player with the given name.
|
||||||
|
*
|
||||||
|
* @param name the player's name
|
||||||
|
*/
|
||||||
public LocalPlayer(String name) {
|
public LocalPlayer(String name) {
|
||||||
super(name);
|
super(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a copy of another local player.
|
||||||
|
*
|
||||||
|
* @param other the player to copy
|
||||||
|
*/
|
||||||
public LocalPlayer(LocalPlayer<T> other) {
|
public LocalPlayer(LocalPlayer<T> other) {
|
||||||
super(other);
|
super(other);
|
||||||
|
this.LastMove = other.LastMove;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Waits for and returns the player's next legal move.
|
||||||
|
*
|
||||||
|
* @param gameCopy a copy of the current game
|
||||||
|
* @return the chosen move
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public long getMove(T gameCopy) {
|
protected long determineMove(T gameCopy) {
|
||||||
return getValidMove(gameCopy);
|
long legalMoves = gameCopy.getLegalMoves();
|
||||||
|
long move;
|
||||||
|
|
||||||
|
do {
|
||||||
|
move = getLastMove();
|
||||||
|
} while ((legalMoves & move) == 0);
|
||||||
|
|
||||||
|
return move;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setMove(long move) {
|
/**
|
||||||
|
* Sets the player's last move.
|
||||||
|
*
|
||||||
|
* @param move the move to set
|
||||||
|
*/
|
||||||
|
public void setLastMove(long move) {
|
||||||
LastMove.complete(move);
|
LastMove.complete(move);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: helper function, would like to replace to get rid of this method
|
/**
|
||||||
public static boolean contains(int[] array, int value){
|
* Waits for the next move from the player.
|
||||||
for (int i : array) if (i == value) return true;
|
*
|
||||||
return false;
|
* @return the chosen move or 0 if interrupted
|
||||||
}
|
*/
|
||||||
|
private long getLastMove() {
|
||||||
private long getMove2(T gameCopy) {
|
LastMove = new CompletableFuture<>(); // Reset the future
|
||||||
LastMove = new CompletableFuture<>();
|
|
||||||
long move = 0;
|
|
||||||
try {
|
try {
|
||||||
move = LastMove.get();
|
return LastMove.get();
|
||||||
System.out.println(Long.toBinaryString(move));
|
} catch (ExecutionException | InterruptedException e) {
|
||||||
} catch (InterruptedException | ExecutionException e) {
|
return 0;
|
||||||
// TODO: Add proper logging.
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
}
|
||||||
return move;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected long getValidMove(T gameCopy){
|
|
||||||
// Get this player's valid moves
|
|
||||||
long validMoves = gameCopy.getLegalMoves();
|
|
||||||
// Make sure provided move is valid
|
|
||||||
// TODO: Limit amount of retries?
|
|
||||||
// TODO: Stop copying game so many times
|
|
||||||
long move = getMove2(gameCopy.deepCopy());
|
|
||||||
while ((validMoves & move) == 0) {
|
|
||||||
System.out.println("Not a valid move, try again");
|
|
||||||
move = getMove2(gameCopy.deepCopy());
|
|
||||||
}
|
|
||||||
return move;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a deep copy of this local player.
|
||||||
|
*
|
||||||
|
* @return a copy of this player
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public LocalPlayer<T> deepCopy() {
|
public LocalPlayer<T> deepCopy() {
|
||||||
return new LocalPlayer<T>(this.getName());
|
return new LocalPlayer<>(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*public void register() {
|
|
||||||
// Listening to PlayerAttemptedMove
|
|
||||||
new EventFlow().listen(GUIEvents.PlayerAttemptedMove.class, event -> {
|
|
||||||
if (!LastMove.isDone()) {
|
|
||||||
LastMove.complete(event.move()); // complete the future
|
|
||||||
}
|
|
||||||
}, true); // auto-unsubscribe
|
|
||||||
}
|
|
||||||
|
|
||||||
// This blocks until the next move arrives
|
|
||||||
public int take() throws ExecutionException, InterruptedException {
|
|
||||||
int move = LastMove.get(); // blocking
|
|
||||||
LastMove = new CompletableFuture<>(); // reset for next move
|
|
||||||
return move;
|
|
||||||
}*/
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,30 +5,45 @@ import org.toop.framework.gameFramework.model.player.AbstractPlayer;
|
|||||||
import org.toop.framework.gameFramework.model.player.Player;
|
import org.toop.framework.gameFramework.model.player.Player;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a player controlled remotely or over a network.
|
* Represents a player that participates online.
|
||||||
* <p>
|
*
|
||||||
* This class extends {@link AbstractPlayer} and can be used to implement game logic
|
* @param <T> the type of turn-based game
|
||||||
* where moves are provided by an external source (e.g., another user or a server).
|
|
||||||
* 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<T extends TurnBasedGame<T>> extends AbstractPlayer<T> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a new OnlinePlayer.
|
* Creates a new online player with the given name.
|
||||||
* <p>
|
*
|
||||||
* Currently, no additional initialization is performed. Subclasses or
|
* @param name the name of the player
|
||||||
* future implementations should provide mechanisms to receive moves from
|
|
||||||
* an external source.
|
|
||||||
*/
|
*/
|
||||||
public OnlinePlayer(String name) {
|
public OnlinePlayer(String name) {
|
||||||
super(name);
|
super(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a copy of another online player.
|
||||||
|
*
|
||||||
|
* @param other the player to copy
|
||||||
|
*/
|
||||||
public OnlinePlayer(OnlinePlayer<T> other) {
|
public OnlinePlayer(OnlinePlayer<T> other) {
|
||||||
super(other);
|
super(other);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
* <p>
|
||||||
|
* This method is not supported for online players.
|
||||||
|
*
|
||||||
|
* @throws UnsupportedOperationException always
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected long determineMove(T gameCopy) {
|
||||||
|
throw new UnsupportedOperationException("An online player does not support determining move");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Player<T> deepCopy() {
|
public Player<T> deepCopy() {
|
||||||
return new OnlinePlayer<>(this);
|
return new OnlinePlayer<>(this);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
package org.toop.game.players;
|
package org.toop.game.players.ai;
|
||||||
|
|
||||||
import org.toop.framework.gameFramework.GameState;
|
import org.toop.framework.gameFramework.GameState;
|
||||||
import org.toop.framework.gameFramework.model.game.PlayResult;
|
import org.toop.framework.gameFramework.model.game.PlayResult;
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package org.toop.game.players;
|
package org.toop.game.players.ai;
|
||||||
|
|
||||||
import org.toop.framework.gameFramework.model.game.TurnBasedGame;
|
import org.toop.framework.gameFramework.model.game.TurnBasedGame;
|
||||||
import org.toop.framework.gameFramework.model.player.AbstractAI;
|
import org.toop.framework.gameFramework.model.player.AbstractAI;
|
||||||
Reference in New Issue
Block a user