Examples:

  • HelloWorld.inf
  • ITP.inf
  • Two starter kits by Nick Montfort
  • IBG examples by Roger Firth and Sonja Kesserich. Use along with the Inform Beginnner’s Guide.
  • Reading:

  • Toward a Theory of Interactive Fiction, Nick Montfort
  • Interactive Fiction Recommendations, Nick Montfort (pick one to play and write a short response on the course blog.)
  • The Inform Beginner’s Guide, Chapters 1-5
  • Twisty Little Passages, Nick Montfort (suggested)
  • Inform User’s Manual (suggested)
  • Assignment:

  • Develop your own interactive fiction work using Inform. Feel free to work in groups and base your story off of the provided examples. Keep it simple. Do not feel obligated to make your work a game or puzzle. Publish your work along with the source to the course blog.
  • Exercises (optional):

  • Examine the simple ITP text adventure above. What is missing? What doesn’t really make sense / work? Can you fix / improve it?
  • Why Interactive Fiction

    Interactive Fiction (IF), sometimes referred to as “text adventure” and not to be confused with Hypertext Fiction, describes an experience where a user inputs text and receives a reply in the form of text output. Interactive fiction walks back and forth across the line between literary narrative and computer game where a player character, or “interactor,” explores a simulated world.

    To date, we’ve focused our energies on strategies and techinques for programming algorithms that analyze and generate text, mostly in Java, with some discussion of perl / php along the way. Why take a break for interactive fiction? First and foremost, playing interactive fiction is good for you. The skills you pick up problem-solving your way through a simulated world are the same skills you need to write good code. Logic, creativity, ingenuity, organization.

    Part of our goal this semester is to look at ways a computer can understand and process text, whether in the form of natural language or simply as abstract data. Interactive fiction deals with this problem head on and has been since 1975 when Will Crowther, a programmer and cave enthusiast, developed Adventure in Fortran. Learning the basics of this stripped-down-to-the-bare-text-essentials medium (no hiding behind fancy visualizations) should provide us with some insight into our own process for developing engaging and interesting text-based work. And if you’re feeling particularly saucy, you might run with this and consider entering your work in the annual Interactive Fiction competition.

    How to play: Interpreters and basic commands

    Just as java programs run on a Java vitual machine (the same java bytecode can be run on different platforms as long as a virtual machine exists for that platform) most interactive fiction programs run via a virtual machine, also known as an “interpreter.” For the Mac OS X, I suggest you download and install Zoom as your interpreter, for Windows: Windows Frotz 2002. Note that not all interactive fiction works exist as Z-code files that run on Z-machine interpreters. TADS (Text Adventures Development System) is also a popular authoring tool for IF and for these works, you’ll need a TADS interpreter.

    If you want to incorporate IF into your java programs, you might be interested in checking out zplet, an open-source java interpreter. Here’s an example of the IF work Shade by Andrew Plotkin running as a zplet.

    zork

    A comprehensive resource for tools to play IF can be found on the Interactive Fiction wiki. To find works, you might look through the Interactive Fiction Archive or check out this list of recommendations by Nick Montfort. Baf’s Guide to the Interactive Fiction Archive is another good resource.

    Exploring interactive fiction worlds is often a relatively intuitive process (certainly, there are exceptions). However, if you’re new to it, there are some useful conventions and familiarizing yourself with a few basic commands (see: this article) will help you get started.

    Some examples of common IF commands:

    >look
    >examine something
    >take something
    >go west
    >north
    >put something in something
    >open something
    >listen to something (or someone)
    >up
    >exit
    >inventory
    >give something to someone
    

    Inform: compiling

    To develop your own interactive fiction works, you’re probably going to want to use an existing authoring environment, such as Inform or TADs. The following instructions document how to compile interactive fiction works using Inform on a Mac (PC instructions).

    First, download the appropriate compiler for your system. Extract the files to your hard drive. With the Mac OS X compiler, you’ll have two crucial elements: “inform630_macosx” — the executable compiler — and “lib” — a directory with all the required library files. (Note you may find it interesting to look through the library files, as they will provide insight into the guts of the Inform parser.)

    Ok, you’re ready to compile. Download HelloWorld.inf and use the syntax below (note I placed the inform compiler in the applications directory, but you may have placed it somewhere else).

    $ /Applications/inform/inform630_macosx +include_path=/Applications/inform/lib/ HelloWorld.inf
    

    Some basic unix knowledge can make life a little easier, you probably want to consider making an alias (syntax below is for bash):

    $ alias inform='/Applications/inform/inform630_macosx +include_path=/Applications/inform/lib'
    

    You might also consider adding the alias to your profile (.profile or .bash_profile depending on your shell) to make it permanent. With the alias compiling is less wordy:

    $ inform HelloWorld.inf
    

    How it might look:
    compiling

    Compiling should yield the z-code file HelloWorld.z5 which you can then run with Zoom.

    Inform: coding

    For a full guide to programming interactive fiction with Inform I suggest you read the Designer’s Manual or the Inform beginner’s guide. David Cornelson’s House Tutorial is also an excellent resource. In addition, Nick Montfort provides two introductory starter kits for Inform.

    Fortunately, we have a head start here since we already understand basic computer programming concepts such as conditional statments, variables, arrays, functions, and objects (an understanding of object-oriented design is fundamental to IF development). The following is not, by any means, a substitute for the above resources. This brief discussion barely scratches the surface of IF development and glosses over some of the finer points.

    Comments

    Any text that appears after an exclamation point is ignored by the compiler as a comment:

    !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    !  Hello World
    !  HelloWorld.inf
    !  by Daniel Shiffman
    !  Example for Programming from A to Z, Spring 2006
    

    Variables

    Global constants/variables are defined at the top.

    Constant Story "ITP";
    Constant Headline
                "^A simple Inform example
                 ^A story about ITP
    	     ^by Daniel Shiffman.^
    	     ^Programming from A to Z, Spring 2006^
    	     ^Special thanks to the examples of Nick Monfort, Roger Firth, and Sonja Kesserich^";
    

    The “Story” and “Headline” are displayed to the user when the game begins (if you didn’t declare and define them, nothing would appear.) A ^ inside a string is a metacharacter that indicates new line.

    Including Libraries
    It’s also necessary to import the appropriate libraries, using an “include” statement. “Parser” and “Verblib” are the fundamental components of the Inform parser library. Nothing will work without including them!

    Include "Parser";
    Include "VerbLib";
    

    Objects
    Everything in your interactive fiction world is an Object. Objects can be defined with the following elements:

  • object_id – this is essentially your “variable name” for the object, i.e. how you refer to it in your source code.
  • interpreter_name — this is the name that the interpreter will display when talking about the object
  • parent_object — if the object has a parent. For example, the parent of a “sheep” object might be a “meadow” object, assuming the sheep in your story lives in a meadow. Generally speaking, “room” objects do not have parents and things that are found in a room are “children” of room objects.
  • properties — objects can have one or more properties. For example, an object can have a description property. This is what would appear when the user types “look.” In the case of a “room”, it might have a property like “w_to”. This property would indicate what object is west of a given object. Properties can deal with events and actions associated with a given object. What happens when you take an object or listen to an object, etc.?
  • attributes — Attributes are boolean values that describe the state of an object. A room might have “light” or “~light” (no light).
  • There’s more things you can do with objects, but these basic elements will get you started!
  •  
    Let’s look at the basic syntax for describing an object:

    Object   object_id "interpreter name" parent_object_id
    with     property value,
             property value,
             .
             .
             .
             property value,
    has      attribute attribute . . . attribute
    

    For example, a computer lab in the example ITP.inf is described as follows:

    Object  lab "The Computer Lab."
      with  description
              "A mysterious figure in the corner types madly at a keyboard.
    	   To the west is a classroom. You see a printer.",
            e_to lobby,
            w_to four0four,
      has   light;
    

    Translated the above code reads as follows: Define an object called “lab” that will be displayed as “The Computer Lab” to the user. The object has no parent (it is a room.) Display this description when the user enters the lab. The object (room) “lobby” is to the east, and “four0four” is to the west. There is light in the lab so the user can see things upon entering.

    We could also place an object in the lab. For example:

    Object  student "mysterious figure" lab
      with  description
               "The mysterious figure appears to be a stressed out student, quietly muttering.",
            name 'student' 'person' 'figure' 'man' 'woman' 'mysterious figure',
            before [;
              Listen: "Paper.  It needs paper.  Find the paper.";
            ],
      has   scenery;
    

    Note the additional properties. “Name” indicates all the possible valid words that can be used to refer to a given object. The “before” block handles events and actions that occur in association with that object. If the user types “Listen to person,” the interpreter will reply with the above message. Before indicates we want our code to be executed before the default action taken by the interpreter. If we wanted something to happen afterwards, we would use after. This object is also “scenery”, meaning it cannot be removed from the parent, nor will the user be made aware of its existence upon entering the room (note the description of the computer lab explicitly mentions the so-called “mysterious figure.”)

    In some examples, you will see an alternative syntax for creating a parent-child relationship between objects. The code below is equivalent to above (assuming the “student” object appears directly after the “lab”).

    Object -> student "mysterious figure"
    

    We can also use conditional statements inside our objects to handle different events depending on what has occured previously, what is currently in the user’s inventory, etc. Here’s a slightly more advanced object, a “printer” which also resides in the computer lab.

    Object  printer "printer" lab
      with  description
               "Your standard ol' HP printer.",
     	name 'printer',
            after [;
    	  SwitchOn:
    	  if (paper in printer) {
    	    Achieved(0);
    	    move thesis to printer;
    	    "The printer begins to hum.  Beautiful pages emerge.  It's your thesis!";
    	  } else {
    	    "The printer begins to hum.
    	    A red light blinks and a message reads 'PC Load Letter.'
    	    It beeps loudly.  This is rather annoying.";
    	  }
    	  Receive:
    	  if (noun == paper) {
    	    if (self has on) {
                  Achieved(0);
    	      move thesis to printer;
    	      "The printer begins to hum.  Beautiful pages emerge.  It's your thesis!";
    	    } else {
                  "You should probably turn the printer on.";
    	    }
    	  }
            ],
      has	scenery container openable switchable;
    

    There’s a lot more going on in this object. For example, the printer has many attributes. It is a container, meaning it can hold objects. It is openable, i.e. it can be opened or closed. It is switchable, meaning it can be turned on and off. We are also handling certain types of actions using “after.” When the printer is switched on, if it has paper in it, it prints out a thesis. If it does not have paper it beeps. We are also handling the “Receive” action. Here, the keyword noun works like an argument to “receive,” holding on to a reference to the object that was actually placed in or on an object. (We place objects in a “container” and on a “supporter”). So, in the case of the printer, if it receives paper, assuming it is on, it prints out the thesis. If not, it displays a message indicating that the user should consider turning on the printer.

    This example also includes specific tasks that when achieved by the user increase his/her score. When the thesis is printed, “Achieved(0)” calls a function to indicate the first task has been completed. At the top of the code, we would include the following variables to describe the total number of tasks and respective scores for each task.

    Constant NUMBER_TASKS = 3;
    Constant MAX_SCORE = 3;
    Array task_scores -> 1 1 1;
    

    Routines
    As with any programming language, routines (i.e. functions) will prove to be very useful. The syntax for writing a function is as follows:

    [ function_name argument argument;
      ! whatever code you want
      ! whatever code you want
    ];
    

    Some functions are required. For example, the “Initialise” function defines what happens when the work starts up.

    [ Initialise;
       location = lab;   ! the interactor will begin in the lab
    ];
    

    Grammar and Vocabulary

    Finally, we can extend the grammar / vocabulary of our world by “extending” existing commands or creating our own new ones. For example, this creates a new command “about”:

    Verb "bloop" * noun                                    -> Bloop;
    
    [ BloopSub;
      print "Way to bloop!";
    ];
    

    A verb “bloop” is defined. “noun” indicates that you need to bloop something. “-> Bloop” indicates that the verb should call the subroutine “BloopSub” which simply prints out a message.


    No Responses to “Interactive Fiction”  

    1. No Comments

    Leave a Reply