0

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.

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
SchrodingersStat
  • 291
  • 3
  • 19
  • Besides the fine answer from Martijn Pieters the line `new_room_name = self.Room.exits['Room']` may cause a problem (if I understand correctly). This should possibly be `new_room_name = self.Room.exits[direction]`. – mkiever Jul 11 '17 at 17:34

2 Answers2

2

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.

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
  • Hey, I tried this unfortunately it did not work. I tried renaming both the attribute and the function separately, both led me to the same error regarding strings not being callable. – SchrodingersStat Jul 11 '17 at 18:02
  • Without a proper [MCVE] that's impossible to follow up on. Make sure you have restarted your interpreter; if you renamed the method *and* the call (so `def do_move(...): ...` and `player.do_move()` *and the traceback did not change* you did not run the new code. – Martijn Pieters Jul 11 '17 at 18:09
  • Hi Martjin, sorry that actually did solve the error I asked about, I made a couple mistakes while re-naming. – SchrodingersStat Jul 11 '17 at 18:19
  • 1
    @Schrodinger'sStat: sorry, you can't just go and change your question to something else. Please post a **new** question with the new problem you have. Posts here are meant to be helpful to future visitors, not just to you, and we want question and answer posts to form a whole. By altering your question, you just made this answer wrong and out of place. I had to roll back your question, making the other answer wrong and out of place. You did both me and the other answerer a disservice here. – Martijn Pieters Jul 11 '17 at 20:48
0

The travel function is defined outside of your Player class. It takes two arguments instead of one. I'm assuming you meant to have it defined in the class? Indent the travel function and move it under the Player class.

MxLDevs
  • 19,048
  • 36
  • 123
  • 194
  • Hi, I moved my travel function into the Player class like you said, however it was still not taking command as my argument. I then added in self to the travel(command) call as a first argument, and it worked. Thank you. – SchrodingersStat Jul 11 '17 at 19:16
  • Sorry, the OP should not have changed the question like that. I've rolled back the question to the original state. – Martijn Pieters Jul 11 '17 at 20:49
  • Given the original question, Martjin Pieters answer would be correct. – MxLDevs Jul 11 '17 at 20:51