chmengine.engines.cmhmey3¶
Cmhmey the 3rd!! Son of Cmhmey Jr. (mother unknown, rumor is this might be a Canaan situation)
Classes
|
A time-limited, single-process chess engine that extends CMHMEngine2 with per-move caching and iterative deepening on the current best move. |
- class chmengine.engines.cmhmey3.CMHMEngine3(board: Optional[Board] = None, depth: int = 1, time_limit: float64 = inf, overhead: float64 = 0.0)¶
Bases:
CMHMEngine2
A time-limited, single-process chess engine that extends CMHMEngine2 with per-move caching and iterative deepening on the current best move.
Warning
- The default time_limit is positive infinity—by default the engine will search
until you manually stop it.
- Even if you interrupt the process (for example via KeyboardInterrupt) before
pick_move returns, all the Q-table updates performed up to that point remain committed. That ongoing learning can improve future lookups.
- To avoid unbounded CPU use, supply an explicit finite time_limit either when
constructing the engine or in each pick_move call.
Notes
- Builds a snapshot for each legal root move and attaches a Pick(move, score)
seeded from the Q-table or static eval.
- Iteratively deepens along the current best move’s branch until the time_limit
expires, restarting from root whenever a different move becomes best.
Backs up improved scores into the Q-table after each deeper evaluation.
- property board: Board¶
Get the current chess board.
- Returns:
- chess.Board
The current board state.
Examples
>>> from chmengine import CMHMEngine >>> engine = CMHMEngine() >>> engine.board Board('rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1')
- board_copy_pushed(move: Move, board: Optional[Board] = None) Board ¶
Return a copy of the board with the given move applied.
- Parameters:
- movechess.Move
The move to push onto the board.
- boardOptional[chess.Board], optional
The board to copy; if None, uses the engine’s current board.
- Returns:
- chess.Board
A new board instance with the move applied.
Examples
>>> from chmengine import CMHMEngine >>> from chess import Move >>> engine = CMHMEngine() >>> new_board = engine.board_copy_pushed(Move.from_uci('e2e4')) >>> new_board Board('rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq - 0 1')
- cache_dir: str = '.\\SQLite3Caches\\QTables'¶
- current_moves_list(board: Optional[Board] = None) List[Move] ¶
Retrieve the list of legal moves for the current board position.
- Parameters:
- boardOptional[chess.Board], default: None
The board for which to get legal moves. If None, the engine’s current board is used.
- Returns:
- List[chess.Move]
A list of legal moves available on the board.
Examples
>>> from chmengine import CMHMEngine >>> engine = CMHMEngine() >>> moves = engine.current_moves_list() >>> moves[15] Move.from_uci('e2e4')
- current_picks_list(board: Optional[Board] = None) List[Pick] ¶
Retrieve the list of legal null-scored picks for the current board position.
- Parameters:
- boardOptional[chess.Board], default: None
The board for which to get legal moves. If None, the engine’s current board is used.
- Returns:
- List[Pick]
A list of null-scored picks available on the board.
- current_player_heatmap_index(board: Optional[Board] = None) int ¶
Get the heatmap index corresponding to the active (current) player.
- Parameters:
- boardOptional[chess.Board]
- Returns:
- int
The index for the current player. Typically, if the current turn is White (index 0), this returns 0, and vice versa.
Examples
>>> from chmengine import CMHMEngine >>> engine = CMHMEngine() >>> engine.current_player_heatmap_index() 0
- property depth: int¶
Get the current recursion depth setting.
- Returns:
- int
The current recursion depth used for heatmap calculations.
Examples
>>> from chmengine import CMHMEngine >>> engine = CMHMEngine() >>> engine.depth 1
- fen(board: Optional[Board] = None) str ¶
Obtain the FEN string for a given board state. If no board is provided, the engine’s current board is used.
- Parameters:
- boardOptional[Board]
The board for which to retrieve the FEN string.
- Returns:
- str
The FEN string representing the board state.
Examples
>>> from chmengine import CMHMEngine2 >>> engine = CMHMEngine2() >>> engine.fen() 'rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1'
- get_king_boxes(board: Optional[Board] = None) Tuple[List[int], List[int]] ¶
Compute the bounding boxes for the kings on the board.
For both the current and opponent kings, this method calculates a “box” (a list of square indices) representing the king’s immediate surroundings.
- Parameters:
- boardOptional[chess.Board], default: None
The board to use; if None, the engine’s current board is used.
- Returns:
- Tuple[List[int], List[int]]
A tuple containing two lists: the first is the box for the current king, and the second is the box for the opponent king.
- get_or_calc_deeper_score(board: Board) float64 ¶
- Parameters:
- boardBoard
- Returns:
- float64
- get_or_calc_move_maps(depth: Optional[int] = None) Dict[Move, GradientHeatmap] ¶
Compute or retrieve precomputed heatmaps for all legal moves from the current board.
For each legal move from the current board, this method generates a corresponding heatmap by applying the move and evaluating the resulting position with a given recursion depth.
- Parameters:
- depthOptional[int], default: None
The recursion depth for the heatmap calculation. If None, the engine’s current depth is used.
- Returns:
- Dict[Move, GradientHeatmap]
A dictionary mapping each legal move to its corresponding heatmap.
- Raises:
- ValueError
If the current board has no legal moves.
Examples
>>> from chmengine import CMHMEngine >>> engine = CMHMEngine() >>> move_maps = engine.get_or_calc_move_maps() >>> some_move = list(move_maps.keys())[0] >>> type(move_maps[some_move]) <class 'heatmaps.ChessMoveHeatmap'>
- get_or_calc_move_maps_list() List[Tuple[Move, GradientHeatmap]] ¶
Retrieve a list of move-to-heatmap mappings.
This method converts the dictionary returned by get_or_calc_move_maps() into a list of tuples for easier iteration, where each tuple contains a move and its corresponding heatmap.
- Returns:
- List[Tuple[Move, GradientHeatmap]]
A list of (move, heatmap) tuples.
Examples
>>> from chmengine import CMHMEngine >>> engine = CMHMEngine() >>> first_move = engine.get_or_calc_move_maps_list()[0][0] >>> first_move Move.from_uci('g1h3')
- get_or_calc_score(board: Board) float64 ¶
Retrieve a Q-table score for board, or compute & cache a static eval if missing.
This ensures every position’s score is seeded in the Q-table before any search deeper into it.
- Parameters:
- boardBoard
The position for which to fetch or compute a score.
- Returns:
- float64
The stored or newly calculated evaluation (positive = White-good).
- get_q_value(fen: Optional[str] = None, board: Optional[Board] = None, pieces_count: Optional[int] = None) Optional[float64] ¶
Retrieve a cached Q‑value for a position, or None if uncached.
- Parameters:
- fenstr, optional
FEN of the position (deprecated; use board).
- boardchess.Board, optional
Board object for filename lookup.
- pieces_countint, optional
Override piece count for selecting DB file.
- Returns:
- float64 or None
Stored Q‑value, or None if no entry exists.
Examples
>>> from chmengine import CMHMEngine2 >>> engine = CMHMEngine2() >>> q = engine.get_q_value()
- static heatmap_data_is_zeros(heatmap: GradientHeatmap) bool ¶
Check if the heatmap data is entirely zero.
- Parameters:
- heatmapheatmaps.GradientHeatmap
The heatmap object to check.
- Returns:
- bool
True if all values in the heatmap data are zero; otherwise, False.
Examples
>>> from chmengine import CMHMEngine >>> from heatmaps import GradientHeatmap >>> hmap = GradientHeatmap() >>> CMHMEngine.heatmap_data_is_zeros(hmap) True >>> hmap[32][1] = 1.0 >>> CMHMEngine.heatmap_data_is_zeros(hmap) False
- other_player_heatmap_index(board: Optional[Board] = None) int ¶
Get the heatmap index corresponding to the inactive (other) player.
- Returns:
- int
The index for the other player. Typically, if the current turn is White (index 0), this returns 1, and vice versa.
Examples
>>> from chmengine import CMHMEngine >>> engine = CMHMEngine() >>> engine.other_player_heatmap_index() 1
- overhead: float64 = 0.0¶
- pick_board_generator(board: Optional[Board] = None) Iterator[Tuple[Pick, Board]] ¶
Lazily generate (Pick, Board) pairs for each legal move from board.
For each legal move: 1) Snapshot the board after the move. 2) Create Pick(move, score) where score is pulled from the Q-table
or computed on demand via get_or_calc_score.
This generator is the entry point for building the per-move cache in pick_move.
- Parameters:
- boardUnion[Board, None]
The position to branch from; defaults to this engine’s internal board.
- Returns:
- Iterator[Tuple[Pick, Board]]
An iterator over each legal move’s Pick and the resulting Board.
- pick_move(*args, board: Optional[Board] = None, time_limit: Optional[float] = None, debug: bool = False, **kwargs) Pick ¶
Choose the best move using iterative deepening on the current best branch.
If no finite time_limit is provided (and the class’s time_limit remains infinite), this will search until manually interrupted.
Otherwise, it: 1) Takes a snapshot board (defaulting to self.board or the provided board). 2) Generates all legal moves and creates a list of (Pick, Board) pairs,
with Pick.score seeded from the Q-table or a static heatmap eval.
Sorts that list to find the best and second-best scores.
- While time remains (< deadline), calls _search_current_best_ on the top entry.
If the second-best score ever exceeds the updated best, it re-roots by resorting to the full move list.
- At timeout (or if only one move), returns the Pick with the best score
and writes that score back into the Q-table for the root position.
- Parameters:
- *args, **kwargspassed through to super().pick_move for fallback
- boardOptional[Board]
Position to analyze; defaults to this engine’s internal board.
- time_limitOptional[float]
If set, overrides the engine’s time_limit for this call.
- debugbool
If True, enables verbose timing and score-change logs.
- Returns:
- Pick
The chosen move and its evaluation score, from the root’s perspective.
Warning
Without a finite time_limit, pick_move will continue indefinitely.
- You can safely cancel an infinite search at any moment; any Q-table writes
already performed will persist and benefit later searches.
- pieces_count(board: Optional[Board] = None) int ¶
Return the number of pieces on the board in O(1) time.
This uses Board.occupied.bit_count() when given a board.
- Parameters:
- boardchess.Board, optional
Board whose pieces to count. Preferred parameter.
- Returns:
- int
Total number of pieces on the board.
Examples
>>> from chmengine.engines.cmhmey2 import CMHMEngine2 >>> engine = CMHMEngine2() >>> engine.pieces_count() 32
- qdb_path(board: Optional[Board] = None, pieces_count: Optional[Union[int, str]] = None) str ¶
Get the full path to the Q‑table database file.
- Parameters:
- boardchess.Board, optional
Board object for file naming.
- pieces_countint or str, optional
Explicit piece count override.
- Returns:
- str
Relative path: <cache_dir>/<qtable_filename(…)>
Examples
>>> import os >>> from chmengine.engines.cmhmey2 import CMHMEngine2 >>> engine = CMHMEngine2() >>> engine.qdb_path() == os.path.join(engine.cache_dir, engine.qtable_filename()) True
- qtable_filename(board: Optional[Board] = None, pieces_count: Optional[Union[int, str]] = None) str ¶
Build the Q‑table filename based on depth and piece count.
- Parameters:
- boardchess.Board, optional
Board object to derive FEN (and piece count) if fen is not given.
- pieces_countint or str, optional
Explicit piece count to use. If provided, skips recomputing from board/FEN.
- Returns:
- str
File name of the form “qtable_depth_{depth}_piece_count_{pieces_count}.db”.
Examples
>>> import os >>> from chmengine.engines.cmhmey2 import CMHMEngine2 >>> engine = CMHMEngine2() >>> engine.qtable_filename() in os.listdir(path=engine.cache_dir) True
- set_q_value(value: float, fen: Optional[str] = None, board: Optional[Board] = None, pieces_count: Optional[int] = None) None ¶
Insert or update the Q‑value for a given position in the DB.
- Parameters:
- valuefloat
Q‑value to store.
- fenstr, optional
Position FEN (deprecated; prefer board).
- boardchess.Board, optional
Board object for filename lookup.
- pieces_countint, optional
Override piece count for selecting DB file.
Examples
>>> from chmengine import CMHMEngine2 >>> engine = CMHMEngine2() >>> engine.set_q_value(0.0, '1k6/8/8/8/8/3K4/8/8 w - - 0 1')
- time_limit: float64 = inf¶
- update_q_values(debug: bool = False) None ¶
Back-propagate game outcome through the Q-table.
Pops all moves from the current board history and adjusts each stored Q-value in the database based on the final result (win/lose/draw).
- Parameters:
- debugbool, default=False
If True, print diagnostics for each back-step.
Notes
Updates the SQLite Q-table entries for every move in the game.
Examples
>>> from io import StringIO >>> from chess import pgn >>> from chmengine import CMHMEngine2 >>> pgn_buffer = StringIO( ... ''' ... 1. f3 e5 2. g4 Qh4# 0-1 ... ... ... ''' ... ) >>> game = pgn.read_game(pgn_buffer) >>> board = game.board() >>> for move in game.mainline_moves(): ... board.push(move) >>> engine = CMHMEngine2(board=board) >>> engine.fen() 'rnb1kbnr/pppp1ppp/8/4p3/6Pq/5P2/PPPPP2P/RNBQKBNR w KQkq - 1 3' >>> engine.update_q_values() >>> engine.fen() 'rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1'
- static update_target_moves_by_delta(target_moves_by_delta: List[Union[Tuple[None, None], Pick]], current_player_sum: float64, other_player_sum: float64, move: Move) List[Pick] ¶
Update the candidate moves based on the delta between current and other player’s sums.
The delta is computed as the difference between the current player’s sum and the other player’s sum. If the calculated delta is greater than the current best, the candidate list is replaced; if equal, the move is appended.
- Parameters:
- target_moves_by_deltaList[Union[Tuple[None, None], Pick]]
The current list of candidate moves and their delta scores.
- current_player_sumnumpy.float64
The sum of move intensities for the current player.
- other_player_sumnumpy.float64
The sum of move intensities for the other player.
- movechess.Move
The move being evaluated.
- Returns:
- List[Pick]
The updated list of candidate moves with their delta scores.
- static update_target_moves_by_king_delta(target_moves_by_king_delta: List[Union[Tuple[None, None], Pick]], move: Move, current_king_min: float64, other_king_sum: float64) List[Pick] ¶
Update candidate moves based on the king’s delta value.
Calculates the delta between the opponent’s king intensity and the current king’s minimum intensity, updating the candidate list if this delta is greater than the current best.
- Parameters:
- target_moves_by_king_deltaList[Union[Tuple[None, None], Pick]]
The current candidate moves for the king delta criterion.
- movechess.Move
The move being evaluated.
- current_king_minnumpy.float64
The minimum intensity value for the current king.
- other_king_sumnumpy.float64
The total intensity value for the opponent’s king.
- Returns:
- List[Pick]
The updated list of candidate moves based on king delta.
- static update_target_moves_by_max_current(target_moves_by_max_current: List[Union[Tuple[None, None], Pick]], transposed_map: ndarray, move: Move, color_index: int) Tuple[float64, List[Pick]] ¶
Update the candidate moves for maximizing the current player’s intensity.
Computes the current player’s total intensity from the transposed heatmap and updates the candidate list if the new sum is greater than the current best.
- Parameters:
- target_moves_by_max_currentList[Union[Tuple[None, None], Pick]]
The current candidate moves for maximizing the current player’s intensity.
- transposed_mapnumpy.ndarray
The transposed heatmap data array.
- movechess.Move
The move being evaluated.
- color_indexint
The index corresponding to the current player.
- Returns:
- Tuple[float64, List[Pick]]
A tuple containing the current player’s sum and the updated candidate list.
- static update_target_moves_by_max_other_king(target_moves_by_max_other_king: List[Union[Tuple[None, None], Pick]], heatmap: GradientHeatmap, move: Move, color_index: int, other_king_box: List[int]) Tuple[float64, List[Pick]] ¶
Update candidate moves for maximizing the opponent king’s intensity.
Calculates the opponent king’s total intensity from the heatmap over the specified area and updates the candidate list if a higher intensity sum is found.
- Parameters:
- target_moves_by_max_other_kingList[Union[Tuple[None, None], Pick]]
The candidate moves list for maximizing opponent king’s intensity.
- heatmapheatmaps.GradientHeatmap
The heatmap object containing move intensities.
- movechess.Move
The move being evaluated.
- color_indexint
The index corresponding to the opponent.
- other_king_boxList[int]
A list of board squares representing the area around the opponent’s king.
- Returns:
- Tuple[float64, List[Pick]]
A tuple containing the opponent king’s sum and the updated candidate list.
- static update_target_moves_by_min_current_king(target_moves_by_min_current_king: List[Union[Tuple[None, None], Pick]], heatmap: GradientHeatmap, move: Move, other_index: int, current_king_box: List[int]) Tuple[float64, List[Pick]] ¶
Update candidate moves for minimizing the current king’s intensity.
Extracts the intensity values for the current king from the heatmap and updates the candidate list if a lower intensity sum is found.
- Parameters:
- target_moves_by_min_current_kingList[Union[Tuple[None, None], Pick]]
The candidate moves list for minimizing current king’s intensity.
- heatmapheatmaps.GradientHeatmap
The heatmap object containing move intensities.
- movechess.Move
The move being evaluated.
- other_indexint
The index corresponding to the opponent.
- current_king_boxList[int]
A list of board squares representing the area around the current king.
- Returns:
- Tuple[float64, List[Pick]]
A tuple containing the current king’s sum and the updated candidate list.
- static update_target_moves_by_min_other(target_moves_by_min_other: List[Union[Tuple[None, None], Pick]], transposed_map: ndarray, move: Move, other_index: int) Tuple[float64, List[Pick]] ¶
Update the candidate moves for minimizing the opponent’s sum.
Calculates the opponent’s total move intensity from the transposed heatmap, and updates the candidate list if the new sum is lower than the current best.
- Parameters:
- target_moves_by_min_otherList[Union[Tuple[None, None], Pick]]
The current candidate moves for minimizing the opponent’s intensity.
- transposed_mapnumpy.ndarray
The transposed heatmap data array.
- movechess.Move
The move being evaluated.
- other_indexint
The index corresponding to the opponent.
- Returns:
- Tuple[float64, List[Pick]]
A tuple containing the opponent’s sum and the updated candidate list.