[][src]Module intfic::parse_file

Parses story files and constructs a list of StoryBlock's.

intfic Story File Markup Specification.

Story files house a collection of Story Blocks that make up the narrative of your game. You can link together multiple story files to write and organize your story in a cohesive manner.

Here is an example of a simple story block:

:- start
 
It's nearly pitch black out tonight. There's a bit of light from the city up north, but no stars are peeking out through the clouds.
You wonder if he'll come after you; if you're going to be in more trouble for storming out like that.
What if it made him more angry? The thought makes you walk a bit faster towards the intersection ahead.
As you turn you see the flash of a car's headlights from the direction you came.
 
  What do you do?
*- Keep walking -> walk -> walk_car
*- Hide from the car -> hide -> hide_car
*- Run from the car -> run -> run_car

Story Blocks have three main parts:

TITLE
 
TEXT & EFFECTS
 
QUESTION & OPTIONS

TITLE

A title indicates the start of a new StoryBlock. It always starts with the characters ":- ", followed by the name of the new block.

:- lose_computer

TEXT & EFFECTS

The middle section of a Story Block contains the text the player will see, and any effects that will be applied to the GameState.

He abruptly yanks the power cord out of the computer and power strip, it shuts off with a sharp buzz.
?- saved_work => Thank god you had just saved, you can't imagine having lost all that work. => You can't believe what just happened. Why didn't you save? So much work just gone.
=- computer_access = false
-b "You aren't supposed to do that!" You protest. "It can permanently damage the machine!"
#- score >= 50 => -y "I'm sorry son, but I think this will help." He says calmly. => -y "You won't learn any other way!" He yells back.
Your younger brother and sister, having heard the commotion, appear at the doorway between the computer room and kitchen.
-g "Dad, can we still use the computer?" Your brother asks, innocently.
-y "Yes that's fine, just ask me for the cord when you need it, and make sure to give it back to me after"
They seem satisfied and grin at him before heading back to the tv. You feel a pang of embarrassment.
+- shame + 1

The folowing character combinations, when used at the start of a line or conditional line, have special effects:

  • "-b ": Prints the line in blue.
  • "-c ": Prints the line in cyan.
  • "-g ": Prints the line in green.
  • "-p ": Prints the line in purple.
  • "-r ": Prints the line in red.
  • "-y ": Prints the line in yellow.
  • "=- ": Sets the given flag to the given value in our GameState

    Example: "=- computer_access = false" sets computer_access to false.

  • "+- ": Adds the given value to the given counter in our GameState

    Example: "+- shame + 1" adds 1 to whatever value shame has, or sets it to 1 if it is not set.

  • "?- ": Prints a "then" or optional "else" line based on the given flag's value in our GameState.

    Example: "?- saved_work => saved_work then line => saved_work else line"
       This will print "saved_work then line" if saved_work is true,
          and will print "saved_work else line" otherwise.
       The "else" line is optional, if you would rather no line be read should the condition fail.
       Note that conditional lines are parsed recursively, so you may use colors or nested conditionals in them.

  • "#- ": Prints a "then" or optional "else" line based on the given predicate's value in our GameState's counter environment.

    Example: "#- score >= 50 => score check then line => score check else line"
       This will print "score check then line" if score >= 50 is true,
          and will print "score check else line" otherwise.
       The "else" line is optional, if you would rather no line be read should the condition fail.
       Note that conditional lines are parsed recursively, so you may use colors or nested conditionals in them.

QUESTION & OPTIONS

The final section of a StoryBlock is the question and options presented.

  What do you do?
*- #- strength >= 25 => Punch your dad. -> punch him, violence -> fight_dad.txt
*- Leave the house. -> take walk, run -> wander_neighborhood.txt
*- Go to bed. ->  -> sleep
*- ?- have_time_machine => Go five minutes in the past to fix this -> go back in time, time travel -> time_fix

The "question" is usually indicated by a line of text just before the options with two extra spaces at its start. These spaces tell the parser to print the question in cyan, but they and the question itself are completely optional, and in fact are just part of the block's text. (Meaning that you could ask different questions based on a conditional query).

Options have the following structure:

*- Text the player will see -> strings to match input -> block or file to read if matched

Example: "*- Leave the house. -> take walk, run -> wander_neighborhood.txt"
   This option will be presented as "#) Leave the house." to the player,
      Where "#" is the number it is presented as, either 1 or 2 in the above example.
   The number of an option may be entered by the player to choose that option.
   When the player types their answer and hits enter, "take walk, run" will be searched
      to see if it contains that input as a substring.
   Additionally, a match may be made if the input matches the option text or result string exactly.
   If a match is found, then the Story File "wander_neighborhood.txt" will be loaded
      and the story will pick up at the first block of that file.

Example: "*- Go to bed. -> -> sleep"
   This option will be presented as "#) Go to bed." to the player,
      Where "#" is the number it is presented as, either 2 or 3 in the above example.
   The number of an option may be entered by the player to choose that option.
   This example does not use any keywords to match input against. So the player can only choose it
      by typing the number, "Go to bed", or "sleep" exactly.
   Though I don't recommend not including extra keywords to match against,
      You may do so as long as you keep two spaces between the "->" delimiters.
   If a match is found, then the Story Block "sleep" will be played.

The folowing character combinations, when used at the start of an option, have special effects:

  • "?- ": Presents the option only if the given flag's value is true in our GameState.

    Example: "*- ?- have_time_machine => Time Travel -> go back -> time_fix"
       This option will only be available to choose from if have_time_machine is true.
       Note that their is no "else" option available to show.

  • "#- ": Prints the option only if the given predicate's value is true in our GameState's counter environment.

    Example: "*- #- strength >= 25 => Punch your dad. -> fight -> fight_dad.txt"
       This option will only be available to choose from if strength >= 25 is true.
       Note that their is no "else" option available to show.

Functions

load_file

Takes the name of a story file and parses it, returning Some(Vec<StoryBlock>) if successful