Actions

Work Header

Rating:
Archive Warning:
Category:
Fandom:
Additional Tags:
Language:
English
Stats:
Published:
2026-02-21
Words:
1,194
Chapters:
1/1
Kudos:
1
Hits:
13

SIFL capabilities teaser

Summary:

Brief overview of Simple Interactive Fiction Language and its capabilities.

Notes:

I wrote this with a headache, so the prose is a bit off. I'll come back to rewrite it at some point.

Work Text:

This is a very brief teaser of SIFL (Simple Interactive Fiction Language). It's a language which can be used to create interactive fiction compatible with AO3. I have a demo available here.

Basic structure

SIFL documents are made up of sections or areas. Each section has an ID, which is used to reference the area whenever the player clicks on a travel option. A section starts with a header, like so:

# @example Example section

The hash marks the line as being a header, with the @example being its ID. The text after the ID is shown to the player as a heading.

The first section in a document will be the first one shown to the player.

Sections contain paragraphs, which are just plain text with optional HTML. Like so:

# @example Example section

This is a paragraph.

This is also
just one paragraph.

And this is the third <strong>paragraph</strong>.

Paragraphs which are split across lines will be joined into a single continuous paragraph. This is useful for code styling and organization.

Options/choices

Choices are the primary form of user interaction in SIFL documents. Choice elements are started using a > symbol on a new line, with multiple choice elements next to each other forming a choice block.

The traveler asks "Where is this place?"

> It is your home.
> It is the final resting place for your kind.
> How can I trust you?

The player will then be presented with all of these options at once when the execution reaches this point.

Every choice can have an optional body, which is an indented section immediately following the > line. Choices which have been selected will show their own body, as well as any block immediately after their block.

"How are you?" the elder asks.

> I am fine, but pained.
  "Warrior, do not fret." the elder calls forth the healer.

  "The healer may cure your pains."
> The healer must tend to my wounds.
  "As I feared." the elder retreats to a cabin.

  When they emerge, an ancient healer follows.

"What is your pain, warrior?" the healer asks.

The player will be presented with the option to select either "I am fine, but pained." or "The healer must tend to my wounds." once the story reaches this point. If they select the first option, the indented block under it will show, as well as the line where the healer asks where the pain is, similar for if they select the second option. Effectively, depending on which option the player selects, they will see one of these two options play out:

"How are you?" the elder asks.

> I am fine, but pained.

"Warrior, do not fret." the elder calls forth the healer.

"The healer may cure your pains."

"What is your pain, warrior?" the healer asks.

OR

"How are you?" the elder asks.

> The healer must tend to my wounds.

"As I feared." the elder retreats to a cabin.

When they emerge, an ancient healer follows.

"What is your pain, warrior?" the healer asks.

The behavior of options joining together allows for branching storylines which converge and diverge. It also makes illusions of choice (even long-running sequences) trivial to include.

Choice bodies nest, meaning that a choice body can include choices, which themselves contain further choices, and so on. For example:

"So, where are you going?"

> The club.
  "On a Wednesday night?!"
> The theater.
  "Awesome! Which movie?"
  > That new sequel.
    "Ah, pretty boring I heard. They need to start making new series, really."
  > The raunchy comedy.
    "Are you so sure..."

"Well, hope you have fun regardless"

Traveling

To move the player between areas, use an option that has no body, and contains the @id of the target area. For example:

# @home Your home

You're at your home.

> @bridge Go to the bridge
> Bathe in the sun
  You bask in the light.
  > @@ Go back


# @bridge The bridge

Welcome to the bridge.

This demonstrates traveling to other areas, as well as traveling to the same area. The bridge option will send the player to the bridge section, but the go back option with the @@ target will send the player back to the start of the home option, as if they hadn't clicked any dialogue options.

When the player selects a travel option the whole screen will turn into a series of buttons. Each of these buttons is actually a dialogue option they had selected in the area they are leaving from, as well as the links required to actually change the area. This allows the player to come back to areas they had already visited and explore different paths.

Flags/variables and conditionals

As far as I'm aware, SIFL's ability to store state in variables is unique. I haven't seen other interactive story fics with the ability to have flags which can be queried as in SIFL.

Flags are boolean variables which can be used to convey change between areas and across dialogue branches. Flags are useful for noting which items the player has, which features they have interacted with, if they've pressed a button or flipped a lever, etc.

Flags are set or cleared by the user, and appear in a dedicated flag selection panel whenever the fic prompts the player, which is done using a flag block. Here's an example of a flag block:

You open the chest.

[key] Ornate key
[health_potion] Pearlescent potion of health
[dagger] Iron dagger

The player can then check or uncheck any of these items, which will set or clear the corresponding flag accordingly.

Paragraphs and options can then query combinations of flags to conditionally appear. For instance:

You open the chest.

[key] Ornate key
[health_potion] Pearlescent potion of health
[dagger] Iron dagger

An ogre jumps from the hallway.

> {? dagger } Stab the ogre
  You stab the ogre in the heart.
  > @victory Leave through the hallway
> Run from the ogre
  You run, but the ogre is too fast. You are killed.
  > @defeat Accept fate

The option to stab the ogre will only appear if the user decides to take the dagger, since it has a flag query {? dagger } which will evaluate to true (and therefore show the option) if and only if the dagger flag is true/selected.

Conditional queries can be arbitrarily complex boolean logic formulae. Flags can be combined using logical AND and OR, negation, as well as parenthetical grouping. The query {? (bowtie && !tie) || (tie && !bowtie) } will evaluate to true if and only if bowtie and not tie, or tie and not bowtie, is selected.

Upcoming features

Everything listed above (except the @@ as an alias for the current area ID) is already implemented in the compiler. There are a lot of features that I'd like to implement in the future. Some features I'd consider as must-haves are custom class injection and the ability to embed CSS in SIFL documents, which would make custom styling much easier. Another useful feature would be to have force set/unset flag prompts, which would require the user to change the state of a flag to either set or unset. This would be useful in cases where the user is really only presented with a single option, that still has to be implemented as a flag.