initial commit

This commit is contained in:
Daniel Tsvetkov 2021-12-29 19:28:23 +02:00
commit 8c4eb355bf
2 changed files with 293 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
venv
.idea

291
main.py Normal file
View File

@ -0,0 +1,291 @@
from collections import defaultdict
from copy import deepcopy
E = "_" # no pawn
O = "O" # pawn
_ = " " # empty space
COLS = "ABCDEFG"
ROWS = "1234567"
STARTING_BOARD = [
[_, _, O, O, O, _, _],
[_, _, O, O, O, _, _],
[O, O, O, O, O, O, O],
[O, O, O, E, O, O, O],
[O, O, O, O, O, O, O],
[_, _, O, O, O, _, _],
[_, _, O, O, O, _, _],
]
def translate_rc_pos(r, c):
return COLS[c] + ROWS[r]
def translate_pos_rc(pos):
return ROWS.find(pos[1]), COLS.find(pos[0])
def gen_around(r, c, board):
moves = []
pawn = board[r][c]
if pawn in [_, E]:
return []
# pawn exists
cur_pawn = translate_rc_pos(r, c)
# bottom pawn
if c + 2 < len(board[r]):
r_pawn = board[r][c + 1]
rr_pawn = board[r][c + 2]
if r_pawn == O and rr_pawn == E:
next_pawn = translate_rc_pos(r, c + 2)
moves.append(cur_pawn + next_pawn)
# top pawn
if c - 2 >= 0:
r_pawn = board[r][c - 1]
rr_pawn = board[r][c - 2]
if r_pawn == O and rr_pawn == E:
next_pawn = translate_rc_pos(r, c - 2)
moves.append(cur_pawn + next_pawn)
# right pawn
if r + 2 < len(board):
r_pawn = board[r + 1][c]
rr_pawn = board[r + 2][c]
if r_pawn == O and rr_pawn == E:
next_pawn = translate_rc_pos(r + 2, c)
moves.append(cur_pawn + next_pawn)
# left pawn
if r - 2 >= 0:
r_pawn = board[r - 1][c]
rr_pawn = board[r - 2][c]
if r_pawn == O and rr_pawn == E:
next_pawn = translate_rc_pos(r - 2, c)
moves.append(cur_pawn + next_pawn)
return moves
def gen_moves(board):
moves = []
for r, row in enumerate(board):
for c, pawn in enumerate(row):
if pawn == O:
pos_moves = gen_around(r, c, board)
moves += pos_moves
return moves
def play_move(move, board):
move = move.upper()
start_pos, end_pos = move[0:2], move[2:4]
# start row, start column; end row, end column
sr, sc = translate_pos_rc(start_pos)
er, ec = translate_pos_rc(end_pos)
assert board[sr][sc] == O, "starting position is not pawn"
assert board[er][ec] == E, "ending position is not empty"
if ec == sc:
if er - sr == 2:
assert board[er - 1][ec] == O, "No pawn in between (ec==sc, er-sr)"
board[er - 1][ec] = E
elif sr - er == 2:
assert board[er + 1][ec] == O, "No pawn in between (ec==sc, sr-er)"
board[er + 1][ec] = E
else:
raise Exception("There must be a pawn in between.")
elif er == sr:
if ec - sc == 2:
assert board[er][ec - 1] == O, "No pawn in between (er==sr, ec-sc)"
board[er][ec - 1] = E
elif sc - ec == 2:
assert board[er][ec + 1] == O, "No pawn in between (er==sr, sc-ec)"
board[er][ec + 1] = E
else:
raise Exception("There must be a pawn in between.")
else:
raise Exception("You can only jump 1.")
board[sr][sc] = E
board[er][ec] = O
return board
def undo_move(move, board):
move = move.upper()
start_pos, end_pos = move[2:4], move[0:2]
sr, sc = translate_pos_rc(start_pos)
er, ec = translate_pos_rc(end_pos)
assert board[sr][sc] == O, "starting position is not pawn"
assert board[er][ec] == E, "ending position is not empty"
if ec == sc:
if er - sr == 2:
assert board[er - 1][ec] == E, "pawn in between (ec==sc, er-sr)"
board[er - 1][ec] = O
elif sr - er == 2:
assert board[er + 1][ec] == E, "pawn in between (ec==sc, sr-er)"
board[er + 1][ec] = O
else:
raise Exception("There must NOT be a pawn in between.")
elif er == sr:
if ec - sc == 2:
assert board[er][ec - 1] == E, "pawn in between (er==sr, ec-sc)"
board[er][ec - 1] = O
elif sc - ec == 2:
assert board[er][ec + 1] == E, "pawn in between (er==sr, sc-ec)"
board[er][ec + 1] = O
else:
raise Exception("There must NOT be a pawn in between.")
else:
raise Exception("You can only jump 1.")
board[sr][sc] = E
board[er][ec] = O
return board
def print_board(board):
print(" ", end="")
for r in COLS:
print(" ", r, " ", end="")
print()
for c, row in zip(ROWS, board):
print(c, row, end="")
print()
def count_pawns(board):
count = 0
for row in board:
for pawn in row:
if pawn == O:
count += 1
return count
def play():
moves_this_game = []
stat = dict(
moves=defaultdict(int),
num_moves=0,
)
board = deepcopy(STARTING_BOARD)
i = 0
while True:
print("MOVE: {}".format(i))
print_board(board)
moves = gen_moves(board)
stat["moves"][len(moves)] += 1
print("MOVES: {}".format(moves))
if len(moves) == 0:
print("No valid moves left")
break
# this_move = random.choice(moves)\
# print("Chose Move: {}".format(this_move))
this_move = input("> ")
moves_this_game.append(this_move)
try:
board = play_move(this_move, board)
except Exception as e:
print("invalid move")
print(e)
continue
i += 1
stat["num_moves"] = i
return board, moves_this_game, stat
def main_play():
game_no = 1
gauss = defaultdict(int)
while True:
board, moves_this_game, stat = play()
count = count_pawns(board)
# print("{} Left pawns: {} | {} | {}".format(game_no, count, stat["num_moves"], sorted([(a,b) for a, b in stat['moves'].items()], key=lambda x: x[1], reverse=True)))
print("{} Left pawns: {}".format(game_no, count))
gauss[count] += 1
game_no += 1
if count == 1:
print("Moves this game: {}".format(moves_this_game))
print("FINISHED!")
break
HASHES = {}
def rot_board(board):
A = deepcopy(board)
N = len(A[0])
for i in range(N // 2):
for j in range(i, N - i - 1):
temp = A[i][j]
A[i][j] = A[N - 1 - j][i]
A[N - 1 - j][i] = A[N - 1 - i][N - 1 - j]
A[N - 1 - i][N - 1 - j] = A[j][N - 1 - i]
A[j][N - 1 - i] = temp
return A
def hash_board(board):
the_hash, cnt = "", 0
prev_cell = None
for row in board:
for cell in row:
if cell == _:
continue
if prev_cell is not None and prev_cell != cell:
the_hash += "{}{}|".format(cnt, prev_cell)
cnt = 0
prev_cell = cell
cnt += 1
if cnt != 0:
the_hash += "{}{}".format(cnt, prev_cell)
return the_hash
def rot_hash_board(board):
value = len(HASHES)
for i in range(4):
hash0 = hash_board(board)
HASHES[hash0] = value
board = rot_board(board)
class Node(object):
def __init__(self, board):
self.board = board
self.moves = gen_moves(board)
self.visited = False
self.children = []
def main():
board = deepcopy(STARTING_BOARD)
moves_this_game = []
while True:
moves = gen_moves(board)
if len(moves) <= 0:
print("finished")
pawns = count_pawns(board)
if pawns == 1:
print(moves_this_game)
break
print_board(board)
print(moves_this_game)
rot_hash_board(board)
this_move = moves_this_game[-1]
board = undo_move(this_move, board)
this_move = moves[0]
moves_this_game.append(this_move)
board = play_move(this_move, board)
if __name__ == "__main__":
main()