Search code examples
pythonstringdictionaryinputtext-based

Str object not callable (using input as arg for a function in a class)


I'm a very new coder learning python for the first time, working on making a text based adventure game as a project to teach myself. I've managed (I think) to almost get a working "engine" going, (Thanks to the wonderful people here at stackoverflow and over at Gamedev) with only some fine tuning needed before I can work on expanding the game and adding in fun stuff (I'm sure you will all tell me I am wrong and need to change a lot, but hey that's why I'm here.)

Anyway, I'm hitting a wall in my code at line 81.

world = {}


def addToInventory(item):
    player.bag.append(item)


class Items:
    def __init__(self, name, info, weight, position):
        self.name = name
        self.position = position
        self.info = info
        self.weight = weight


class Weapon(Items):
    def __init__(self, name, info, damage, speed, weight, position):
        super().__init__(name, info, weight, position)
        self.damage = damage
        self.speed = speed


sword = Weapon("Sword", "A sharp looking sword. Good for fighting goblins!", 7, 5, 5, 0)
knife = Weapon("Knife", "A wicked looking knife, seems sharp!", 5, 7, 3, 5)
stick = Weapon("Stick", "You could probably hit someone with this stick if you needed to", 2, 3, 3, 2)
shackkey = Items("Shack Key", "A key! I wonder what it opens.", .01, 3)
cottagekey = Items("Cottage Key", "An ornate key with an engraving of a small cottage on one side", .01, 5)
Moonstone = Items("Moonstone", "A smooth white stone that seems to radiate soft white light", .05, 6)
flower = Items("Flower", "A beautiful wildflower", .001, 1)


class Room:

    def __init__(self, name, description, exits, actions, roominv):  # Runs every time a new room is created
        self.name = name
        self.description = description
        self.exits = exits
        self.actions = actions
        self.roominv = roominv


world['introd'] = Room('introd', "You are in a forest, you can hear wildlife all around you. Your sword lies at your feet. There seems to be a clearing in the distance.", {'N': "clearing"}, {"Search the ground", "Go North"}, [sword])

world['clearing'] = Room('clearing', "You are in a clearing surrounded by forest. Sunlight is streaming in, illuminating a bright white flower in the center of the clearing. To the South is the way you entered the forest. A well worn path goes to the East. In the distance a harp can be heard.", {'S': "introd", 'E': "forest path"}, {"Take flower", "Go south", "Go East"}, [flower])  # Flower is not coded as an item that can be added to inv. To do this, create an ITEM class and make WEAPON a subclass of ITEM, SHOULD ALSO MAKE "KEY" SUBCLASS
world['forest path'] = Room('forest path', "You begin walking down a well beaten path. The sounds of the forest surround you. Ahead you can see a fork in the road branching to the South and East. You can smell smoke coming from the South, and can hear a stream to the East", {'S': "cottage", 'E': "stream"}, {"Go South", "Go East"}, [stick])
world['stream'] = Room('stream', "You come upon a relaxing stream at the edge of the woods. It looks like there is something shiny in the water. To your South is a rickety looking shack, to your West is the forest path you came down", {'S': "shack", 'W': "forest path"}, {"Go South", "Go West"}, [shackkey])

world['shack'] = Room('shack', "In front of you is a shack, possibly used as an outpost for hunting. It looks dilapidated.", {'S': "inside shack", 'N': "stream"}, {"Go South", "Go North"}, None)


world['inside shack'] = Room('inside shack', "The inside of the shack is dirty. Bits of ragged fur are scattered about the floor and on a table against the back wall. A sharp looking knife is on the table. There is a key hanging on the wall by a string.", {'N': "shack"}, {"Go North", "Take Knife", "Take Key"}, [knife, cottagekey])

world['cottage'] = Room('cottage', "A quaint cottage sits in the middle of a small clearing, smoke drifting lazily from the chimney.", {'N': "forest path", 'S': "inside cottage"}, {"Go north", "Go South"}, [Moonstone])

The problem is below, in the Player class.

class Player:
    def __init__(self, name, health, bag, room_name, move):
        self.name = name
        self.health = health
        self.bag = bag
        self.room = world[room_name]
        self.move = move


command = input('>>> ')
player = Player("Jeff", 100, [], 'introd', command)

As you can see below (hopefully), what I'm trying to do is have python take in a users input, check to see if their input is an acceptable direction, then check to see if there is an exit corresponding to that direction, and if there is, to set the player's room to the room corresponding to that exit.

Unfortunately, it's not letting me use my command attribute as the "direction" argument in the player.move method.

def move(self, direction):
    if direction not in self.Room.exits:
        print("You can't go that way!")
        return
    new_room_name = self.Room.exits['Room']
    print("moving to", new_room_name)
    self.room = world[new_room_name]


while True:

    if command in {'N', 'E', 'S', 'W'}:
        **player.move(command)**
    elif command == 'look':
        print(player.room.description)
        print('Exits', player.room.exits.keys())
    else:
        print('Invalid command')

Traceback (most recent call last):
  File "C:\Users\Daniel\Desktop\PythonPR\FlubbosRoomAndItem.py", line 81, in <module>
    player.move(command)
TypeError: 'str' object is not callable

My problem here stems from a general unfamiliarity with Python. I'm still learning the basics and using this project as a kind of "crash course" while also studying youtube tutorials. This is something that nags me as probably having a simple solution, but I don't even know where to begin to look. Searching the error hasn't helped as it's something that comes up in many different situations from what I gather.

Anyway, there are other problems in this code, but those are things that I'd rather figure out on my own so no need to nitpick me too hard unless there is something alarmingly wrong that I need to fix. Any tips, Pseudo-code/just telling me what the hell to google would be much appreciated. Thanks.


Solution

  • You have an attribute on your instance named move:

    class Player:
        def __init__(self, name, health, bag, room_name, move):
            # ...
            self.move = move
    

    This masks the method. Attribute look-up on an instance first looks at the instance attributes before attributes (including methods) on the class are found.

    Rename that attribute or the method.