-
Notifications
You must be signed in to change notification settings - Fork 0
/
game_tree.py
103 lines (86 loc) · 3.18 KB
/
game_tree.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
from constants import BLACK, WHITE, SKIP
"""
Game Tree where the current state is the state of the board and the current turn, and
the children are a mapping of possible actions to GameTrees with the resulting board state
"""
class GameTree:
def __init__(self, board, curr_turn, children=None):
self.board = board
self.curr_turn = curr_turn
self.children = children or {}
def __eq__(self, other):
return type(other) is GameTree and self.board == other.board
def __ne__(self, other):
return type(other) is not GameTree and self.board != other.board
def is_game_over(self):
"""
Whether the game has ended, when neither player can make another move
# TODO check if this is actually the condition where game over
void -> Boolean
"""
return len(self.board.get_valid_moves(BLACK)) == 0 and \
len(self.board.get_valid_moves(WHITE)) == 0
def get_actions(self):
"""
Lazily generates the next layer of the tree and returns the next layer of the
game tree, a mapping of moves to the next game tree state
void -> {Move : GameTree}
"""
moves = self.board.get_valid_moves(self.curr_turn)
for m in moves:
self.apply_move(m)
if len(moves) == 0:
self.apply_move(SKIP)
return list(self.children.keys())
def apply_move(self, move):
"""
Applies the given move to the current state and updates the tree to the next
state if it is valid.
Posn -> [GameTree]
"""
# lazy generation
if move in self.children:
return self.children[move]
# otherwise need to generate the child
if move == SKIP:
self.children[move] = GameTree(self.board.copy(), self.next_turn())
else:
# TODO need to check if its valid? because board assumes it is valid
next_board = self.board.apply_move(move, self.curr_turn)
self.children[move] = GameTree(next_board, self.next_turn())
return self.children[move]
def next_turn(self):
"""
Get the player whose turn is next.
void -> Color
"""
if self.curr_turn == WHITE:
return BLACK
else:
return WHITE
def get_score(self, color):
"""
Get the score for the given player in this game.
Color -> Natural
"""
return self.board.get_score(color)
def get_winner(self):
"""Get the winner of the game if there is one.
False if there is no winner (the game is not over or it is a tie).
void -> [Maybe Player]
"""
if self.is_game_over():
return self.get_leader()
return False
def get_leader(self):
"""Get the player with the leading score. False if they are tied
void -> [Maybe Player]
"""
# determine who has more points
blk_score = self.get_score(BLACK)
wht_score = self.get_score(WHITE)
if blk_score > wht_score:
return BLACK
elif wht_score > blk_score:
return WHITE
return False