import sys; args = sys.
argv[1:]
import math, re
gameBoardStr = '.'*27+'ox......xo'+'.'*27
moves = []
snapshot = False
# INPUT GAME STATE
if args and len(args[0])==64:
gameBoardStr = args.pop(0)
gameBoardStr = list(gameBoardStr) # listify
gameBoardStr = [g.lower() for g in gameBoardStr]
# TOKEN
TOKEN = ['x', 'o']
token_lookup = {'x':0, 'o':1}
tok_indx = len([t for t in gameBoardStr if t=='.'])%2
if args and args[0].lower() in token_lookup.keys():
tok_indx = token_lookup[ args.pop(0).lower() ]
def a1toind(a1):
if a1 == '-S':
return(a1)
return (int(a1[1])-1)*8 + (ord(a1[0].lower())-97)
# MOVES
if args:
moves = [arg for arg in args if not re.findall(r"^-\d+$", arg) ]
moves = [int(arg) if arg.isdigit() else a1toind(arg) for arg in moves if arg ]
# snapshot from moves
if '-S' in moves:
snapshot = True
moves.pop()
# CONSTRUCT NEIGHBORS
The board will always be an 8x8.
def traceOut(direction, location, gameBoardStr,test_piece):
if this location is not within bounds
return [] or something that indicates return nothing from recursion
if the game has an empty piece at this location
return [location]
if this location is the same as the root piece that we are checking
return [] or something that indicates return nothing from recursion
res = traceOut(
direction,
neighbors[location][direction],
gameBoardStr,
test_piece
);
if res:
return [location] + res // (i.e. append the result upwards to produce a
list of all results)
return []
def boardToMoves(gameBoardStr, token):
token is the current piece (black or white; x or o)
# IDENTIFY LOCATIONS ON THE BOARD TO OUTWARDLY TRACE FROM
x_locations = list of locations on the board where the piece == token
# PERFORM RADIAL INSPECTIONNS
radial_traces = []
for each x in x_locations
for each radial direction of x
trace in that direction
append trace to radial_traces if len(trace)>1
radial_traces => [ [13,14], [16,8,0], ...] (e.g)
# THE IMPORTANT THING ABOUT EACH TRACE IS WHERE IT FINISHES!!!
# -- and ---
# THERE COULD BE MULTIPLE TRACES THAT FINISH AT THE SAME LOCATION.
# we can deal with this by keying each terimal location to the
# indices that will be flipped when we place our token there.
flip_map = {r[last_element] : set() for r in radial_traces}
for r in radial_traces:
flip_map[ r[-last_element] ].update( set(r[last_element]) )
return flip_map
def printMoves(gameStr, flip_map, TOKEN):
spots = GET THE PLAYABLE LOCATIONS (keys of flip_map)
make_a_copy_of_gameStr_to_display_*s
# FILL IN THE BOARD WITH STARS
for s in spots:
a_copy_of_gameStr_to_display_*s[s] = '*'
# COUNT THE NUMBER OF xS ON THE BOARD
# COUNT THE NUMBER OF oS ON THE BOARD
[print( "".join(a_copy_of_gameStr_to_display_*s[8*b: 8*b+8]) ) for b in
range(8)]
print('')
print( "".join(gameBoardStr), f"{num_x}/{num_o}" )
if spots:
playableSpotsString = ", ".join([str(s) for s in spots])
print(f"Possible moves for {TOKEN}: {playableSpotsString}")
else:
print(f"No moves possible for {TOKEN}")
# DO THE ACTUAL OPERATION OF FINDING MOVES, UPDATING BOARD, ETC
flip_map = boardToMoves(gameBoardStr,TOKEN)
printMoves(gameBoardStr, flip_map, TOKEN)
for m in moves:
# IF THE MOVE IS NOT ACTUALLY PLAYABLE, TRY IT FOR THE OTHER COLOR
if m not in flip_map:
CHANGE THE TOKEN FROM x to o (OR VICE VERSA), then
flip_map = boardToMoves(gameBoardStr,TOKEN)
# ACTUALLY PLACE THE PIECE IN THE REPRESENTATION OF THE BOARD
gameBoardStr[m] = TOKEN
print('')
print(f"{TOKEN} plays to {m}")
# -------------------------------
# FILL THE BOARD W/ NEW PIECE !!!
# ---
for s in flip_map[m]:
gameBoardStr[s] = TOKEN
CHANGE THE TOKEN FROM x to o (OR VICE VERSA), then
# GENERATE A NEW FLIP MAP
flip_map = boardToMoves(gameBoardStr,TOKEN)
if flip_map:
# IF THERE ARE ACTUALLY PLAYABLE MOVES FOR THIS LOCATION, PRINT THEM
printMoves(gameBoardStr, flip_map, TOKEN)
else:
# ELSE, THERE AREN'T MOVES - SO TRY THE OTHER PIECE
CHANGE THE TOKEN FROM x to o (OR VICE VERSA), then
flip_map = boardToMoves(gameBoardStr,TOKEN)
printMoves(gameBoardStr, flip_map, TOKEN)