Zork like text based game python

Started by
18 comments, last by BeerNutts 10 years, 1 month ago

also can someone help me with using multiple source files in python?

the game is getting large now so I want to put new functions on a separate file but i'm having trouble getting it to work.

I know in C you could just do "#include whatever.c" or something

right now I have main.py

I want to create a blank file called functionstwo.py to add into main

EDIT: SOLUTION FOUND

Advertisement

also can somebody tell me how to error handle no input

for example below is a typical function in my game to handle an "area" or "room" - if the command isn't part of any of the IF tests, it simply prints "unknown command"

but if the player types no input and just presses enter, the game crashes. How should I check for no input in the "command" variable to then print "please enter a command" instead of the game just crashing? Thanks in advance!


def southernfields():
    here = 1
    print("Southern Fields")
    while here == 1:
        command = str(input("\n> "))
        lowcommand = command.lower()
        splitCommand = lowcommand.split()
        if splitCommand[0] == "inv" or splitCommand[0] == "inventory":
            globalz.displayinventory()
        elif splitCommand[0] == "talk":
            print("nobody here to talk to")
        elif splitCommand[0] == "attack":
            print("nothing here to attack")
        elif splitCommand[0] == "look":
            print("You are in vegetation filled fields to the south of the castle. To the north, archers can be seen practicing"
            " near the castles southern wall. To the east, more plains are seen on the horizon. To the west, mountainous terrain"
            " with what looks like a tower barely visible in the distance.")
            print("\nitems: ")
            itemsize = len(globalz.southernfieldsitems)
            if itemsize > 0:
                for i in globalz.southernfieldsitems:
                    print(i)
            else:
                print("nothing here")
        elif splitCommand[0] == "take":
            size = len(splitCommand)
            if size > 1:
                    if splitCommand[1] in globalz.southernfieldsitems:
                        if globalz.playeritems < 5:
                            globalz.inventory.append(splitCommand[1])
                            globalz.southernfieldsitems.remove(splitCommand[1])
                            globalz.playeritems += 1
                            print(splitCommand[1] + " taken.")
                        else:
                            print("you cannot carry more than 5 items.")
                    else:
                        print("there is no item of that sort here")
            else:
                print("take which item?")
        elif splitCommand[0] == "drop":
            size = len(splitCommand)
            if size > 1:
                if splitCommand[1] in globalz.inventory:
                    globalz.inventory.remove(splitCommand[1])
                    globalz.southernfieldsitems.append(splitCommand[1])
                    globalz.playeritems -= 1
                    print(splitCommand[1] + " dropped.")
                else:
                    print("you have no such item")
            else:
                print("drop which item?")
        elif splitCommand[0] == "examine":
            size = len(splitCommand)
            if size > 1:
                    if splitCommand[1] in globalz.southernfieldsitems or splitCommand[1] in globalz.inventory:
                        globalz.whatisit(splitCommand[1])
                    else:
                        print("no such item")
            else:
                print("examine which item?")
        elif lowcommand == "go east":
            here = 0
            easternfields()
        elif lowcommand == "go west":
            here = 0
            westernfields()
        elif lowcommand == "go north":
            here = 0
            northern1()
        elif lowcommand == "go south":
            print("South leads back to the villages where you came from, the people aren't expecting you to return"
            " until your task is done...")
        elif lowcommand == "go":
            print("go where?")
        elif lowcommand == "location":
            print("southern fields")
        elif lowcommand == "status":
            globalz.displaystatus()
        elif splitCommand[0] == "use":
            size = len(splitCommand)
            if size > 1:
                if splitCommand[1] in globalz.inventory:
                    globalz.usewhat(splitCommand[1])
                else:
                    print("you have no such item")
            else:
                print("use which item?")
        else:
            print("unknown command")


also can someone help me with using multiple source files in python?


also can somebody tell me how to error handle no input

If you have a new problem it's best to start a new topic. This makes it easier for other people who have the same problem in the future find a thread that might have the answers they're looking for.





There are a few things going on that you should think about:


def displayinventory():
print("\nInventory:")
for i in inventory:
print(inventory)

You're printing "inventory" for each item "i". You should have: "print i" not "print inventory" (no need for () around the parameter)

That is only valid if you are not using python 3.0+ so it is generally consider a better practice to use the parentheses because it works across more version of python.

-Josh

You would be printing i as a tuple in versions of Python preceding 3.0 .

