From 8fcedbbc8c691639758c6bcde9883b71dae2147b Mon Sep 17 00:00:00 2001 From: Lukas Wieser Date: Mon, 29 Jan 2024 00:56:24 +0100 Subject: [PATCH] Change package /src/chesspp to just /chesspp --- {src => chesspp}/__init__.py | 0 {src/chesspp => chesspp}/baysian_mcts.py | 0 {src/chesspp => chesspp}/classic_mcts.py | 222 +++++++++--------- {src/chesspp => chesspp}/engine.py | 0 {src/chesspp => chesspp}/eval.py | 0 {src/chesspp => chesspp}/i_mcts.py | 0 {src/chesspp => chesspp}/i_strategy.py | 0 {src/chesspp => chesspp}/lichess-engine.py | 0 {src/chesspp => chesspp}/random_strategy.py | 26 +- {src/chesspp => chesspp}/simulation.py | 0 {src/chesspp => chesspp}/static_data/bB.png | Bin {src/chesspp => chesspp}/static_data/bK.png | Bin {src/chesspp => chesspp}/static_data/bN.png | Bin {src/chesspp => chesspp}/static_data/bP.png | Bin {src/chesspp => chesspp}/static_data/bQ.png | Bin {src/chesspp => chesspp}/static_data/bR.png | Bin .../static_data/index.html | 0 {src/chesspp => chesspp}/static_data/wB.png | Bin {src/chesspp => chesspp}/static_data/wK.png | Bin {src/chesspp => chesspp}/static_data/wN.png | Bin {src/chesspp => chesspp}/static_data/wP.png | Bin {src/chesspp => chesspp}/static_data/wQ.png | Bin {src/chesspp => chesspp}/static_data/wR.png | Bin {src/chesspp => chesspp}/util.py | 0 {src/chesspp => chesspp}/util_gaussian.py | 0 {src/chesspp => chesspp}/web.py | 0 src/chesspp/__init__.py | 0 27 files changed, 124 insertions(+), 124 deletions(-) rename {src => chesspp}/__init__.py (100%) rename {src/chesspp => chesspp}/baysian_mcts.py (100%) rename {src/chesspp => chesspp}/classic_mcts.py (97%) rename {src/chesspp => chesspp}/engine.py (100%) rename {src/chesspp => chesspp}/eval.py (100%) rename {src/chesspp => chesspp}/i_mcts.py (100%) rename {src/chesspp => chesspp}/i_strategy.py (100%) rename {src/chesspp => chesspp}/lichess-engine.py (100%) rename {src/chesspp => chesspp}/random_strategy.py (96%) rename {src/chesspp => chesspp}/simulation.py (100%) rename {src/chesspp => chesspp}/static_data/bB.png (100%) rename {src/chesspp => chesspp}/static_data/bK.png (100%) rename {src/chesspp => chesspp}/static_data/bN.png (100%) rename {src/chesspp => chesspp}/static_data/bP.png (100%) rename {src/chesspp => chesspp}/static_data/bQ.png (100%) rename {src/chesspp => chesspp}/static_data/bR.png (100%) rename {src/chesspp => chesspp}/static_data/index.html (100%) rename {src/chesspp => chesspp}/static_data/wB.png (100%) rename {src/chesspp => chesspp}/static_data/wK.png (100%) rename {src/chesspp => chesspp}/static_data/wN.png (100%) rename {src/chesspp => chesspp}/static_data/wP.png (100%) rename {src/chesspp => chesspp}/static_data/wQ.png (100%) rename {src/chesspp => chesspp}/static_data/wR.png (100%) rename {src/chesspp => chesspp}/util.py (100%) rename {src/chesspp => chesspp}/util_gaussian.py (100%) rename {src/chesspp => chesspp}/web.py (100%) delete mode 100644 src/chesspp/__init__.py diff --git a/src/__init__.py b/chesspp/__init__.py similarity index 100% rename from src/__init__.py rename to chesspp/__init__.py diff --git a/src/chesspp/baysian_mcts.py b/chesspp/baysian_mcts.py similarity index 100% rename from src/chesspp/baysian_mcts.py rename to chesspp/baysian_mcts.py diff --git a/src/chesspp/classic_mcts.py b/chesspp/classic_mcts.py similarity index 97% rename from src/chesspp/classic_mcts.py rename to chesspp/classic_mcts.py index 05b4657..46ff5f3 100644 --- a/src/chesspp/classic_mcts.py +++ b/chesspp/classic_mcts.py @@ -1,111 +1,111 @@ -import chess -import random -import numpy as np - - -from chesspp import eval -from chesspp import util - - -class ClassicMcts: - - def __init__(self, board: chess.Board, color: chess.Color, parent=None, move: chess.Move | None = None, - random_state: int | None = None): - self.random = random.Random(random_state) - self.board = board - self.color = color - self.parent = parent - self.move = move - self.children = [] - self.visits = 0 - self.legal_moves = list(board.legal_moves) - self.untried_actions = self.legal_moves - self.score = 0 - - def _expand(self) -> 'ClassicMcts': - """ - Expands the node, i.e., choose an action and apply it to the board - :return: - """ - move = self.random.choice(self.untried_actions) - self.untried_actions.remove(move) - next_board = self.board.copy() - next_board.push(move) - child_node = ClassicMcts(next_board, color=self.color, parent=self, move=move) - self.children.append(child_node) - return child_node - - def _rollout(self, rollout_depth: int = 20) -> int: - """ - Rolls out the node by simulating a game for a given depth. - Sometimes this step is called 'simulation' or 'playout'. - :return: the score of the rolled out game - """ - copied_board = self.board.copy() - steps = 1 - for i in range(rollout_depth): - if copied_board.is_game_over(): - break - - m = util.pick_move(copied_board) - copied_board.push(m) - steps += 1 - - return eval.score_manual(copied_board) // steps - - def _backpropagate(self, score: float) -> None: - """ - Backpropagates the results of the rollout - :param score: - :return: - """ - self.visits += 1 - # TODO: maybe use score + num of moves together (a win in 1 move is better than a win in 20 moves) - self.score += score - if self.parent: - self.parent._backpropagate(score) - - def is_fully_expanded(self) -> bool: - return len(self.untried_actions) == 0 - - def _best_child(self) -> 'ClassicMcts': - """ - Picks the best child according to our policy - :return: the best child - """ - # NOTE: maybe clamp the score between [-1, +1] instead of [-inf, +inf] - choices_weights = [(c.score / c.visits) + np.sqrt(((2 * np.log(self.visits)) / c.visits)) - for c in self.children] - best_child_index = np.argmax(choices_weights) if self.color == chess.WHITE else np.argmin(choices_weights) - return self.children[best_child_index] - - def _select_leaf(self) -> 'ClassicMcts': - """ - Selects a leaf node. - If the node is not expanded is will be expanded. - :return: Leaf node - """ - current_node = self - while not current_node.board.is_game_over(): - if not current_node.is_fully_expanded(): - return current_node._expand() - else: - current_node = current_node._best_child() - - return current_node - - def build_tree(self, samples: int = 1000) -> 'ClassicMcts': - """ - Runs the MCTS with the given number of samples - :param samples: number of simulations - :return: best node containing the best move - """ - for i in range(samples): - # selection & expansion - # rollout - # backpropagate score - node = self._select_leaf() - score = node._rollout() - node._backpropagate(score) - - return self._best_child() +import chess +import random +import numpy as np + + +from chesspp import eval +from chesspp import util + + +class ClassicMcts: + + def __init__(self, board: chess.Board, color: chess.Color, parent=None, move: chess.Move | None = None, + random_state: int | None = None): + self.random = random.Random(random_state) + self.board = board + self.color = color + self.parent = parent + self.move = move + self.children = [] + self.visits = 0 + self.legal_moves = list(board.legal_moves) + self.untried_actions = self.legal_moves + self.score = 0 + + def _expand(self) -> 'ClassicMcts': + """ + Expands the node, i.e., choose an action and apply it to the board + :return: + """ + move = self.random.choice(self.untried_actions) + self.untried_actions.remove(move) + next_board = self.board.copy() + next_board.push(move) + child_node = ClassicMcts(next_board, color=self.color, parent=self, move=move) + self.children.append(child_node) + return child_node + + def _rollout(self, rollout_depth: int = 20) -> int: + """ + Rolls out the node by simulating a game for a given depth. + Sometimes this step is called 'simulation' or 'playout'. + :return: the score of the rolled out game + """ + copied_board = self.board.copy() + steps = 1 + for i in range(rollout_depth): + if copied_board.is_game_over(): + break + + m = util.pick_move(copied_board) + copied_board.push(m) + steps += 1 + + return eval.score_manual(copied_board) // steps + + def _backpropagate(self, score: float) -> None: + """ + Backpropagates the results of the rollout + :param score: + :return: + """ + self.visits += 1 + # TODO: maybe use score + num of moves together (a win in 1 move is better than a win in 20 moves) + self.score += score + if self.parent: + self.parent._backpropagate(score) + + def is_fully_expanded(self) -> bool: + return len(self.untried_actions) == 0 + + def _best_child(self) -> 'ClassicMcts': + """ + Picks the best child according to our policy + :return: the best child + """ + # NOTE: maybe clamp the score between [-1, +1] instead of [-inf, +inf] + choices_weights = [(c.score / c.visits) + np.sqrt(((2 * np.log(self.visits)) / c.visits)) + for c in self.children] + best_child_index = np.argmax(choices_weights) if self.color == chess.WHITE else np.argmin(choices_weights) + return self.children[best_child_index] + + def _select_leaf(self) -> 'ClassicMcts': + """ + Selects a leaf node. + If the node is not expanded is will be expanded. + :return: Leaf node + """ + current_node = self + while not current_node.board.is_game_over(): + if not current_node.is_fully_expanded(): + return current_node._expand() + else: + current_node = current_node._best_child() + + return current_node + + def build_tree(self, samples: int = 1000) -> 'ClassicMcts': + """ + Runs the MCTS with the given number of samples + :param samples: number of simulations + :return: best node containing the best move + """ + for i in range(samples): + # selection & expansion + # rollout + # backpropagate score + node = self._select_leaf() + score = node._rollout() + node._backpropagate(score) + + return self._best_child() diff --git a/src/chesspp/engine.py b/chesspp/engine.py similarity index 100% rename from src/chesspp/engine.py rename to chesspp/engine.py diff --git a/src/chesspp/eval.py b/chesspp/eval.py similarity index 100% rename from src/chesspp/eval.py rename to chesspp/eval.py diff --git a/src/chesspp/i_mcts.py b/chesspp/i_mcts.py similarity index 100% rename from src/chesspp/i_mcts.py rename to chesspp/i_mcts.py diff --git a/src/chesspp/i_strategy.py b/chesspp/i_strategy.py similarity index 100% rename from src/chesspp/i_strategy.py rename to chesspp/i_strategy.py diff --git a/src/chesspp/lichess-engine.py b/chesspp/lichess-engine.py similarity index 100% rename from src/chesspp/lichess-engine.py rename to chesspp/lichess-engine.py diff --git a/src/chesspp/random_strategy.py b/chesspp/random_strategy.py similarity index 96% rename from src/chesspp/random_strategy.py rename to chesspp/random_strategy.py index 6a819a3..09a0988 100644 --- a/src/chesspp/random_strategy.py +++ b/chesspp/random_strategy.py @@ -1,13 +1,13 @@ -import chess -import random -from chesspp.i_strategy import IStrategy - - -class RandomStrategy(IStrategy): - def __init__(self, random_state: random.Random): - self.random_state = random_state - - def pick_next_move(self, board: chess.Board) -> chess.Move | None: - if len(list(board.legal_moves)) == 0: - return None - return self.random_state.choice(list(board.legal_moves)) +import chess +import random +from chesspp.i_strategy import IStrategy + + +class RandomStrategy(IStrategy): + def __init__(self, random_state: random.Random): + self.random_state = random_state + + def pick_next_move(self, board: chess.Board) -> chess.Move | None: + if len(list(board.legal_moves)) == 0: + return None + return self.random_state.choice(list(board.legal_moves)) diff --git a/src/chesspp/simulation.py b/chesspp/simulation.py similarity index 100% rename from src/chesspp/simulation.py rename to chesspp/simulation.py diff --git a/src/chesspp/static_data/bB.png b/chesspp/static_data/bB.png similarity index 100% rename from src/chesspp/static_data/bB.png rename to chesspp/static_data/bB.png diff --git a/src/chesspp/static_data/bK.png b/chesspp/static_data/bK.png similarity index 100% rename from src/chesspp/static_data/bK.png rename to chesspp/static_data/bK.png diff --git a/src/chesspp/static_data/bN.png b/chesspp/static_data/bN.png similarity index 100% rename from src/chesspp/static_data/bN.png rename to chesspp/static_data/bN.png diff --git a/src/chesspp/static_data/bP.png b/chesspp/static_data/bP.png similarity index 100% rename from src/chesspp/static_data/bP.png rename to chesspp/static_data/bP.png diff --git a/src/chesspp/static_data/bQ.png b/chesspp/static_data/bQ.png similarity index 100% rename from src/chesspp/static_data/bQ.png rename to chesspp/static_data/bQ.png diff --git a/src/chesspp/static_data/bR.png b/chesspp/static_data/bR.png similarity index 100% rename from src/chesspp/static_data/bR.png rename to chesspp/static_data/bR.png diff --git a/src/chesspp/static_data/index.html b/chesspp/static_data/index.html similarity index 100% rename from src/chesspp/static_data/index.html rename to chesspp/static_data/index.html diff --git a/src/chesspp/static_data/wB.png b/chesspp/static_data/wB.png similarity index 100% rename from src/chesspp/static_data/wB.png rename to chesspp/static_data/wB.png diff --git a/src/chesspp/static_data/wK.png b/chesspp/static_data/wK.png similarity index 100% rename from src/chesspp/static_data/wK.png rename to chesspp/static_data/wK.png diff --git a/src/chesspp/static_data/wN.png b/chesspp/static_data/wN.png similarity index 100% rename from src/chesspp/static_data/wN.png rename to chesspp/static_data/wN.png diff --git a/src/chesspp/static_data/wP.png b/chesspp/static_data/wP.png similarity index 100% rename from src/chesspp/static_data/wP.png rename to chesspp/static_data/wP.png diff --git a/src/chesspp/static_data/wQ.png b/chesspp/static_data/wQ.png similarity index 100% rename from src/chesspp/static_data/wQ.png rename to chesspp/static_data/wQ.png diff --git a/src/chesspp/static_data/wR.png b/chesspp/static_data/wR.png similarity index 100% rename from src/chesspp/static_data/wR.png rename to chesspp/static_data/wR.png diff --git a/src/chesspp/util.py b/chesspp/util.py similarity index 100% rename from src/chesspp/util.py rename to chesspp/util.py diff --git a/src/chesspp/util_gaussian.py b/chesspp/util_gaussian.py similarity index 100% rename from src/chesspp/util_gaussian.py rename to chesspp/util_gaussian.py diff --git a/src/chesspp/web.py b/chesspp/web.py similarity index 100% rename from src/chesspp/web.py rename to chesspp/web.py diff --git a/src/chesspp/__init__.py b/src/chesspp/__init__.py deleted file mode 100644 index e69de29..0000000