Files
chess/scripts/evaluation.py
Josh 4fc982eac2
All checks were successful
Python tests (make) / test (push) Successful in 11s
Add some basic algorithms and eval functions for an AI
2025-08-23 13:10:05 -04:00

62 lines
1.7 KiB
Python

import random
import ctypes as C
from binding.python_c_ffi import ChessFFI
from binding.python_c_ffi import Move
class BaseEvaluation:
def __init__(self, chess_ffi=None):
if chess_ffi is None:
chess_ffi = ChessFFI()
self.chess_ffi = chess_ffi
def get_best_move(self, board, legal_moves):
pass
"""
We will use a random move evaluation as our base AI. This
is expected to be the worst performing strategy. We can
play our other AI evaluation methods against this one to
confirm if our other strategies are at least better than
a simplistic approach.
"""
class RandomEval(BaseEvaluation):
def __init__(self, chess_ffi=None):
super().__init__(chess_ffi)
def get_best_move(self, board, legal_moves):
return random.choice(legal_moves)
class NegaMaxEval(BaseEvaluation):
def __init__(self, depth=6, cp_window=20, chess_ffi=None):
super().__init__(chess_ffi)
self.depth = depth
self.window = cp_window
def _same(self, a, b):
return (int(getattr(a, "from")) == int(getattr(b, "from"))
and int(a.to) == int(b.to)
and int(getattr(a, "promo", 0) or 0) == int(getattr(b, "promo", 0) or 0))
def get_best_move(self, board, legal_moves):
if not legal_moves:
raise RuntimeError("No legal moves")
best = Move()
ok = self.chess_ffi._c_ai_find_best_move_with_window(
board,
self.depth,
self.window,
best
)
if ok:
for m in legal_moves:
if self._same(m, best):
return m
return legal_moves[0]