Glottys - an event-driven, python based text adventure engine
Daniel - Mar 12, 2012 - Games CodeThis is something I spent the weekend working on: it's an event-driven, python based text adventure engine. I built it for my brother who's interested in learning to write python. I figured I'd write some quick docs for it here, and if you're interested in more features or even contributing, please comment!
It's written to be very new-user friendly and also as powerful as you need it to be -- hopefully, my brother's success with it having never programmed before should be proof of this.
Here's the python module: glottys.zip
If you're looking for an extensive example, here's the game my brother created: fatal_tryst.zip
So, let's launch into creating a text adventure with glottys!
Example game: Trapped!
First things first, create a file called trapped.py, and put it in the same directory as the glottys folder from glottys.zip above.
First things first, import everything you need from the glottys module:
from glottys import *
Great! Now we can create a new game:
Trapped = Game('Trapped!')
And some areas:
Cell = Area('Cell')
Street = Area('Street')
Now let's link the two areas:
Cell.add_path(North, Street)
Because our cell is locked, we want to disable the escape route for now!
Street.disable()
Now let's create our protagonist:
Convict = MainCharacter('Convict', game=Trapped, startlocation=Cell)
And some items for our area, along with the descriptions for our first puzzle:
Window = StaticItem('Window', owner=Cell)
Wall = StaticItem('Wall', owner=Cell)
Wall.description = 'This wall is made up of some pretty loose bricks. I wonder if I can move them?'
Bricks = StaticItem('Bricks', owner=Cell)
Bricks.description = 'These {self} look pretty loose!'
Bricks.use_text = 'You break through the loose {self} easily, revealing an escape route to the street'
Bricks.hide()
Now let's add some of the mechanics of our game. First, we need to reveal the bricks when the wall is looked at, using the onLook event:
@Wall.onLook def revealbricks(): Bricks.show()
Now, we need to let the player use the bricks to break through the wall:
@Bricks.onUse def createhole(): Street.enable()
Now, all we need to do is finish the game when the user moves into the street!
@Street.onEnter def endgame(): Trapped.endgame()
Great! Now we've declared our game, let's run it:
Trapped.run()
The full source for this example is available at http://bluesuncorp.co.uk/files/articles/glottys-event-driven-python-based-text-adventure-engine/trapped.zip
Key Concepts
Let's take a look at some of the concepts we've dealt with in making our game. First, we have game objects, which we create. So:
Cell = Area('Cell')
The first parameter of a game object will always be its name. Other parameters may be available or required, depending on the type of object. (see below)
Next, we have object attributes, which determine how individual objects behave. Most of these at present allow you to change the default text which appears when something happens in relation to the object. So, for example:
Bricks.description = 'These {self} look pretty loose!'
Note that the {self} in this string refers to the name of the object, which is automatically filled out for you.
Next, we have object methods, which allow us to "do" things with the object. For example:
Street.enable()
Finally, we have events, which allow us to perform actions whenever something happens in relation to an object:
@Wall.onLook def revealbricks(): Bricks.show()
If you want to cancel the default action for an event (for example, if you want to prevent a character from looking at an item) just return False in your event function.
Commands
There are a number of commands built into the engine, and you can also define your own. The defaults are:
- Use <item1> [item2] [etc]
- Look [item]
- Get <item>
- Move <direction>
- Open <item>
- Talk <character>
- Drop <item>
- Inventory
- Help
Defining your own commands couldn't be easier:
@Command('sleep'):
def dosleep():
MyGame.echo('You doze off for a few hours and awake refreshed')
Conversations
Defining a conversation is as simple as creating a character, and defining the conversation threads:
Zombie = Character('Zombie', location=Crypt)
Hello = Thread('Hello Zombie', 'Brraaaaaaaiins', character=Zombie)
Escape = Thread("I'm getting out of here...", 'Waaaaaagh', parent=Hello)
Respond = Thread("I don't have any brains...", 'Mmmhghhh', parent=Hello)
Use / Combinations
If you want to use two or more objects together, the syntax is simple:
@Use(Rake, Leaves)
def tidylawn():
MyGame.echo('The lawn is tidy now!')
Alternatively you can have a combination of items return another item:
@Use(Flour, Milk, result=Pancake)
def makepancake():
MyGame.echo('Yum, pancake!')
Available objects, attributes, methods and events
In order to really flesh out your game, you'll want to know the full range of available object types, attributes, methods and events. Here they are!
Game
Parameters:
- name: the name of your game
Attributes:
- intro_text = 'Welcome to... {self}'
- end_text = 'End of game {self}'
Methods:
- run(): run your game after creating it
- help(): print out help text
- endgame(): end the game
Events:
- onRun: when the game is run
- onExit: when the game is exited
- onEndGame: when the user reaches the end of the game
Area
Parameters:
- name: the name of the area
Attributes:
- first_enter_text = None
- enter_text = 'You enter {self}'
-
enter_fail_text = 'You can not currently enter {self}'
-
look_area_text = 'You are in {self}'
- look_inventory_text = 'You can see the following items: {items}'
- look_character_text = 'You can see the following people: {self.characters}'
- look_direction_text = 'To the {direction} is {location}'
Methods:
- add_path(direction, area): Create a path from direction to area
- enable(): Enable area
- disable(): Disable area
- look(): Look at area
- enter(character): Have the character enter the area
Events:
- onLook: when the player looks at the area
- onFirstEnter: when the player first enters the area
- onEnter: when the player enters the area
- onExit: when the player leaves the area
MainCharacter
Parameters:
- name: the name of the character
- game: the game the character is associated with
- startlocation: the area the player will start in
Attributes:
- move_text = 'You move {direction}'
- inventory_text = "I'm carrying {items}"
Methods:
- move(direction): move the character in the given direction
- pickup(item): have the character pick up the given item
- open(item): have the character open the item
- look(): have the character look at the current area
- talk(character): have the character talk to the given character
- checkinv(): list the character's inventory
- discard(item): have the character discard the given item
- has(item): check if the player has the given item
- drop(item): have the character drop the given item
- give(item): give the character the item
- use(*items): have the character use the given items together
Events:
- onMove: when the character moves
- onPickup: when the character picks an item up
- onLook: when the character looks
- onOpen: when the character opens an item
- onCheckInv: when the character checks their inventory
- onUse: when the character uses an item
- onDiscard: when the character discards an item
Character
Parameters:
- name: the name of the character
- location: the location of the character
Attributes:
- description = "It's {self}"
- talk_fail = "I don't think I want to talk to {self}"
Methods:
- talk(): begin talking to the character
- look(): look at the character
Events:
- onLook: when the character is looked at
- onTalk: when the character is talked to
InventoryItem / StaticItem
Parameters:
- name: the name of the item
- owner: the owner of the item (a character, area, or container item)
- synonyms: a list of synonyms
- container: whether the item is a container or not (may contain other items and be opened, etc.)
Attributes:
-
description = 'This is a {self}'
-
use_text = 'You can not use {self}'
-
pickup_text = 'You pick up {self}'
-
pickup_fail_text = 'You can not pick up {self}'
-
open_text = 'You open {self}'
- locked_text = '{self} is locked'
- empty_text = '{self} is empty '
-
not_container_text = '{self} is not a container'
-
contains_text = '{self} contains {items}'
-
discard_text = 'You discard {self}'
- discard_fail_text = 'You might need the {self}, probably best to keep it for now'
Methods:
- look(): look at the item
- open(inventory, staticitems): open the item
- pickup(location, inventory): pick up the item
- discard(): discard the item
- use(): use the item
Events:
- onPickup: when the item is picked up
- onLook: when the item is looked at
- onFirstLook: when the item is first looked at
- onUse: when the item is used
- onOpen: when the item is opened
- onDiscard: when the item is discarded
Thread
Parameters:
- query: text which is said to the character
- response: text response to the main character
- parent: parent thread
- persistent: whether or not the thread remains after being activated
- character: the character the thread applies to (only necessary for top level thread)
- uplevel: whether or not the thread takes the conversation up a level
- end: whether or not the thread ends the conversation
- auto: whether or not the thread is automatically selected if it is the only remaining option
Methods:
- initiate(): initiate the conversation thread
- endconversation(): end the conversation
Events:
- onInitiate: when the thread is initiated
- onDialogue: after the query and response, before the options are presented
- onEnd: when the conversation is ended

Robert Ian Hawdon
Wow, a new post!
I'll have to check this out :D
Tarball Mcgee
Wow, Interesting. I'll have to check this out! Any way that games made with Glottys can play sound &/or display graphics? I know Pygame can do this, but is there any way I can do this with Glottys? Thanks in advance, Tarball.