Converting coding challenge 'Self-avoiding walk backtracing' from p5.js to Processing (Java)

Decided to convert my sketch to Python Mode too: :snake:

“Self_Avoiding_Walk_II.pyde”:

"""
 * Self Avoiding Walk II [with Backtracking]
 * Coding Challenge #162
 * by The Coding Train / Daniel Shiffman
 *
 * https://TheCodingTrain.com/CodingChallenges/162-self-avoiding-walk.html
 *
 * Python Mode conversion by GoToLoop (2022/Feb/22) (v1.0.5)
 *
 * https://Discourse.Processing.org/t/
 * converting-coding-challenge-self-avoiding-walk-backtracing-
 * from-p5-js-to-processing-java/35047/15
 *
 * OpenProcessing.org/sketch/1475931
"""

from functions import *

removals = 0

def setup():
    size(650, 500)
    noFill()

    createGrid()
    states[BG] = randomColor()


def draw():
    if states[FINISHED]: return

    states[REMOVED] and removeTailSpotIfTooOld()
    states[REMOVED] or  getNextSpot()

    global removals
    removals += states[REMOVED] and 1 or -removals
    removals == Spot.MAX_STRAIGHT_REMOVALS and resetAllSpotsAgesFromPath()

    drawGridPath()
    drawTrailPoint()


def mousePressed():
    if mouseButton == LEFT:
        states[PAUSED] ^= True
        noLoop() if states[PAUSED] else loop()
    elif mouseButton == RIGHT:  states[BG] = randomColor()
    elif mouseButton == CENTER: createGrid()
    else: saveFrame()


def randomColor(): return int(random(Spot.ALL_COLORS))

“functions.py”:

from spot import Spot

REMOVED, PAUSED, FINISHED, BG = 'removed', 'paused', 'finished', 'bg'
states = { REMOVED: False, PAUSED: False, FINISHED: False, BG: 0 }

path = []

def createGrid():
    rows = height // Spot.SPACING
    cols = width  // Spot.SPACING

    global grid, spot, path, matrix

    matrix = rows * cols
    states[FINISHED] = states[REMOVED] = False

    grid = tuple(tuple(Spot(r, c) for c in range(cols)) for r in range(rows))

    spot = grid[rows >> 1][cols >> 1]
    spot.visited = True

    path *= 0
    path.append(spot)


def resetAllSpotsAgesFromPath():
    for spot in path: spot.age = frameCount


def removeTailSpotIfTooOld():
    states[REMOVED] = frameCount - spot.age >= Spot.AGE_THRESHOLD
    if states[REMOVED]: removeTailSpotFromPath(); rejuvenateAllSpotsFromPath()


def removeTailSpotFromPath():
    states[REMOVED] = len(path) >= 2
    states[REMOVED] and path.pop().clear()

    global spot
    spot = path[-1]


def rejuvenateAllSpotsFromPath():
    size = len(path) - 1
    if not size: return

    for i in range(size + 1):
        path[i].age += round(map(i, 0, size, 1, Spot.AGE_INCREASE))


def getNextSpot(DONE = 'Solved!'):
    global spot
    spot = spot.nextSpot(grid)

    if spot:
        path.append(spot)
        spot.visited = True
        states[REMOVED] = False

    else: removeTailSpotFromPath();

    if len(path) == matrix:
        print DONE
        states[FINISHED] = True


def drawGridPath():
    background(states[BG])
    translate(Spot.HALF_SPACE, Spot.HALF_SPACE)

    strokeWeight(Spot.QUARTER_SPACE)
    stroke(Spot.PATH_STROKE)

    with beginShape():
        for spot in path: vertex(spot.x, spot.y)


def drawTrailPoint():
    strokeWeight(Spot.HALF_SPACE)
    stroke(Spot.TRAIL_STROKE)
    point(spot.x, spot.y)

“spot.py”:

from step import Step

class Spot:
    AGE_THRESHOLD = 200
    AGE_INCREASE = 5
    MAX_STRAIGHT_REMOVALS = 200

    SPACING = 10
    HALF_SPACE = SPACING * .5
    QUARTER_SPACE = SPACING * .25

    PATH_STROKE = -1
    TRAIL_STROKE = 0xffFFA000
    ALL_COLORS = (0xff << 0o30) - (1 << 0o40)

    def __init__(s, row, col):
        s.x = col * s.SPACING
        s.y = row * s.SPACING

        s.c = col
        s.r = row

        s.visited = False
        s.age = frameCount

        s.options = Step.allDirections()


    def clear(s):
        for step in s.options: step.tried = False
        s.visited = False
        s.age = frameCount
        return s


    def nextSpot(s, grid, dirs = []):
        rr = len(grid)
        cc = len(grid[0])

        valid = Step.isValid2
        dirs *= 0

        for step in s.options:
            r = s.r + step.y
            c = s.c + step.x
            not step.tried and valid(grid, r, c, rr, cc) and dirs.append(step)

        size = len(dirs)
        if not size: return

        step = dirs[int(random(size))]
        step.tried = True

        return grid[s.r + step.y][s.c + step.x]

“step.py”:

class Step:
    def __init__(s, x, y):
        s.x = x
        s.y = y
        s.tried = False


    @staticmethod
    def allDirections():
        return Step(1, 0), Step(-1, 0), Step(0, 1), Step(0, -1)


    @staticmethod
    def isValid(grid, r, c):
        return\
        0 <= r < len(grid) and\
        0 <= c < len(grid[r]) and\
        not grid[r][c].visited


    @staticmethod
    def isValid2(grid, r, c, rows, cols):
        return 0 <= r < rows and 0 <= c < cols and not grid[r][c].visited
1 Like