-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathgametree.py
88 lines (77 loc) · 3.19 KB
/
gametree.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
from pieces import *
from state_representation import *
from random import shuffle
class GameTree(object):
'''
Class is used to find the best move based on a game tree search with
alpha beta pruning. It must be initialized as Gametree(gamestate,depth)
where gamestate is a game object representing current game state and depth
is the depth of the tree you wish to search in. It's function is a move
functions (GameTree.move()) which returns the best move as [row,column]
(i.e. ['a',5]). The heuristic function must be externally overwritten.
If no move improves our position, it will recomend a pass returning
['pass',-1]
'''
def __init__ (self, gamestate, depth):
self.current = gamestate
self.depth = depth
# Maximum depth of the tree search.
# Increase for better AI, decrease for time improvement
def move(self):
'''navigate the game tree to come up with best configuration,
return that gamestate'''
possibilities = self.current.successors()
shuffle(possibilities)
if len(possibilities) == 0:
#case of no valid moves
return self.current.value()
value = float("inf")
choice = "no moves"
if self.current.turn:
value = -float("inf")
if self.current.turn:
for child in possibilities:
if child.won==1:
return child
child_value = self.nodeval(child, self.depth-1, value)
if child_value > value:
value = child_value
choice = child
else:
for child in possibilities:
if child.won==-1:
return child
child_value = self.nodeval(child, self.depth-1, value)
if child_value < value:
value = child_value
choice = child
return choice
#note if there is no valid moves, it will return the string "no moves", otherwise it returns the best gamestate
def nodeval(self, state, depth, parent_val):
#evaluates the value of chosing each child in the gametree by considering up to debth nodes beneath it.
if depth == 0:
return state.value()
possibilities = state.successors()
shuffle(possibilities)
if len(possibilities) == 0:
#case of no valid moves
return state.value()
if state.turn:
value = -float("inf")
for child in possibilities:
if child.won==1:
return float("inf")
child_value = self.nodeval(child, depth-1, value)
value = max(child_value, value)
if value > parent_val:
return value
else:
value = float("inf")
for child in possibilities:
if child.won==-1:
return -float("inf")
child_value = self.nodeval(child, depth-1, value)
value = min(child_value, value)
if value < parent_val:
return value
return value