-
Notifications
You must be signed in to change notification settings - Fork 0
/
bot_plays.py
384 lines (331 loc) · 18 KB
/
bot_plays.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
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
from random import choice
groups = [[1, 2, 3], [4, 5, 6], [7, 8, 9], [7, 4, 1], [8, 5, 2], [9, 6, 3], [7, 5, 3], [9, 5, 1]]
corners = [1, 3, 7, 9]
r_corners = [9, 7, 3, 1]
middles = [2, 4, 6, 8]
opposites = {
2: [7, 9],
4: [3, 9],
6: [1, 7],
8: [1, 3]
}
plays = 1
bot_last_move = 0
strategy = 0
# groups -> Possible marks to win
# This variables above will be used just in the level 3 bot
# ↳ corners -> The board corners
# ↳ r_corners -> The corners, but reversed
# ↳ middles -> The middles of the board
# ↳ plays -> The number of times that the bot played
# ↳ bot_last_move -> The last move that the bot did
# ↳ strategy -> The strategy that the bot will use, actualy, this will only be usend on the level 3 bot
# This functions bellow will always return the board given, but with the modification of the bot's move
def bot_turn_1(board: dict):
# Level 1 of difficulty
# This level will make totally random moves everytime
options = []
# For every house in the board, if it's empty, append it on options
for option in board.items():
if option[1] == ' ':
options.append(option[0])
move = choice(options)
board[move] = 'X'
return board
def bot_turn_2(board: dict):
# Level 2 of difficulty
# This level will draw if make a random play or a kinda smart play
smart = choice([1, 2]) # 1 -> smart move / 2 -> not smart move
if smart == 1:
# Check if someone is near to a win
for possibility in groups:
group = (board[possibility[0]], board[possibility[1]], board[possibility[2]])
if group.count('X') == 2 and group.count(' ') == 1: # Means that the bot is near to a win
move = group.index(' ') # Finding where to move to win
board[possibility[move]] = 'X'
return board
# If arrived here, it means that the bot isn't near to a win, so the bot is going to check if the player is near to a win
for possibility in groups:
group = (board[possibility[0]], board[possibility[1]], board[possibility[2]])
if group.count('O') == 2 and group.count(' ') == 1: # Means that the player is near to a win
move = group.index(' ') # Finding where to block the player
board[possibility[move]] = 'X'
return board
# If arrived here, it means that anyone is near to a win or that the draw resulted in 2 so the bot does a random play
board = bot_turn_1(board)
return board
def bot_turn_3(board: dict, last_move: int):
global plays, groups, bot_last_move, corners, r_corners, strategy, opposites
# Strategy 1 and 2 is when the bot is startin the game
# ↳ Strategy 1 -> Start from the cernter of the board
# ↳ Strategy 2 -> Start from the corner of the board
if last_move == 0: # It means that the bot is starting the game
strategy = choice([1, 2])
elif last_move != 0 and plays == 1: # It means that the player has already started the game
# So we have to check if the player moved to 5, if yes, we have a problem, so, strategy 3
if last_move == 5:
strategy = 3
# If the player didn't moved to 5, we had luck, so, strategy 4
else:
strategy = 4
if strategy == 1: # The bot is starting, and the strategy is start from center
if plays == 1: # If it's the first move
board[5] = 'X'
plays += 1
bot_last_move = 5
return board
elif plays == 2: # If this is the second bot's move
if last_move in corners: # If the player's first move was in the corners
move = r_corners[corners.index(last_move)] # The bot will find the oposite side of the player's move
board[move] = 'X'
plays += 1
bot_last_move = move
return board
else: # If the player's first move was in the middles, the bot will win
move = choice(opposites[last_move])
board[move] = 'X'
plays += 1
bot_last_move = move
return board
elif plays == 3: # If this is the third bot's move
# Check if someone is near to a win
for possibility in groups:
group = (board[possibility[0]], board[possibility[1]], board[possibility[2]])
if group.count('X') == 2 and group.count(' ') == 1: # Means that the bot is near to a win
move = group.index(' ') # Finding where to move to win
board[possibility[move]] = 'X'
return board
# If arrived here, it means that the bot isn't near to a win, so the bot is going to check if the player is near to a win
for possibility in groups:
group = (board[possibility[0]], board[possibility[1]], board[possibility[2]])
if group.count('O') == 2 and group.count(' ') == 1: # Means that the player is near to a win
move = group.index(' ') # Finding where to block the player
board[possibility[move]] = 'X'
return board
# If arrived here, so nobody is near to a win
# The bot will move to the opposite side of the player's play
for a in choice([[0, 1], [1, 0]]):
if board[opposites[last_move][a]] == ' ':
board[opposites[last_move][a]] = 'X'
plays += 1
bot_last_move = opposites[last_move][a]
return board
else: # If arrived here, it means that the game will end in a draw
# Check if someone is near to a win
for possibility in groups:
group = (board[possibility[0]], board[possibility[1]], board[possibility[2]])
if group.count('X') == 2 and group.count(' ') == 1: # Means that the bot is near to a win
move = group.index(' ') # Finding where to move to win
board[possibility[move]] = 'X'
return board
# If arrived here, it means that the bot isn't near to a win, so the bot is going to check if the player is near to a win
for possibility in groups:
group = (board[possibility[0]], board[possibility[1]], board[possibility[2]])
if group.count('O') == 2 and group.count(' ') == 1: # Means that the player is near to a win
move = group.index(' ') # Finding where to block the player
board[possibility[move]] = 'X'
return board
# If arrived here, the bot will make a random play, because the game will end in a draw
return bot_turn_1(board)
elif strategy == 2: # The bot is starting, and the strategy is start from the corners
if plays == 1: # The first move will be any of the corners
move = choice(corners)
board[move] = 'X'
plays += 1
bot_last_move = move
return board
elif plays == 2: # The seconde move is kinda complicated
# First, find the lines of the bot_last_move
bot_lines = []
for line in groups:
if bot_last_move in line and line not in ([7, 5, 3], [9, 5, 1]):
bot_lines.append(line)
if last_move in middles: # If the player moved in a middle, the bot won
opposites_options = opposites[last_move]
for option in opposites_options:
if option in bot_lines[0] or option in bot_lines[1]:
if board[option] == ' ':
move = option
board[move] = 'X'
plays += 1
bot_last_move = move
return board
elif last_move in corners: # If the player moved in a corner, the bot will try to move to the opposite side
opposite_player_move = r_corners[corners.index(last_move)]
if board[opposite_player_move] == ' ':
move = opposite_player_move
board[move] = 'X'
plays += 1
bot_last_move = move
return board
# If we can't move to an opposite side, we will go to some of the other corners last
else:
if last_move in (1, 9):
move = choice([3, 7])
board[move] = 'X'
plays += 1
bot_last_move = move
return board
else:
move = choice([1, 9])
board[move] = 'X'
plays += 1
bot_last_move = move
return board
if last_move == 5: # If the player moved to the center, the bot have to go to the opposite side of his first move
opposite_bot_move = r_corners[corners.index(bot_last_move)]
move = opposite_bot_move
board[move] = 'X'
plays += 1
bot_last_move = move
return board
elif plays == 3:# If arrived here, probably, this game will end in a draw
# Check if someone is near to a win
for possibility in groups:
group = (board[possibility[0]], board[possibility[1]], board[possibility[2]])
if group.count('X') == 2 and group.count(' ') == 1: # Means that the bot is near to a win
move = group.index(' ') # Finding where to move to win
board[possibility[move]] = 'X'
return board
# If arrived here, it means that the bot isn't near to a win, so the bot is going to check if the player is near to a win
for possibility in groups:
group = (board[possibility[0]], board[possibility[1]], board[possibility[2]])
if group.count('O') == 2 and group.count(' ') == 1: # Means that the player is near to a win
move = group.index(' ') # Finding where to block the player
board[possibility[move]] = 'X'
return board
move = choice([a for a in corners if board[a] == ' '])
board[move] = 'X'
plays += 1
bot_last_move = move
return board
else:
# Check if someone is near to a win
for possibility in groups:
group = (board[possibility[0]], board[possibility[1]], board[possibility[2]])
if group.count('X') == 2 and group.count(' ') == 1: # Means that the bot is near to a win
move = group.index(' ') # Finding where to move to win
board[possibility[move]] = 'X'
return board
# If arrived here, it means that the bot isn't near to a win, so the bot is going to check if the player is near to a win
for possibility in groups:
group = (board[possibility[0]], board[possibility[1]], board[possibility[2]])
if group.count('O') == 2 and group.count(' ') == 1: # Means that the player is near to a win
move = group.index(' ') # Finding where to block the player
board[possibility[move]] = 'X'
return board
return bot_turn_1(board)
elif strategy == 3: # The player is starting from the center
if plays == 1:
# As the player moved to 5, we have to move to one of the corners
move = choice(corners)
board[move] = 'X'
plays += 1
bot_last_move = move
return board
elif plays == 2:
# Checking if someone is near to a win
for possibility in groups:
group = (board[possibility[0]], board[possibility[1]], board[possibility[2]])
if group.count('X') == 2 and group.count(' ') == 1: # Means that the bot is near to a win
move = group.index(' ') # Finding where to move to win
board[possibility[move]] = 'X'
plays += 1
bot_last_move = move
return board
for possibility in groups:
group = (board[possibility[0]], board[possibility[1]], board[possibility[2]])
if group.count('O') == 2 and group.count(' ') == 1: # Means that the player is near to a win
move = group.index(' ') # Finding where to block the player
board[possibility[move]] = 'X'
plays += 1
bot_last_move = move
return board
if last_move in corners: # The player isn't near to a win
# If the player moved to the opposite corner of the first play of the bot
# The bot will move to a random empty corner
for move in [a for a in corners if board[a] == ' ' and r_corners[corners.index(bot_last_move)] != a]:
board[move] = 'X'
plays += 1
bot_last_move = move
return board
else:
# If arrived here, it means that the game will probably end in a draw
for possibility in groups:
group = (board[possibility[0]], board[possibility[1]], board[possibility[2]])
if group.count('X') == 2 and group.count(' ') == 1: # Means that the bot is near to a win
move = group.index(' ') # Finding where to move to win
board[possibility[move]] = 'X'
plays += 1
bot_last_move = move
return board
for possibility in groups:
group = (board[possibility[0]], board[possibility[1]], board[possibility[2]])
if group.count('O') == 2 and group.count(' ') == 1: # Means that the player is near to a win
move = group.index(' ') # Finding where to block the player
board[possibility[move]] = 'X'
plays += 1
bot_last_move = move
return board
return bot_turn_1(board)
elif strategy == 4: # The player is starting from the corners
if plays == 1:
# As the player started from the corners, the bot has to go to the mid
board[5] = 'X'
plays += 1
bot_last_move = 5
return board
elif plays == 2:
if last_move in corners:
# First, check if the player is near to a win
for possibility in groups:
group = (board[possibility[0]], board[possibility[1]], board[possibility[2]])
if group.count('O') == 2 and group.count(' ') == 1: # Means that the player is near to a win
move = group.index(' ') # Finding where to block the player
board[possibility[move]] = 'X'
plays += 1
bot_last_move = move
return board
# If the player isn't near to a win, so he is making a trap
# Move to any of the middles will block his trap
move = choice(middles)
board[move] = 'X'
plays += 1
bot_last_move = move
return board
else:
# If the player moved to a mid, so he is probably near to a win
for possibility in groups:
group = (board[possibility[0]], board[possibility[1]], board[possibility[2]])
if group.count('O') == 2 and group.count(' ') == 1: # Means that the player is near to a win
move = group.index(' ') # Finding where to block the player
board[possibility[move]] = 'X'
plays += 1
bot_last_move = move
return board
# If the player isn't near to a win, the bot will make a random play in "return bot_turn_1(board)"
else:
# If arrived here, the game will probably end in a draw
for possibility in groups:
group = (board[possibility[0]], board[possibility[1]], board[possibility[2]])
if group.count('X') == 2 and group.count(' ') == 1: # Means that the bot is near to a win
move = group.index(' ') # Finding where to move to win
board[possibility[move]] = 'X'
plays += 1
bot_last_move = move
return board
for possibility in groups:
group = (board[possibility[0]], board[possibility[1]], board[possibility[2]])
if group.count('O') == 2 and group.count(' ') == 1: # Means that the player is near to a win
move = group.index(' ') # Finding where to block the player
board[possibility[move]] = 'X'
plays += 1
bot_last_move = move
return board
return bot_turn_1(board)
def reset():
# Everytime that the game restarts, this function will reset the variables that has been changed
global plays, bot_last_move, strategy
strategy = 0
plays = 1
bot_last_move = 0