• Announcements

    • khawk

      Download the Game Design and Indie Game Marketing Freebook   07/19/17

      GameDev.net and CRC Press have teamed up to bring a free ebook of content curated from top titles published by CRC Press. The freebook, Practices of Game Design & Indie Game Marketing, includes chapters from The Art of Game Design: A Book of Lenses, A Practical Guide to Indie Game Marketing, and An Architectural Approach to Level Design. The GameDev.net FreeBook is relevant to game designers, developers, and those interested in learning more about the challenges in game development. We know game development can be a tough discipline and business, so we picked several chapters from CRC Press titles that we thought would be of interest to you, the GameDev.net audience, in your journey to design, develop, and market your next game. The free ebook is available through CRC Press by clicking here. The Curated Books The Art of Game Design: A Book of Lenses, Second Edition, by Jesse Schell Presents 100+ sets of questions, or different lenses, for viewing a game’s design, encompassing diverse fields such as psychology, architecture, music, film, software engineering, theme park design, mathematics, anthropology, and more. Written by one of the world's top game designers, this book describes the deepest and most fundamental principles of game design, demonstrating how tactics used in board, card, and athletic games also work in video games. It provides practical instruction on creating world-class games that will be played again and again. View it here. A Practical Guide to Indie Game Marketing, by Joel Dreskin Marketing is an essential but too frequently overlooked or minimized component of the release plan for indie games. A Practical Guide to Indie Game Marketing provides you with the tools needed to build visibility and sell your indie games. With special focus on those developers with small budgets and limited staff and resources, this book is packed with tangible recommendations and techniques that you can put to use immediately. As a seasoned professional of the indie game arena, author Joel Dreskin gives you insight into practical, real-world experiences of marketing numerous successful games and also provides stories of the failures. View it here. An Architectural Approach to Level Design This is one of the first books to integrate architectural and spatial design theory with the field of level design. The book presents architectural techniques and theories for level designers to use in their own work. It connects architecture and level design in different ways that address the practical elements of how designers construct space and the experiential elements of how and why humans interact with this space. Throughout the text, readers learn skills for spatial layout, evoking emotion through gamespaces, and creating better levels through architectural theory. View it here. Learn more and download the ebook by clicking here. Did you know? GameDev.net and CRC Press also recently teamed up to bring GDNet+ Members up to a 20% discount on all CRC Press books. Learn more about this and other benefits here.
Sign in to follow this  
Followers 0
JonathanCCC

Zork like text based game python

19 posts in this topic

hello, 

 

i've an absolute beginner and i'm trying to create a zork like text based game to learn. I have 2 questions, the first is that when I add 2 items to the list "inventory" it displays them like this:

 

flask, knife

flask, knife

 

so it displays them twice and i'm not sure why, also, i'd like it to just display them each on a different line such as

 

flask

knife

 

secondly, i'm sure what I have done so far is a really bad an inefficient way of doing it, are there any tips or ideas I could use to write it better and re-use certain code for the commands etc before I go further? thanks a lot

import os, random, time

global name
name = "unknown"
inventory = []

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

def introduction():
    global name
    print("banner")
    print("do intro text")
    name = str(input("Your name:"))

def easternfields():
    here = 1
    knifetaken = 0
    print("\nEastern Fields")
    print("\nDescription")
    while here == 1:
        command = str(input("> "))
        command.lower()
        lowcommand = command.lower()
        if lowcommand == "inv":
            displayinventory()
        elif lowcommand == "look":
            print("\nYou look around the eastern fields")
        elif lowcommand == "take knife" and knifetaken != 1:
            print("\nknife taken.")
            knifetaken = 1
            inventory.append('knife')
            lowcommand = ""
        elif lowcommand == "take knife" and knifetaken == 1:
            print("knife already taken")
        elif lowcommand == "drop":
            whichitem = str(input("item: "))
            if whichitem in inventory:
                inventory.remove(whichitem)
        else:
            print("\nCommand not recognised")


