FRISE - the FRee Interactive Story Engine

Interactive Story Engine

FRISE is a small, MPL 2.0 licensed, Javascript program that let's you write interactive fiction and games directly in HTML -- the format of the World Wide Web.
FRISE games are played in your browser. Games can be hosted on a web site, or can be downloaded and played offline. To play a downloaded game, you just click on the HTML file to launch your browser and start playing!
You write games in your favorite text editor. Choose-Your-Own-Adventure stories are written directly in conforming HTML, without the need to learn a specialized story format language.
More complicated interactions in stories, such as remembering state, are achieved using standard Javascript. FRISE comes will a small number of useful functions to help you.

An Example Story

Below is the code for an example game. The comments explain the FRISE features being used.
 <!doctype html>
 <html lang="en">
 <head>
    <title>An Example Story</title>
    <meta charset="UTF-8" >
    <link rel="stylesheet" href="frise/css/game.css" >
 </head>
 <body onload="initGame();">
 <x-game><!-- Tags beginning with x- are valid HTML, FRISE makes use a small
              number of these. The x-game tag goes around the game code. -->
 <x-object id="main-character"><!-- Games can have many object's for people,
                                things, etc., but must have a main-character-->
    <x-position>start</x-position><!-- x-position is used to say the location
                                    of an object. The game always presents
                                    the location of the main character.
                                    For other objects, position is optional -->
    <x-name>Frise Guy</x-name><!-- name to use when object speaks -->
    <x-icon>images/frise_guy.jpg</x-icon><!-- icon used if an object speaks -->
    <x-smile>Muted</x-smile><!-- Feel free to make up x-tags for other
                                 attributes of your objects -->
 </x-object>
 <x-location id="start"><!-- An x-location tag is used to define a location --
                             somewhere an object can be -->
     <x-present><!-- x-present tags are used to describe a location when
                     the main-character is there -->
     <h1>The Adventure Begins</h1><!-- Notice how we can use
                                   vanilla HTML in our description -->
     <img src="images/fork.jpg" alt="A left road and a right road separated by
        a giant stainless steel fork -- Made in Dall-E" >
     <p>It is a dark and stormy night... You reach a fork in the road.</p>
     <x-speaker name="main-character">Whoa! That's a big fork!</x-speaker>
                       <!-- x-speaker tags can simplify drawing conversations-->
     <ul>
     <li><a href="#right">Go Right</a></li><!--To create links from one
                                               location to another
                                               url fragments are used. I.e,
                                               #right to go to location right
                                               -->
     <li><a href="#change-smile;left">Go Left</a></li><!-- We can also use
                                               fragments to specify actions to
                                               do before going to a location -->
     </ul>
     </x-present>
     <x-action id="change-smile">
     obj('main-character').smile = "Brilliant";
         /* obj(some_name) is the syntax to refer to the object some_name
            loc(some_name) is the syntax to refer to a loc.
            x-action tags; otherwise, contain straight Javascript
            Notice in the above we used .smile to refer to the smile property
            we had defined with the x-smile tags earlier.
          */
     </x-action>
 </x-location>
 <x-location id="right">
     <x-foo>bar</x-foo><!-- Feel free to make up x-tag attributes for
                            locations too -->
     <x-present>
     <h1>Victorious!</h1>
     <p>You, ${obj('main-character').name},
        flash a ${obj('main-character').smile} smile. You win!</p>
     <!-- $ {some_expression} is the standard format for Javascript string
         interpolation of variables and expressions. FRISE let's you use it in
         HTML x-present sections -->
     </x-present>
     <x-present ck="loc('right').foo == 'bar'" ><!-- the check must be
         true for the text below to be presented.-->
     Somehow though it felt too easy.
     </x-present>
     <x-present>
     <div><x-button href="#reset;start">Restart</x-button></div><!--
        x-button's are another way to make links between locations-->
     </x-present>
     <x-action id="reset">
         game.reset(); // game is the Javascript name for the current game
     </x-action>
 </x-location>
 <x-location id="left">
     <x-present>
     <h1>The Left Path</h1>
     <p>The left path at first seemed very sinister...</p>
     </x-present>
     <x-present ck="clickProceed('And then...')" ><!-- a link must be clicked
                                                for the below to display -->
     <p>And then you, <input data-for="main-character" name="name">,
         had a moment of personal growth and
         traversing it became easier.</p><!-- Using the data-for attribute
             input tags can be bound to values of object properties.
             In the case, above the name property of the main-character. -->
     <p><a href="#right">Until...</a></p>
     </x-present>
     <x-default-action>
     /*
        Default Actions are run for any object or location that has them,
        once per turn
      */
     if (obj('main-character').position == 'left') {
         loc('right').foo = "left";
     }
     </x-default-action>
 </x-location>
 </x-game>
 <script src="frise/js/game.js" ></script>
 </body>
 </html>
Try the game. Or download it together with other FRISE examples to try it offline.
FRISE has built-in support for a side navigation bar, handling game saving, and more. Details can be found in the Documentation .