FRISE - the FRee Interactive Story Engine

Interactive Story Engine and Visual Novel 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, linking our free interactive story engine script. 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 stage="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, game save and load buttons, and more. Details about our free interactive story engine can be found in the Documentation .