Undum Hypertext Fiction with Vorple

Introduction to Vorple

Vorple is a user interface library for interactive literature. Its goal is to let online hypertext fiction and parser interactive fiction systems break out of their sandboxes and let story authors use the full scale of the vast possibilities of technologies that are commonly used in the World Wide Web.

An author might use Vorple only to theme their story with one of the provided custom themes, or make a multimedia spectacle with pictures, video, sound effects and interactive elements, or anything in between.

A web developer might ask if we really need Yet Another JavaScript Library. There are many general-purpose libraries, like jQuery which Vorple uses extensively, but there are none made specifically for this purpose. Libraries for “normal” web sites work usually by modifying the page elements directly, which is the best choice when you are building on top of an existing structure, but interactive fiction is different in that the content is continuously being pushed from an engine that runs the story.

The project’s headquarters are at vorple-if.com where you’ll find all the official material and downloads. JavaScript developers who want to dig into the innards of the system can find the source code at GitHub.

The library and all official material are open source and free for anyone to use for any purpose. (Mandatory footnote: Do still read all the licenses if you want to use it commercially or as a part of a closed system. Some third party themes, for example, are subject to slightly more restrictive licenses.)

Introduction to Undum

Undum is a JavaScript framework for creating works of hypertext and CYOA games. It is completely browser-based and provides beautiful visual design and smooth interaction out of the box. Undum is created and maintained by I D Millington.

Undum is programmed purely in JavaScript, the native language of all modern web browsers. The framework is very loose, providing only the basic functionality, which makes it easy to add more elements if so needed.

Here are some examples of stories authored with Undum:

More Undum stories can be found at IFDB.

As mentioned before, it’s relatively easy to modify Undum’s functionality and The Matter of the Monster, Leaks and Almost Goodbye all use this possibility to add more features to the stories. The official Undum tutorial uses only the basic features, as do Cavity of Time, The Play and Living Will.

As a contrast to “vanilla” Undum stories, Starborn is a story that uses Vorple to add multimedia features and e.g. an interactive map. Autumn’s Daughter uses Vorple, not for extra features but to facilitate the generation of HTML with Vorple’s helper functions.

How to read this manual

This manual does not teach how to write hypertext fiction with Undum. At the moment the tutorial game at undum.com is the best way to learn the basics. From now on we’ll assume that the reader knows at least how to create situations and actions and the difference between Situation and SimpleSituation.

Here’s how the rest of this manual is structured:

  • Getting started instructs on how to install and set up the system.
  • Developing with Vorple tells how to actually use the system and discusses some of the caveats.
  • Modules is a reference for the included features.
  • Complete examples introduces Vorple stories that can be studied to see how different features are used in actual scenarios.

The manual does not try to be a comprehensive reference. When looking for information about a certain feature, these are the primary learning resources:

  • The API for reference
  • This manual (under Modules) for usage
  • The examples for seeing how it all fits in a larger picture.

Quick start for the impatient

People have different ways of learning new things. For those who learn best by getting their hands dirty from the start and not by reading a book from cover to cover, here’s how to pick the important parts:

Different coding practices

If you have followed the official Undum tutorial you’ll notice that this manual uses slightly different conventions to structure the code.

The official tutorial builds the situations in a single block:

undum.game.situations = {
    start: new undum.SimpleSituation( "..." ),
    foo: new undum.SimpleSituation( "..." ),
    bar: new undum.SimpleSituation( "..." )
};

This manual, and the accompanying examples, create one situation at a time independent of each other.

undum.game.situations.start = new undum.SimpleSituation( "..." );
undum.game.situations.foo = new undum.SimpleSituation( "..." );
undum.game.situations.bar = new undum.SimpleSituation( "..." );

There’s a small caveat associated with the latter method: Undum allows hyphens in situation names. If a situation’s name contains a hyphen, it must be created using again a slightly different syntax:

undum.game.situations[ "end-scene" ] = new undum.SimpleSituation( "..." );

Both approaches are functionally equal. The reason why this manual takes a different approach is mainly because by creating the situations independently there’s no need to include a complete story for each code snippet, and secondarily because it reduces the amount of required punctuation and therefore reduces the possibility of mistakes.

Another difference is that long lines of text are split to multiple lines by concatenating smaller strings instead of using backslashes at the end of lines. That is, the Undum tutorial does this:

"<p>Now we're almost at the end of the road. But so\
far you have moved through this tutorial linearly - from one\
situation to the next, without any choice. Undum is designed to\
support narratives that branch and merge.</p>"

…but we do this instead:

"<p>Now we're almost at the end of the road. But so "
+ "far you have moved through this tutorial linearly - from one "
+ "situation to the next, without any choice. Undum is designed to "
+ "support narratives that branch and merge.</p>"

Again there’s no practical difference, but since Vorple functions must be concatenated with + characters it’s simpler to use the same method with normal text as well.

Getting started

Starting a new project

The download page at vorple-if.com has ready made packages for different themes. Choose a theme that pleases your eye the most, download the package and unpack.

Each theme package has at least these files and directories:

  • css
  • lib
  • media
    • audio
    • image
    • music
    • video
  • vorple.game.en.js
  • index.html

The media folder and its subfolders are meant for story-specific multimedia files.

You can verify that everything works ok by opening the index.html file with your browser. You should see an extremely minimal but functioning Undum story.

Go through the index.html file and replace the placeholder texts like story title and description. (You can also do this at any point later.)

vorple.game.en.js is an empty story file. If you want to call it something else, rename it to whatever you wish and change the filename in index.html so that it gets loaded properly.

Finally, open vorple.game.en.js and go through it, there are more instructions there on how to complete the story’s basic setup.

As with vanilla Undum, if you don't have a local webserver installed on your computer it's best to use Firefox when developing the stories. Other browsers might disable features as a security measure when local web pages contain JavaScript.

Migrating an existing project

If you already have an existing Undum project where you want to use Vorple, download any theme package from the download page. You only need the library files so if you don’t want to change your existing theme it doesn’t matter which package you download. Unpack it and copy the library directory lib/ to the same directory where the story’s HTML file is.

If you want to change the layout as well, skip the rest of this chapter and read Migrating to a new theme for further instructions.

Modify your existing main HTML file (usually storyname.en.html) and add Vorple’s libraries and resources after the line that loads Undum. In the standard Undum template the line is almost at the end of the file.

<!-- Find this line... -->
<script type="text/javascript" src="media/js/undum.js"></script>

<!-- ...and add these lines below it: -->
<script type="text/javascript" src="lib/jquery.qtip.min.js"></script>
<script type="text/javascript" src="lib/soundmanager.min.js"></script>
<script type="text/javascript" src="lib/vorple.min.js"></script>

<!-- Make sure those lines come before the line that loads your story file,
        for example: -->
<script type="text/javascript"
        src="media/games/tutorial/tutorial.game.en.js"></script>

If you plan for the story to feature sounds or music, see chapter Mute controls for instructions on how to add the controls to the layout.

Vorple is designed to be fully compatible with stories created for standard Undum. If you have a story that works with vanilla Undum but not with Vorple, please file a bug report.

Migrating to a new theme

If you want to start using one of the Vorple-provided themes, download the theme package, unpack it and copy your storyname.game.en.js story file to its main directory. The theme’s index.html file becomes the new main HTML file.

You’ll need to manually edit index.html to match the contents of your old HTML file (titles, descriptions, other custom content you’ve added). At the same time when you go through index.html, check if the theme requires other attention as well. Special instructions will be given as comments where necessary.

Before you can start using Vorple’s features, you have to make the following changes to the story file:

  • Add vorple.core.init( system ); to the undum.game.init() function.</li>
  • If you’re using undum.game.afterEnter() or undum.game.afterAction() global event hooks, you have to make sure that they run vorple.undum.afterEnterTrigger( character, system, from, to ); and vorple.undum.afterActionTrigger( character, system, situation, action ); respectively by adding them to the beginning of the event hooks.

