from fast_P_nim import P def safe_int_parse(s): try: return int(s) except ValueError: return -1 def display_game(game: dict) -> None: for i in range(game['size']): if game['board'][i]: print(f'{i+1:02d}', end="") else: print(' ', end="") if i + 1 != game['size']: print('-', end="") print() def valid_move(game: dict, i: int): if i >= game['size'] or i < 0: return False if game['board'][i]: if i > 0: if i < game['size']-1: return game['board'][i-1] or game['board'][i+1] else: return game['board'][i-1] else: if i < game['size']-1: return game['board'][i+1] else: return True def make_move(game: dict, i: int): gs = game['board'].copy() gs[i] = False if i > 0: gs[i-1] = not gs[i-1] if i < game['size']-1: gs[i+1] = not gs[i+1] return gs def get_nimber(gs: list) -> int: n = len(gs) nimber_so_far = 0 path_size = 0 for i in range(n): if gs[i]: path_size += 1 else: if path_size == 1 and n != 1: path_size = 0 nimber_so_far = nimber_so_far ^ P(path_size) path_size = 0 if path_size == 1 and n != 1: path_size = 0 nimber_so_far = nimber_so_far ^ P(path_size) return nimber_so_far def i_have_won(game: dict) -> bool: for i in range(game['size']): if valid_move(game, i): return False return True def find_move(game: dict) -> int: game_state_orig = game['board'].copy() for i in range(game['size']): if valid_move(game, i): gs = make_move(game, i) if get_nimber(gs) == 0: return i raise Exception("I have been beat!") def new_game(size: int) -> dict: game = {} game['board'] = [True] * size game['human_turn'] = not P(size) > 0 game['size'] = size game['version'] = '0.0.0' game['finished'] = False game['winner'] = "" game['turn'] = 1 return game def main(): n = int(input("Path size to play on> ")) game = new_game(n) if game['human_turn']: print("You can play first!") else: print("I'll play first!") while True: display_game(game) if game['human_turn']: if i_have_won(game): print("You're out of moves. I win!") game['finished'] = True game['winner'] = "Computer" break game['human_turn'] = False i = -1 # placeholder while True: i = safe_int_parse(input("Make your move> ")) - 1 if valid_move(game, i): break print("Hey! That's not allowed!") display_game(game) game['turn'] += 1 game['board'] = make_move(game, i) else: game['human_turn'] = True i = find_move(game) print(f"Hmm... I'll toggle {i + 1}") game['turn'] += 1 game['board'] = make_move(game, i) print('-'*8) for key, val in game.items(): print(f'{key}: {val}') if __name__ == "__main__": main()