1
1
import json
2
- from typing import Any , Dict , NoReturn
2
+ from typing import Any , Tuple , List , Dict , NoReturn
3
3
4
4
from program import PROGRAM_NAME , VERSION , PROTOCOL_VERSION
5
- from board .go_board import GoBoard
5
+ from board .go_board import GoBoard , copy_board
6
6
from board .coordinate import Coordinate
7
7
from board .stone import Stone
8
8
from mcts .constant import NOT_EXPANDED
@@ -19,10 +19,12 @@ def dump_mcts_to_json(tree_dict: Dict[str, Any], board: GoBoard, superko: bool)
19
19
str: MCTSの状態を表すJSON文字列。
20
20
"""
21
21
state = {
22
- "dump_version" : 1 ,
22
+ "dump_version" : 2 ,
23
23
"tree" : tree_dict ,
24
24
"board_size" : board .get_board_size (),
25
25
"komi" : board .get_komi (),
26
+ "move_history" : _serializable_move_history (board .get_move_history ()),
27
+ "handicap_history" : board .get_handicap_history (),
26
28
"superko" : superko ,
27
29
"name" : PROGRAM_NAME ,
28
30
"version" : VERSION ,
@@ -36,7 +38,12 @@ def enrich_mcts_dict(state: Dict[str, Any]) -> NoReturn:
36
38
Args:
37
39
state (Dict[str, Any]): MCTSの状態を表す辞書。
38
40
"""
39
- coord = Coordinate (board_size = state ["board_size" ])
41
+ root_board = GoBoard (board_size = state ["board_size" ], komi = state ["komi" ], \
42
+ check_superko = state ["superko" ])
43
+ root_board .set_history (_recovered_move_history (state ["move_history" ]), \
44
+ state ["handicap_history" ])
45
+
46
+ coord = Coordinate (board_size = root_board .get_board_size ())
40
47
tree = state ["tree" ]
41
48
node = tree ["node" ]
42
49
@@ -73,24 +80,31 @@ def enrich_mcts_dict(state: Dict[str, Any]) -> NoReturn:
73
80
nodes_pool += expanded_children
74
81
75
82
# その他いろいろな便利項目を追加
83
+ initial_move_color = _str_to_stone (tree ["to_move" ])
76
84
for item in node :
77
85
is_root = "parent_index" not in item
78
86
if is_root :
79
87
item ["level" ] = 0
80
88
item ["orders_along_path" ] = []
89
+ item ["gtp_moves_along_path" ] = []
81
90
item ["to_move" ] = tree ["to_move" ]
91
+ item ["board_string" ] = root_board .get_board_string ()
82
92
continue
83
93
parent = node [item ["parent_index" ]]
94
+ index_in_brother = item ["index_in_brother" ]
95
+ gtp_move = coord .convert_to_gtp_format (parent ["action" ][index_in_brother ])
84
96
item ["level" ] = parent ["level" ] + 1
85
97
item ["orders_along_path" ] = [* parent ["orders_along_path" ], item ["order" ]]
86
98
item ["to_move" ] = _opposite_color (parent ["to_move" ])
99
+ item ["gtp_moves_along_path" ] = [* parent ["gtp_moves_along_path" ], gtp_move ]
100
+ item ["board_string" ] = _get_updated_board_string (root_board , initial_move_color , \
101
+ item ["gtp_moves_along_path" ])
87
102
# ルートノードは以下の項目を持たないことに注意
88
- index_in_brother = item ["index_in_brother" ]
89
103
item ["policy" ] = parent ["children_policy" ][index_in_brother ]
90
104
item ["visits" ] = parent ["children_visits" ][index_in_brother ]
91
105
item ["value" ] = parent ["children_value" ][index_in_brother ]
92
106
item ["value_sum" ] = parent ["children_value_sum" ][index_in_brother ]
93
- item ["gtp_move" ] = coord . convert_to_gtp_format ( parent [ "action" ][ index_in_brother ])
107
+ item ["gtp_move" ] = gtp_move
94
108
item ["mean_value" ] = item ["value_sum" ] / item ["visits" ]
95
109
last_move_color = _opposite_color (item ["to_move" ])
96
110
item ["raw_black_winrate" ] = _black_winrate (item ["value" ], last_move_color )
@@ -101,3 +115,54 @@ def _opposite_color(color):
101
115
102
116
def _black_winrate (value , last_move_color ):
103
117
return value if last_move_color == "black" else 1.0 - value
118
+
119
+ def _serializable_move_history (move_history : List [Tuple [Stone , int , Any ]]) -> List [Tuple [str , int ]]:
120
+ """着手の履歴をシリアライズ可能な値に変換する。ただしハッシュ値は廃棄する。
121
+
122
+ Args:
123
+ move_history (List[Tuple[Stone, int, np.array]]): 着手の履歴。
124
+
125
+ Returns:
126
+ Lizt[Tuple[str, int]]: シリアライズ可能なよう変換された着手履歴。
127
+ """
128
+ return [(_stone_to_str (color ), pos ) for (color , pos , _ ) in move_history ]
129
+
130
+ def _recovered_move_history (converted_move_history : List [Tuple [str , int ]]) -> List [Tuple [Stone , int , Any ]]:
131
+ """_serializable_move_historyで変換された着手履歴から元の着手履歴を復元する。
132
+ ただしハッシュ値はNoneに置きかえられる。
133
+
134
+ Args:
135
+ converted_move_history (Lizt[Tuple[str, int]]): 変換された着手履歴。
136
+
137
+ Returns:
138
+ List[Tuple[Stone, int, Any]]: 復元された着手履歴。
139
+ """
140
+ return [(_str_to_stone (color_str ), pos , None ) for (color_str , pos ) in converted_move_history ]
141
+
142
+ def _stone_to_str (color : Stone ) -> str :
143
+ return 'black' if color == Stone .BLACK else 'white'
144
+
145
+ def _str_to_stone (color_str : str ) -> str :
146
+ return Stone .BLACK if color_str == 'black' else Stone .WHITE
147
+
148
+ def _get_updated_board_string (root_board : GoBoard , initial_move_color : Stone , gtp_moves_along_path : List [str ]) -> str :
149
+ """一連の着手後の盤面を表わす文字列を返す。
150
+
151
+ Args:
152
+ root_board (GoBoard): 着手前の盤面。
153
+ initial_move_color (Stone): 最初の着手の色。
154
+ gtp_moves_along_path (List[str]): 着手位置のリスト。
155
+
156
+ Returns:
157
+ str: 着手後の盤面を表わす文字列。
158
+ """
159
+ coord = Coordinate (board_size = root_board .get_board_size ())
160
+ move_color = initial_move_color
161
+ # 「board = copy.deepcopy(root_board)」は遅いので避ける。
162
+ board = GoBoard (board_size = root_board .get_board_size (), komi = root_board .get_komi (), check_superko = root_board .check_superko )
163
+ copy_board (dst = board , src = root_board )
164
+ for (k , move ) in enumerate (gtp_moves_along_path ):
165
+ pos = coord .convert_from_gtp_format (move )
166
+ board .put_stone (pos , move_color )
167
+ move_color = Stone .get_opponent_color (move_color )
168
+ return board .get_board_string ()
0 commit comments