While we're posting code, here's one I've conjectured to always work:
def loses(triplet):
c,b,a = sorted(triplet); mod = 1
if (a,b,c) == (a,a,(0 if a==1 else a)): return True
while c >= mod//2:
if (b%mod,c%mod,(b//mod)&~(b//mod+c//mod)) == (mod//2,mod//2,0): return a == b + c + (1 - mod//2 if mod > 1 else 2)
mod *= 2
return a == b + c + 1
def move(triplet): #example input: move((99,100,101))
if loses(triplet): print(triplet,"loses"); return
a,b,c = triplet
for trip in [(i,b,c) for i in range(a)]+[(a,j,c) for j in range(b)]+[(a,b,k) for k in range(c)]:
if loses(trip): print(trip)
Here's my code too. It lists only winning positions on the left and the two positions to the right are the moves you should make in case one gets rejected.
from functools import cache
@cache
def is_winnable(pos):
if sum(pos) == 0:
return False
elif sum(pos) == 1:
return True
lose_psns = []
for i in range(len(pos)):
for dots in range(pos[i]):
child_pos = tuple(sorted(pos[:i] + (dots,) + pos[i+1:], reverse=True))
if not is_winnable(child_pos):
lose_psns.append(child_pos)
if len(lose_psns) >= 2:
print(pos, lose_psns)
return True
return False
for a in range(6):
for b in range(6):
for c in range(6):
is_winnable(tuple(sorted((a, b, c), reverse=True)))
← Return to game
Comments
Log in with itch.io to leave a comment.
While we're posting code, here's one I've conjectured to always work:
Here's my code too. It lists only winning positions on the left and the two positions to the right are the moves you should make in case one gets rejected.
#Here's my code to calculate all must-win or must-lose
#forms in 3d.
set_lose={(0,0,0)}
set_win={(0,1,0),(1,0,0),(0,0,1)}
limit=5
def add_win(i,j,k):
set_win.add((i,j,k))
set_win.add((i,k,j))
set_win.add((k,i,j))
set_win.add((k,j,i))
set_win.add((j,i,k))
set_win.add((j,k,i))
def have_common(a,b):
if a[0]==b[0]:
if a[1]==b[1]:
for i in range(max(a[2],b[2])+1,limit+1):
add_win(a[0],a[1],i)
elif a[2]==b[2]:
for i in range(max(a[1],b[1])+1,limit+1):
add_win(a[0],i,a[2])
else:
if (a[1]>b[1]) and (a[2]<b[2]):
add_win(a[0],a[1],b[2])
if(a[1]<b[1]) and (a[2]>b[2]):
add_win(a[0],b[1],a[2])
elif a[1]==b[1]:
if a[2]==b[2]:
for i in range(max(a[0],b[0])+1,limit+1):
add_win(i,a[1],a[2])
else:
if(a[0]>b[0]) and (a[2]<b[2]):
add_win(a[0],a[1],b[2])
if(a[0]<b[0]) and(a[2]>b[2]):
add_win(b[0],a[1],a[2])
elif a[2]==b[2]:
if(a[0]>b[0]) and (a[1]<b[1]):
add_win(a[0],b[1],a[2])
if(a[0]<b[0]) and (a[1]>b[1]):
add_win(b[0],a[1],a[2])
def xinzeng(dot):
for i in set_lose:
have_common(i,dot)
for i in range(0,limit+1):
for j in range(0,limit+1):
for k in range(0,limit+1):
dot=(i,j,k)
if (dot not in set_win)and(dot not in set_lose):
# print(i,j,k)
xinzeng(dot)
set_lose.add(dot)
print(len(set_lose))
for i in set_lose:
print(i)