Interactive stories, as we have been describing them, are inherently complex. Programming their behavior is a potentially daunting challenge, all the more so if the author is not a programmer by training.

One idea I have to simplify story programming is to adopt a dataflow approach. Dataflow is a programming paradigm whereby operations are triggered by the flow of data rather than procedural logic. There are many variations, but in the one I have in mind the programmer defines the necessary inputs for each operation, and the operation executes whenever a new set of such inputs becomes available.

The great advantage of this approach is that it frees the author from the burden of managing the dependencies between scenes. There is no need for explicit logic defining paths from scene to scene. A scene doesn’t need to specify which scenes it may come from or which scenes it may lead to. All the author has to do is define the conditions under which the scene may or may not occur.

This means that managing the directed graph which defines the story structure is the responsibility of the story engine, not the author. So as the author adds, removes and modifies scenes, there is no possibility of dangling scenes, invalid scene references or other graph errors, because the graph doesn’t exist until runtime.

Another consequence of this is an increased possibility of serendipity. The story graph in the author’s head can be fuzzy, or even nonexistent, and the story may unfold in unforeseen ways.

Whether this is an advantage or disadvantage is arguable. I see it as a big advantage, because it doesn’t prevent precisely delineated scene sequences (the author simple needs to make the occurrence of scene A an explicit requirement for scene B), it just makes such exactitude optional.

The result is a more forgiving and less deterministic system, which in my view is the best approach for a complex and experimental medium.

In the model I have in mind, an interactive story is modeled in space as well as time. It’s most natural to think of it as physical space, but it’s really the interactive space. The user has some power of navigation, and the range of that navigation defines a space. The user can go places, so there must be places.

In a linear story, there is a fixed correlation between place, time and story. At every step of the way, the story says where and when it is, and every time the story is told the answer is the same. So places and movement become irrelevant to the structure of the story.

Not so with interactive stories. The user generally has a say in where the story unfolds. Typically the way the author maintains control over the story is by requiring the user to go to a particular place (as part of solving a particular puzzle) in order for the story to advance. This preserves the story structure, but at a cost: the user might go to many other places in the meantime, and all this extra movement may be largely or entirely pointless.

The solution to this is not, in my opinion, to eliminate the user’s ability to move freely (though inevitably it is necessary to establish limits). An interactive story naturally unfolds in space rather than time; the trick is to structure the space, and the relationship between the story and the space, so that a lot, maybe even most, of the movement advances the story.

In traditional, non-interactive stories, the natural flow of time is the scaffolding. The flow of time doesn’t have to be continuous; but changing the flow to skip into the future or jump into the past requires engineering on the part of the author. In between such manipulations, the story flows in perceived real time — perceived, as opposed to exact, because a clever author will reproduce the natural distortions in our sense of time, as when time seems to slow down in the course of an unusually jarring or traumatic event.

So how do we maintain timing, when our scaffolding is space rather than time? I believe there are many potential solutions — interactive literary devices, you might call them — and that successful interactive stories will depend on lots of them to achieve something close to the flow of time desired by the author.

A key approach, as I see it, is to have more than one story going on at a time. The more stories, the more opportunities for one of them to be suitable for wherever the user might be.

The most extreme example of this would be to have an independent story for each location. Go to location A, you get story A; move to B, you interrupt story A and start on story B; go back to A, you pause story B and resume story A. Wherever you go, a story would be progressing. So it would work. But it’s not a very satisfying solution, because there is nothing to be gained in the story by moving around; it’s the equivalent of channel surfing.

But multiple stories don’t have to be independent, and more importantly they don’t need to be isolated, each in its own place. Stories can cross paths, sharing a location for one scene, or many scenes. They may also share characters, objects, events. They might be subplots of the main story, thoroughly integrated. Or they might just coincidentally find themselves in the same place.

Another key ingredient to reconciling space and time is fuzziness and flexibility. To the extent that a story specifies kinds of places rather than specific places, it will naturally allow for a faster pace. For example, if a story takes place in a hotel, a scene that can take place in any hotel room will tend to occur much sooner that a scene that can only take place in a specifically designated room. I think that in many cases, there are plenty of details of a story that the author would be willing to leave vague in exchange for greater control over timing.

At the same time, I think it would be a mistake to use the flow of time in traditional stories as the yardstick for interactive stories. An important part of the enjoyment of an interactive story comes from the joy of exploration and discovery. An empty room is not boring, if its emptiness is a surprise, and if there are other doors left to check.

In fact, I don’t think we yet know the rules of thumb for creating the most enjoyable interactive stories. So above all we should provide the means for authors to experiment.