Not sure what you mean, but calling print(i) simply prints out the value of i in either python2 or python3 and has nothing to do with tuples.

-Josh

You are right:

(it is not sufficient to enclose a single value in parentheses).
Intel Core 2 Quad CPU Q6600, 2.4 GHz. 3GB RAM. ATI Radeon HD 3400.

Jonathan,

The way you're going about writing that single room is going to lead to A LOT of coding. Let me show you a little snippet of pseudo-code that might give you an idea of a generic way to handle this stuff


# setup the 'field' room
Rooms['field'].description = "You are in a large wheat field.  It looks to have been recently harvested."
Rooms['field'].exits = {'n': 'outside_house', 'e': 'well'}
Rooms['field'].items = ('sycthe')
 
# setup the 'well' room
Rooms['well'].description = "You are standing, looking down a well."
Rooms['well'].actions = ('cut rope')
Rooms['well'].exits = {'w': 'field'}
 
# setup 'outside_house' room
Rooms['outside_house'].description = "You're standing outside an old farm house."
Rooms['outside_house'].exits = {'s': 'field'}
 
currentRoom = 'field'
 
while isRunning:
  # print the description of the current room
  print Rooms[currentRoom].description
  # list the items in the room
  if Rooms[currentRoom].items:
    while item in Rooms[currentRoom].items:
      print ' You see a ' + item
  print 'The available exits are: '
  while exitDirs in Rooms[currentRoom].exits:
    print exitDirs 
  print 'command> '
 
  # get the command
 
  # check for all the generic commands: look, invenrtory, help, quit, etc.
 
  # loop through all the possible exits for this room
  while exitDirs in Rooms[currentRoom].exits:
    if command[0] == exitDirs:
      # change our room to this one
      currentRoom = Rooms[currentRoom].exits[exitDirs]
      break
    # if the user issues  aget, check the item is in the room...
    if command[0] == 'get':
      while item in Rooms[currentRoom].Items:
        # if so, add the item to the inventory, and remove the item form the room
        if command[1] == item:
          Inventory.append(item)
          Rooms.currentRoom].Items.remove(item)
  # check if the user performed some available action
  while action in Rooms[currentRoom].actions:
    if command == action:
      PerformAction(currentRoom, action)
      break
 
def PerformAction(currentRoom, action):
  # check the room versus the action and see if it's still viable

I know the above will not compile in python (I've done very little in it), but you should be able to get the gist of it.

My Gamedev Journal: 2D Game Making, the Easy Way

---(Old Blog, still has good info): 2dGameMaking
-----
"No one ever posts on that message board; it's too crowded." - Yoga Berra (sorta)

thanks BeerNutts, I see what you mean. I can see my code is really "dirty", does the pseudo code you use things like classes and objects?

thanks BeerNutts, I see what you mean. I can see my code is really "dirty", does the pseudo code you use things like classes and objects?

It can use a class, but it doesn't have to. You can use dict's to hold the Rooms variables as well.

If using dicts...


Rooms['field'] = {'description': 'You are in a large wheat field.  It looks to have been recently harvested.', \
                          'exits': {'n': 'outside_house', 'e': 'well'}, 'actions': [], 'items': ['scythe']}
...
# and access them via
print Rooms['field']['description']

Or If you use classes, it might be like this:


class Room:
  def __init__(self, description, exits, actions, items)
    self.Description = description
    self.Exits = exits
    self.Actions = actions
    self.Items = items
  
Rooms['field'] = Room("You are in a large wheat field.  It looks to have been recently harvested.", \
                                    {'n': 'outside_house', 'e': 'well'}, [], ['scythe'])
...
# And access them like this
print Rooms['field'].Description
 

I think that's how it works (again, my python is shaky), but you should get the idea. Keep working at it and you'll get it. Use the internet to find the answers.

My Gamedev Journal: 2D Game Making, the Easy Way

---(Old Blog, still has good info): 2dGameMaking
-----
"No one ever posts on that message board; it's too crowded." - Yoga Berra (sorta)

thanks very much :)

ok i've started doing a new one to test classes and OOP for the first time, so i'm very new to this part of programming, before as you've seen I would just have global variables and functions all over the place for every room etc. So i'm seeing how much I can condense it and if it's possible to just have a class, a main game loop, and a few check command side functions.

