initial commit
This commit is contained in:
commit
8c4eb355bf
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
venv
|
||||
.idea
|
291
main.py
Normal file
291
main.py
Normal 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()
|
Loading…
Reference in New Issue
Block a user