3
3
import math
4
4
from square import Square
5
5
from constants import SIZE , GAMES , KOMI , EMPTY , WHITE , BLACK , SHOW , PASS , MAXMOVES , TIMESTAMP , MOVES
6
- from typing import List
6
+ from typing import List , final , Set
7
7
import time
8
8
9
9
#@fields({'empties':List(int)
10
10
# ,'board':{'useful':Function(NamedParameters([('pos',int)])
11
11
# ,int)}
12
12
# ,'empty_pos':List(int)})
13
+ @final
13
14
class EmptySet :
14
15
#def __init__(self:EmptySet, board:{'useful':Function(NamedParameters([('pos',int)]), int)})->Void:
15
16
def __init__ (self , board : Board ) -> None :
16
- self .board = board
17
- self .empties = list (range (SIZE * SIZE ))
18
- self .empty_pos = list (range (SIZE * SIZE ))
17
+ self .board : Board = board
18
+ self .empties : List [ int ] = list (range (SIZE * SIZE ))
19
+ self .empty_pos : List [ int ] = list (range (SIZE * SIZE ))
19
20
20
21
#def random_choice(self:EmptySet)->int:
21
22
def random_choice (self ) -> int :
@@ -46,11 +47,12 @@ def set(self, i: int, pos: int) -> None:
46
47
self .empty_pos [pos ] = i
47
48
48
49
#@fields({'hash':int})
50
+ @final
49
51
class ZobristHash :
50
52
#def __init__(self:ZobristHash, board:{'squares':List(Square)})->Void:
51
53
def __init__ (self , board : Board ) -> None :
52
- self .hash_set = set ()
53
- self .hash = 0
54
+ self .hash_set : Set [ int ] = set ()
55
+ self .hash : int = 0
54
56
for square in board .squares :
55
57
self .hash ^= square .zobrist_strings [EMPTY ]
56
58
self .hash_set .clear ()
@@ -77,18 +79,19 @@ def dupe(self) -> bool:
77
79
# ,'white_dead':int
78
80
# ,'black_dead':int
79
81
# ,'lastmove':int})
82
+ @final
80
83
class Board :
81
84
#def __init__(self:Board)->Void:
82
85
def __init__ (self ) -> None :
83
- self .squares = []
84
- self .emptyset = EmptySet (self )
85
- self .zobrist = ZobristHash (self )
86
- self .color = BLACK
87
- self .finished = False
88
- self .lastmove = - 2
89
- self .history = []
90
- self .white_dead = 0
91
- self .black_dead = 0
86
+ self .squares : List [ Square ] = []
87
+ self .emptyset : EmptySet = EmptySet (self )
88
+ self .zobrist : ZobristHash = ZobristHash (self )
89
+ self .color : int = BLACK
90
+ self .finished : bool = False
91
+ self .lastmove : int = - 2
92
+ self .history : List [ int ] = []
93
+ self .white_dead : int = 0
94
+ self .black_dead : int = 0
92
95
self .squares = [Square (self , pos ) for pos in range (SIZE * SIZE )]
93
96
for square in self .squares :
94
97
square .set_neighbours ()
@@ -241,16 +244,17 @@ def check(self) -> None:
241
244
242
245
243
246
#@fields({'pos':int, 'wins':int, 'losses':int})
247
+ @final
244
248
class UCTNode :
245
249
#def __init__(self:UCTNode)->Void:
246
250
def __init__ (self ) -> None :
247
- self .bestchild = None
248
- self .pos = - 1
249
- self .wins = 0
250
- self .losses = 0
251
- self .pos_child = [None for x in range (SIZE * SIZE )]
252
- self .parent = None
253
- self .unexplored = True
251
+ self .bestchild : None | UCTNode = None
252
+ self .pos : int = - 1
253
+ self .wins : int = 0
254
+ self .losses : int = 0
255
+ self .pos_child : List [ None | UCTNode ] = [None for x in range (SIZE * SIZE )]
256
+ self .parent : None | UCTNode = None
257
+ self .unexplored : List [ int ] = []
254
258
255
259
#def play(self:UCTNode, board:Board)->Void:
256
260
def play (self , board : Board ) -> None :
@@ -285,7 +289,7 @@ def select(self, board: Board) -> int:
285
289
self .unexplored [i ] = self .unexplored [len (self .unexplored )- 1 ]
286
290
self .unexplored .pop ()
287
291
return pos
288
- elif self .bestchild :
292
+ elif self .bestchild is not None :
289
293
return self .bestchild .pos
290
294
else :
291
295
return PASS
@@ -315,7 +319,11 @@ def update_path(self, board: Board, color: int, path: List[UCTNode]) -> None:
315
319
#def score(self:UCTNode)->float:
316
320
def score (self ) -> float :
317
321
winrate = self .wins / float (self .wins + self .losses )
318
- parentvisits = self .parent .wins + self .parent .losses
322
+ parentvisits = 0
323
+ if self .parent is not None :
324
+ parentvisits += self .parent .wins
325
+ if self .parent is not None :
326
+ parentvisits += self .parent .losses
319
327
if not parentvisits :
320
328
return winrate
321
329
nodevisits = self .wins + self .losses
0 commit comments