jdf / Processing.py-Bugs

A home for all bugs and feature requests about Python Mode for the Processing Development Environment.
41 stars 8 forks source link

IndexError not returning a line number #269

Open Xevion opened 5 years ago

Xevion commented 5 years ago
import random, time

class Cell:
    def __init__(self, x, y):
        self.x, self.y = x, y
        self.identity = None
        self.right, self.bottom, self.visited, self.current, self.start = True, True, False, False, False
    def __str__(self):
        return 'Cell({}, {}, bottom: {}, right: {}, visited: {})'.format(self.x, self.y, self.bottom, self.right, self.visited)

    def neighbors(self, identityCheck=True):
        global offsets
        neighbors = []
        for offset in offsets:
            neighbor = (self.x + offset[0], self.y + offset[1])
            # If the neighbor isn't real
            if not valid(neighbor):
                continue
            # If the neighbor hasn't been claimed
            elif not grid[neighbor[0]][neighbor[1]].visited:
                neighbors.append(neighbor)
                continue
            # We're checking for their identity
            elif identityCheck:
                # If the neighbor isn't like me
                if grid[neighbor[0]][neighbor[1]].identity != self.identity:
                    neighbors.append(neighbor)
                    continue
        return neighbors

    def render(self):
        global divX, divY
        translate(self.x * divX, self.y * divY)
        # Drawing Cell Background
        # Visited, Unvisited, Highlighted
        if self.visited:
            fill(0, 42, 135)
        else:
            fill(0, 2, 30)

        if self.current:
            fill(0, 127, 196)
            self.current = False
        noStroke()
        rect(0, 0, divX, divY)

        # Drawing Cell Lines
        stroke(255)
        fill(255)
        strokeWeight(2.5)
        if not self.visited:
            noStroke()
        if self.bottom:
            line(0, divY, divX, divY)
        if self.right:
            line(divX, 0, divX, divY)
        resetMatrix()

def openWalls(x1, y1, x2, y2):
    global offsets, grid
    # Bottom, Right, Left, Top
    offset = (x2 - x1, y2 - y1)
    if offset == offsets[0]:
        grid[x1][y1].bottom = False
    if offset == offsets[1]:
        grid[x1][y1].right = False
    if offset == offsets[2]:
        grid[x2][y2].right = False
    if offset == offsets[3]:
        grid[x2][y2].bottom = False

def valid(coordinate):
    global columns, rows
    return not (coordinate[0] < 0 or coordinate[0] >= columns or coordinate[1] < 0 or coordinate[1] >= rows)

def generate():
    global columns, rows, grid, divX, divY, offsets
    # Bottom, Right, Left, Top
    offsets = [(0, 1), (1, 0), (-1, 0), (0, -1)]
    columns, rows = 10, 10
    divX, divY = width / float(columns), height / float(rows)
    grid = [[Cell(x, y) for y in range(rows)] for x in range(columns)]

    global treeSet, i
    i = 0
    mazeset = []

# Tree Class. But it's really not a tree.
class Tree:
    def __init__(self, identity):
        self.tree = []
        self.identifier = identity

    def append(self, node):
        self.tree.append(node)
        grid[node[0]][node[1]].visited = True

    # Merge another tree with this tree
    def merge(self, other):
        for node in other.tree:
            grid[node[0]][node[1]].identity = self.identity
            self.tree.append(node)

    # Find a node in the list with an edge
    def getEdge(self):
        random.shuffle(self.tree)
        for index, node in enumerate(self.tree):
            if len(grid[node[0]][node[1]].neighbors()) > 0:
                return node
def setup():
    size(750, 750)
    generate()

# Kruskall's algorithm
def tick():
    # choose a node, find it's tree
    # if it has no tree, create a tree
    # get the tree to return a node with an edge
    # merge the two trees together
    # continue until no edges can be found in any tree (how to implement this without guesswork or expensive iterating?)

    global treeSet, i
    choice = random.randint(0, columns-1), random.randint(0, rows-1)
    # If the node is unclaimed
    if grid[choice[0]][choice[1]].identity == None:
        # Find it's unclaimed neighbors (if any)
        neighbors = grid[choice[0]][choice[1]].neighbors()
        neighbors = [neighbor for neighbor in neighbors if grid[neighbor[0]][neighbor[1]].identity == None]

        # We got a unclaimed lone node, just skip it (crap implementation)
        if len(neighbors) < 0:
            return
        else:
            tree = Tree(i)
            i += 1
            neighbor = random.choice(neighbors)
            openWalls(choice[0], choice[1], neighbor[0], neighbor[1])
            tree.append(choice)
            tree.append(neighbor)

# Render the maze   
def render():
    background(0)
    for column in grid:
        for cell in column:
            cell.render()

def draw():
    render()
    tick()

Sorry for the long and complicated code. It's a maze generation algorithm I'm working on, implementing the Kruskal algorithm. The tick() function should contain the IndexError, and my debug method has been placing print() functions identifying the flow until I can see where it is.

I'm starting to get tired of this debug method and am wondering if I'm doing something wrong inside my code (that causes it not to show me the line number).

Anyways, for purposes of helping you guys out, I've located the error. Line 132, I accidentally put a < 0 instead of <= 0, < 1 or == 0. Changing that allows the rest of the maze implementation to fill in for now.

The Error (screenshot since I can't copy it for some reason) image

I've been getting this in multiple sketches and have not found a consensus on what the problem is. I'm not sure if I've seen an index error reporting a line number in more complicated sketches, but on simple sketches, it does report the line number via highlighting.

jdf commented 5 years ago

Thanks. Was this a saved sketch? Please paste here the complete path to the saved sketch.

Xevion commented 5 years ago

I'm not sure if it was saved. I save my sketches onto a 2TB Portable Drive, this one ended up saving at A:\Programming\Processing\Python\MazeGenKruskal.

Edit: Is this implying that issues are caused when a sketch is not saved? I usually end up doing entire mini-projects (like this one) without saving because I simply forget until I close Processing.