Without these additions some of Vorple’s features might not work correctly or at all. Refer to the vorple.game.en.js file for an example.

Developing with Vorple

Initializing the library

Always remember to initialize Vorple. Some features won't work or work incorrectly if the library isn't initialized.

Some of Vorple’s features are initialized by calling vorple.core.init()API. undum.game.init() is a good place to do so. The Undum engine must be given as the first parameter to the initialization function. The engine is the undum.game.init()’s second parameter, system.

 
undum.game.init = function( character, system ) {
    // other Undum initialization
    // ...

    vorple.core.init( system );
};

Using the library functions

Vorple adds enhancements to Undum’s basic functionality (with the core module) and extends its capabilities (with the Undum module). The setup and usage of these features are covered in the respective module chapters.

To help write the HTML contents of an Undum story, the HTML module has helper functions that create HTML tags. For example, here’s the (abbreviated) starting situation from the Undum tutorial game:

 
start: new undum.SimpleSituation(
    "<h1>Starting Out with Undum</h1>\
    <img src='media/games/tutorial/woodcut1.png' class='float_right'>\
    <p>Welcome to the Undum tutorial. Undum is a tool for writing\
    hypertext interactive fiction. It has some unique features\
    and a visual design that encourages narrative games.</p>\
    \
    <p class='transient'>For now, lets move on with the tutorial.\
    <a href='rooms'>Click this link</a> to move on.</p>"
)

Using Vorple’s HTML helpers it would be written like this:

 
undum.situations.start = new undum.SimpleSituation(
    vorple.html.tag( "h1", "Starting Out with Undum" )
    + vorple.media.image( 'woodcut1.png', { classes: 'float_right' } )
    + vorple.html.p(
        "Welcome to the Undum tutorial. Undum is a tool for writing "
        + "hypertext interactive fiction. It has some unique features "
        + "and a visual design that encourages narrative games."
       ) + vorple.html.p(
        "For now, lets move on with the tutorial. "
        + vorple.html.link( "rooms", "Click this link" )
        + " to move on.", { classes: 'transient' }
       )
)
See the Different coding practices chapter for an explanation why the long lines are split differently in the above examples.

Using the helpers reduces the chance of typos and missing end tags and they make the code more structured and readable (although your mileage may vary).

Other functions that don’t create story text but do something else like play sounds or create tooltips are called inside functions.

 
undum.situations.maze = new undum.SimpleSituation( function() {
    vorple.media.playMusic({ mp3: "background.mp3", oga: "background.ogg" });
    return vorple.html.p( "You are in a maze of twisty passages, all alike." );
});

The exact syntax is described in each feature’s documentation in this manual and in the API.

Reading the API

Vorple’s modules and functions are documented in detail in the API. The API is included in the zip package and a link to the online version is in the main menu of the Vorple project website.

Functions mentioned in this manual have a link appended to them that takes you to the corresponding place in the API: vorple.core.init()API

In the API the “namespaces” top menu leads to the documentation of different Vorple modules. Clicking on a module’s name opens a page that details the fields (variables) and methods (functions) included in the module.

Here’s an example documentation of vorple.core.generateId()API:

An example from the API

The first line tells that this function:

  • is called requireRelease() (and is part of the core namespace, therefore it’s full name is vorple.core.requireRelease())
  • accepts one parameter called length
  • returns a string

The paragraph that follows describes the use and behavior of the function.

Next there’s a description of accepted parameters.

  • The first column is the parameter’s name.
  • The second column shows the accepted type or types of the parameter.
  • The text “optional” in the third column means that this parameter can be left out.
  • If the parameter defaults to some value if it’s left out, it’s shown in the fourth column.
  • The fifth column gives a brief description of the parameter and its purpose.

After the parameters there’s a link to the method’s source code. If reading the manual and the API still leaves you wondering what a function does or how it’s used, you can always look at its source code and try to figure it out from there.

Finally there’s the description and type of the return value (if any). There might also be links to other parts of the API or to external resources.

Remember that Vorple uses the jQuery library that has its own API. Other included libraries have their own documentation, but the API has links to them when necessary.

Of functions and strings

We need to go through some JavaScript theory for this one. Let’s say we want to make a situation where we show “Hello world!” to the reader. There are three ways to do it:

 
// SimpleSituation with a string argument
new undum.SimpleSituation( "<p>Hello world!</p>" );

// SimpleSituation with a function argument
new undum.SimpleSituation( function() {
    return "<p>Hello world!</p>";
});

// Situation
new undum.Situation({
    enter: function( character, system, from ) {
        system.write( "<p>Hello world!</p>" );
    }
});

The end result is always the same, words “Hello world!” displayed on the screen. The difference is that the first method uses a string argument which is evaluated on initialization and the two others use functions whose contents are evaluated when they are called.

What does this fancy tech jargon mean and why is it important? Let’s look at a practical example where we want to play a sound effect when the reader enters a situation:

// This won't work:
new undum.SimpleSituation(
    "<p>You hear a loud bang.</p>"
    + vorple.media.playSound({ mp3: "gunshot.mp3" })
);

// Do this instead:
new undum.SimpleSituation( function() {
    vorple.media.playSound({ mp3: "gunshot.mp3" });
    return "<p>You hear a loud bang.</p>";
});

What happens with the first (incorrect) method is that the string contents are evaluated when the story loads and therefore you hear the sound effect right away, not when the reader enters the situation. In the latter version the sound playing function call is inside a function that’s called only when the situation is entered so the sound plays at the correct time.

Vorple’s functions can be divided into two categories: active functions that do something the moment they’re called, and passive functions that return a string of HTML code.

The following modules or functions are always passive and therefore safe to use in undum.SimpleSituation as a string argument:

  • everything in the html module
  • vorple.media.image()
  • vorple.media.youtube()

For everything else it’s safer to use them in functions only.

Modules

Cookies are small snippets of text web pages can save to the user’s computer. Cookies can be used to identify a returning user or save data across sessions.

Cookies can be set using the vorple.cookie.write()API method and read with vorple.cookie.read()API. Cookies can be deleted using vorple.cookie.remove()API. A cookie has text content and a name that’s used to identify the cookie.

 
vorple.cookie.write( 'greeting', 'Hello!' );  // sets a cookie called "greeting"
vorple.cookie.read( 'greeting' );             // returns "Hello!"
vorple.cookie.remove( 'greeting' );           // removes the cookie

The cookie’s contents can be updated by overwriting it with vorple.cookie.write().

By default cookies are set to expire in one year. The expiration period can be set using an expires option while writing the cookie, as a number of days the cookie is valid or as a JavaScript Date object:

 
vorple.cookie.write( 'greeting', 'Hello!', { expires: 7 } );
There's no guarantee that the user's browser keeps the cookies for the full duration of the expiration period, or that the browser accepts them at all. You shouldn't rely on cookies alone for important features.

The specification says that a browser should accept at least 20 cookies per web site, each with maximum content length of 4096 bytes (characters). Most browsers allow much more than this, but it’s safest to stay within these boundaries. Some browsers also limit the total length of all cookies per web site to 4096 bytes or some other value.

Resources

Core

The core module has mainly helper functions for other modules and general settings and features.

Settings

vorple.core.settings contains two variables: vorple.core.settings.confirmWindowClose (default false) and vorple.core.settings.debug (default false).

vorple.core.settings.confirmWindowClose defines whether or not the browser should alert the reader that they’re leaving the page when they close the browser window or try to navigate to another page. The purpose is to prevent the reader from accidentally leaving the page and inadvertently erasing their progress at the same time.

Firefox versions 4 and up disregard the custom message and always show the browser's default message in the confirmation dialog.

