Skip to content
This repository has been archived by the owner on Apr 15, 2024. It is now read-only.

Jared refactoring #26

Open
wants to merge 10 commits into
base: main
Choose a base branch
from
252 changes: 0 additions & 252 deletions src/main/java/ubc/cosc322/algorithms/BFSAmazons.java

This file was deleted.

51 changes: 9 additions & 42 deletions src/main/java/ubc/cosc322/algorithms/MonteCarloTreeSearch.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,7 @@ public class MonteCarloTreeSearch {
// Lists to hold the positions of black and white queens on the board.
List<List<Integer>> blackPositions = new ArrayList<>();
List<List<Integer>> whitePositions = new ArrayList<>();
final String OPPONENT = "white"; // Assumed opponent color.
static final int WIN_SCORE = 10; // Score indicating a win in simulations.
int level; // Represents the current level in the tree.
final int UPPER_TIME_LIMIT = 25000;
public static int numberOfNodes = 0;
long end;
Expand Down Expand Up @@ -46,18 +44,6 @@ public void initializePositions() {
whitePositions.add(Arrays.asList(10, 4));
}

/**
* Sends a move message to the game server with the specified queen positions and the arrow position.
*
* @param queenPosCurrent The current position of the queen.
* @param queenPosNew The new position of the queen.
* @param arrowPos The position where the arrow is shot.
*/
public void sendMoveMessage(java.util.ArrayList<java.lang.Integer> queenPosCurrent,
java.util.ArrayList<java.lang.Integer> queenPosNew,
java.util.ArrayList<java.lang.Integer> arrowPos) {
}

/**
* Finds the next best move using the MCTS algorithm.
*
Expand All @@ -70,10 +56,13 @@ public Board findNextMove(Board board, int playerNo) {
Node rootNode = new Node(playerNo);
rootNode.setState(board);
expandNode(rootNode, rootNode.getPlayerNo());
System.out.println("Size of child array from root node: "+rootNode.getChildArray().size());
if(rootNode.getChildArray().isEmpty()){
return board;
}
// Use a single threaded context to manage the overall time-bound loop.
ExecutorService executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());

// Use parallel computing to increase efficiency of simulateRandomPlayout
while (System.currentTimeMillis() < end) {
List<Callable<Void>> tasks = new ArrayList<>();
for (Node childNode : rootNode.getChildren()) {
Expand All @@ -91,31 +80,25 @@ public Board findNextMove(Board board, int playerNo) {
}
executor.shutdown();
System.out.println("Games played: "+Board.gamesPlayed);
//System.out.println("Score of root node " + rootNode.getScore());
Node winnerNode = selectPromisingNode(rootNode);

//Node winnerNode = rootNode.getChildWithMaxScore();
System.out.println("Winner node child with highest score: "+winnerNode.getScore());
System.out.println("Number of children for node: " + rootNode.getChildren().size());
numberOfNodes = numberOfNodes + (rootNode.getChildren().size());
if (winnerNode == null) {
System.out.println("winnerNode = null");
return board;
}
System.out.println("Winner node found.");
//Board.printBoard(winnerNode.getState().getBoard());
return winnerNode.getState();
}

/**
* Selects the most promising node to explore based on the UCT value.
*
* @param node The node from which to select the promising node.
* @param rootNode The node from which to select the promising node.
* @return The selected promising node.
*/
public Node selectPromisingNode(Node rootNode) {
//System.out.println("selectpromisingnode activated");
//node with the highest amount of playouts is returned
Node node;
node = UCT.findBestNodeWithUCT(rootNode);
return node;
Expand All @@ -124,50 +107,40 @@ public Node selectPromisingNode(Node rootNode) {
private void simulateRandomPlayout(Node currentNode, int playerNo) {
int counter = 0;
while (currentNode.getState().checkStatus() == Board.IN_PROGRESS && System.currentTimeMillis() < end) {
//System.out.println("Debug 1.2");
// Perform a random move and create a new state
Board nextBoardState = currentNode.getState().clone();
nextBoardState.randomPlay(playerNo); // Assuming this method updates the board state

// Create a new node for this state and link it
Node childNode = new Node(playerNo);
childNode.setState(nextBoardState);
// Must synchronize adding child nodes
synchronized (currentNode) {
//Following line prints out boards synchronized so we can see the states
//Board.printSynchronizedBoard(childNode.getState());
currentNode.addChild(childNode);
}
childNode.setNodeDepth(currentNode.getNodeDepth()+1);

// Prepare for the next iteration
currentNode = childNode; // Move the "focus" to the child node for the next iteration
currentNode = childNode;
playerNo = 3 - playerNo; // Toggle Players
counter++;
//System.out.println("Debug: status of current node state - " + childNode.getState().checkStatus());
}
int status = currentNode.getState().checkStatus();
// int result = evaluatePlayoutResult(status);
backPropagation(currentNode, status);
}

/**
* Backpropagates the result of the simulation up the tree, updating the statistics of the nodes.
* Backpropagates the result of the simulation up the nodes, updating the statistics of the nodes.
*
* @param node The node from which to start backpropagation.
* @param status The result of the playout to be backpropagated.
*/
public void backPropagation(Node node, int status) {
//System.out.println("activate back propagation");
final int finalDepth = 0;
while (node != null && node.getNodeDepth() != finalDepth) {
node.incrementVisit();
// Only add score if the playout result corresponds to the node's player winning
if (status == Board.getCurrentPlayer()) {
//System.out.println("node before add score " + node.getScore());
node.addScore(WIN_SCORE);
//System.out.println("Debug: Node WINSCORE");
} else if (status == (3 - (Board.getCurrentPlayer()))) {
//System.out.println("node before minus score " + node.getScore());
node.addScore(-WIN_SCORE);
} else if (status == 0) {
node.addScore(-WIN_SCORE);
Expand All @@ -178,13 +151,7 @@ public void backPropagation(Node node, int status) {

/**
* Expands the given node by creating new child nodes that represent all possible future game states
* arising from the current state. This method leverages parallel processing to concurrently evaluate
* different potential game states and associated moves, enhancing the computational efficiency.
* The expansion considers all possible movements for each queen followed by all potential arrow shots
* for those moves, encapsulating the breadth of possible game progressions from the current state.
*
* Note: The method synchronizes access to the node's children to safely add new child nodes in a
* multithreaded environment, preventing concurrent modification issues.
* arising from the current state.
*
* @param node The node to be expanded, representing the current game state.
* @param playerNo The player number (1 or 2) for whom the expansion is being done.
Expand Down
Loading