Argax Project

Node Status: COMPLETE

Story-Level Events: Scenes

A scene is a pre-authored bundle of narration and world-level manipulations to be made by the DM. Like an action, a scene is a story-level event. The difference between the two is essentially that action events are produced by the player while scene events are produced by the drama manager.

Scenes serve three purposes in Marlinspike. The first is to provide reactions to player actions. While verbs provide narration of their world-level effects, only scenes provide narration of NPC responses and other story-level effects. The second purpose of scenes is to advance the story by introducing new incidents and material. Finally, scenes can provide a story context that may affect later verb-to-action casting and action-to-action recasting (as previously described above).

Every scene has a list of preconditions that determines whether it can currently be performed and appended to the story-so-far. Preconditions might include the current story-world time, character locations, prop states, character attributes, or previous story events.

Besides preconditions that must be true for a particular scene to run, scenes can also include hooks, which are previous events that the scene can refer to or otherwise reincorporate if they have occurred. This aids in threading (described below).

Each scene belongs to one of three functions. Beginning scenes have no preconditions and are selected by the drama manager to start a new story. The bulk of scenes are middle scenes, which have preconditions and serve to advance the story in some way. They, in turn, usually satisfy the preconditions of later scenes. Ending scenes also have preconditions, but provide a conclusion to the current story. A story will end as soon as the drama manager can meet the preconditions of an ending scene.

Like a paragraph in a novel, scenes vary in how much action they present. A scene may be only a single line of dialog delivered by an NPC in response to a question asked by the PC. On the other hand, a scene may be paragraphs long or summarize the passage of hours. Regardless of length, no user input--and thus no deeds or actions--are possible during a scene. Like actions, completed scenes are appended to the story event history.

Also like actions, scenes have an import value. This value indicates the narrative significance of the content that the scene just contributed to the story. Scenes also have an author-assigned imperative value that gives a certain weight to scenes during their selection process. (The details of this process are explained later in this chapter.) In brief, when other considerations are equal, scenes with higher imperative values will be chosen over those with lower imperatives.

Like actions, scenes have a very simple structure in Marlinspike. Each turn, every scene's canPlay function is polled to see whether that scene has its preconditions met. Then, once a scene that can play has been selected, its play function is called.

To illustrate this, here is a pseudo-code example of a very simple scene.

MiddleScene NPC_is_Insulted {

  super.import = 3
  super.imperative = 2
  
  //internal state specific to this scene
  this.insult = null
  this.hook = null
  
  function canPlay() {
    // If all preconditions have been met, returns a list of
    // those precondition events and any optional hooks.
    // Otherwise, the scene can't currently play and so returns null.
   
    if EventHistory.current contains Event(any, INSULT, any, ofclass NPC, any, any):    
      //precondition met: Some NPC was just insulted
      this.insult = EventHistory.current
      List reincs = new List()
      reincs.add(this.insult)

      this.hook = EventHistory.past contains 
                  Event(this.insult.actor, INSULT, any, this.insult.dirObj, any, any)
      if this.hook:
        //hook found: This is not the first time this actor has insulted the same NPC
        reincs.add(this.hook)      
              
      return reincs
  }   
  
  function play() {
    // Plays this scene
    
    print this.insult.dirObj.name.uppercase()
    print ": "
    print random("How dare you!", "How rude!", this.insult.dirObj.insultedReply)
    if this.hook:
      print " Your continued petty belligerence is tiresome indeed."
    print lineEnd
  }
  
  function getTriggers() {
    //This scene does not add any triggers to the story context
    return null;
  }
}
Example psuedo-code definition of a simple NPC_Is_Insulted scene.

As demonstrated by this example, although scenes are pre-authored, they can be written in such a way that most of their specific details are filled in at run-time. For example, this scene will play for any NPC that is insulted, regardless of the location or the character that did the insulting (PC or another NPC). Also, this scene sometimes pulls text from the specific individual NPC that is replying in order to further customize the scene. This example also shows the use of a hook in that the output of the scene can change to refer to an earlier event when it exists in the event history. In practice, an repeatedly insulted NPC might want to warn the insulter not to do that again. Such an interdiction would add to the story context, which brings us to triggers.

Marlinspike architecture: scenes.
The drama manager replies to actions by playing scenes.