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
|
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()
|