rmed

blog

Good old text adventures

2016-03-14 20:49

Some days ago I fixed/updated my micro-engine for text adventures: texture. This project was first created for a minigame we had planned at GUL UC3M for an event at the University: El discurso de Zoe (Zoe's speech). Here is a showcase of the game in action (in Spanish).

Funny thing is, this is not my first project related to text adventures.

The beginning

Some years ago (three, actually), while I was on holiday, I was talking to my brother about good old text adventures like Zork. If I recall correctly this was due to a reference to the game that appeared in a TV show. I reached the conclusion that I could write some sort of engine for this kind of games in Python in order to get more experience with the language (back then I was just getting started with Python). That's how I started writing TextVentures.

I thought I could write something so generic that anyone willing to use it wouldn't need to write any Python code. Therefore I decided to base all the architecture for adventures around XML files. Nowadays, I can't believe I actually thought that was a good idea. By writing scenarios using XML files, there were more limitations than benefits: no game state, no inventory (did I even think about implementing that kind of functionality?), rather large scenario files, etc. A scenario looked like this:

<scenario>
    <!-- Basic data of the scenario -->
    <!-- Title of the scenario -->
    <title>Chapter 1: Prelude</title> 
    <!-- Paragraphs with text of the scenario. Paragraphs are separated by a blank line  -->
    <scenariop>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec id eleifend orci. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Nam leo arcu, blandit et sollicitudin at, consectetur in leo. Nulla vestibulum semper scelerisque. Phasellus ornare facilisis sollicitudin. Aliquam elementum nisi ut lectus semper eu.</scenariop>
    <scenariop>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec sed orci vel nibh vehicula lobortis vel ut augue. Fusce massa arcu, congue id volutpat sit.</scenariop>

    <!-- List of actions -->
    <!-- Action input 'default' is executed when the player writes an unknown command. There can only be one of these -->
    <action input="default" type="text" content="That does not seem to be of any help here"></action>
        <!-- Type 'print' will print a message on screen -->

    <!-- Action input 'player' is executed when the input of the player is equal to any of the commands -->
    <action input="player" type="jump" content="Chapter_2">
        <!-- Type 'jump' will lead the player to another scenario, in this case, the destination file of the jump is Chapter_2 -->
        <command>onward</action>
        <command>forward</action>
    </action>
</scenario>

I did, however, take into account the localization of the adventures, which was done by creating subdirectories with a two-character language code, as well as state saves (using XML... again...). The user would simply need to choose the adventure to start using the CLI included in TextVentures in order to start playing.

Enter texture

Back to the future (pun intended). I now know just a bit more Python and can write more complex things. I directly scrapped the idea of creating something generic and instead focused on making it as simple as possible for adventure writers. Python isn't so hard to write, even for newcomers, so writing scenarios for texture is not so hard:

import texture

class Scenario(texture.BaseScenario):

    def load(self):
        if self.state.get('in_start', False):
            # Start of the game
            print('Started the game')
            self.state['in_start'] = True

        else:
            # Already been here
            print('You have already been here')

    def do_action(self, cmd):
        if cmd == 'go south':
            print('You go south')

            # Load different scenario
            return texture.loader('south')

        elif cmd == 'go north':
            print ('You go north')

            # Load different scenario
            return texture.loader('north')

        else:
            # Unrecognized command
            print('What are you doing!?')

            # Optinonally, continue main game loop
            return texture.dotick

That is a complete scenario right there. Instead of considering all possible features that could be included in an adventure, I simply wrote the basic stuff:

  • Main game loop
  • Global game state
  • User input

And decided to let the writer implement what they need without imposing too many restrictions. The result is a very silly micro-engine with a very silly documentation available at http://texture.readthedocs.org/en/latest/ that just works (or should work...).

P.S. Thinking about it, it may be possible to write (not too complex) CLI software using the library as well, how silly can this get!?