-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathgame_node.py
128 lines (93 loc) · 3.35 KB
/
game_node.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
from typing import Self
from board import Board
class GameNode(Board):
"""
Internal class for GameTree
Args:
size: length of one dimension of the board
komi: The komi applied to white's score
move: move number at current position (default = 0)
prev: parent GameNode
prev_move: the move played at the parent to make this
nexts: list of child GameNodes
"""
def __init__(self, size: int, komi: float = 7.5, move: int = 0,
prev: Self = None, prev_move: tuple[int, int] = None,
nexts: list[Self] = []):
if komi - int(komi) == 0:
raise ValueError(f"Invalid komi {komi}: komi must contain" +
" a fractional tie-breaker")
super().__init__(
size = size,
komi = komi,
move = move
)
self.prev = prev
self.prev_move = prev_move
self.nexts = nexts
def copy(self) -> Self:
"""Returns a deep copy of this GameNode"""
res = GameNode(
size = self.size,
komi = self.komi,
move = self.move,
prev = self.prev,
prev_move = self.prev_move,
nexts = self.nexts.copy()
)
# Board deep copy
res.grid = self.grid.copy()
res.seen = self.seen.copy()
res.num_passes = self.num_passes
res.groups = [group.copy() for group in self.groups]
res.index = Board.board_index
Board.board_index += 1
return res
def play_stone(self, row: int, col: int, move: bool) -> None:
"""
GameNode shouldn't support play_stone because it violates
tree invariants. create_child handles the tree components
while maintaining the same general function
"""
raise Exception("GameNode doesn't support play_stone. Use create_child instead.")
def create_child(self, loc: tuple[int, int]) -> Self:
"""
Returns the child GameNode after placing a stone at the
location provided
Args:
loc: index tuple for the location to place the stone
or (-1, -1) to pass
"""
child = self.copy()
if not super(type(child), child).play_stone(loc[0], loc[1], True):
raise ValueError(f"Invalid move location \"{loc}\"")
self.nexts.append(child)
child.prev = self
child.prev_move = loc
return child
if __name__ == "__main__":
board = GameNode(size = 9)
while not board.is_terminal():
try:
print("\nSelect a move")
row = int(input("Row: "))
col = int(input("Column: "))
board = board.create_child((row, col))
except KeyboardInterrupt:
print("\nKeyboard Interrupt. Game Ended")
break
except:
print("Error while processing move. Try again.")
else:
print(board)
scores = board.compute_simple_area_score()
print("Stats:")
print(f"Player 1 (black) score: {scores[0]}")
print(f"Player 2 (white) score: {scores[1]}")
print(f"Final score eval: {board.compute_winner()}")
print("PATH:")
while board.prev != None:
board = board.prev
while len(board.nexts) != 0:
print(board)
board = board.nexts[0]