implement limit and fix evaluation
This commit is contained in:
@@ -94,7 +94,7 @@ class BayesMctsEngine(Engine):
|
|||||||
def play(self, board: chess.Board, limit: Limit) -> chess.engine.PlayResult:
|
def play(self, board: chess.Board, limit: Limit) -> chess.engine.PlayResult:
|
||||||
if len(board.move_stack) != 0: # apply previous move to mcts --> reuse previous simulation results
|
if len(board.move_stack) != 0: # apply previous move to mcts --> reuse previous simulation results
|
||||||
self.mcts.apply_move(board.peek())
|
self.mcts.apply_move(board.peek())
|
||||||
self.mcts.sample()
|
limit.run(lambda: self.mcts.sample(1))
|
||||||
# limit.run(lambda: mcts_root.build_tree())
|
# limit.run(lambda: mcts_root.build_tree())
|
||||||
best_move = max(self.mcts.get_moves().items(), key=lambda x: x[1])[0] if board.turn == chess.WHITE else (
|
best_move = max(self.mcts.get_moves().items(), key=lambda x: x[1])[0] if board.turn == chess.WHITE else (
|
||||||
min(self.mcts.get_moves().items(), key=lambda x: x[1])[0])
|
min(self.mcts.get_moves().items(), key=lambda x: x[1])[0])
|
||||||
|
|||||||
@@ -24,9 +24,6 @@ class EvaluationResult:
|
|||||||
def simulate_game(white: Engine, black: Engine, limit: Limit, board: chess.Board) -> chess.pgn.Game:
|
def simulate_game(white: Engine, black: Engine, limit: Limit, board: chess.Board) -> chess.pgn.Game:
|
||||||
is_white_playing = True
|
is_white_playing = True
|
||||||
while not board.is_game_over():
|
while not board.is_game_over():
|
||||||
print("simulation board:\n", board)
|
|
||||||
print()
|
|
||||||
print("mcts board:\n", white.mcts.board)
|
|
||||||
play_result = white.play(board, limit) if is_white_playing else black.play(board, limit)
|
play_result = white.play(board, limit) if is_white_playing else black.play(board, limit)
|
||||||
board.push(play_result.move)
|
board.push(play_result.move)
|
||||||
is_white_playing = not is_white_playing
|
is_white_playing = not is_white_playing
|
||||||
@@ -38,26 +35,31 @@ def simulate_game(white: Engine, black: Engine, limit: Limit, board: chess.Board
|
|||||||
|
|
||||||
|
|
||||||
class Evaluation:
|
class Evaluation:
|
||||||
def __init__(self, engine_a: Engine.__class__, engine_b: Engine.__class__, limit: Limit):
|
def __init__(self, engine_a: Engine.__class__, strategy_a, engine_b: Engine.__class__, strategy_b, limit: Limit):
|
||||||
self.engine_a = engine_a
|
self.engine_a = engine_a
|
||||||
|
self.strategy_a = strategy_a
|
||||||
self.engine_b = engine_b
|
self.engine_b = engine_b
|
||||||
|
self.strategy_b = strategy_b
|
||||||
self.limit = limit
|
self.limit = limit
|
||||||
|
|
||||||
def run(self, n_games=100) -> List[EvaluationResult]:
|
def run(self, n_games=100) -> List[EvaluationResult]:
|
||||||
with mp.Pool(mp.cpu_count()) as pool:
|
with mp.Pool(mp.cpu_count()) as pool:
|
||||||
args = [(self.engine_a, self.engine_b, self.limit) for i in range(n_games)]
|
args = [(self.engine_a, self.strategy_a, self.engine_b, self.strategy_b, self.limit) for i in range(n_games)]
|
||||||
return pool.map(Evaluation._test_simulate, args)
|
return pool.map(Evaluation._test_simulate, args)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _test_simulate(arg: Tuple[Engine.__class__, Engine.__class__, Limit]) -> EvaluationResult:
|
def _test_simulate(arg: Tuple[Engine.__class__, Engine.__class__, Limit]) -> EvaluationResult:
|
||||||
engine_a, engine_b, limit = arg
|
engine_a, strategy_a, engine_b, strategy_b, limit = arg
|
||||||
flip_engines = bool(random.getrandbits(1))
|
flip_engines = bool(random.getrandbits(1))
|
||||||
if flip_engines:
|
|
||||||
black, white = engine_a(chess.BLACK), engine_b(chess.WHITE)
|
|
||||||
else:
|
|
||||||
white, black = engine_a(chess.WHITE), engine_b(chess.BLACK)
|
|
||||||
|
|
||||||
game = simulate_game(white, black, limit)
|
board = chess.Board()
|
||||||
|
|
||||||
|
if flip_engines:
|
||||||
|
black, white = engine_a(board.copy(), chess.BLACK, strategy_a), engine_b(board.copy(), chess.WHITE, strategy_b)
|
||||||
|
else:
|
||||||
|
white, black = engine_a(board.copy(), chess.WHITE, strategy_a), engine_b(board.copy(), chess.BLACK, strategy_b)
|
||||||
|
|
||||||
|
game = simulate_game(white, black, limit, board)
|
||||||
winner = game.end().board().outcome().winner
|
winner = game.end().board().outcome().winner
|
||||||
|
|
||||||
result = Winner.Draw
|
result = Winner.Draw
|
||||||
|
|||||||
@@ -1,14 +1,25 @@
|
|||||||
|
import os
|
||||||
import chess
|
import chess
|
||||||
from chesspp.i_strategy import IStrategy
|
from chesspp.i_strategy import IStrategy
|
||||||
import chess.engine
|
import chess.engine
|
||||||
|
|
||||||
|
_DIR = os.path.abspath(os.path.dirname(__file__))
|
||||||
|
|
||||||
class StockFishStrategy(IStrategy):
|
class StockFishStrategy(IStrategy):
|
||||||
stockfish: chess.engine.SimpleEngine
|
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.stockfish = chess.engine.SimpleEngine.popen_uci(
|
self._stockfish = None
|
||||||
"/home/luke/projects/pp-project/chess-engine-pp/stockfish/stockfish-ubuntu-x86-64-avx2")
|
|
||||||
|
@property
|
||||||
|
def stockfish(self) -> chess.engine.SimpleEngine:
|
||||||
|
if self._stockfish is None:
|
||||||
|
self._stockfish = self.stockfish = chess.engine.SimpleEngine.popen_uci(
|
||||||
|
os.path.join(_DIR, "../stockfish/stockfish-ubuntu-x86-64-avx2"))
|
||||||
|
return self._stockfish
|
||||||
|
|
||||||
|
@stockfish.setter
|
||||||
|
def stockfish(self, stockfish):
|
||||||
|
self._stockfish = stockfish
|
||||||
|
|
||||||
def pick_next_move(self, board: chess.Board) -> chess.Move | None:
|
def pick_next_move(self, board: chess.Board) -> chess.Move | None:
|
||||||
move = self.stockfish.play(board, chess.engine.Limit(depth=4)).move
|
move = self.stockfish.play(board, chess.engine.Limit(depth=4)).move
|
||||||
|
|||||||
@@ -75,8 +75,8 @@ class WebInterface:
|
|||||||
|
|
||||||
async def turns():
|
async def turns():
|
||||||
""" Simulates the game and sends the response to the client """
|
""" Simulates the game and sends the response to the client """
|
||||||
runner = Simulate(self.white(chess.Board(), chess.WHITE, RandomStrategy(random.Random())), self.black(
|
runner = Simulate(self.white(chess.Board(), chess.WHITE, StockFishStrategy()), self.black(
|
||||||
chess.Board(), chess.BLACK, RandomStrategy(random.Random()))).run(limit)
|
chess.Board(), chess.BLACK, StockFishStrategy())).run(self.limit)
|
||||||
def sim():
|
def sim():
|
||||||
return next(runner, None)
|
return next(runner, None)
|
||||||
|
|
||||||
@@ -103,6 +103,6 @@ class WebInterface:
|
|||||||
])
|
])
|
||||||
web.run_app(app)
|
web.run_app(app)
|
||||||
|
|
||||||
if __name__ == '__main__':
|
def run_sample():
|
||||||
limit = engine.Limit(time=0.5)
|
limit = engine.Limit(time=0.5)
|
||||||
WebInterface(engine.BayesMctsEngine, engine.ClassicMctsEngine, limit).run_app()
|
WebInterface(engine.BayesMctsEngine, engine.ClassicMctsEngine, limit).run_app()
|
||||||
|
|||||||
12
main.py
12
main.py
@@ -80,11 +80,11 @@ def analyze_results(moves: dict):
|
|||||||
|
|
||||||
|
|
||||||
def test_evaluation():
|
def test_evaluation():
|
||||||
a = engine.ClassicMctsEngine
|
a = engine.BayesMctsEngine
|
||||||
b = engine.RandomEngine
|
b = engine.ClassicMctsEngine
|
||||||
limit = engine.Limit(time=0.5)
|
limit = engine.Limit(time=0.5)
|
||||||
evaluator = simulation.Evaluation(a, b, limit)
|
evaluator = simulation.Evaluation(a, StockFishStrategy(), b, RandomStrategy(random.Random()), limit)
|
||||||
results = evaluator.run(1)
|
results = evaluator.run(2)
|
||||||
a_results = len(list(filter(lambda x: x.winner == simulation.Winner.Engine_A, results))) / len(results) * 100
|
a_results = len(list(filter(lambda x: x.winner == simulation.Winner.Engine_A, results))) / len(results) * 100
|
||||||
b_results = len(list(filter(lambda x: x.winner == simulation.Winner.Engine_B, results))) / len(results) * 100
|
b_results = len(list(filter(lambda x: x.winner == simulation.Winner.Engine_B, results))) / len(results) * 100
|
||||||
draws = len(list(filter(lambda x: x.winner == simulation.Winner.Draw, results))) / len(results) * 100
|
draws = len(list(filter(lambda x: x.winner == simulation.Winner.Draw, results))) / len(results) * 100
|
||||||
@@ -95,8 +95,8 @@ def test_evaluation():
|
|||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
# test_evaluation()
|
test_evaluation()
|
||||||
test_simulate()
|
#test_simulate()
|
||||||
# test_mcts()
|
# test_mcts()
|
||||||
# test_stockfish()
|
# test_stockfish()
|
||||||
# test_stockfish_prob()
|
# test_stockfish_prob()
|
||||||
|
|||||||
Reference in New Issue
Block a user