If the variable is set to true a default message will be used: “You are about to leave the story. Any unsaved progress will be lost. Are you sure you want to continue?” If the variable is a string, it will be used as the message: vorple.core.settings.confirmWindowClose = "Are you sure you want to leave the game?"

The variable vorple.core.settings.debug can be set to true while developing the story. The flag can be used to add code used for debugging so that they don’t accidentally appear in the released version of the story: if( vorple.core.settings.debug ) { ... }

Setting the debug flag disables confirmWindowClose so that you don’t have to dismiss the confirmation dialog every time you reload the page.

The setting variables can be set at the beginning of the story file so that they’re immediately active.

Version numbers

vorple.core.getVersion() retrieves the Vorple library’s version number, e.g. “2.5”.

A plugin or another library can require a certain version of the Vorple library by calling vorple.core.requireVersion()API. An error is thrown if the library is not recent enough.

If the page layout contains an element with class vorple-version, the contents of the element are replaced by the Vorple’s version number in the version.release format. The default Vorple themes have this in the page footer:

 
Powered by <a href="http://undum.com">Undum</a>
and    <a href="http://vorple-if.com">Vorple
<span class="vorple-version"></span></a>.

In the page itself it will look like this:

Powered by Undum and Vorple 2.5.

Initialization event

vorple.core.init()API triggers an init.vorple event that can be used to add custom initialization methods:

 
$( document ).on( 'init.vorple', function() {
    // custom initialization here
});

This is mostly useful for plugins. Individual stories can just add any initialization they need to undum.game.init() which runs at the time Undum has been initialized.

vorple.core.init() must be called in the Undum’s initialization method, even if there are no custom initialization methods attached to it:

undum.game.init = function( character, system ) {
    // other Undum initialization
    // ...

    vorple.core.init( system );
};

HTML

In all HTML module functions that create HTML tags you can add tag attributes as the last parameter. The attributes are given as an object that has the attributes’ names as keys and contents as values:

 
vorple.html.p(
    "Test",
    {
        id: "foo",
        classes: "bar",
        title: "baz"
    }
);
// --> <p id="foo" class="bar" title="baz">Test</p>

Note how the class attribute must be named classes because “class” is a reserved word in JavaScript.

Paragraphs

vorple.html.p()API wraps given contents inside <p> tags. The following are equal:

 
// the "pure" Undum method
new undum.SimpleSituation( "<p>Hello World!</p>" );

// with the HTML helper
new undum.SimpleSituation( vorple.html.p( "Hello World!" ) );

// with a custom class
vorple.html.p( "Hello World!", { classes: "transient" } );
// --> <p class="transient">Hello World!);

Links can be added with vorple.html.link()API. The first parameter is the link target, the second parameter the contents, and the third the <a> tag options.

 
vorple.html.link( "./book", "Open the book", { classes: 'unique' } );
// --> <a href="./book" class="unique">Open the book</a>

The parameters can be given as a single object that has keys for at least the url and the contents:

 
vorple.html.link({
    url: "./book",
    content: "Open the book",
    options: { classes: 'unique' }
});

Choice popup

If an array of multiple links is given as the first parameter, a choice popup is created. A choice popup is a list of choices that appears when the main link is clicked.

The popup is hidden when any of the choices are selected or if the reader clicks on outside the popup.

 
vorple.html.link([
    {
        url: "http://vorple-if.com",
        content: 'Vorple'
    },
    {
        url: "http://undum.com",
        content: 'Undum'
    }],
    'useful links'
);

Quotes

vorple.html.quote()API can be used to wrap contents inside quotes. The reason you might want to use this helper instead of just writing the quotes is that this way you can’t forget to add the closing quote and you don’t have to escape the quotes as in the example below.

 
// vanilla Undum
new undum.SimpleSituation( "<p>\"Hello,\" she said.</p>" );

// HTML helper
new undum.SimpleSituation(
    vorple.html.p( vorple.html.quote( "Hello," ) + " she said." )
);

