"""Base class for draughts engines."""
from abc import ABC, abstractmethod
from typing import Optional
from draughts.boards.base import BaseBoard
from draughts.move import Move
[docs]
class Engine(ABC):
"""
Abstract base class for draughts engines.
Implement this interface to create custom engines compatible with
the :class:`~draughts.Server` for interactive play and testing.
Attributes:
depth_limit: Maximum search depth (if applicable).
time_limit: Maximum time per move in seconds (if applicable).
name: Engine name (defaults to class name).
Example:
>>> from draughts import Engine
>>> import random
>>>
>>> class RandomEngine(Engine):
... def get_best_move(self, board, with_evaluation=False):
... move = random.choice(list(board.legal_moves))
... return (move, 0.0) if with_evaluation else move
"""
depth_limit: Optional[int]
time_limit: Optional[float]
def __init__(
self,
depth_limit: Optional[int] = 6,
time_limit: Optional[float] = None,
name: Optional[str] = None,
):
"""
Initialize the engine.
Args:
depth_limit: Maximum search depth. Interpretation depends on engine.
time_limit: Maximum time in seconds per move.
name: Custom engine name. Defaults to class name.
"""
self.depth_limit = depth_limit
self.time_limit = time_limit
self.name = name or self.__class__.__name__
[docs]
@abstractmethod
def get_best_move(
self, board: BaseBoard, with_evaluation: bool = False
) -> Move | tuple[Move, float]:
"""
Find the best move for the current position.
Args:
board: The current board state.
with_evaluation: If True, return ``(move, score)`` tuple.
Returns:
Best :class:`Move`, or ``(Move, float)`` if ``with_evaluation=True``.
Positive scores favor the current player.
Example:
>>> move = engine.get_best_move(board)
>>> move, score = engine.get_best_move(board, with_evaluation=True)
"""
...