def southernfields():
    here = 1
    flasktaken = 0
    print("\nSouthern Fields")
    print("\nDescription")
    while here == 1:
        command = str(input("> "))
        command.lower()
        lowcommand = command.lower()
        if lowcommand == "inv":
            displayinventory()
        elif lowcommand == "look":
            print("\nYou look around the southern fields")
        elif lowcommand == "take flask" and flasktaken != 1:
            print("\nflask taken.")
            flasktaken = 1
            inventory.append('flask')
            lowcommand = ""
        elif lowcommand == "take flask" and flasktaken == 1:
            print("flask already taken")
        elif lowcommand == "drop":
            whichitem = str(input("item: "))
            if whichitem in inventory:
                inventory.remove(whichitem)
        elif lowcommand == "go east":
            here = 0
            easternfields()
        else:
            print("\nCommand not recognised")


southernfields()
0

Share this post


Link to post
Share on other sites

I am not sure about what language you are using (I should pay more attention to titles), but it looks to me like this code:

for i in inventory:
        print(inventory)

actually means: "For all items in the inventory, print the entire inventory." ph34r.png'd
So, maybe this will work?

for i in inventory:
        print( inventory[i] )
// Or maybe
for i in inventory:
        print( i )

About the efficiency, don't worry, ignoring this is probably the best thing you can do for now.
Concentrate on learning the basics first, then you can start to think about efficiency.

Edited by dejaime
0

Share this post


Link to post
Share on other sites

thanks alot for your help and suggestions guys,

 

I did indeed fix the inventory listing problem by printing i instead of inventory

for i in inventory:
        print(i)

I also took up the suggestion of adding an item list for each area, allowing the user to drop items and return to them with this code for example:

southernfieldsitems = ['flask', 'shoe']

elif lowcommand == "look":
            print("\nYou look around the southern fields")
            print("\navailable items: ")
            for i in southernfieldsitems:
                print(i)

elif lowcommand == "take":
            takewhat = str(input("item: "))
            takewhatlow = takewhat.lower()
            if takewhatlow in southernfieldsitems:
                inventory.append(takewhatlow)
                southernfieldsitems.remove(takewhatlow)
            else:
                print("There is no item of that sort here")
        elif lowcommand == "drop":
            whichitem = str(input("item: "))
            if whichitem in inventory:
                inventory.remove(whichitem)
                southernfieldsitems.append(whichitem)
        elif lowcommand == "go east":
            here = 0
            easternfields()


I thought about creating a function that waits for the commands but i'm not quite sure how i'd do it because some commands will depend on whats in the area, plus I intend to add things like NPCs etc later on and combat. I suppose I wouldn't know how to pass all the relevant information back and forth between a command function and the area function so it knows what's going on.

 

also you'll notice i've been using 2 variables for the "take" and "drop" command, after you type either it asks you to type which item, that is because I don't know how to check the second word in a string variable so that instead the user could simply type "take flask" all in one line, then I check the second word against the areas item list. Is there an easy way to do that?

 

thanks again :)

 

2

Share this post


Link to post
Share on other sites

Something like this should help.

splitCommand = lowcommand.split()
if splitCommand[0] == 'take':
    takewhat = splitCommand[1]

The split method of strings returns a list of what was in the string separated by whitespace like spaces. So 'take flask' would return ['take', 'flask'].

2

Share this post


Link to post
Share on other sites

 

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]i[/i] as a tuple in versions of Python preceding 3.0 .

0

Share this post


Link to post
Share on other sites

Something like this should help.

splitCommand = lowcommand.split()
if splitCommand[0] == 'take':
    takewhat = splitCommand[1]

The split method of strings returns a list of what was in the string separated by whitespace like spaces. So 'take flask' would return ['take', 'flask'].

 

yep, works perfect thank you

0

Share this post


Link to post
Share on other sites

 



 



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

1

Share this post


Link to post
Share on other sites

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

Edited by JonathanCCC
0

Share this post


Link to post
Share on other sites

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")
0

Share this post


Link to post
Share on other sites


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.

2

Share this post


Link to post
Share on other sites

 

 



 



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

 

[url=http://docs.python.org/3/tutorial/datastructures.html#tuples-and-sequences]You are right:[/url]

(it is not sufficient to enclose a single value in parentheses).
1

Share this post


Link to post
Share on other sites

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.

Edited by BeerNutts
1

Share this post


Link to post
Share on other sites

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?

0

Share this post


Link to post
Share on other sites

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()

0

Share this post


Link to post
Share on other sites

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
Edited by BeerNutts
1

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0