First working version of CSS generation. Bot not that good yet. Haha.
This commit is contained in:
105
bot.py
Normal file
105
bot.py
Normal file
@@ -0,0 +1,105 @@
|
||||
from functools import lru_cache
|
||||
from collections import namedtuple
|
||||
|
||||
|
||||
def get_sudoku_moves():
|
||||
PLAYER_1 = "X"
|
||||
PLAYER_2 = "O"
|
||||
EMPTY = "_"
|
||||
Move = namedtuple("Move", ["ps", "n"])
|
||||
Position = namedtuple("Position", ["t", "i"])
|
||||
|
||||
def all_rows(field):
|
||||
""" Returns all rows of a Sudoku field. """
|
||||
f = field
|
||||
return [
|
||||
f[0:3], f[3:6], f[6:9], # horizontals
|
||||
f[0:7:3], f[1:8:3], f[2:9:3], # verticals
|
||||
f[0:9:4], f[2:7:2] # diagonals
|
||||
]
|
||||
|
||||
assert(all_rows(list(range(9))) == [
|
||||
[0, 1, 2], [3, 4, 5], [6, 7, 8],
|
||||
[0, 3, 6], [1, 4, 7], [2, 5, 8],
|
||||
[0, 4, 8], [2, 4, 6]])
|
||||
|
||||
def all_equal_to(row, value):
|
||||
""" Returns True if all elements in row are
|
||||
equal to value. Returns False otherwise. """
|
||||
for e in row:
|
||||
if e != value:
|
||||
return False
|
||||
return True
|
||||
|
||||
def player_won(field, player):
|
||||
for row in all_rows(field):
|
||||
if all_equal_to(row, player):
|
||||
return True
|
||||
return False
|
||||
|
||||
def player_lost(field, player):
|
||||
other_player = PLAYER_2 if player == PLAYER_1 else PLAYER_1
|
||||
return player_won(field, other_player)
|
||||
|
||||
def game_over(field):
|
||||
for f in field:
|
||||
if f == EMPTY:
|
||||
return False
|
||||
return True
|
||||
|
||||
def possible_moves(field):
|
||||
return [i for i in range(len(field)) if field[i] == EMPTY]
|
||||
|
||||
@lru_cache(maxsize=2**16)
|
||||
def get_equity(field, player):
|
||||
if player_won(field, player):
|
||||
return 1
|
||||
elif player_lost(field, player):
|
||||
return -1
|
||||
elif game_over(field):
|
||||
return 0
|
||||
|
||||
other_player = PLAYER_2 if player == PLAYER_1 else PLAYER_1
|
||||
equities = []
|
||||
for possible_move in possible_moves(field):
|
||||
new_field = list(field)
|
||||
new_field[possible_move] = player
|
||||
new_field = tuple(new_field)
|
||||
equity = get_equity(new_field, other_player)
|
||||
equities.append(equity)
|
||||
return min(equities) * -1
|
||||
|
||||
def get_moves(field, turn, moves, moves_acc, bots_turn):
|
||||
|
||||
if player_won(field, PLAYER_1) or player_won(field, PLAYER_2):
|
||||
return
|
||||
|
||||
if game_over(field):
|
||||
return
|
||||
|
||||
if not bots_turn:
|
||||
for move in possible_moves(field):
|
||||
new_field = list(field)
|
||||
new_field[move] = PLAYER_1
|
||||
new_field = tuple(new_field)
|
||||
new_moves = Move(moves.ps + [Position(turn, move)], None)
|
||||
get_moves(new_field, turn + 1, new_moves, moves_acc, True)
|
||||
else:
|
||||
equities = []
|
||||
for move in possible_moves(field):
|
||||
new_field = list(field)
|
||||
new_field[move] = PLAYER_2
|
||||
new_field = tuple(new_field)
|
||||
equity = get_equity(new_field, PLAYER_2)
|
||||
equities.append((equity, move))
|
||||
move = max(equities)[1]
|
||||
new_field = list(field)
|
||||
new_field[move] = PLAYER_2
|
||||
new_field = tuple(new_field)
|
||||
bot_move = Move(moves.ps, Position(turn, move))
|
||||
moves_acc.append(bot_move)
|
||||
get_moves(new_field, turn + 1, moves, moves_acc, False)
|
||||
return moves_acc
|
||||
|
||||
EMPTY_FIELD = tuple([EMPTY for _ in range(9)])
|
||||
return get_moves(EMPTY_FIELD, 0, Move([], None), [], False)
|
||||
Reference in New Issue
Block a user