Cannot unpack non-iterable method object error in Python

Viewed 3520

I'm building a visualization tool for A* Search in Python and have come across the following error when trying to calculate the g-score of my nodes.

    line 115, in g
    x1, y1 = s
TypeError: cannot unpack non-iterable method object

See code below:

from graphics import *
import pygame, sys
import math
import numpy as np
from queue import PriorityQueue

pygame.init()

# #set the screen size and captions
size = (500, 500)
rows = 50
margin = 1
screen = pygame.display.set_mode(size)
pygame.display.set_caption("A* Pathfinding")
screen.fill((173, 172, 166))

#define colors
aqua = (0, 255, 255)
black = (0, 0, 0)
blue = (0, 0, 255)
green = (0, 128, 0)
red = (255, 0, 0)
white = (255, 255, 255)
purple = (128, 0, 128)

#initialize PriorityQueue
q = PriorityQueue()



#define all possible states of each node
class Node:
    def __init__(self, row, col, width):
        self.row = row
        self.col = col
        self.x = row*width
        self.y = col*width  
        self.color = white
        self.width = width
        self.neighbors = [(col+1, row), (col-1, row), (col, row+1), (col, row-1)]
        #self.neighbors = []
    
    def get_pos(self):
        return self.row, self.col
    
    def is_closed(self):
        return self.color == red
    
    def is_open(self):
        return self.color == aqua
    
    def is_barrier(self):
        return self.color == black
    
    def is_start(self):
        return self.color == green
    
    def is_end(self):
        return self.color == blue
    
    def reset(self):
        return self.color == white
    
    def close(self):
        self.color = red
    
    def open_node(self):
        self.color = blue
    
    def barrier(self):
        self.color = black
    
    def start(self):
        self.color = green
    
    def end(self):
        self.color = aqua
        
    def path(self):
        self.color = purple

    


def init_grid():
    board = []
    for i in range(rows):
        board.append([])
        for j in range(rows):
            node = Node(i, j, size[0]/rows)
            board[i].append(node)
    return board


#heuristic
def h(c, end):
    x1, y1 = c
    x2, y2 = end
    return abs(x1 - x2) + abs(y1 - y2)


#distance between current node and start node
def g(c, s):
    x1, y1 = s
    x2, y2 = c
    return abs(x1 - x2) + abs(y1 - y2)



    

board = init_grid()


barrier = []
frontier = {}
path = {} 


#starting conditions using Node class and associated methods
start = board[5][5]
goal = board[30][35]
current = start
count = 0

q.put(0, (start))


#main game loop
while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()
            
        #allows user to draw barriers
        elif pygame.mouse.get_pressed()[0]:
            pos = pygame.mouse.get_pos()
            y_pos = int(pos[0] // (board[0][0].width + margin))
            x_pos = int(pos[1] // (board[0][0].width + margin))
            board[x_pos][y_pos].barrier()
            barrier.append(board[x_pos][y_pos].get_pos())
    
    #draw the grid
    for i in range(rows):
        for j in range(rows):
            color = board[i][j].color
            #print(board[i][j].color)
            if board[i][j] == start:
                board[i][j].start()
            elif board[i][j] == goal:
                board[i][j].end()
             
            

            pygame.draw.rect(screen, color, [j*(board[0][0].width + margin), i*(board[0][0].width + margin), board[0][0].width, board[0][0].width])
   
    
    #game loop
    if event.type == pygame.KEYDOWN:
        if event.key == pygame.K_SPACE:
            while not q.empty():
                for neighbor in current.neighbors:
                    g_temp = g(current.get_pos, start.get_pos) + 1
                    if g_temp < g(neighbor, start.get_pos()): 
                        f = g_temp + h(current.get_pos(), goal.get_pos())
                        if neighbor not in frontier:
                            q.put((f, neighbor))
                            frontier.add(neighbor)
                            board[neighbor[0]][neighbor[1]].open_node()
                
                
                if current != goal:
                    new = q.get()[1]
                    path.add(current)
                    current = board[new[0]][new[1]]
                
                if current == goal:
                    break


    pygame.display.flip()
        
pygame.quit()

I have tried debugging this issue but I don't understand why it is giving me this error. The function should take in two tuple arguments and return an integer as the g-score, which I believe is what I am passing through in the game loop.

Please let me know if there is some obvious error that I missed here, I am still new to programming. Thank you so much for your time and help!

1 Answers

you have a long piece of code.

It seems you don't pass a tuple to g().

I spotted at least one error: You have to add the "()" after a method call, otherwise you pass the method name instead of the method value to g().

example from your code:

g_temp = g(current.get_pos, start.get_pos) + 1

should be:

g_temp = g(current.get_pos(), start.get_pos()) + 1

This is probably the problem. I haven't checked all the other lines as this code is very long ;) Test and come back tell us.

Related