nitasema strives to be a versatile interactive fiction generator. it takes a script file and produces a self-contained html file that can be played in a web brower. nitasema has minimal dependencies and is fast. the name is Swahili and means "I will speak."
- a C++11 compiler (default is
to build, run
make dbg, or
./make.sh from the root directory. the only difference between the
dbg targets is that
dbg includes debugging symbols and doesn't strip the resulting binary.
./make.sh is the same as running
rel, provided for systems without make installed.
the nitasema *.n file format is based on simplified s-exps. it is designed primarily as an intermediate format for a forthcoming GUI editor but in the meantime it's perfectly intelligible to humans to and only slightly verbose.
lines can be commented out with the
; character. there are currently no multiline comments.
whitespace is used to delimit values and is otherwise insignificant.
the data types are atoms, strings, and lists. strings are delimited by single-quotes (
') and can span any number of lines. lists are delimited by
] (not the more usual parentheses, for ease of typing). atoms may contain any character in the ascii range '-' ~ 'z' | 'A' ~ 'Z' and any unicode character outside the ascii range. backslash (
\\) can escape single quotes in a string.
the first term in the *.n file must be a string naming the story. it may be followed by atoms to mark various flags.
by: sets the author. takes a string argument. currently has no effect on output. (
by 'alexis hale')
flags: declares booleans. must be followed by a list of booleans. (
flags [bloodsoaked screaming bleeding])
vars: declares variables. must be followed by a list of variables. (
vars [health sanity terror])
no-select: disables text selection to make the story seem more app-like.
start: indicates the starting passage. takes an atom argument. required. (
[passage name (stylesheet) ...] declaration creates a passage. a passage is a screenful of nodes; passages are rendered and displayed to the player once at a time and users can navigate from passage to passage with links. the first term must be the id of the passage as an atom. optionally a stylesheet name may follow. all following terms must be nodes.
[passage the-beginning-of-the-end doom-passage]
creates a passage with the id
the-beginning-of-the-end with stylesheet
doom-passage. ids are used only in the front end of the compiler and do not appear in the compiled html.
[passage the-beginning-of-the-end 'doom had at long last come to Las Vegas.' ]
creates a passage with the id
the-beginning-of-the-end and adds a text node. all macro nodes regardless of position are evaluated before the passage renders, though macros in conditionals will only be evaluated if the conditional evaluates correctly.
[passage the-beginning-of-the-end [p 'doom had at long last come to Las Vegas.'] [p 'soon the mushrooms clouds of thermonuclear armageddon would envelop the globe.'] ]
instead of creating text nodes, this example creates paragraph nodes. paragraph nodes are a better way to organize text.
to link to another passage, use the
[link id 'title'] node.
[passage the-beginning-of-the-end [p 'doom had at long last come to Las Vegas.'] [p 'soon the mushroom clouds of ' [link doooom 'thermonuclear armageddon'] ' would envelop the globe.'] ]
to create a link to another passage that can only be clicked once (and will afterwards disappear forever), use
[passage the-beginning-of-the-end [p 'doom had at long last come to Las Vegas.'] [p 'soon the mushrooms clouds of thermonuclear armageddon would envelop the globe.'] [p [action make-tea 'make tea.']] ]
to set a flag, use the
[set flag] and
[passage doooom [set world-destroyed] [clear hankering-for-brunch] [p 'welp looks like everyone\'s dead now. i hope you learned a' 'valuable lesson on the futility of existence.'] ]
to test a flag, use the
[flag? flag [#t-pred] ([#f-pred])] node. #f-preds (else clauses) are optional.
[passage tea-with-aunt-holly [flag? world-destroyed [ [p 'unfortunately, the world where both all tea in the universe and' 'aunt holly were located has been destroyed in thermonuclear' 'armageddon.'] [p 'better luck next time, sport!'] ][ [clear hankering-for-brunch] [p 'you enjoy a lovely evening sipping tea with aunt holly.'] [p 'you have been cured of <b>HANKERING FOR BRUNCH</b>!'] ]] ]
a link can invoke a passage as a subroutine.
[passage bed [p 'you are in bed.'] [sub inventory 'inventory']] [passage bridge [p 'you are on the bridge of the Unrelenting Fist of Endless Imperial Wrath.'] [p 'crew bustle about, trying to make a good impression for your inspection.'] [sub inventory 'inventory']] [passage inventory [p 'you have <b>HALF-EATEN FISH HEAD</b>, <b>HORRIFIC STENCH</b>, and <b>REGRETS</b>.'] [p [ret 'back']]]
an action can also invoke a subroutine, with the
sub-action node. its syntax is identical to
to make nodes appear only once, and not on subsequent views, use
[passage start [once [[p 'you wake up and immediately wish you hadn\'t, wish you\'d never wake up again.']]] [p 'you are in your office.'] [p 'the papers that need grading are still here.'] [once [ [p 'you pick one up, wondering if they could possibly be as bad as you remembered.'] [p 'they\'re not. they\'re worse.'] ]] ]
to create an event that will interrupt the story only on the first click of a link, use
[passage home [p 'you are home with a nice cup of tea.'] [p [gate fight-monster outside 'go outside.']] ] [passage outside [p 'you admire the splendour of the great outdoors.'] ] [passage fight-monster [p 'a dreadful beast covered in the intestines of its victims bursts from the sewers!'] [p [ret 'kill monster with umbrella.']] ]
once takes two lists of nodes, the second optional. the second will be displayed on any subsequent visits.
[passage offal-gardens [once [ [p 'it is said the offal gardens of betelgeuse must be seen to be believed.'] [p 'well, they\'re not wrong.'] ][ [p 'the offal gardens stretch away into the distance. you wish they didn\'t.'] ]] ]
colors may be set by the "colors" declaration. this overrides the default stylesheet.
colors [ bg '#121212' ]
the colors that may be changed are
shadow-hover. any valid CSS color specification may be used.
url() can also be used to set a background image:
colors [ bg 'url(bg.png)' ]
the default stylesheet is set by the
colors declaration. different passages may have different stylesheets. stylesheets are declared as follows:
[style name [global-rule 'expression'] [.link [local-rule 'expression'] ] ]
"rules" are simply css rules.
[rule 'expression'] is translated to
rule: expression; at compile time.
anything in the global scope affects the entire passage. to set the background to slowly turn black on passages tagged "doom":
[style doom [background 'black'] [transition '10s'] ]
to style links, use the
.link selector. to style text, use the
to suppress the default stylesheet completely, use the
nitasema takes a filename on the commandline and prints its output to
./nitasema input-file.n > output-file.html
the html file can be opened by any browser.
- code needs major refactoring
- i wrote the entire thing in a 12-hour-long fugue and was up until 8am working on it, so there's bound to be lots wrong.
- fully implement all node types
- implement other types of variable assignment besides =
- show line number & context on compile errors, not just parse errors
- add multiline comments
- change colors, stylesheet
- title screens
- enable determining whether a passage was invoked as a subroutine
nitasema is developed by lexi hale and released under the AGPL license. (see LICENSE)