Just to prove that I’ve been thinking about this stuff for a long time, I posted a paper I wrote in 1995 called A Plot Beyond a Line. Though much has changed in the world of art and technology in the last 14 years, progress in the field of interactive narrative has been rather slim. So the core ideas in this paper are not really out of date, and the potential paths for experimentation that I identified are mostly still just that, potential paths, as opposed to well-established techniques in wide use (or discredited cheap tricks for that matter).

The heart of the gofp application, and the most original and interesting module, is the story engine. Its purpose is something that some might argue is impossible: to ensure that the story the user experiences is a good story, despite being interactive and therefore constructed on the fly.

There are two main schools of thought that I have encountered regarding how this goal may be achieved. They represent I suspect two distinct philosophies of storytelling.

One school, I’ll call them the characterists, holds that if you can model the characters astutely and deeply enough, give them the right motives and behavior, and set them loose then they will create a good story on their own. The other school, the structuralists, believes that if you can control the structure of the story, forcing it to follow the arc you want, then even if the details can vary widely the story will be a good one. It’s not that characterists don’t believe in the importance of structure, or that structuralists don’t believe in the importance of character. It’s more a matter of which of these two pillars of every good narrative you think should be the axis around which the story will dynamically and interactively unfold.

The ironic thing is that the school you belong to is most often determined by which of the two, character or structure, you are most in awe of — inversely. That is, characterists tend to believe that imposing a particular narrative structure on an interactive story is too hard, while structuralists tend to believe that programming a character to generate convincing behavior that advances the story in a good way on the fly is too hard.

I happen to be a structuralist. I believe that it is possible to essentially force a strong narrative structure onto an interactive story. I don’t think it’s a trivial problem by any means; I think it will require an entirely new reportoire of storytelling tricks and mnarrative devices. But I think it will work, because I think a user’s sense of freedom, discovery and involvement, which are the things that make an interactive story fun, depend on the quality, not quantity, of actual choices.

Yet the characterists are right to be skeptical. The mathematics are brutal; with even just a handful of choices per scene, the complexity could easily spiral out of control by act 2. The answer can only be that all or almost all of the choices must eventually converge. The millions of possible paths must be relentlessly pruned. But this must happen naturally, even invisibly, or the story won’t seem very interactive to the user.

So how do we do this? I suggest borrowing a strategy from 3D graphics, which faces an analagous problem when it comes to modeling lighting effects realistically. Imagine multiple light sources illuminating a complex scene containing objects with various reflective and refractive properties. You could try to model all the light emanating from each source as it bounces off objects, then off other objects, etc. until the light either leaves the scene or is blocked. But only a small fraction of all the light in the scene makes it to the viewer’s eye. Ray tracing leverages this fact by tracing the light rays backwards from viewer’s eye to the light sources. Thus only the light that actually makes it to the viewer is modeled; the rest is ignored.

My idea could be called arc tracing, as in story arc. With this approach, the story engine determines what choices are available at any point by working backwards from the endpoint.

Let’s say the endpoint is a final reunion between two characters. Perhaps that reunion can occur in one of two ways: by character A succeeding in some climactic struggle to get to where character B is, or by character B succeeding in some climactic struggle to get to where character A is. Each of these is a distinct scene, with a particular set of further scenes that might lead to it.

With arc tracing, the story engine attempts to trace paths from each scene back to the current point in the story. The story engine tests each scene for viability, given its requirements and the current state of the story. It could be that something required by the scene is no longer present in the story, or something that prevents the scene has happened in the story. In this case the scene is eliminated from consideration. The story engine also eliminates scenes it has already considered. The process is applied recursively to all the scenes which survive elimination until finally the current point in the story is reached.

This process may not be sufficient by itself. For one thing, finding the path is not necessarily a computable problem for every possible arrangement of scenes. There might not be a path from the start to the end, or there might be loops or other peculiarities in the structure that make the path impossible to compute. So certain additional constraints and rules may be necessary.

Moreover, this technique in no way guarantees that every path, or any path for that matter, constitutes a good story. That’s up to the author. The goal is simply to make it feasible for an author to devise an arrangement that guarantees a good story.

When it comes to implementing something, managing state is often the devil in the details. State is entropy. The problem specifically is that state accumulates, and begets more state, and then more state to manage and keep up with all the previous state. Inevitably, applications end up with more state than necessary. And state is inherently complexity-inducing, leading to layers of models and managers and controllers to deal with it. After a certain point, you may have huge quantities of information, and the theoretical ability to do all sorts of things with it, but in practice you are stuck — the complexity is such that you no longer can predict what the effect of a change will be, and you can only grope forward, making incremental changes and seeing what happens.

There are ways to reduce the need for state. Functional and declarative programming come to mind. You can actually come tantalizingly close to elimination of state. But programs don’t operate in a vacuum; they are controlled by users. So you can never actually eliminate state, unless you eliminate users, who are highly stateful creatures, and then you’d end up with something rather pointless (speaking as a user). More importantly, at some point the cure becomes worse than the disease and programs become incomprehensible.

