Skip to content

Instantly share code, notes, and snippets.

@iam4722202468
Created August 28, 2021 04:22
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save iam4722202468/3b4ed283c75bc11f823569ff25e08999 to your computer and use it in GitHub Desktop.
Save iam4722202468/3b4ed283c75bc11f823569ff25e08999 to your computer and use it in GitHub Desktop.
Free Flow Puzzle Generator
import random
paths = {}
SIZE = 7
def printPuzzle():
puzzle = []
for x in range(0, SIZE):
p_ = []
for y in range(0, SIZE):
p_.append(-1)
puzzle.append(p_)
for colour in paths:
for v in paths[colour]:
puzzle[v[1]][v[0]] = colour
for x in puzzle:
print(x)
def initPuzzle():
for colour in range(0,SIZE):
paths[colour] = []
for y in range(0,SIZE):
paths[colour].append((colour, y))
initPuzzle()
def distance(pos1, pos2):
x = pos1[0] - pos2[0]
y = pos1[1] - pos2[1]
return abs(x) + abs(y)
def checkDistOneCount (path):
distOneCount = 0
for v in path:
for v2 in path:
distOneCount += distance(v, v2) == 1
# Every point has two connections, left and right, except for the top and bottom.
# Ex. 1 - 1 - 1 has a total neighbor count of 2*1 + 2 = 4
return distOneCount > 1+(len(path) - 2)*2 + 2
def stepPuzzle():
flowChosen = random.randrange(SIZE)
while len(paths[flowChosen]) <= 3:
flowChosen = random.randrange(SIZE)
isTail = bool(random.getrandbits(1))
# Shorten head / tail by 1 and see if anyone can replace it
pos = None
if isTail:
pos = paths[flowChosen][0]
for colour in range(0,SIZE):
comparePos = paths[colour][0]
dist = distance(pos, comparePos)
if checkDistOneCount(paths[colour] + [pos]):
continue
if dist == 1:
oldPos = paths[flowChosen].pop(0)
paths[colour].insert(0, oldPos)
return
else:
pos = paths[flowChosen][-1]
for colour in range(0,SIZE):
comparePos = paths[colour][-1]
dist = distance(pos, comparePos)
if checkDistOneCount(paths[colour] + [pos]):
continue
if dist == 1:
oldPos = paths[flowChosen].pop()
paths[colour].append(oldPos)
return
def stepPuzzleTakeover():
flowChosen = random.randrange(SIZE)
while len(paths[flowChosen]) <= 3:
flowChosen = random.randrange(SIZE)
pos = paths[flowChosen][0]
canReplace = []
# Search for surrounding squares
for colour in paths:
if colour == flowChosen:
continue
for i, v in enumerate(paths[colour]):
if distance(pos, v) == 1:
if i != 0 and i != len(paths[colour])-1:
canReplace.append((colour, i))
for c in canReplace:
portionUp = paths[c[0]][0:c[1]+1] + paths[flowChosen]
if checkDistOneCount(portionUp):
portionUp = []
portionDown = list(reversed(paths[c[0]][c[1]:])) + paths[flowChosen]
if checkDistOneCount(portionDown):
portionDown = []
if len(portionUp) > 0 and len(paths[c[0]][c[1]+1:]) >= 3:
paths[flowChosen] = portionUp
paths[c[0]] = paths[c[0]][c[1]+1:]
return
if len(portionDown) > 0 and len(paths[c[0]][:c[1]]) >= 3:
paths[flowChosen] = portionDown
paths[c[0]] = paths[c[0]][:c[1]]
return
def checkValid():
for x in paths:
old = paths[x][0]
for v in paths[x][1:]:
dist = distance(old, v)
if dist != 1:
return False
old = v
return True
for v in range(0, 1000):
stepPuzzle()
stepPuzzleTakeover()
for x in paths:
print(x, paths[x])
print()
printPuzzle()
print(checkValid())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment