0

I'm working my way through the libtcod python tutorial, I've decided to mess around with some of the code to make it more unique today, and decided to start off with a feature to allow the player to hover the mouse over an object and press 'd' for a description of that object.

I'm currently running into an attribute error: 'str' object has no attribute 'describe' line 657. I've tried many different things but notihng seems to work, unfortunately my level of understanding is pretty limited right now so I can't figure out what's going wrong.

Here are the relevant classes and functions:

class Object:
    #this is a generic object: the player, a monster, an item, the stairs...
    #it's always represented by a character on screen.
    def __init__(self, x, y, char, name, color, blocks=False, fighter=None, ai=None, item=None, description=None):
        self.x = x
        self.y = y
        self.char = char
        self.name = name
        self.color = color
        self.blocks = blocks
        self.fighter = fighter
        if self.fighter: #let the fighter component know who owns it
            self.fighter.owner = self
        self.ai = ai
        if self.ai: #let the ai component know who owns it
            self.ai.owner = self
        self.item = item
        if self.item: #let the item component know who owns it, like a bitch
            self.item.owner = self
        self.description = self
        if self.description: #let the description component know who owns it
            self.description.owner = self

    def describe(self):
        #describe this object
        message(self.description, libtcod.white)

def handle_keys():
    global keys;

            if key_char == 'd':
                #show the description menu, if an item is selected, describe it.
                chosen_object = description_menu('Press the key next to an object to see its description.\n')
                if chosen_object is not None:
                    chosen_object.describe()

            return 'didnt-take-turn'

def description_menu(header):

    global mouse

    #return a string with the names of all objects under the mouse
    (x, y) = (mouse.cx, mouse.cy)

    #create a list with the names of all objects at the mouse's coordinates and in FOV
    names = [obj.name for obj in objects if obj.x == x and obj.y == y and libtcod.map_is_in_fov(fov_map, obj.x, obj.y)]

    names = ', '.join(names) #join the names, seperated by commas
    return names.capitalize()

    #show a menu with each object under the mouse as an option
    if len(names) == 0:
        options = ['There is nothing here.']
    else:
        options = [item.name for item in names]

    index = menu(header, options, INVENTORY_WIDTH)

    #if an item was chosen, return it
    if index is None or len(names) == 0: return None
    return names[index].description

Any help would be much appreciated!

B-mo
  • 49
  • 1
  • 9

1 Answers1

1

The function description_menu() has the following return

names[index].description

This is a string member that belongs to Object.
When you say

chosen_object.describe()

You are calling the describe() method, but that belongs to the Object class, not a string (hence the attribute error: 'str' object has no attribute 'describe'). You would have to have description_menu() return the Object instead of just the name of it.

Cory Kramer
  • 114,268
  • 16
  • 167
  • 218
  • Do you mean like this: '#if an item was chosen, return it if index is None or len(names) == 0: return None return object' Sorry if I'm slow to understand, and thank you very much for the response. – B-mo Jul 16 '14 at 14:42
  • Ok I changed the code as best I could and I got a little further but now returning a 'list' object has no attribute 'describe'. Have you got any ideas? – B-mo Jul 16 '14 at 15:13
  • `def description_menu(header): global mouse (x, y) = (mouse.cx, mouse.cy) names = [obj for obj in objects if obj.x == x and obj.y == y and libtcod.map_is_in_fov(fov_map, obj.x, obj.y)] return names if len(names) == 0: options = ['There is nothing here.'] else: options = [object.name for object in names] index = menu(header, options, INVENTORY_WIDTH) #if an item was chosen, return it if index is None or len(names) == 0: return None return names` – B-mo Jul 16 '14 at 15:14
  • `names` is a list of `Objects`. The method `describe()` only applies to a single `Object` so you need to index which one you want out of `names`. – Cory Kramer Jul 16 '14 at 15:23
  • Just came here to say that I figured out I need to call a specific object out of the list, I tried doing this by `return [index].names` but I still get the list error. – B-mo Jul 16 '14 at 15:33
  • Not `names[index].object` either. – B-mo Jul 16 '14 at 15:35
  • Ok fixed it, there was a double `return names` in the menu function. I fixed a bunch of other bugs on the way but I have an even weirder bug now, it's printing to the console, but it's not printing the `message(str(self.description), libtcod.white`, instead it prints `<__main__.object instance at 0x03d707d8>`. Sorry for the flurry of comments, I'm kind of excited to finish it I guess. – B-mo Jul 16 '14 at 16:00