A little complexity can actually be a good thing. Employing leverage is a complication, for example. You have to find or provide a lever and a fulcrum. But it can be worth it.

My proposal for reducing complexity while maintaining leverage is to move away from the user/session model to a new model with fewer layers: stories and tellings.

It sounds odd to say it, but the idea is to throw personalization in reverse, to make sessions something associated with the content, not the user. You start with the raw content, which is actually a description of how to create the content. Then you create instances of this content. It might so happen that each user has her own individual copy of the content, but if so it would be a purposeful arrangement — purposeful on the part of the author, I mean. The author could just as purposefully require that every user receive the same exact copy. No personalization at all.

Or the author could come up with something somewhere in between. That’s where the creative potential lies. Think of all the arrangements that are possible. You might share content with a small group. Maybe you know who you are sharing content with. Maybe not. Maybe you’re sharing content, but not exactly the same content. Hippo? That’s not a hippo. It’s a dirigible. How could a hippo be floating a mile up in the air? Oh.

Of course who a user is might matter. Have a layer that does all the necessary user stuff, as secure as you want it. But once you get past that membrane, you are in the story. Your identity as a user is subservient to the story.

It’s not that you don’t have a session. It’s that your session is populated with state associated with something else — the telling of a story. That telling exists apart from your session. And your session might be one of many populated with the same state, from the same telling.

How does this reduce complexity? It does so by allowing the author, not the users, to set the limits. There are as many tellings as the author determines — or as few. They are as complex as the author determines — or as simple.

How is this good for the user? Because a session in and of itself does no good to a user. The properties of a session — the user’s identity, the user’s preferences — do not constitute useful information to the user. They are only valuable if they somehow add value to the raw information available from the application.

But the raw information puts a hard floor on the value. Useless information is useless no matter how nicely you dress it up.

So the question becomes, how do you maximize the ultimate value to the user? I would suggest that you get more value by providing a very rich flow of raw information with a rudimentary ability to extract additional value than you do by providing a rudimentary flow of raw information with a very sophisticated ability to extract additional value. The best of course is to have both, but to get there I prefer the high road.

Here is a rough overview of the architecture of the GOFP application.

Modules:

  1. Control Panel: a browser-based user interface for the application, allowing the author to load scripts, activate stories, enable features, set various options and monitor the application as it runs.
  2. Script Parser: reads scripts provided by the author and builds an internal representation of the script contents.
  3. Story Engine: selects scenes and transitions based on the state of the story, directions in the script, user actions and other sources of information.
  4. Presentation Module includes:
    1. Scene Handler: presents scenes selected by the story engine.
    2. Transition Handler: presents transitions selected by the story engine.
  5. Persistence Module: saves the state of a story so that it can resume from that point in a subsequent session.

An interactive story, like a play or a movie, begins as a script. The story consists of an arrangement of acts, each consisting of an arrangement of scenes and transitions. (a.k.a. cut scenes).  A scene involves characters and occurs at a place. Places are connected by paths, which is where transitions occur.

Characters include actors (whose behavior is defined by the author) and interactors (user-controlled characters). The author provides content for the actors (for example, lines of dialog) and specifies their actions. Interactors, meanwhile, are allowed some freedom of movement and are presented with choices. The degree of freedom, the choices and the way in which those choices affect the story are all defined by the author.

Unlike a play or a movie, the scenes in an act and the acts in a story don’t necessarily go in a set order.  Some scenes or acts may not appear at all in some tellings of the story.  Or the order might change. The logic which chooses scenes and acts is controlled by story directions provided by the author.

Story directions may be based on many things, including the events of the story up to that point, viewers’ actions, outside sources of information (e.g. time and weather at a particular location) and random chance. Each such event, viewer action or other bit of information is encapsulated in a story token.

Story directions define relationships between story tokens and scenes, such as stating that a particular token is required for a given scene to occur, or prevents the scene from occurring, or influences the scene in some way, or is created or destroyed in the scene.

Some story tokens are relevant to particular characters; for example, a change that occurred to the character. Such story tokens are carried from scene to scene by the characters they pertain to. Other story tokens are tied to particular places, such as an event that occurs there. Other story tokens start out associated with a place, then become associated with a character, such as an object sitting somewhere that a character acquires at some point. Finally, some story tokens are global, such as the elapsed time in the story.

All of the above is spelled out, loosely or precisely, sketchily or in detail, in a script. On the basis of such a script, the story engine, the application I am building, creates a user experience. Where the script is vague, the story engine does its best.

Finally, a story may play out in parallel with other stories, by the same author or other authors. The stories are woven together by the story engine.