Story Format

This article is a proposal for a file format for interactive story content in PARPG. It follows on from Proposal:Story Engine which describes the overall framework.

= WORK IN PROGRESS =

Quick overview
An event has a set of preconditions (things that must have happened beforehand) and a set of postconditions (things that should be done afterwards). Each event can have a title, a set of people involved and a description. The description is used to inform the player (in words) about what is happening; it could be the dialogue the player says, it could be a description of what is happening ("The box hums." or "Die traitor!"). The description is what appears in any dialogue tree that is shown by the game.

For example: "Save princess quest" - "John": 'I will save you princess! ' . Beforehand: - "princess kidnapped" and "health" of "john" greater than 5. Afterwards: - start combat between "John" and (guard). - add journal entry for 'I said I '' d rescue the princess.'. - begin "princess rescue plot arc" with "princess guard" as (guard).

Each story event in the file is separated from the others by a blank line, which it might helpful to think of as marking a paragraph. Story events can be grouped into story arcs (and story arcs can contain other story arcs). Individual events in a story arc can share a cast of characters, and props (the explanation of why you'd want to do this will have to wait for later), and some pre- and post-conditions. When a story arc has pre-conditions, those pre-conditions must be met for every event in the arc. For example, if "princess is alive" is a precondition for the whole arc, then every event in the arc depends on the princess being alive - if she dies the whole arc becomes unavailable.

"Princess rescue plot arc" ========================== Cast: A "princess guard" & "John". Props: A "wooden sword". Beforehand either: - "princess kidnapped". - "princess dead" and "queen kidnapped".

The most useful pre-conditions are in the form of pre-defined sentences supplied by the game not the story engine. For example, the game might say that it can answer a question like "%% is alive" where the story writer is invited to supply a name for %%; you might write: "John" is alive. These can be pairwise relations, so another possible sentence would be "%% has met %%"; the story writer might write: "John" has met "Alice".

Post-conditions take the form of instructions, and the most useful are again are supplied by the game as pre-defined sentences. A possible sentence might be "Add to the journal %%" and the story writer would write: Add to the journal 'Got a quest to rescue the Martian king'.

Story events
The main layout of a story event is as follows (parts in bold are keywords; all the punctuation is important): *** "Event title" ("Arc title") - Arcs: - An arcs this event belongs to. - Another arc this event belongs to. Actors to targets: ' Description of event that takes place''' '.  Actors to targets: ' Another part of the event that takes place '.  unless role is actor in which case actors to targets: ' An alternate description for this part '.  Beforehand:''' - A thing that must be true beforehand. - Another thing that must be true beforehand. Afterwards: - Something that must be done if this event occurs. - Another thing that must be done if this event occurs.

In choosing names, titles and descriptions, the writer has complete freedom. Names and titles are enclosed in double quotes, and descriptions are enclosed in single quotes. So for example if your character is called John, in the story file you will always write "John". Single quoted strings can span multiple lines, but double quoted strings cannot.

If you want to include quotes and apostrophes, you'll need to double them up (so "John '' s car" rather than "John's car") - this is again because the parser isn't smart enough to know the difference between nested quotes, or between apostrophes and quotes.

Many parts of the above form are optional. The title is optional, but if there is a title, it must be underlined with dashes. A story event without a title can't be referenced elsewhere by its title. In the example we had "princess kidnapped" which might be a story event, so somewhere else there would be an event that begins "Princess kidnapped"  ...

The title can have two extra bits we haven't seen in the examples. The stars are a shorthand way of saying "This story event follows the one before it." More precisely, when a title starts with stars, it follows the story event most closely before it in the file with a smaller number of stars. So if we take this example: "Story event one" - * "Story event two" - ** "Story event three" --- * "Story event four" --

Then story event one is followed by story events two and four, and story event two is followed by story event three. Of course you could also write:

"Story event one" - "Story event two" - Beforehand "story event one". "Story event three" --- Beforehand "story event two". "Story event four" -- Beforehand "story event one".

These are two ways of saying the same thing, the first is just an easy shorthand for the second. Stars can be given even when the rest of the title is missing. So you could, if you wanted an unnamed event dependent on the previous event, say something like: * "John": 'Watch this...'

Inevitably, there could be very many stars in some situations. To help with this, a star can be followed by a number indicating how many stars it should be read as, for example *5 means *****. With large numbers of stars, or with editing, keeping the star counts correct might become difficult. Its also possible to say *=, meaning same number of stars as the last event, *< for fewer stars than the last event, and *> for more. Of course these can be used in combinations *<< means two fewer stars, *>4 means four more stars. And so on.

The second optional part of the title is an arc name, giving a plot arc this story event is involved in. There is also the option to give multiple arc names underneath in the arcs section. We'll talk more about plot arcs later.

The actors, targets and description are all optional so you could have any of:
 * "John" : 'Hello!'.
 * "John" to "Jack": 'Hello!'.
 * to "Jack": 'You feel sleepy!'.
 * "John".
 * "John" to "Jack".
 * to "Jack".
 * 'The box begins to play music!'.

You can have multiples of these, or you can also omit this part entirely.

The actors are the people performing the event. If there's no person "doing" the event, then there's no actor. The targets are the people on the receiving end of this event, be it speech or whatever. If there's no-one this event is to specifically, it doesn't have a target. The description is the text that will be shown to the player by the game. If there's no description, the player won't see any text.

The format is a little more powerful than this because it allows you have a list of actors and a list of targets (but each description has its own list of actors and targets). Lists have a particular form that might be hard to remember at first (again due to the limitations of the parser in understanding human language). Lists look like this:
 * "John"
 * "John" & "Jack"
 * "John", "Jack" & "Fred"
 * "John", "Jack", "Fred" & "Wilma"

and so on. So that a complicated story event might be described as: "A greeting event!" --- "John", "Jack" & "Fred" to "Wilma" & "Betty": 'Hello (in unison)'.

Note that the comma goes outside the quotes.

Unless clauses are used with plot arcs that have cast roles. They indicate different dialogue to be used in the event a particular individual was cast in a particular role.

Preconditions
A set of preconditions consists of the keyword Beforehand followed by a rule which will decide whether the story event could occur at any given moment or not.

Event Names
The simplest kind of rule is just the name of a story event, for example we could have any of:
 * Beforehand "princess has been saved".
 * Beforehand "the tea party at the inn".
 * Beforehand "John's dad comes to visit".

In this case, beforehand means right before. Unfortunately, to make it read a little more naturally, it's slightly more complicated to say what right before really means. It goes something like this: when a story event happens, any story event that depends on it happening right before becomes available. When any of those story events that followed it happens, it no longer happened right before and so they all become unavailable (because they depended on it happening right before!) Some examples should make this clearer.

"Step one" -- Beforehand: "step zero". "Step two" -- Beforehand: "step one". "Step three" Beforehand: "step one". "Step four" Beforehand: "step two".

Imagine this is our story. Let's suppose step one just happened. Either step two or step three could happen next, because step one happened right before and both of them depend on that. If step two happens next, then step one no longer happened right before, which means neither step two or step three is available anymore. However, step two did happen right before so step four is now available. This basically means that it works out the way you expect naively in most cases.

Sometimes, we might want to depend only on a story event having ever happened; perhaps part of a previous conversation for example. In that case we can use the built in sentence has happened, for example we could say:
 * Beforehand "step three" has happened.

Of course if this was the only condition on an event in a real dialogue, once step three had happened, it would always be available and the player might see it over and over again!

There are other names kept by the story called story knowledge which we shall talk about when we talk about remember and forget in post-conditions. These are true if they have been remembered, false if they have been forgotten, and also false if the story engine has never heard of them.

Predicates
To find out information from the game (rather than just the plot) the story writer must use predicates. Don't be put off by the name, these are just sentences provided by the game which have some missing words to fill as appropriate. For example, the game might supply a sentence "%% is alive", which allows the story to contain phrases like:
 * Beforehand "John" is alive.
 * Beforehand "Harry" is alive.
 * Beforehand "the great scaly dragon" is alive.

It depends on the game to define a set of predicates that make sense. These sentences can have two blanks, so for example we could have "%% can see %%", and then we could write:
 * Beforehand "John" can see "Fred".
 * Beforehand "the evil arch-villain" can see "the princess".
 * Beforehand "Toby" can see "Wilma".

Extra flexibility is provided by allowing the blanks to be substituted for lists, for example:
 * Beforehand "John" & "Toby" can see "the evil arch-villain".
 * Beforehand "Toby", "Wilma" & "the princess" can see "Tom", "Jerry" & "Larry".
 * Beforehand "John", "Toby" & "Wilma" are alive.

The last example is important: the story engine doesn't know about is and are (which is grammatically correct) it's just looking at sentences like "%% is alive" "%% are alive"; it's a good idea for the game to provide plural forms to allow the story to scan more naturally.

More complex logic
We've seen the basic sources of knowledge available to the story engine: it's own base of story events that have happened and knowledge it was told to remember, and also predicates for asking the game about its situation. We don't want to just rely on one of these per story event though; often we'll want a combination of several things to be true.

Story files allow information to be built up using basic logical phrases. For example, if "princess has been rescued" and "princess" is alive are two pieces of information, we can combine them simply:


 * "princess has been rescued" and "princess" is alive.
 * "princess has been rescued" or "princess" is alive.
 * not "princess has been rescued".
 * not "princess" is alive.

These correspond to the ordinary meanings of these words. The form for not might look a little alien, but it's like this because the parser isn't clever enough to know that the right forms should be "princess hasn't been rescued" and "princess" isn't alive. The final way of combining two pieces of information is xor which is probably unfamiliar to anyone without an engineering or mathematical background. xor means either one or the other is true, but not both. For example:


 * "princess has been rescued" xor "princess" is alive.

This means either the princess has been rescued, or the princess is alive, but both aren't true. So if the princess had been rescued and was alive, this wouldn't be true, only if one or other was true.

The next problem is that it's a little difficult to work out what we mean when we say:


 * "thing one is true" or "thing two is true" and "thing three is true"

Do we mean that thing three has to be true always, or do we mean that it doesn't matter if thing three is true so long as thing one is? In actual fact, the parser thinks of things connected together with or as closer together than things with and so sentence does mean that thing three always has to be true. But this is not very clear! The best way to make this clear is to split it over multiple lines, using bullet points.

The above example can be rewritten as:


 * The following are true:
 * - Either:
 * -- "thing one is true".
 * -- "thing two is true".
 * - "thing three is true".

Here the length of the bullet points lets us know how the things group together. The phrase the following are true starts a set of bullet points, all of which must turn out to be true. So for example:


 * the following are true:
 * - "the princess is alive".
 * - the season is "winter".
 * - it is night time.

This would only be true when all of the bullets below it were true. The alternative is to start with either, for example:


 * Either:
 * - "horse" of "John" is lame.
 * - "princess has been rescued".

Which is true when any of the bullets below it is true. These phrases can be nested as we saw in the first example, with each level adding another length onto the bullet point, just like normal bullet points.

As a special case, after beforehand you don't need the following are true; it's implied, so you can say:

Beforehand: - "thing one is true". - "thing two is true".

to mean both thing one and thing two must be true.

It might occasionally be the case that you don't want to introduce more bullet points, perhaps what you have to say is short, or you think it would be clearer without adding an extra level of bullet points. In these cases there is also bracketing for logic, which isn't very much like English, but is very much like a logical system.

Our original example could have been written:


 * {"thing one is true" or "thing two is true"} and "thing three is true"

The brackets mean "do this bit first", so in the example, they say to work out whether thing one or thing two is true before working out whether thing three is true. If we wanted to say that "thing three doesn't matter if thing one is true" we could change the brackets:


 * "thing one is true" or {"thing two is true" and "thing three is true"}

Generally bullets are clearer, although more verbose, but there is the option to use brackets if you so desire. Note that these are curly braces not parentheses.

Postconditions
Postconditions consist of a keyword afterwards followed by a set of bullet points describing what actions should occur if this event comes to pass. For example:

Afterwards: - start combat between "John" and "Fred". - add journal entry for 'I said I '' d rescue the princess.'. - begin "princess rescue plot arc" with "princess guard" as "Fred". - remember "Fred and John fought". - forget "Fred and John are friends".

Plot Arcs
The layout of an arc description is: Arc title ========= Cast: characters. Props: objects. Beforehand: - A thing that must be true beforehand. - Another thing that must also be true beforehand. Afterwards: - Something that must be done if this event occurs. - Another thing that must be done if this event occurs.

Loops
We can use the right before behaviour of story elements, together with some logic, to set up a loop of steps:

"Step one" -- Beforehand either: - "step zero". - "step three". "Step two" -- Beforehand "step one". "Step three" Beforehand "step two".

If more than one set of preconditions is given, they must all be true (which is what you'd expect).

Why not just use XML? XML can do anything!
XML is a tree structured data format most naturally. Dialogue "trees" may look like trees when you're clicking through them, but if you think about it they really aren't "trees" in the sense of building them. Certain elements reoccur, there are often loops, they may depend on external checks. The dialogue graph is really directed and partially connected.

Of course, you can represent any graph structure you want in XML using some kind of reference system but you've lost any neat mapping with the "dialogue tree". In fact, you could take the above proposals, wrap them up in lots and lots of angle brackets and have an XML input format. However, it must be remembered that making a dialogue editor will take time, and making writers write XML is a sure way to get fewer writers and less progress. Hence the need for a more human friendly format.

Why not YAML? YAML can do anything!
YAML is a format for representing structured data. What will be your execution model for your YAML structure? Let's assume you can avoid verbosity and get something readable using YAML (it's just syntax - you'll still have to establish your conventions). Now what? Where will your predicates or postconditions be encoded, and how will they be encoded? Most likely you now hand roll a half-baked parser to deal with string values that encode expressions. You can put any kind of front end on the story engine; the parser is not the complicated bit. It just so happens this version is readable in combination with the powerful features we might want. If you can do better in YAML (you still have to represent all the same data, none of it is there for its sheer baroque glory) please do, and we'll use that.