-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathtic_tac_toe_priorities.py
140 lines (105 loc) · 4.14 KB
/
tic_tac_toe_priorities.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
129
130
131
132
133
134
135
136
137
138
139
140
from bppy import *
x = lambda row, col: BEvent('X' + str(row) + str(col))
o = lambda row, col: BEvent('O' + str(row) + str(col))
LINES = [[(i, j) for j in range(3)] for i in range(3)] + [[(i, j) for i in range(3)] for j in range(3)] + [
[(i, i) for i in range(3)]] + [[(i, 3 - i - 1) for i in range(3)]]
x_lines = [[x(i, j) for (i, j) in line] for line in LINES]
o_lines = [[o(i, j) for (i, j) in line] for line in LINES]
any_x = [x(i, j) for i in range(3) for j in range(3)]
any_o = [o(i, j) for i in range(3) for j in range(3)]
move_events = EventSet(lambda e: e.name.startswith('X') or e.name.startswith('O'))
static_event = {
'OWin': BEvent('OWin'),
'XWin': BEvent('XWin'),
'draw': BEvent('Draw')
}
@b_thread
def square_taken(row, col):
yield {waitFor: [x(row, col), o(row, col)]}
yield {block: [x(row, col), o(row, col)]}
@b_thread
def enforce_turns():
while True:
yield {waitFor: any_x, block: any_o}
yield {waitFor: any_o, block: any_x}
@b_thread
def end_of_game():
yield {waitFor: list(static_event.values())}
yield {block: All()}
@b_thread
def detect_draw():
for r in range(3):
for c in range(3):
yield {waitFor: move_events}
yield {request: static_event['draw'], priority: 90}
@b_thread
def detect_x_win(line):
for i in range(3):
yield {waitFor: line}
yield {request: static_event['XWin'], priority: 100}
@b_thread
def detect_o_win(line):
for i in range(3):
yield {waitFor: line}
yield {request: static_event['OWin'], priority: 100}
# Preference to put O on the center
@b_thread
def center_preference():
while True:
yield {request: o(1, 1), priority: 35}
# Preference to put O on the corners
@b_thread
def corner_preference():
while True:
yield {request: [o(0, 0), o(0, 2), o(2, 0), o(2, 2)], priority: 20}
# Preference to put O on the sides
@b_thread
def side_preference():
while True:
yield {request: [o(0, 1), o(1, 0), o(1, 2), o(2, 1)], priority: 10}
# player O strategy to add a third O to win
@b_thread
def add_third_o(line):
for i in range(2):
yield {waitFor: line}
yield {request: line, priority: 50}
# player O strategy to prevent a third X
@b_thread
def prevent_third_x(xline, oline):
for i in range(2):
yield {waitFor: xline}
yield {request: oline, priority: 40}
@b_thread
def block_fork(xfork, ofork):
for i in range(2):
yield {waitFor: xfork}
yield {request: ofork, priority: 30}
forks22 = [[x(1, 2), x(2, 0)], [x(2, 1), x(0, 2)], [x(1, 2), x(2, 1)]], [o(2, 2), o(0, 2), o(2, 0)]
forks02 = [[x(1, 2), x(0, 0)], [x(0, 1), x(2, 2)], [x(1, 2), x(0, 1)]], [o(0, 2), o(0, 0), o(2, 2)]
forks20 = [[x(1, 0), x(2, 2)], [x(2, 1), x(0, 0)], [x(2, 1), x(1, 0)]], [o(2, 0), o(0, 0), o(2, 2)]
forks00 = [[x(0, 1), x(2, 0)], [x(1, 0), x(0, 2)], [x(0, 1), x(1, 0)]], [o(0, 0), o(0, 2), o(2, 0)]
forks_diag = [[x(0, 2), x(2, 0)], [x(0, 0), x(2, 2)]], [o(0, 1), o(1, 0), o(1, 2), o(2, 1)]
# simulate player X
@b_thread
def player_x():
while True:
yield {request: any_x}
if __name__ == "__main__":
bprog = BProgram(
bthreads=[square_taken(i, j) for i in range(3) for j in range(3)] +
[enforce_turns(), end_of_game(), detect_draw()] +
[detect_x_win(line) for line in x_lines] +
[detect_o_win(line) for line in o_lines] +
[center_preference(), corner_preference(), side_preference()] +
[add_third_o(line) for line in o_lines] +
[prevent_third_x(xline, oline) for (xline, oline) in zip(x_lines, o_lines)] +
[block_fork(xfork, forks22[1]) for xfork in forks22[0]] +
[block_fork(xfork, forks02[1]) for xfork in forks02[0]] +
[block_fork(xfork, forks20[1]) for xfork in forks20[0]] +
[block_fork(xfork, forks00[1]) for xfork in forks00[0]] +
[block_fork(xfork, forks_diag[1]) for xfork in forks_diag[0]] +
[player_x()],
event_selection_strategy=PriorityBasedEventSelectionStrategy(default_priority=0),
listener=PrintBProgramRunnerListener()
)
bprog.run()