Double quotes (") are used by default but another character or characters can be given as the second parameter, or an array with two members where the first member is the opening quote and the second character the closing quote. If you assign a character to the vorple.html.defaults.quotemarks variable, it’s used as a default from there on.

 
vorple.html.quote( "Hello", "'" );                       // --> 'Hello'
vorple.html.quote( "Hello", [ "&laquo;", "&raquo;" ] );  // --> «Hello»

(Character entity references were used to create the arrow quotes.)

Other tags

You can add any HTML tags using vorple.html.tag()API. The first parameter is the tag’s name, the second is the contents inside the tag and the third parameter the options and attributes.

 
vorple.html.tag(
    "div",
    "Hello World!",
    {
        classes: "transient",
        title: "Greeting"
    }
);
// --> <div class="transient" title="greeting">Hello World!</div>

The end tag is added automatically if text content is given, and the tag is self-closed if the content is not a string.

 
vorple.html.tag( "br" );       // --> <br />
vorple.html.tag( "div", "" );  // --> <div></div>
vorple.html.tag(               // --> <hr class="wide" />
    "hr",
    null,
    { classes: "wide" }
);

If you want to make sure the end tag is always added, use endTag: "always" option:

 
vorple.html.tag(
    "div",
    contents,
    { endTag: "always" }
);

Instead of the generic vorple.html.tag() use

Media

Images

vorple.media.image()API creates an <img> tag. The first parameter is the picture’s file name and the second optional parameter an object with tag attribute options.

 
vorple.media.image( 'pic.png', { classes: 'once', title: 'A nice picture' } );
// result: <img src="media/image/pic.png" class="once" title="A nice picture" />

Unless an absolute path to the file is given (/other/folder/pic.png or http://example.com/pic.png), a path specified by vorple.media.defaults.imagePath is used. The default is the media/image/ directory that comes pre-made in all theme packages. It can be changed by assigning a new path to the variable.

 
vorple.media.image( 'pic.png' );    // --> media/image/pic.png

vorple.media.defaults.imagePath = '/resources/pics/';
vorple.media.image( 'pic.png' );    // --> /resources/pics/pic.png

Preloading images

By default the web browser loads images included in the story only when they are first encountered. The reader might see the image appear on the page slightly after the text, or they might see the image slowly loading, depending on their Internet connection and the size of the image.

This can be countered by preloading the image files. vorple.media.preloadImage()API makes the browser load the images beforehand so that they can be displayed immediately when the story actually needs them. Multiple images can be given to the function as an array at the same time.

 
vorple.media.preloadImage([ 'image1.png', 'image2.jpg' ]);

undum.game.init() is a good place to preload the images. The default image path is assumed, just like with vorple.media.image().

The downside is that preloading consumes bandwith unnecessarily if the reader doesn’t actually come to the point in the story where the image is needed. You might consider preloading images only at some point during the story, for example one situation before the one that shows the image or at the point when the reader enters a branch in the story that leads to the situation that has the image.

Sound effects

The sounds are played automatically with sound down if the reader has muted sounds. The same applies to music.

Audio and local video files are played using the SoundManager 2 library.

Sound effects can be played by using vorple.media.playSound()API. Mp3 files are probably the best supported, but OGG files should work as well.

 
vorple.media.playSound( "sound.mp3" );

Audio files are loaded from the project’s media/audio directory unless other path is given, just like with images. The default path is stored in vorple.media.defaults.audioPath.

vorple.media.stopSounds()API stops all currently playing sounds. If you need to stop or pause a single sound, you have to manipulate the player object directly. vorple.media.playSound() returns the sound objects id. If you assign the return value to a variable, you can use vorple.media.stopSound()API to stop the sound, or use any SoundManager methods to manipulate the sound.

iOS devices (iPhone, iPad, iPod) support only _one_ sound playing simultaneously. If you specifically target these devices, it's best to use either background music or sound effects, but not both. Otherwise any sound effect will stop the background music.

Music

For music these functions can be used:

  • vorple.media.playMusic()API to start a music track
  • vorple.media.stopMusic()API to stop playing music

They work identically to vorple.media.playSound() and vorple.media.stopSounds(). There’s also vorple.media.stopAll()API that will stop both sound effects and music.

The default directory for music files is media/music. It can be changed by assigning the new directory to vorple.media.defaults.musicPath.

Why not just play background music the same way you’d play sound effects? There are a couple of key differences:

  • You can play only one music track at the same time. When you start playing a new music track, you don’t have to stop the existing track. Starting a music track will automatically stop the previous track from playing.
  • You can easily stop or mute only music or only sound effects.
  • When loading a saved story, sound effects will not be played again (remember that Undum replays the whole story from the start when it’s loading from a save). The last played music track will start playing when the story is loaded unless it was manually stopped.

Another difference is that music is set to loop automatically (the same track starts again right after it has ended). If looping is not desired it can be disabled with a loop: false option:

 
vorple.media.playMusic( "filename.mp3", { loop: false } );

Conversely the same option set to true can be passed to vorple.media.playSound() to make sound effects looping.

Volume, fading out and callbacks

The default volume for sound effects and music is 80, with 100 being the maximum. It can be changed with the volume option.

All functions that stop sounds, including the vorple.media.playMusic() when it stops the previous music, have an option to fade the sound out gradually instead of stopping it abruptly.

The fade out speed is given as a number between 1 and 100, where higher number means faster fade out. The volume is decreased every 50 milliseconds (0.05 seconds) and the number tells how much the volume is decreased each time until it reaches zero. With fade out speed 5 it takes 80 / 5 * 50 = 800 milliseconds (0.8 seconds) for a sound to fade out from the default volume.

Passing a fade out speed of 100 will stop the sound immediately without fading. vorple.media.stopSound() and vorple.media.stopSounds() have 100 as the default. vorple.media.stopAll(), vorple.media.stopMusic() and vorple.media.playMusic() have 5.

Functions that stop sounds also have an option to pass a callback function that’s executed when the sound has actually stopped, i.e. when the fade out has completed.

Here’s an example of stopping background music with slow fade out and showing a notification when the fade out is completed.

 
vorple.media.stopMusic(
	3,
	function() {
		vorple.notify.show( 'The music has stopped!' );
	}
);

YouTube videos

YouTube videos can be embedded with vorple.embed.youtube()API. The function takes as the first parameter the id of the video to embed and as the second parameter the options.

OptionTypeDefaultDescription
heightinteger390Height of the video player
widthinteger640Width of the video player
parametersobjectsee belowYouTube embedding parameters

All available embedding parameters are listed in the YouTube API documentation. Default parameters are:

 
autoplay: '1',
controls: '0',
disablekb: '1',
modestbranding: '1',
rel: '0'

That is, start playing the video immediately, hide controls, disable keyboard controls, hide YouTube logos and don’t show related videos at the end.

When the story is being reloaded from a save position, the video player is embedded but parameters.autoplay is set to 0 so that it won’t start playing automatically.

An example of usage where we show a video in an Undum situation:

 
undum.game.situations.livingroom = new undum.SimpleSituation(
    vorple.html.p(
        "You find yourself in a living room where a film has just "
        + "started playing on the DVD player."
    ) + vorple.html.p(
        vorple.embed.youtube(
            'bsGEWHNJ3s8',
            {
                width: '500',
                height: '280',
                parameters: {
                    controls: '1',  // allow the user to control the video
                    loop: '1'       // start again from beginning when playback ends
                }
            }
        )
    )
);

Mute controls

Themes included with Vorple already have the mute checkboxes in the HTML files, but by default they are not displayed. Remove the <!-- --> tags around the checkboxes to enable them.

If the story uses audio, it’s polite to offer the reader a possibility to mute sounds. If you put the following piece of code into the story’s HTML file, that is, checkboxes with class mute and value sound, music or all, Vorple will automatically make them function as you’d expect.

 
<div>
    <input type="checkbox" id="muteMusic" class="mute" value="music" />
    <label for="muteMusic">Mute music</label>
</div>
<div>
    <input type="checkbox" id="muteSound" class="mute" value="sound" />
    <label for="muteSound">Mute sound effects</label>
</div>
<div>
    <input type="checkbox" id="muteAll" class="mute" value="all" />
    <label for="muteAll">Mute all</label>
</div>

If you want to use the opposite scheme where a checked box means that sounds are enabled, you can use the unmute class instead. The functionality is identical but reversed.

 
<div>
    <input type="checkbox" id="unmuteMusic" class="unmute" value="music" />
    <label for="unmuteMusic">Music</label>
</div>
<div>
    <input type="checkbox" id="unmuteSound" class="unmute" value="sound" />
    <label for="unmuteSound">Sound effects</label>
</div>
<div>
    <input type="checkbox" id="unmuteAll" class="unmute" value="all" />
    <label for="unmuteAll">All sounds</label>
</div>

The mute status is written to a browser cookie every time it changes. In other words if the reader mutes audio, the preference is automatically remembered the next time they load the story.

To toggle the mute state manually you can use vorple.media.mute()API to mute or unmute sounds, music or videos, or vorple.media.muteAll()API to mute or unmute all sounds. vorple.media.muteAll() is a shortcut for vorple.media.mute({ sound: true, music: true }).

vorple.media.mute() uses an object that describes what elements to mute or unmute:

 
vorple.media.mute( { music: true } );                // mute music
vorple.media.mute( { music: true, sound: false } );  // mute music and unmute sound

vorple.media.muteAll() is used by giving the mute status as a parameter:

 
vorple.media.muteAll( true );    // mute everything
vorple.media.muteAll( false );   // unmute everything
Local videos respect the mute sound option. Embedded YouTube videos are always played with the sound on.

The mute checkboxes are automatically toggled to reflect the current mute status even when the muting is done manually.

Mute status can be toggled with vorple.media.toggleMute()API. It will unmute muted media and vice versa. The return value is true if the new status of the media is muted and false if it’s now unmuted.

Limitations

Native audio and video support in web browsers is still far from standard. Some browsers can play only MP3 files, some only OGG files, some both, some neither. SoundManager uses primarily a Flash player and tries to use the browser’s native playback capabilities if Flash player isn’t available.

YouTube videos always require Flash (with some exceptions; iOS browsers (iPhone, iPod, iPad) can launch YouTube videos in a separate player).

Mobile Safari (iPhone, iPad, iPod) supports only one sound channel. If you start a new sound while another is playing, the other sound will be stopped. If you target mobile devices, it’s best to disable either background music or sound effects (if you have them), otherwise any sound effect during the story will make background music stop abruptly.

Notify

Vorple uses the noty library to create notifications. They can be used to e.g. inform the reader of important events or acknowledge their actions.

Notifications are created using vorple.notify.show()API with the content of the notification as the first parameter. The notification’s behavior can be altered with options given as the second parameter. All the available options can be found on noty’s web site.

 
vorple.notify.show(
	'Note this!',
	{
		speed: 2000,  // animations take 2 seconds (2000 ms)
		closeOnSelfClick: false  // don't close the notification on click
	}
);

The notification’s position can be given with the layout option. The available positions are the four corners of the screen (topLeft, topRight, bottomLeft and bottomRight), as a wide bar on the top or the bottom of the screen (top or bottom), in the center on top (topCenter), or in the middle of the screen (center). The default is bottom right.

Multiple notifications in the four corners of the screen are displayed simultaneously. In every other position the notifications are put into a common queue and displayed sequentially. The queue can be emptied with vorple.notify.clearQueue()API.

The oldest notification can be dismissed with vorple.notify.close()API and all notifications dismissed with vorple.notify.closeAll()API, which will also empty the queue.

In the noty library the default duration of notifications is 5 seconds (5000 ms), but Vorple’s default is that the notifications are automatically hidden after seven seconds. The average reading speed is about three words per second so 7 seconds is good for messages of about 20 words. In addition to the default location (bottom right) this is the only change to noty’s defaults.

vorple.notify.defaults contains the story-specific defaults.

vorple.notify.defaults.textAlign = 'left';
vorple.notify.defaults.timeout = false;

vorple.notify.show( "This notification's text is aligned left "
    + "and it must be clicked to dismiss." );

Tooltip

Creating tooltips

Vorple comes bundled with the qTip2 tooltip library.

To add a tooltip to every link in the game, we’ll add the vorple.tooltip.enable( 'a' )API to undum.game.init():

 
vorple.tooltip.enable( 'a' );

As simple as that! Now every link that has the title attribute will show the contents of the title as a tooltip when the mouse is put over them.

 
<a href="foo" title="This is the tooltip's text!">Link</a>

Or using the HTML module:

 
vorple.html.link(
    'foo',
    'Link',
    { title: "This is the tooltip's content!" }
);

The parameter is a jQuery selector. If you need to add tooltips more accurately or to other elements, refer to the jQuery documentation.

All qTip2 options are supported. The documentation is at http://craigsworks.com/projects/qtip2/docs/ (look under “Options”).

Manually triggered tooltips

Sometimes we might want to display a tooltip in response to an unrelated event or as part of the story’s plot. vorple.tooltip.show()API creates a tooltip and shows it after a delay, then hides it again after another delay.

 
vorple.tooltip.show(
    '.targetClass',
    'Tooltip content',
    {
        delay: 1000,    // 1 second
        duration: 5000    // 5 seconds
    }
);

The first parameter is the element’s jQuery selector, the second the text to be displayed in the tooltip, and the third is the options, including the delay before showing the tooltip and the duration how long the tooltip is displayed in milliseconds. The defaults for the delay and duration are 3000 milliseconds and 10000 milliseconds respectively.

Undum

Undum’s once-links disable themselves after they’ve been clicked, but the effect is temporary. If the reader encounters the same link later, it’s active again.

Disposable links are similar to once-links, but the effect is permanent: after the reader has clicked on a disposable link, it will never be shown during the same story again. (Links with the same target (href-attribute) are considered being the same link.)

There are two ways to define disposable links: either give them as a list, or specify that all links should be disposable and list only the exceptions.

The disposable link list should be assigned as an array to vorple.undum.settings.disposableLinks:

 
vorple.undum.settings.disposableLinks = [ 'discard', 'these', 'links' ];

To use the latter method and specify that all links should be disposable, set vorple.undum.settings.allDisposable to true and, if necessary, list the exceptions as an array in vorple.undum.settings.disposableExceptions.

 
vorple.undum.settings.allDisposable = true;
vorple.undum.settings.disposableExceptions = [ 'non-disposable', 'links' ];

If vorple.undum.settings.allDisposable is true, vorple.undum.settings.disposableLinks will be ignored.

Disposing a link will dispose of both actions and situations with the same name, so it's generally best to always use unique action and situation names.

Disposable links don’t make a difference between situations and actions. Links to actions should be listed without the ./ prefix.

Disposable links can be defined anywhere in the story file. Using undum.game.init() is recommended.

A link’s status can be checked with vorple.undum.isDisposed()API which will return true if the link has been disposed.

Links can be disposed manually by calling vorple.undum.dispose()API. The function can dispose any number of links at the same time, given either as separate arguments or as an array.

 
vorple.undum.dispose( 'name' );
vorple.undum.dispose( 'first', 'second', 'third' );
vorple.undum.dispose( [ 'first', 'second', 'third' ] );

You can dispose even links that are not in the vorple.undum.settings.disposableLinks list.

To reactivate a link call vorple.undum.reactivate()API. You can reactivate one or multiple links at the same time, just like with vorple.undum.dispose().

 
vorple.undum.reactivate( 'name' );
vorple.undum.reactivate( 'first', 'second', 'third' );
vorple.undum.reactivate( [ 'first', 'second', 'third' ] );

Reactivation applies only to future links. Any inactive links currently visible on the screen will not be activated. Reactivated links are not automatically removed from the list of disposable links, so clicking on them later will again dispose of them.

If a link has class unique applied to it, all other instances of the same link will be automatically disabled. This can be used to make sure that only one instance of a link will be visible at the same time.

 
Here's a <a href="name" class="unique>link</a>
and <a href="name">another</a>
but only the former one will be active because it's marked as unique
and the latter links to the same place.

Or, using Vorple’s HTML helpers:

 
vorple.html.link( 'name', 'link', { classes: 'unique' } );
// --> <a href="name" class="unique>link</a>
Resources

undum.doClick() and undum.doLink() are exposed as vorple.undum.doClick()API and vorple.undum.doLink()API. This lets the author use them outside Undum’s own methods, when the undum object is not available.

Complete examples

The examples can be downloaded separately from the download page.

One With Everything

The example story One With Everything uses all standard Vorple features. It’s not really a story or a game by itself, but if you want to see a real-life code example of any of the features you can probably find it in the story’s source code.

Down the Rabbit-Hole

Down the Rabbit-Hole showcases Vorple’s features. It doesn’t include every feature like One With Everything does and it uses some more advanced techniques to e.g. show custom popup windows.

Starborn

Starborn is an Undum/Vorple adaptation of an Inform 7 keyword-based story. The adaptation adds background music, an interactive map, clickable buttons and other eye candy. Some of the features are straight-up Vorple, some are custom-made for the story.

Inform 6 Interactive Fiction with Vorple

Introduction to Vorple

Vorple is a custom web interpreter and a set of extensions for Inform 6 that lets you do things that so far haven’t been possible such as displaying images, playing sounds, adding tooltips and notifications and much more. Take a look at the demo page for some examples.

For an explanation on how the system works, see chapter Vorple in depth below.

Known limitations

Vorple is experimental software and in early stages of development. There are a number of known issues that will be fixed in later releases:

  • Command history (browsing old commands with the up arrow key) isn’t available.
  • Undoing is not reliable if the browser communicates with the story file using hidden commands.
  • Saving and restoring stories is likely to work erratically.
  • The function KeyCharPrimitive() (to wait for a key) is not supported.

At the moment only Z-machine is supported. Glulx support is on the works.

Installation and usage

Getting started

First of all, you need both the Inform 6 compiler and the Inform 6 librairies. We’re assuming you know the basics, but if not, you can look at the Inform Beginner’s Guide to get you started.

Note that Vorple is also available for Inform 7, as well as Undum.

Vorple is structured around a core extension, contained in the “vorple.h” file. The other extensions provide the following capabilities:

  • Vorple Hyperlinks: Clickable web links and commands
  • Vorple Multimedia: Images, sounds and videos
  • Vorple Notifications: Notifications as text banners
  • Vorple Screen Effects: Text and font effects. Roughly the equivalent of the built-in Basic Screen Effects extension.
  • Vorple Tooltips: Pop-up tooltips, timed or on mouse hover

Using Vorple

After downloading the extensions, you can start using them! The rule is simple: you need to include Vorple twice: once before including the parser, and once after including the verblib. (Those are usually defined together anyway.) Don’t worry, Vorple will handle everything correctly; it’s just that some things need to be defined before including the parser and others after including it. So your code would look like:

Include "vorple.h";
Include "parser.h";
Include "verblib.h";
Include "vorple.h";
! and then write your game

If you are using another extension relying on Vorple (say, vorple-notifications.h), you need to include the extension after including the parser, but don’t forget to include Vorple! So your code will be:

Include "vorple.h";
Include "parser.h";
Include "verblib.h";
Include "vorple-notifications.h";

In either case, the other thing you need to do is initialise Vorple, which you do in your Initialise routine:

[ Initialise ;
    location = room;
    VorpleInitialise();	! this initialises Vorple
];

Time to do a quick example: type the following source code:

Constant Story "My story";
Include "vorple.h";
Include "parser.h";
Include "verblib.h";
Include "vorple-notifications.h";
Include "grammar.h";

[ Initialise ;
    location = room;
    VorpleInitialise();
    VorpleNotification("Welcome to Vorple!");
];

Object room "The Room"
    with description "You're in a nondescript room.",
has light;

After compiling it, you should have a .z5 (or .z8) file – remember that Vorple doesn’t work with Glulx for now. If you run it in a standard interpreter, it likely won’t support Vorple – but it won’t crash, and your game will still be playable. However, we have a web interpreter that will run the Vorple effects correctly!

In the download package there is a file called “play.html”. If you edit the file you should see a line that looks like like

parchment.options.default_story = [ "test.z5" ];

Just replace “test.z5” by the name of your story file, and you’re good to go! To publish your work, upload the “play.html” file and the “interpreter” directory along with its contents to a web server.

Technical note about I6 stubs

Vorple makes use of a few I6 entry points that are defined as stubs in the I6 librairies (usually at the end of your language grammar definition file). Those stubs are ParserError (called every time the parser didn’t understand the sentence) and LookRoutine (called after each >look command including the initial one).

You might have defined (un-stubbed) those routines in your code, before including “grammar”; if that is the case, the I6 compiler will return an error. However Vorple creates 2 stubs with the names “MyParserError” and “MyLookRoutine”, that are called in those routines. Hence, you simply need to rename your “ParserError” routine in “MyParserError” (and same for LookRoutine), and move the definition of those routines to before including a vorple file for the second time. And everything should be fine! (See the “How to II” example for sample code.)

Additionally, Vorple defines the stub “VorpleStartup”, that allows you to do things while Vorple is initialising (i.e. during VorpleInitialise). This is useful mostly for one thing, which is queueing commands so that they are parsed and executed before the game even starts.

A note about Internet Explorer

Vorple is compatible with Internet Explorer, but only if played online. If you try to open the interpreter directly from the hard drive (as you do when you open the online interpreter using the “browse” link as discussed above) the page will crash in the loading screen.

The simple solution to this problem is to use some other browser, like Chrome or Firefox. If the “browse” link opens the interpreter in Internet Explorer, copy the address from the address bar, open the other browser, and paste it in the other browser’s address bar instead.

Compatibility with non-Vorple interpreters

The Z-code story files that use Vorple are compatible with offline interpreters and non-Vorple web interpreters. In most cases the Vorple-specific features just do nothing.

The story file can test whether it’s being run on the Vorple interpreter or not using a call to the Vorple function isVorpleSupported(). Like this:

if (isVorpleSupported() == 0)
	print "Welcome to a boring old interpreter!"
else
	VorpleNotification("Welcome to Vorple!");

It’s a good idea to make sure that a text-only version of the story works as intended, for accessibility and archiving reasons.

Vorple in depth

Back in the days when home computers first entered consumer markets there were many competing companies selling computers that weren’t compatible with each other. To maximize the amount of potential customers Infocom had to solve the problem of programming and distributing their games to a wide array of computers with varying specifications and limitations.

The solution was to create a virtual machine that would harmonize the differences between computer systems. The game file would always be the same for each system and there would be a system-specific interpreter program that would translate the game file into instructions the computer understood. This way the game could be programmed and compiled only once and it would work on any system that had an interpreter written for it.

Virtual machine inside operating system

The virtual machine was called Z-machine after Zork, the first game that used it. Decades later Inform 6 still compiles to Z-machine (and Glulx, the contemporary virtual machine that works basically the same way).

To a modern consumer of interactive fiction the virtual machine model has other benefits in addition to being able to play the stories in a wide selection of devices. The virtual machine is effectively a sandbox that limits what story files are allowed to do. They can’t, for example, delete files from the computer, install malicious software or access your webcam. When you download an interactive fiction story file you can be certain that it isn’t a virus and it can’t do anything harmful.

To an author of interactive fiction the sandbox can sometimes feel rather limiting. We’ve come a long way since the early days of Infocom and the things we now casually do with computers is far more than anyone could have dreamed of 30 years ago. Yet interactive fiction is still confined to streaming text, displaying pictures, playing sounds and performing some limited file operations.

Cue the Internet age. Parchment is an online Z-machine/Glulx interpreter that lets you play interactive fiction on any computer with Internet access and a web browser. A modern web browser is also a sandbox, but with quite a lot of more capabilities (but still with restrictions in place so that in theory you can visit any web page and be sure that you can’t catch anything malicious).

Virtual machine inside web browser inside operating system

Parchment was a small revolution in itself and turned the community focus from downloadable story files to Internet play, but Parchment is still “only” an implementation of existing virtual machines. It restricts the story files to the same sandbox as offline interpreters do.

This is where Vorple comes in. It makes a small addition to the interpreter so that the story files can break free of the Z-machine sandbox and communicate with the browser running the interpreter.

Vorple creating a bridge between the virtual machine and the browser

With this bridge in place the story file can do pretty much whatever it wants with the user interface and the story text—even story text that has already been printed.

Additionally Vorple provides a JavaScript library that makes it easier to add features specifically to interactive fiction stories (as opposed to usual web pages). The Inform 6 extensions are mainly interfaces to the underlying JavaScript library.

To recap, Vorple for Inform consists of three main features:

  • JavaScript library for building and handling user interface elements
  • Inform 6 extensions that can use the library
  • Customized interpreter that lets the extensions access the library

The project’s headquarters are at vorple-if.com where you’ll find all the official materials and downloads. JavaScript developers who want to dig into the innards of the system can find the source code at GitHub.

The library and all official materials are open source and free for anyone to use for any purpose. (Mandatory footnote: Do still read all the licenses if you want to use it commercially or as a part of a closed system. Some third party themes, for example, are subject to slightly more restrictive licenses.)

Support

The best place to look for assistance is the community forum at intfiction.org. Vorple’s author frequents the forum, as do other experienced authors who are happy to answer civilized help requests about authoring with Inform, Vorple or other systems.

Bugs can be reported at the project’s GitHub pages or by sending mail to bugs@vorple-if.com. # Inform 6 Interactive Fiction with Vorple

List of Vorple functions

Here’s a handy list of the functionalities that Vorple can provide, and what the corresponding functions are.

Vorple.h

This provides the basic functionality of Vorple:

  • VorpleInitialise(): initialises Vorple ; call once, in your Initialise routine.
  • isVorpleSupported(): returns 0 if Vorple isn’t supported, 1 if it is. Note: calling the functions from the Vorple extensions will not create any side-effects if the interpreter doesn’t support Vorple; rather, Vorple will fail silently. But this function could be interesting if you wanted to change what your game says or does depending on this!

Other functions are available:

  • VorpleExecuteJavaScriptCommand(str): the javascript command str will be sent to the interpreter, which will execute it.
  • Placing HTML elements:
    • VorplePlaceElement(elt, name, text): create a HTML tag of type elt (this could be <tag>, <div>, anything!), with the name name and containing the text text. The shorthands VorplePlaceSpanElement(name,txt) (to place <span>) or VorplePlaceDivElement(name,txt) (for <div>) are also available.
    • VorplePutContentInAllElements(name, text): put the text text in all HTML elements that have the name name. You can put it only in the last (or only) one created with this name using VorplePutContentInElement(name,text).
  • Queuing commands:
    • VorpleQueueCommand(cmd, flagDontShow): make it so that at the next turn the command cmd (of the ‘go north’ type) will be sent to the parser; call with flagDontShow=1 if you don’t want the player to see the command that was sent, but if she should see the game’s reply.
    • VorpleQueueSilentCommand(cmd): at the next turn, the command cmd will be sent to the parser without the player noticing; that is to say, the command will not be displayed, but neither will the game’s reply.
    • VorpleQueuePrimaryCommand(cmd, flagDontShow) and VorpleQueueSilentCommand(cmd): the same, except primary commands have their own queue, which is dealt with before the standard command queue that the other commands above use. Basically, if you want to have communication between the interpreter and the story file between two commands, put the first in the primary command and the other one in the standard one.
  • VorpleTypeOfTurn(type): Vorple distinguishes several types of turn: "normal" (by default), "meta" (for actions that shouldn’t take a turn), and "error" (for parser errors, that will be hidden from the display). Call this function with one of those arguments to set the current type of turn; for instance, call VorpleTypeOfTurn("error") in a verb definition at the point where your code can’t make sense of the player’s command.

As well as utility functions:

  • UniqueIdentifier(): generates a 12-digit unique identifier; you can use that for the names of your HTML elements.
  • IntToString(i): returns an array representing the integer i.
  • PrintStringOrArray(txt): displays the given string or buffer array.
  • BuildCommand(str1, ..., str7): usage of this function is discouraged! It is used internally to concatenate strings, in almost every call to the Vorple interface; if you use it several times in a row, you overwrite hugehugestr, and you lose information. If you need a function to concatenate things, declare an array that’s not hugehugestr and adapt the code of this function.

Finally, write your own VorpleStartup() routine to do things while Vorple is starting up; for instance you can queue silent commands, that will be executed by Vorple before the Initialise routine is done.

Relevant examples: Convenience Store, Spy Games, Scrambled Eggs, The Sum of Human Knowledge (note that this one uses its own CSS sheet), and all the other ones.

Vorple-hyperlinks.h

  • VorpleLinkWebsiteText(url, text, flag): this allows you to create a hypertext link on the text pointing to the specified url; the optional flag can be set to SAME_WINDOW if you want the page to open in the same window (for instance, if your game is over).
  • VorpleLinkWebsite(url, sameWindow): similar, but the link will read the explicit url.

  • VorpleLinkCommandText(cmd, text, dontShow): this creates a hyperlink showing the text such that when the player clicks on it, the command cmd is sent to the parser; use this for example to have clickable directions, by putting a link to “go north” on the word “north”. The optional argument dontShow can take the following values: 0 by default (show the command and the response), or any of DONT_SHOW_COMMAND, DONT_SHOW_RESPONSE or DONT_SHOW_COMMAND_OR_RESPONSE.
  • VorpleLinkCommand(cmd, dontShow): similar, but the link will read the explicit command.

Relevant examples: Click to Learn More, Click to Retry.

Vorple-multimedia.h

In order to use this extension, you have to point the interpreter to the folder where your multimedia files are. This is done by modifying the play.html file. For example, change

vorple.media.defaults.audioPath = 'examples/resources/';

to set the folder in which Vorple will look for your audio files.

  • VorpleImage(file, alignment): display the image in the file, with an optional argument for the alignmnent; the values you can specify are IMAGE_CENTERED, IMAGE_LEFT_ALIGNED, IMAGE_RIGHT_ALIGNED, IMAGE_LEFT_FLOATING, and IMAGE_RIGHT_FLOATING.
  • VorplePreloadImage(file): preload the image, i.e. have the interpreter load the image before it is displayed (for instance, to avoid loading times).
  • VorplePreloadImages(list): preload all images in the table.

  • VorplePlaySound(file, loop): play the specified sound; put the second argument to LOOP_SOUND (or 1) to loop it.
  • VorplePlayMusic(file, loop): play the specified music; put the second argument to LOOP_MUSIC (or 1) to loop it.
  • VorpleStopMusic(): stop all music.
  • VorpleStopSounds(): stop all sounds.
  • VorpleStopAudio(): stop all music and sounds.
  • VorplePlayYoutubeVideo(youtubeID): play the YouTube video of your choice by specifying its YouTube ID; Vorple will play the video at the URL https://www.youtube.com/watch?youtubeID

Relevant examples: Serinette, Port Royal Reggae, The Trampoline.

Vorple-notifications.h

Note: you can only have 16 notifications at the same time on the screen; should you need more, you need to modify the VORPLE_MAX_NUMBER_NOTIFS variable.

  • VorpleNotification(text, pos): show the notification reading the text; the optional argument specifies where the notification should be displayed. It can take the following values: VORPLE_POSITION_TOP_BANNER, VORPLE_POSITION_BOTTOM_BANNER, VORPLE_POSITION_TOP_LEFT, VORPLE_POSITION_TOP_CENTER, VORPLE_POSITION_TOP_RIGHT, VORPLE_POSITION_CENTER_LEFT, VORPLE_POSITION_SCREEN_CENTER, VORPLE_POSITION_CENTER_RIGHT, VORPLE_POSITION_BOTTOM_LEFT, VORPLE_POSITION_BOTTOM_CENTER, VORPLE_POSITION_BOTTOM_RIGHT.
  • VorpleAlert(text): display an alert, that is to say a pop-up dialog box in the browser.
  • VorpleHideNotifications(): hide all notifications.
  • VorpleDefaultNotifPosition(pos): all notifications will be displayed at a specific position by default.

Relevant examples: How to I, Score Notifications.

Vorple-screen-effects.h

  • VorpleStyle(style): from then on, write the letters in a specific style; the values are STYLE_CURSIVE, STYLE_EMPHASIS, STYLE_FANTASY, STYLE_MONOSPACE, STYLE_NOWRAP, STYLE_STRIKETHROUGH, STYLE_STRONG, STYLE_TRANSIENT, STYLE_UNDERLINE, STYLE_XXSMALL, STYLE_XSMALL, STYLE_SMALL, STYLE_LARGE, STYLE_XLARGE, STYLE_XXLARGE.
  • VorpleEndStyle(): disable the latest style.
  • VorpleEndAllStyles(): disable all text styles.

  • VorpleColorLetters(color): from then on, write the letters in a different color.
  • VorpleColorLettersBackground(color): change the color of the space around the letters.
  • VorpleForegroundColor(color): change foreground color.
  • VorpleBackgroundColor(color): change background color.
  • VorpleDefaultStyle(): return to default values. The color values are as follows: BLACK, RED, GREEN, YELLOW, BLUE, VIOLET, CYAN, WHITE.

  • VorpleCenterText(text): print the text with fixed width and centered.
  • VorpleRightAlign(text): print the text with right alignment.
  • VorplePlaceBlockquoteElement(name text): print the text in a blockquote HTML element with the given name and showing the text.
  • VorpleHideLastBlockquote(): hides the last displayed blockquote.
  • VorpleHideAllBlockquotes(): hides all blockquotes.

  • VorpleClearScreen(window): clear all the screen (0), the status bar (1) or the main window (2).
  • VorplePause(): wait for a key press then clear the screen.

Relevant examples: Letters from a Madman, Monty Hall (note that it uses its own CSS sheet).

Vorple-tooltips.h

  • VorpleTooltipMouse(text, tip): writes the text, and opens a tooltip showing the tip when the player points their mouse to the text.
  • VorpleTooltipAllElementsMouse(tip, name): if the player hovers over any HTML element named name in the page, there will be a tooltip.
  • VorpleTooltipElementMouse(tip, name): the same but for the latest of the elements named 'name'.

  • VorpleTooltipElement(tip, name, n): after n tenths of second, a tooltip with the tip will display on the element named name.
  • VorpleTooltipAllElements(tip, name, n): the same, but on all elements named name.
  • VorpleTooltipPrompt(tip, n): after n tenths of second, a tooltip with the tip will display on the prompt.

Relevant examples: Medical Dictionary, How to II, Ibid (2).

Inform 7 Interactive Fiction with Vorple

Introduction to Vorple

Vorple is a custom web interpreter and a set of extensions for Inform 7 that lets you do things that so far haven’t been possible such as displaying images, playing sounds, adding tooltips and notifications and much more. Take a look at the demo page for some examples.

For an explanation on how the system works, see chapter Vorple in depth below.

Known limitations

Vorple is experimental software and in early stages of development. There are a number of known issues that will be fixed in later releases:

  • Command history (browsing old commands with the up arrow key) isn’t available.
  • Undoing is not reliable if the browser communicates with the story file using hidden commands.
  • Saving and restoring stories is likely to work erratically.

At the moment only Z-machine is supported. Glulx support is on the works.

Installation and usage

Getting started

First of all, you need Inform 7 which can be downloaded from its web site at inform7.com. We’re assuming you know the basics, but if not, a good place to start is the included manual or other available documentation.

(If hypertext fiction is more your thing, Vorple is available for Undum as well.)

In addition to Inform 7 we need the custom Vorple interpreter and the Vorple extensions. Luckily the latest Inform 7 release already comes with the interpreter built-in, and installing the extensions is easy from the new Public Library.

Open the Extensions pane and click on the Public Library tab. The Vorple extensions are under subheading §12.5.

Downloading Vorple extensions from the Public Library

Download and install the extensions by clicking on the “download” buttons.

The Public Library is at the moment available only in the OS X IDE. Windows and Unix users have to download and install the extensions separately from the downloads page. The Inform 7 manual has instructions on how to install them.

The extension “Vorple by Juhana Leinonen” contains the basic definitions that are needed for the system to work. It’s required by all other extensions, so it’s the one extension that must be installed. The other extensions are:

  • Vorple Hyperlinks: Clickable web links and commands
  • Vorple Multimedia: Images, sounds and videos
  • Vorple Notifications: Notifications as text banners
  • Vorple Screen Effects: Text and font effects. Roughly the equivalent of the built-in Basic Screen Effects extension.
  • Vorple Tooltips: Pop-up tooltips, timed or on mouse hover

Using the extensions

Now that we have the extensions we can start developing. Let’s pick the Vorple Notifications extension which lets us show information on banners outside the actual story text. Start a new project and type the following:

Include Vorple Notifications by Juhana Leinonen.

The functionality of each extension varies, but in addition to including the extension(s) we need, the custom Vorple interpreter must be specified.

Release along with the "Vorple" interpreter.

As per the extension’s documentation we can display banners with a show notification phrase.

The Parade is a room.

 When play begins:
     show notification "Welcome to Vorple!".

Time to see how it looks like! Vorple is Z-Machine only so before compiling the project we need to change the settings to make the project use Z-Machine instead of Glulx. It can be done in the “Settings” pane.

Setting the project to Z-Machine

The release button

If we would now click on the “Go” button the story would be compiled and run inside the Inform IDE. The problem is that the IDE interpreter is of standard Z-Machine variety which doesn’t support Vorple so we wouldn’t see the banner that way. Instead we have to click on the “Release” button to make the project generate a web page with the custom interpreter.

After Inform has compiled and built the release package, it shows a summary of directories and files it has created. Click on the “browse play-in-browser page” button to open the web interpreter.

Browse play-in-browser page button

If everything went as planned, we should now see the story start and our welcome message pop up in the lower right corner of the web page.

Interpreter view with the notification

From now on instead of going this long route we can just push the release button, switch to the browser and reload the page.

A story compiled this way doesn't have debugging commands available. To re-enable them, try the Extended Debugging extension by Erik Temple. Just remember to disable it again when actually releasing the story.

A note about Internet Explorer

Vorple is compatible with Internet Explorer, but only if played online. If you try to open the interpreter directly from the hard drive (as you do when you open the online interpreter using the “browse” link as discussed above) the page will crash in the loading screen.

The simple solution to this problem is to use some other browser, like Chrome or Firefox. If the “browse” link opens the interpreter in Internet Explorer, copy the address from the address bar, open the other browser, and paste it in the other browser’s address bar instead.

Compatibility with non-Vorple interpreters

The Z-code story files that use Vorple are compatible with offline interpreters and non-Vorple web interpreters. In most cases the Vorple-specific features just do nothing.

The story file can test whether it’s being run on the Vorple interpreter or not using an if Vorple is [not] supported test:

When play begins:
     if Vorple is supported:
         show notification "Welcome to Vorple!";
     otherwise:
         say "Welcome to a boring old interpreter!"

It’s a good idea to make sure that a text-only version of the story works as intended, for accessibility and archiving reasons.

Vorple in depth

Back in the days when home computers first entered consumer markets there were many competing companies selling computers that weren’t compatible with each other. To maximize the amount of potential customers Infocom had to solve the problem of programming and distributing their games to a wide array of computers with varying specifications and limitations.

The solution was to create a virtual machine that would harmonize the differences between computer systems. The game file would always be the same for each system and there would be a system-specific interpreter program that would translate the game file into instructions the computer understood. This way the game could be programmed and compiled only once and it would work on any system that had an interpreter written for it.

Virtual machine inside operating system

The virtual machine was called Z-machine after Zork, the first game that used it. Decades later Inform 7 still compiles to Z-machine (and Glulx, the contemporary virtual machine that works basically the same way).

To a modern consumer of interactive fiction the virtual machine model has other benefits in addition to being able to play the stories in a wide selection of devices. The virtual machine is effectively a sandbox that limits what story files are allowed to do. They can’t, for example, delete files from the computer, install malicious software or access your webcam. When you download an interactive fiction story file you can be certain that it isn’t a virus and it can’t do anything harmful.

To an author of interactive fiction the sandbox can sometimes feel rather limiting. We’ve come a long way since the early days of Infocom and the things we now casually do with computers is far more than anyone could have dreamed of 30 years ago. Yet interactive fiction is still confined to streaming text, displaying pictures, playing sounds and performing some limited file operations.

Cue the Internet age. Parchment is an online Z-machine/Glulx interpreter that lets you play interactive fiction on any computer with Internet access and a web browser. A modern web browser is also a sandbox, but with quite a lot of more capabilities (but still with restrictions in place so that in theory you can visit any web page and be sure that you can’t catch anything malicious).

Virtual machine inside web browser inside operating system

Parchment was a small revolution in itself and turned the community focus from downloadable story files to Internet play, but Parchment is still “only” an implementation of existing virtual machines. It restricts the story files to the same sandbox as offline interpreters do.

This is where Vorple comes in. It makes a small addition to the interpreter so that the story files can break free of the Z-machine sandbox and communicate with the browser running the interpreter.

Vorple creating a bridge between the virtual machine and the browser

With this bridge in place the story file can do pretty much whatever it wants with the user interface and the story text—even story text that has already been printed.

Additionally Vorple provides a JavaScript library that makes it easier to add features specifically to interactive fiction stories (as opposed to usual web pages). The Inform 7 extensions are mainly interfaces to the underlying JavaScript library.

To recap, Vorple for Inform consists of three main features:

  • JavaScript library for building and handling user interface elements
  • Inform 7 extensions that can use the library
  • Customized interpreter that lets the extensions access the library

The project’s headquarters are at vorple-if.com where you’ll find all the official materials and downloads. JavaScript developers who want to dig into the innards of the system can find the source code at GitHub.

The library and all official materials are open source and free for anyone to use for any purpose. (Mandatory footnote: Do still read all the licenses if you want to use it commercially or as a part of a closed system. Some third party themes, for example, are subject to slightly more restrictive licenses.)

Support

The best place to look for assistance is the community forum at intfiction.org. Vorple’s author frequents the forum, as do other experienced authors who are happy to answer civilized help requests about authoring with Inform, Vorple or other systems.

Bugs can be reported at the project’s GitHub pages or by sending mail to bugs@vorple-if.com.