Xiangiqgame
AI engine for Xiangqi
Loading...
Searching...
No Matches
core_dataclass_mirrors.py
Go to the documentation of this file.
1"""
2Contains classes that mirror the structure of some core C++ classes,
3primarily to facilitate easy IO of a GameSummary with msgspec.
4"""
5
6import datetime
7from enum import Enum
8from dataclasses import dataclass
9from typing import Dict, List, TypeAlias
10
11import numpy as np
12import xiangqi_bindings as bindings
13
14
16 """
17 Determines the integer type used for Points int the C++ core, and provides
18 a numpy integer type with the same size and signed-ness.
19 """
20
21 _dtype_map = {
22 (True, 1): np.int8,
23 (True, 2): np.int16,
24 (True, 4): np.int32,
25 (True, 8): np.int64,
26 (False, 1): np.uint8,
27 (False, 2): np.uint16,
28 (False, 4): np.uint32,
29 (False, 8): np.uint64,
30 }
31
32 def get_points_type(self) -> type:
33 dtype_key = (
34 bindings.is_signed_points_type(),
35 bindings.size_of_points_type(),
36 )
37 return self._dtype_map[dtype_key]
38
39
40PointsT: TypeAlias = PointsTypeDeterminer().get_points_type()
41
42
44 """
45 Enum indicating the type of result obtained from Minimax analysis
46 of a single node.
47 """
48
49 Unknown = int(bindings.MinimaxResultType.Unknown)
50 TrTableHit = int(bindings.MinimaxResultType.TrTableHit)
51 EvaluatorLoses = int(bindings.MinimaxResultType.EvaluatorLoses)
52 EvaluatorWins = int(bindings.MinimaxResultType.EvaluatorWins)
53 FullyEvaluatedNode = int(bindings.MinimaxResultType.FullyEvaluatedNode)
54 StandardLeaf = int(bindings.MinimaxResultType.StandardLeaf)
55 AlphaPrune = int(bindings.MinimaxResultType.AlphaPrune)
56 BetaPrune = int(bindings.MinimaxResultType.BetaPrune)
57
58
59@dataclass
61 """
62 A Python GamePiece.
63 """
64
65 piece_color: bindings.PieceColor
66 piece_type: bindings.PieceType
67
68 @classmethod
69 def from_core_game_piece(cls, core_game_piece: bindings.GamePiece):
70 return cls(
71 piece_color=core_game_piece.piece_color,
72 piece_type=core_game_piece.piece_type,
73 )
74
75
76@dataclass
78 """
79 A Python BoardSpace.
80 """
81
82 rank: int
83 file: int
84
85 @classmethod
86 def from_core_board_space(cls, core_board_space: bindings.BoardSpace):
87 return cls(rank=core_board_space.rank, file=core_board_space.file)
88
89
90@dataclass
91class Move:
92 """
93 A Python Move.
94 """
95
96 start: BoardSpace
97 end: BoardSpace
98
99 @classmethod
100 def from_core_move(cls, core_move: bindings.Move):
101 start = BoardSpace.from_core_board_space(core_move.start)
102 end = BoardSpace.from_core_board_space(core_move.end)
103 return cls(start=start, end=end)
104
105
106@dataclass
108 """
109 A Python MoveCollection.
110 """
111
112 moves: List[Move]
113
114 @classmethod
116 cls, core_move_collection: bindings.MoveCollection
117 ):
118 moves = [
119 Move.from_core_move(core_move=core_move)
120 for core_move in core_move_collection.moves
121 ]
122 return cls(moves=moves)
123
124 @property
125 def size(self) -> int:
126 return len(self.moves)
127
128
129@dataclass
131 """
132 A Python EqualScoreMoves.
133 """
134
135 shared_score: PointsT
136 move_collection: MoveCollection
137
138 @classmethod
140 cls, core_equal_score_moves: bindings.EqualScoreMoves
141 ):
142 return cls(
143 shared_score=core_equal_score_moves.shared_score,
144 move_collection=MoveCollection.from_core_move_collection(
145 core_move_collection=core_equal_score_moves.move_collection
146 ),
147 )
148
149
150@dataclass
152 first_illegal_move_request: int | None
153 end_game: int | None
154
155
156@dataclass
158 """
159 A Python ExecutedMove
160 """
161
162 moving_piece: GamePiece
163 destination_piece: GamePiece
164 spaces: Move
165
166 @classmethod
168 cls, core_executed_move: bindings.ExecutedMove
169 ):
170 return cls(
171 moving_piece=GamePiece.from_core_game_piece(
172 core_game_piece=core_executed_move.moving_piece
173 ),
174 destination_piece=GamePiece.from_core_game_piece(
175 core_game_piece=core_executed_move.destination_piece
176 ),
177 spaces=Move.from_core_move(core_move=core_executed_move.spaces),
178 )
179
180
181@dataclass
183 """
184 A Python SearchSummary.
185 """
186
187 num_nodes: int
188 time: datetime.timedelta
189 result_depth_counts: np.ndarray
190 transposition_table_hits: np.ndarray
191 equal_score_moves: EqualScoreMoves
192 selected_move: Move
193 returned_illegal_move: bool
194 num_collisions: int
195 tr_table_size_initial: int
196 tr_table_size_final: int
197
198 @classmethod
200 cls, core_search_summary: bindings.SearchSummary
201 ):
202 return cls(
203 num_nodes=core_search_summary.num_nodes,
204 time=core_search_summary.time,
205 result_depth_counts=np.array(
206 core_search_summary.get_result_depth_counts()
207 ),
208 transposition_table_hits=np.array(
209 core_search_summary.get_transposition_table_hits()
210 ),
211 equal_score_moves=EqualScoreMoves.from_core_equal_score_moves(
212 core_equal_score_moves=core_search_summary.equal_score_moves
213 ),
214 selected_move=Move.from_core_move(
215 core_move=core_search_summary.selected_move
216 ),
217 returned_illegal_move=core_search_summary.returned_illegal_move,
218 num_collisions=core_search_summary.num_collisions,
219 tr_table_size_initial=core_search_summary.tr_table_size_initial,
220 tr_table_size_final=core_search_summary.tr_table_size_final,
221 )
222
223 @property
224 def mean_time_per_node_ns(self) -> float:
225 return 1000000 * self.time.total_seconds() / self.num_nodes
226
227
228@dataclass
230 """
231 A Python SearchSummaries.
232 """
233
234 first_searches: List[SearchSummary]
235 extra_searches: Dict[int, SearchSummary]
236
237 @classmethod
239 cls, core_search_summaries: bindings.SearchSummaries
240 ):
241 return cls(
242 first_searches=[
243 SearchSummary.from_core_search_summary(item)
244 for item in core_search_summaries.first_searches
245 ],
246 extra_searches={
247 key: SearchSummary.from_core_search_summary(val)
248 for key, val in core_search_summaries.extra_searches.items()
249 },
250 )
def from_core_board_space(cls, bindings.BoardSpace core_board_space)
def from_core_equal_score_moves(cls, bindings.EqualScoreMoves core_equal_score_moves)
def from_core_executed_move(cls, bindings.ExecutedMove core_executed_move)
def from_core_game_piece(cls, bindings.GamePiece core_game_piece)
Enum indicating the type of result obtained from Minimax analysis of a single node.
def from_core_move_collection(cls, bindings.MoveCollection core_move_collection)
def from_core_move(cls, bindings.Move core_move)
Determines the integer type used for Points int the C++ core, and provides a numpy integer type with ...
def from_core_search_summaries(cls, bindings.SearchSummaries core_search_summaries)
def from_core_search_summary(cls, bindings.SearchSummary core_search_summary)