mirror of
https://github.com/2OOP/pism.git
synced 2026-02-04 02:44:50 +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.players.ArtificialPlayer;
|
||||
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 java.util.List;
|
||||
|
||||
@@ -55,7 +55,7 @@ public class GenericGameController<T extends TurnBasedGame<T>> implements GameCo
|
||||
// Listen to updates
|
||||
eventFlow
|
||||
.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(){
|
||||
|
||||
@@ -2,9 +2,6 @@ package org.toop.app.widget.view;
|
||||
|
||||
import javafx.application.Platform;
|
||||
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.TicTacToeBitController;
|
||||
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.popup.ErrorPopup;
|
||||
import org.toop.app.widget.tutorial.*;
|
||||
import org.toop.game.players.MiniMaxAI;
|
||||
import org.toop.game.players.RandomAI;
|
||||
import org.toop.game.players.ai.MiniMaxAI;
|
||||
import org.toop.game.players.ai.RandomAI;
|
||||
import org.toop.local.AppContext;
|
||||
|
||||
import javafx.geometry.Pos;
|
||||
@@ -27,9 +24,6 @@ import javafx.scene.control.ScrollPane;
|
||||
import javafx.scene.layout.VBox;
|
||||
import org.toop.local.AppSettings;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Random;
|
||||
|
||||
public class LocalMultiplayerView extends ViewWidget {
|
||||
private final GameInformation information;
|
||||
|
||||
|
||||
@@ -5,46 +5,66 @@ import org.apache.logging.log4j.Logger;
|
||||
import org.toop.framework.gameFramework.model.game.TurnBasedGame;
|
||||
|
||||
/**
|
||||
* Abstract class representing a player in a game.
|
||||
* <p>
|
||||
* Players are entities that can make moves based on the current state of a game.
|
||||
* 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>
|
||||
* Base class for players in a turn-based game.
|
||||
*
|
||||
* @param <T> the game type
|
||||
*/
|
||||
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;
|
||||
|
||||
/**
|
||||
* Creates a new player with the given name.
|
||||
*
|
||||
* @param name the player name
|
||||
*/
|
||||
protected AbstractPlayer(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a copy of another player.
|
||||
*
|
||||
* @param other the player to copy
|
||||
*/
|
||||
protected AbstractPlayer(AbstractPlayer<T> other) {
|
||||
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>
|
||||
* The default implementation throws an {@link UnsupportedOperationException},
|
||||
* indicating that concrete subclasses must override this method to provide
|
||||
* actual move logic.
|
||||
* </p>
|
||||
* This method uses the Template Method Pattern: it defines the fixed
|
||||
* algorithm and delegates the variable part to {@link #determineMove(T)}.
|
||||
*
|
||||
* @param gameCopy a snapshot of the current game state
|
||||
* @return an integer representing the chosen move
|
||||
* @throws UnsupportedOperationException if the method is not overridden
|
||||
* @param game the current game
|
||||
* @return the chosen move
|
||||
*/
|
||||
public long getMove(T gameCopy) {
|
||||
logger.error("Method getMove not implemented.");
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
public final long getMove(T game) {
|
||||
return determineMove(game.deepCopy());
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,52 +4,52 @@ import org.toop.framework.gameFramework.model.player.*;
|
||||
import org.toop.framework.gameFramework.model.game.TurnBasedGame;
|
||||
|
||||
/**
|
||||
* Represents a player controlled by an AI in a game.
|
||||
* <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>
|
||||
* Represents a player controlled by an AI.
|
||||
*
|
||||
* @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> {
|
||||
|
||||
/** The AI instance used to calculate moves. */
|
||||
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) {
|
||||
super(name);
|
||||
this.ai = ai;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a copy of another AI-controlled player.
|
||||
*
|
||||
* @param other the player to copy
|
||||
*/
|
||||
public ArtificialPlayer(ArtificialPlayer<T> other) {
|
||||
super(other);
|
||||
this.ai = other.ai.deepCopy();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines the next move for this player using its 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>
|
||||
* Determines the player's move using the AI.
|
||||
*
|
||||
* @param gameCopy a copy of the current game state
|
||||
* @return the integer representing the chosen move
|
||||
* @throws ClassCastException if {@code gameCopy} is not of type {@code T}
|
||||
* @param gameCopy a copy of the current game
|
||||
* @return the move chosen by the AI
|
||||
*/
|
||||
public long getMove(T gameCopy) {
|
||||
protected long determineMove(T gameCopy) {
|
||||
return ai.getMove(gameCopy);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a deep copy of this AI player.
|
||||
*
|
||||
* @return a copy of this player
|
||||
*/
|
||||
@Override
|
||||
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.player.AbstractPlayer;
|
||||
import org.toop.framework.gameFramework.model.player.Player;
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
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> {
|
||||
// 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) {
|
||||
super(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a copy of another local player.
|
||||
*
|
||||
* @param other the player to copy
|
||||
*/
|
||||
public LocalPlayer(LocalPlayer<T> 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
|
||||
public long getMove(T gameCopy) {
|
||||
return getValidMove(gameCopy);
|
||||
protected long determineMove(T 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);
|
||||
}
|
||||
|
||||
// TODO: helper function, would like to replace to get rid of this method
|
||||
public static boolean contains(int[] array, int value){
|
||||
for (int i : array) if (i == value) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
private long getMove2(T gameCopy) {
|
||||
LastMove = new CompletableFuture<>();
|
||||
long move = 0;
|
||||
/**
|
||||
* Waits for the next move from the player.
|
||||
*
|
||||
* @return the chosen move or 0 if interrupted
|
||||
*/
|
||||
private long getLastMove() {
|
||||
LastMove = new CompletableFuture<>(); // Reset the future
|
||||
try {
|
||||
move = LastMove.get();
|
||||
System.out.println(Long.toBinaryString(move));
|
||||
} catch (InterruptedException | ExecutionException e) {
|
||||
// TODO: Add proper logging.
|
||||
e.printStackTrace();
|
||||
return LastMove.get();
|
||||
} catch (ExecutionException | InterruptedException e) {
|
||||
return 0;
|
||||
}
|
||||
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
|
||||
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;
|
||||
|
||||
/**
|
||||
* Represents a player controlled remotely or over a network.
|
||||
* <p>
|
||||
* This class extends {@link AbstractPlayer} and can be used to implement game logic
|
||||
* 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>
|
||||
* Represents a player that participates online.
|
||||
*
|
||||
* @param <T> the type of turn-based game
|
||||
*/
|
||||
public class OnlinePlayer<T extends TurnBasedGame<T>> extends AbstractPlayer<T> {
|
||||
|
||||
/**
|
||||
* Constructs a new OnlinePlayer.
|
||||
* <p>
|
||||
* Currently, no additional initialization is performed. Subclasses or
|
||||
* future implementations should provide mechanisms to receive moves from
|
||||
* an external source.
|
||||
* Creates a new online player with the given name.
|
||||
*
|
||||
* @param name the name of the player
|
||||
*/
|
||||
public OnlinePlayer(String name) {
|
||||
super(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a copy of another online player.
|
||||
*
|
||||
* @param other the player to copy
|
||||
*/
|
||||
public OnlinePlayer(OnlinePlayer<T> 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
|
||||
public Player<T> deepCopy() {
|
||||
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.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.player.AbstractAI;
|
||||
Reference in New Issue
Block a user