Everyone gather around to hear the story of Little Red Riding Hood:
Granny called Red, and asked her to bring some food. Red goes to the woods.Red makes it to Granny's. Red leaves Granny's and goes to the woods. Red returned home. The End
Wow, that was boring. Let us try again:
Granny called Red, and asked her to bring some food. Red goes to the woods. Red makes it to Granny's. Red leaves Granny's and goes to the woods. Red runs into the wolf and introduces herself. Red hits the wolf. Red tells the wolf about Granny. The Wolf eats Red. The Wolf gets to Granny's. The End
Well that was darker than expected but that is the great thing about getting a story generated by a computer. You never know what you are going to get. These particular stories were generated by an algorithm that chooses the order of events to a story, and even though the text is the same for any particular event, the results can be very entertaining.
This story generator focuses on changes in a story world caused by possible story events. The generation has two important components that consist of the story world and story events. The story events have two important components called preconditions and effects. Preconditions are needed in the story world to use the event, and effects are what changes in the story world after the event is used. The story world is a collection of variables and values that make up the current state of the story.
The algorithm itself is simple. First, to initialize the generation, an initial story event is chosen. The initial story world is set to match the event’s preconditions.
Next, the generation starts with the story world being changed by the chosen event’s effects, overwriting existing variables if necessary. Then, a list of potential events is chosen by checking every event’s preconditions against the story world. An event is rejected if there is a variable in an event’s preconditions that is not contained in, or whose value does not match, the story world. Otherwise the event is added into a list. Once a list of potential events is compiled, an event from the list is chosen at random. This process is repeated until an “theEnd” variable in the story world is set to “true” by an event’s effects.
In the brainstorming stage this generator was more complex. At first there were three levels of generation planned. This algorithm would have been be the same process explained above with each layer, though events used for a different purpose depending on the layer. Once an event was chosen for a layer, another one would not be chosen until the layer below was complete.
The first, and highest, layer had events that controlled the overall direction of the story. The event’s effects on this layer would have set a goal for the story world that would be reached with the next layer of generation.
The second layer would generate how the story progressed from one story event chosen by the first layer to another. The effects of this layer would act as a goal for the next, identical to how the first layer chose the goal for the second layer.
The final layer would have been used to put together tags for a grammar, an abstract structured language, to generate text. This layers effects would actually have changed the story world.
The purpose for constructing the algorithm in this manner would have been to create novel stories that would surprise the author of the generator. The three layers of generation would have abstracted the process enough to create an unpredictable, but enjoyable, story.
However, such a complicated algorithm proved to be unnecessary as this goal ended up being largely accomplished with the simpler algorithm that I did implement without magnifying the numerous problems of the generator, such as authoring.
The authoring process can be both tedious and challenging as the author must manually ensure each event’s preconditions and effects maintain the desired logic of the story. In essence, for each story event, every possible variable in the story world needs to be considered. This calls attention to how complicated the authoring of a story through events can become. In a way, that is intentional as the complexity enables the generation of unexpected stories; however, this structure also makes crafting a desired possibility space of potential stories by hand nearly impossible. Just looking at a graph of a small story makes this evident.
To fix the flaws with the current iteration, better data structures need to be considered. At the highest level of generation, a finite state machine could be used to determine the overarching flow of the story. A planning algorithm should also be implemented to have an easier way of computationally generating and testing the network of possible events. The planning algorithm will also help remove needless repetition during generation and enable the use of multiple agents working simultaneously.
The next iteration will move from Python to Unity. This change will focus on easily authoring new stories using graphical user interfaces, enabling text generation after the events of a story have been decided, and procedurally generating interactivity to immerse readers into the generated story. My hope is that the next iteration with be able to generate consistently enjoyable stories with unforeseen outcomes.