Below is what i've come up with so far, what i'm struggling with already is performing the actions of "go north" or whatever and then performaction function knowing where "go north" is from the current room so I can change the room in the main loop. Any suggestions on the lay-out and basic design so far? Is it possible to have just one main loop for a reasonably interactive text game or am I destined to add a few room functions again?

thanks for any help


import sys, os, time

inventory = []
Running = True

class Room:
    def __init__(self, name):
        self.name = ""
        self.desc = ""
        self.items = []
        self.actions = []
    def addItem(self, item):
        self.items.append(item)
    def addAction(self, action):
        self.actions.append(action)


entrance = Room("Entrance")
entrance.name = "Entrance"
entrance.desc = "You are in at the entrance of the town"
entrance.addItem("Pistol")
entrance.addAction("take pistol")
entrance.addAction("go north")

def main():
        currentRoom = entrance
        while Running == True:
            os.system('clear')
            print("\n\nTest Game\n----------\n\n")
            print(currentRoom.name)
            print("\n" + currentRoom.desc)
            if currentRoom.items:
                print("\nAvailable items:")
                for i in currentRoom.items:
                    print(i)
            command = str(input("\n> "))
            checkaction(currentRoom, command)


def checkaction(room, action):
    if action in room.actions:
        print("Valid action")
        performaction(room, action)
    if action == "inv" or "inventory":
        size = len(inventory)
        if size > 0:
            for i in inventory:
                print(i)
                input("")

def performaction(room, action):
    if action == "take pistol":
        inventory.append("Pistol")
        room.items.remove("Pistol")


main()

You really need to link exits. In all text adventure games, moving in a direction is done via a single letter: n, e, s, w, u, d (up and down are the last 2). You really should assign exits to rooms, and be able to easily link rooms to exits, as I showed in my example above.

Also, I would not include the name of the room in the class defintion, I'd use the name as the key in a dictionary. The dictionary is a mapping of room names to Room objects

Also, you need to use the class constructor. Why pass in the name if you don't assign it in the constructor? In my rooms, all Room variables require at least 2 things: description and exits (as a list of dictionaries). Create your constructor to take those in and use them:


class Room:
def __init__(self, description, exits):
  self.desc = description
  self.exits = exits
  self.items = []
  self.actions = []
 
# This creates a room with the key being the room name Entrance, and the single exit n (north) leads to the room Town_Gate
Rooms['Entrance'] = Room("You are at the entrance to a town", {'n' : 'Town_Gate'})
 
# This creates a room with the key being the room name Town_Gate, and 2 exits, s, back to entrance and e leads to the room Town_Square
Rooms['Town_Gate'] = Room("You are at the gates of the town.", {'s' : 'Entrance', 'e' : 'Town_Square'})
 
# This is copied almost EXACTLY from my post a few posts ago, it just shows how you use the variable CurrentRoom, which is the key  into the dictionary Rooms
 
# start at entrance
currentRoom = 'entrance'
 
while isRunning:
  # print the description of the current room
  print Rooms[currentRoom].description
  # list the items in the room
  if Rooms[currentRoom].items:
    while item in Rooms[currentRoom].items:
      print ' You see a ' + item
  print 'The available exits are: '
  while exitDirs in Rooms[currentRoom].exits:
    print exitDirs 
  print 'command> '
 
  # get the command
 
  # check for all the generic commands: look, invenrtory, help, quit, etc.
 
  # loop through all the possible exits for this room
  while exitDirs in Rooms[currentRoom].exits:
    if command[0] == exitDirs:
      # change our room to this one
      currentRoom = Rooms[currentRoom].exits[exitDirs]
      break
  # if the user issues a get for the 1st word, check the item is in the room...
  if command[0] == 'get':
  while item in Rooms[currentRoom].Items:
    # if so, add the item to the inventory, and remove the item form the room
    if command[1] == item:
    Inventory.append(item)
    Rooms.currentRoom].Items.remove(item)

  # check if the user performed some available action
  while action in Rooms[currentRoom].actions:
    if command == action:
      PerformAction(currentRoom, action)
      break
 
def PerformAction(currentRoom, action):
  # check the room versus the action and see if it's still viable

My Gamedev Journal: 2D Game Making, the Easy Way

---(Old Blog, still has good info): 2dGameMaking
-----
"No one ever posts on that message board; it's too crowded." - Yoga Berra (sorta)

This topic is closed to new replies.

Advertisement