summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNathanael Sensfelder <SpamShield0@MultiAgentSystems.org>2020-12-22 04:08:34 +0100
committerNathanael Sensfelder <SpamShield0@MultiAgentSystems.org>2020-12-22 04:08:34 +0100
commitd0d6117176d68b2345d36e81ccdaa447e9caa724 (patch)
tree6cb8f3e4735a695be8c0922434df4c60f7cf82c7
Moving to Hugo.
-rw-r--r--config.toml12
-rw-r--r--content/_index.md56
-rw-r--r--content/fate_v1/_index.md162
-rw-r--r--content/fate_v1/aliases/default.md41
-rw-r--r--content/fate_v1/computations/_index.md138
-rw-r--r--content/fate_v1/computations/collections/_index.md98
-rw-r--r--content/fate_v1/computations/conditionals/_index.md54
-rw-r--r--content/fate_v1/computations/cons/_index.md22
-rw-r--r--content/fate_v1/computations/lambda_functions/_index.md30
-rw-r--r--content/fate_v1/computations/references/_index.md18
-rw-r--r--content/fate_v1/computations/rich_text/_index.md11
-rw-r--r--content/fate_v1/declarations/_index.md5
-rw-r--r--content/fate_v1/declarations/events/_index.md18
-rw-r--r--content/fate_v1/declarations/files/_index.md48
-rw-r--r--content/fate_v1/declarations/sequences/_index.md113
-rw-r--r--content/fate_v1/declarations/text_effects/_index.md31
-rw-r--r--content/fate_v1/declarations/types/_index.md61
-rw-r--r--content/fate_v1/declarations/variables/_index.md72
-rw-r--r--content/fate_v1/extensions/_index.md4
-rw-r--r--content/fate_v1/instructions/_index.md48
-rw-r--r--content/fate_v1/instructions/collections/_index.md72
-rw-r--r--content/fate_v1/instructions/conditionals/_index.md27
-rw-r--r--content/fate_v1/instructions/loops/_index.md34
-rw-r--r--content/fate_v1/instructions/player_choices/_index.md31
-rw-r--r--content/fate_v1/instructions/references/_index.md7
-rw-r--r--content/images/discord.svg70
-rw-r--r--content/images/github.svg71
-rw-r--r--content/images/reddit.svg63
-rw-r--r--content/images/tonkadur_logo_black.svg97
-rw-r--r--content/images/tonkadur_logo_black_as_path.svg117
-rw-r--r--content/images/tonkadur_logo_white.svg98
-rw-r--r--content/images/tonkadur_logo_white_as_path.svg118
-rw-r--r--content/learn/01.start/_index.md43
-rw-r--r--content/learn/02.choices/_index.md71
-rw-r--r--content/learn/03.variables/default.md90
-rw-r--r--content/learn/04.sequences/default.md123
-rw-r--r--content/learn/05.files/default.md113
-rw-r--r--content/learn/06.pointers/default.md171
-rw-r--r--content/learn/07.structures/default.md201
-rw-r--r--content/learn/08.collections/default.md408
-rw-r--r--content/learn/09.lambdas/default.md366
-rw-r--r--content/learn/10.conditions/default.md402
-rw-r--r--content/learn/_index.md8
-rw-r--r--content/made_with_tonkadur/_index.md3
-rw-r--r--content/made_with_tonkadur/closed_source/_index.md5
-rw-r--r--content/made_with_tonkadur/open_source/_index.md5
-rw-r--r--content/setup/_index.md75
-rw-r--r--content/wyrd_v1/_index.md56
-rw-r--r--content/wyrd_v1/computations/_index.md99
-rw-r--r--content/wyrd_v1/extensions/_index.md4
-rw-r--r--content/wyrd_v1/instructions/_index.md75
-rw-r--r--layouts/shortcodes/fatecode.html2
-rw-r--r--layouts/shortcodes/rawhtml.html2
-rwxr-xr-xstatic/css/prism.css321
-rwxr-xr-xstatic/js/highlight.pack.js9
55 files changed, 4499 insertions, 0 deletions
diff --git a/config.toml b/config.toml
new file mode 100644
index 0000000..61e69cd
--- /dev/null
+++ b/config.toml
@@ -0,0 +1,12 @@
+baseURL = "https://tonkadur.of.tacticians.online/"
+languageCode = "en-us"
+title = "Tonkadur"
+theme = "hugo-theme-learn"
+[params]
+ custom_css = ["css/prism.css"]
+
+# For search functionality
+[outputs]
+home = [ "HTML", "RSS", "JSON"]
+
+
diff --git a/content/_index.md b/content/_index.md
new file mode 100644
index 0000000..6d1c67a
--- /dev/null
+++ b/content/_index.md
@@ -0,0 +1,56 @@
+---
+title: "Main"
+---
+# Welcome to Tonkadur's website!
+Tonkadur is a tool to create game narratives.
+
+### Find out all about Tonkadur
+ * **Plain-text format.** Just write in your favorite editor and use your usual tools.
+ * **Extensive description language (Fate).** You shouldn't feel restrained in what you can write.
+ * **Strong typing.** Reduce the likeliness of errors in your descriptions.
+ * **Very simple and small interpreted language (Wyrd).** Easily add support for Tonkadur to your engine.
+ * **LISP inspired syntax.** No weird symbols everywhere. No annoying indentation restrictions.
+
+Tonkadur provides a compiler from Fate to Wyrd, letting you freely describe
+your stories using a feature rich language without having to worry about the
+implications when it comes time to add support for it to your engine.
+
+### Sample:
+{{< fatecode >}}(define_sequence in_your_room ()
+ (ifelse
+ (is_member visited_your_room progress)
+ (text_effect narrator
+ You room is still a mess. You don't have time to clean things up,
+ though.
+ )
+ (text_effect narrator
+ You room is a mess. You recall having been through every drawer while
+ preparing your bag yesterday. While still unclear on how you are
+ supposed to pack all the necessary things for what promises to be at
+ least a year-long journey inside a small backpack, you cannot avoid
+ but wasting more time contemplating the piles of items that didn't
+ make the cut.
+ )
+ )
+ (add visited_your_room progress)
+ (player_choice
+ (
+ ( Look for healing items )
+ (jump_to look_for_healing_items)
+ )
+ (
+ ( No time! Let's go adventuring! )
+ (jump_to leave_your_room)
+ )
+ )
+)
+{{< /fatecode >}}
+
+### Known alternatives
+* [Inkle's Ink](https://www.inklestudios.com/ink/).
+* [Yarn Spinner](https://yarnspinner.dev/).
+* [DLG](https://github.com/iLambda/language-dlg). Nowhere near as popular as the
+other two alternatives, but its approach shares more similarities with Tonkadur.
+
+
+### Syntax Highlight Test:
diff --git a/content/fate_v1/_index.md b/content/fate_v1/_index.md
new file mode 100644
index 0000000..8b90a7a
--- /dev/null
+++ b/content/fate_v1/_index.md
@@ -0,0 +1,162 @@
+---
+title: "Fate (Version 1)"
+menuTitle: "Fate"
+---
+
+When using Tonkadur, Fate is the language the author writes in. This language is
+meant to provide the writer with as many tools as possible, so that they do not
+feel constrained by the limitations of the language, nor find writing complex
+narratives tedious.
+
+## A few warnings first
+
+Fate uses strong typing. This is intended to make detection of mistakes easier,
+but may lead to some frustrations for authors only used to languages using
+dynamic typing.
+
+Fate does not have any special features for multi-seating/multi-player
+narratives. This is by design, as adding proper support for this would make the
+underlying language more complex, and thus would make it harder to create an
+interpreter for it. This is however something considered for an extension
+(see
+[this GitHub issue about it](https://github.com/nsensfel/tonkadur/issues/5)).
+
+You'll need to learn parentheses management, if you make anything complex. Fate
+uses a LISP inspired syntax, so parentheses are everywhere. The syntax gives you
+free reign over indentation, but so many parentheses does require at least some
+discipline in order to be readable.
+
+Fate is meant to be compiled. This does add an extra step to your existing
+process.
+
+Fate is very much a new language. There isn't many (any?) tools for it.
+
+If for some reason you want to perform memory allocation, there is no automatic
+garbage collection, so you will have to free whatever you allocate.
+
+In what may seem weird for narrative scripting, Fate does not feature string
+manipulation operations. Strings can be made into rich text, with complex
+attributes, but you will not be able to use things like regular expressions
+(or anything other than simple concatenation, really) with just the base
+language. This is because of these operations would need to be implemented
+directly by the interpreter anyway, and their use isn't actually common in
+a narrative description, which would make requiring support for them of
+any Tonkadur interpreter problematic.
+
+## Some nice features
+
+If you haven't closed the tab yet, here are some reasons why you *might* want
+to use Fate.
+
+It *is* a LISP inspired syntax. If that's what you like, you might even enjoy
+this take on it. There's no fiddling with indentation, no wondering what symbol
+does what. It's all about parentheses indicating something is performed on a
+list of other things. It's not a purely functional language, though. In fact,
+it's a mix of both declarative and imperative programming: sequences (or
+procedures) are imperative. Computations are functional. There are lambda
+functions, but they're strongly typed. Collections and structures can only be
+modified through specific instructions, so it's not quite really a LISP-like
+language.
+
+There are pointers. Oh, come on, it's a plus, *right?* This makes it a lot
+easier to refer to things. There's no pointer arithmetic, so you don't have to
+worry about the scary stuff. Also, this lets you allocate memory, which is
+useful when you want a unspecified amount of distinct instances of something.
+Want to describe a story where the player can push a button as many time as
+they choose, create a clone of a creature every time they do so, yet let them
+fight any of these creature as their distinct instance? Well, with memory
+allocation and pointers, it's easily done. Didn't you know? When writing a
+narrative, the RAM's the limit. So yeah, maybe don't forget to `free` the
+thousands of monster the player will no doubt create.
+
+You can do recursion. Wait! I *am* listing the nice features! Do people really
+not like recursion and pointers? Oh, well... Still, you can do recursions with
+both procedures and lambda functions. Not a fan of recursion? That's alright,
+you also have imperative loops: `for`, `while`, `do_while`, and even
+`for_each`.
+
+## The basics
+
+#### Procedures (or Sequences) and Instructions
+Procedures are lists of instructions and things to display. Instructions can be
+applied to values, but they themselves do not return any value. Any value not
+part of an instruction found in a procedure is displayed. Any value being part
+of an instruction is **not** displayed.
+
+One way to think about it is to consider procedures as being actually two types
+of things: sequences and procedures. A sequence is then a scene in the story,
+and a procedure is just a construct called upon to perform instructions.
+
+Procedures can take arguments. Values are passed by copy.
+
+Procedures can be called in two ways: a `call` or a `jump`. A `call` will
+perform the procedure before continuing with the current sequence of
+instructions. A `jump` will perform the procedure **instead of** the
+**current** sequence of instructions.
+
+Procedures can be called before their definition. The compiler will simply tell
+you if the definition ends up being incompatible or missing.
+
+#### Computations
+Computations are operations returning a value. Computations do not modify
+anything, they simply return the result of an operation.
+
+A special type of computation, called *lambda function*, allows the creation of
+a computation that will be performed only when called upon. Those can take
+parameters. What's the use of something as advanced in a narrative scripting
+language? It's convenient when you want to express something like a character's
+name who depends on what the player figured out. Sure, you *could* make each
+instance of the name feature a series of tests to find which value to use, or
+you could just use a lambda function and just put
+`(eval name_of_mysterious_character)` to get the right value.
+
+One last thing about lambda functions, which really are the only potentially
+complicated thing about computations: these *are* computations, so you can use
+them as such. They also cannot modify anything, as they only contain
+computations and not instructions.
+
+#### Declarations and First Level Instructions
+Declarations and First Level Instructions are a special type of instruction
+which can only be done from outside a procedure. This distinction means that,
+for example, you cannot define a procedure from within a procedure.
+
+#### Events
+Sometimes, you might need to communicate something to the interpreter which
+cannot be expressed in Fate. For example, you might want to say: "pause for 30
+seconds", or "play this music". This kind of thing has been considered to not
+be generic enough to mandate every interpreter supports it. Instead, events are
+used.
+
+Events are first declared, by being given a name and a list of types
+corresponding to the parameters they take. Then, the `(event ...)` instruction
+can be used to indicate that a certain event should occur. This will pause the
+execution, and make the interpreter react to the event before continuing.
+
+The effect of an event is purely the interpreter's responsibility. It cannot be
+described in Fate. Thus, you will need to refer to the interpreter you use to
+see what events are available.
+
+#### Types
+The basic `string`, `int`, `float`, and `bool` types are what one would expect.
+
+`rich_text` corresponds to text decorations, see the text effect sub-section.
+
+Two collection types are available: `(list [TYPE])` is a list of `[TYPE]`
+elements, and `(set [COMPARABLE])` is a set of `[COMPARABLE]` elements.
+
+`(ptr [TYPE])` is an address to a value of type `[TYPE]`.
+
+Structures can be defined. They may contain other structures, but cannot be
+recursive: only already defined types can be used. Pointers cannot be used to
+resolve this conundrum in this version of Fate, but it may be added in the next
+version (see [this GitHub
+issue](https://github.com/nsensfel/tonkadur/issues/6)).
+
+#### Player Choices
+Inputs from the players are limited to the `(player_choice ...)` instruction.
+It presents the player with `rich text` options to choose from, which execute
+an associated list of instructions if chosen.
+
+More complicated inputs, such as retrieving a `string` or an `int` from the
+player require the definition and use of events.
+
diff --git a/content/fate_v1/aliases/default.md b/content/fate_v1/aliases/default.md
new file mode 100644
index 0000000..9a6bd8a
--- /dev/null
+++ b/content/fate_v1/aliases/default.md
@@ -0,0 +1,41 @@
+---
+title: Aliases
+---
+Nearly all computations and instructions have aliases, making it easier to
+write in the language when not used to it. This page provides most of them. As
+a general rule, all underscores (`_`) are optional, all `declare` can be
+replaced by `define` and `def`.
+
+* `abs`: `absolute`.
+* `and`: `/\`.
+* `>=`: `greater_equal_than`, `ge`.
+* `/`: `divide`, `div`.
+* `=`: `==`, `equals`, `eq`.
+* `declare_alias_type`: `declare_sub_type`, `typedef`.
+* `declare_structure_type`: `declare_structure`, `declare_dict_type`,
+ `declare_dict`.
+* `declare_event_type`: `declare_event`.
+* `declare_sequence`: `declare_seq`, `declare_procedure`, `declare_proc`.
+* `ignore_error`: `ignore_warning`.
+* `free`: `release`, `destroy`.
+* `implies`: `=>`, `->`.
+* `is_member`: `contains`, `has`.
+* `=<`: `<=`, `lower_equal_than`, `le`.
+* `<`: `lower_than`, `lt`.
+* `-`: `minus`
+* `min`: `minimum`.
+* `max`: `maximum`.
+* `eval`: `evaluate`.
+* `%`: `mod`, `modulo`.
+* `new`: `reserve`, `create`.
+* `not`: `~`, `!`.
+* `add_element`: `add`.
+* `one_in`: `exactly_one_in`, `exactly_one`, `one`.
+* `remove_at`: `remove_element_at`, `remove_elem_at`.
+* `set`: `set_value`, `set_val`, `set_variable`, `set_var`.
+* `var`: `variable`.
+* `visit`: `call`, `call_sequence`, `call_procedure`, `call_seq`, `call_proc`,
+ `visit_sequence`, `visit_procedure`, `visit_seq`, `visit_proc`.
+* `jump_to`: `continue_as`, `continue_to`, `continue_with`, `jump`, `go_to`,
+ `exec`. And you can suffix `_proc`, `_procedure`, `_seq`, or `_sequence` to
+ any of these.
diff --git a/content/fate_v1/computations/_index.md b/content/fate_v1/computations/_index.md
new file mode 100644
index 0000000..9312712
--- /dev/null
+++ b/content/fate_v1/computations/_index.md
@@ -0,0 +1,138 @@
+---
+title: Computations
+---
+Computations are values. They may read from the memory, but do not modify it
+(with a single exception).
+
+### TEXT
+{{< fatecode >}}(text [C0 = COMPUTATION] ... [CN = COMPUTATION]){{< /fatecode >}}
+
+Returns a `text` node containing the text representation of `C0` ... `CN`.
+
+### VARIABLE | REFERENCE
+{{< fatecode >}}(var {String}){{< /fatecode >}}
+
+Returns the value of the variable `{String}`, or a reference to it if
+applicable. Structure members can be accessed by using `.` in `{String}`.
+
+### STRUCTURE FIELD ACCESS
+{{< fatecode >}}{Structure Var Name}.{Field Name}{{< /fatecode >}}
+{{< fatecode >}}(field [STRUCTURE VAR] {String}){{< /fatecode >}}
+
+Accesses the `{String}` field of the structure `<STRUCTURE_VAR>`. Using `.` to
+access fields is recommended over the use of this operator.
+
+### STRUCTURE FIELD VALUE
+{{< fatecode >}}(get_field [STRUCTURE] {String}){{< /fatecode >}}
+Returns the value of the `{String}` field of the structure `[STRUCTURE]`.
+
+### TEMPORARY VARIABLES
+{{< fatecode >}}(let (({V0 = String} [C0 = COMPUTATION]) ... ({VN = String} [CN = COMPUTATION])) [R = COMPUTATION]){{< /fatecode >}}
+
+Defines a hierarchical level and local variables `V0` ... `VN` with values `C0` ... `CN`, and returns the value of `[R]`.
+
+### CAST
+{{< fatecode >}}(cast [TYPE] <COMPUTATION*>){{< /fatecode >}}
+
+Transforms `<COMPUTATION*>` into a value of type `[TYPE]`. Note that the variable
+shorthand cannot be used for `<COMPUTATION*>`. The following type changes are
+allowed:
+* `[FLOAT]` to `[FLOAT]`, `[INT]`, and `[STRING]`.
+* `[INT]` to `[FLOAT]`, `[INT]`, and `[STRING]`.
+* `[BOOL]` to `[BOOL]` and `[STRING]`.
+* `[STRING]` to `[BOOL]` (`true` and `false`), `[FLOAT]`, `[INT]`, and`[STRING]`.
+
+### RANDOM NUMBER
+{{< fatecode >}}(rand [I0 = INT] [IN = INT]){{< /fatecode >}}
+
+Returns a random number between `I0` and `IN` (inclusive).
+
+## Basic Operators
+### BOOL OPERATORS
+{{< fatecode >}}(and [B0 = BOOL] ... [BN = BOOL]){{< /fatecode >}}
+
+Standard conjunction (minimum of 2 arguments).
+
+{{< fatecode >}}(or [B0 = BOOL] ... [BN = BOOL]){{< /fatecode >}}
+
+Standard disjunction (minimum of 2 arguments).
+
+{{< fatecode >}}(not [BOOL]){{< /fatecode >}}
+
+Standard negation.
+
+{{< fatecode >}}(implies [B0 = BOOL] [B1 = BOOL]){{< /fatecode >}}
+
+Standard implication.
+
+
+{{< fatecode >}}(one_in [B0 = BOOL] ... [BN = BOOL]){{< /fatecode >}}
+
+true if, and only if, exactly one of the operands is true.
+
+### MATH OPERATORS
+All operands must be of the same type, which is also the type returned by the
+operation.
+
+{{< fatecode >}}(+ [N0 = NUMBER] ... [NN = NUMBER]){{< /fatecode >}}
+
+Standard addition (minimum of 2 arguments).
+
+{{< fatecode >}}(- [N0 = NUMBER] ... [NN = NUMBER]){{< /fatecode >}}
+
+Standard substraction (minimum of 2 arguments).
+
+{{< fatecode >}}(* [N0 = NUMBER] ... [NN = NUMBER]){{< /fatecode >}}
+
+Standard multiplication (minimum of 2 arguments).
+
+{{< fatecode >}}(/ [N0 = NUMBER] [N1 = NUMBER]){{< /fatecode >}}
+
+Standard division. Note that a division on integers is indeed a integer
+division.
+
+{{< fatecode >}}(^ [N0 = NUMBER] [N1 = NUMBER]){{< /fatecode >}}
+
+Standard exponentiation.
+
+{{< fatecode >}}(% [I0 = INT] [I1 = INT]){{< /fatecode >}}
+
+Standard modulo operation.
+
+{{< fatecode >}}(min [N0 = NUMBER] ... [NN = NUMBER]){{< /fatecode >}}
+
+Lowest value among the operands.
+
+{{< fatecode >}}(max [N0 = NUMBER] ... [NN = NUMBER]){{< /fatecode >}}
+
+Highest value among the operands.
+
+{{< fatecode >}}(clamp [N0 = NUMBER] [N1 = NUMBER] [N2 = NUMBER]){{< /fatecode >}}
+
+Equivalent to `(min N0 (max N1 N2))`.
+
+
+{{< fatecode >}}(abs [NUMBER]){{< /fatecode >}}
+
+Positive value of `[NUMBER]`.
+
+### COMPARISON OPERATORS
+{{< fatecode >}}(= [C0 = COMPUTATION] ... [CN = COMPUTATION]){{< /fatecode >}}
+
+True if, and only if, all operands are equal.
+
+{{< fatecode >}}(< [C0 = COMPARABLE] [C1 = COMPARABLE]){{< /fatecode >}}
+
+True if, and only if, `C0` is strictly lower than `C1`.
+
+{{< fatecode >}}(=< [C0 = COMPARABLE] [C1 = COMPARABLE]){{< /fatecode >}}
+
+True if, and only if, `C0` is lower or equal to/than `C1`.
+
+{{< fatecode >}}(> [C0 = COMPARABLE] [C1 = COMPARABLE]){{< /fatecode >}}
+
+True if, and only if, `C0` is strictly higher than `C1`.
+
+{{< fatecode >}}(>= [C0 = COMPARABLE] [C1 = COMPARABLE]){{< /fatecode >}}
+
+True if, and only if, `C0` is higher or equal to/than `C1`.
diff --git a/content/fate_v1/computations/collections/_index.md b/content/fate_v1/computations/collections/_index.md
new file mode 100644
index 0000000..63c62cc
--- /dev/null
+++ b/content/fate_v1/computations/collections/_index.md
@@ -0,0 +1,98 @@
+---
+title: Collections
+---
+### ACCESS
+{{< fatecode >}}(access [COLLECTION|COLLECTION PTR] [INT]){{< /fatecode >}}
+
+Returns the value of the `[INT]`th element in `[COLLECTION|COLLECTION PTR]`.
+
+### ACCESS CONSTANT INDEX
+{{< fatecode >}}[(COLLECTION|COLLECTION PTR) VAR].{Integer}{{< /fatecode >}}
+
+Returns a variable corresponding to the `[INT]`th element in
+`[(COLLECTION|COLLECTION PTR) VAR]`.
+
+### ACCESS POINTER
+{{< fatecode >}}(access_pointer [(COLLECTION|COLLECTION PTR) VAR] [INT]){{< /fatecode >}}
+
+Returns a pointer to the `[INT]`th element in `[(COLLECTION|COLLECTION PTR)
+VAR]`.
+
+### ADD ELEMENT AT
+{{< fatecode >}}(add_element_at [INT] [COMPUTATION*] [LIST]){{< /fatecode >}}
+
+Returns a copy of `[LIST]` with `[COMPUTATION*]` added at index `[INT]`. Note
+that `[COMPUTATION*]` does not allow use of the variable shorthand.
+
+### ADD ELEMENT
+{{< fatecode >}}(add_element [COMPUTATION*] [COLLECTION]){{< /fatecode >}}
+
+Returns a copy of `[COLLECTION]` with `[COMPUTATION*]` added. If `[COLLECTION]`
+is a `[LIST]`, then the element is added at the end of the list.
+Note that `[COMPUTATION*]` does not allow use of the variable shorthand.
+
+### ADDING MEMBERS
+{{< fatecode >}}(add_all_elements [C0 = COLLECTION] [C1 = COLLECTION]){{< /fatecode >}}
+
+Returns a copy of `[C1]`, with all the elements of `[C2]` added. If `[C1]`
+is a `[LIST]`, the new members are added at the end of the list.
+
+### COUNT
+{{< fatecode >}}(count [COMPUTATION*] [COLLECTION]){{< /fatecode >}}
+
+Returns the number of occurrences of `[COMPUTATION*]` in `[COLLECTION]`.
+Note that `[COMPUTATION*]` does not allow use of the variable shorthand.
+
+### INDEX OF
+{{< fatecode >}}(index_of [COMPUTATION] [COLLECTION]){{< /fatecode >}}
+
+Returns the index of the first occurrence of `[COMPUTATION]` in `[COLLECTION]`,
+starting at 0.
+
+### IS MEMBER
+{{< fatecode >}}(is_member [COMPUTATION] [COLLECTION]){{< /fatecode >}}
+
+Returns true if, and only if, `[COMPUTATION]` is in `[COLLECTION]`.
+
+### SIZE
+{{< fatecode >}}(size [COLLECTION]){{< /fatecode >}}
+
+Returns the size (`[INT]`) of `[COLLECTION]`.
+
+### IS EMPTY
+{{< fatecode >}}(is_empty [COLLECTION]){{< /fatecode >}}
+
+Returns true if, and only if `[COLLECTION]` is empty.
+
+### FILTER ELEMENTS
+{{< fatecode >}}(filter [LAMBDA BOOL (X)] [X COLLECTION]){{< /fatecode >}}
+{{< fatecode >}}(filter [LAMBDA BOOL (X Y0 ... YN)] [X COLLECTION] [Y0 COMPUTATION*] ... [YN COMPUTATION*]){{< /fatecode >}}
+
+Returns a copy of `[X COLLECTION]` in which only the elements for which
+`<LAMBDA BOOL (X)>` returns `true` remain. If the lambda function needs extra
+parameters, use the second syntax, which adds those parameters at the end of the
+`(filter ...)` call. Note that the variable shorthand cannot be used for these
+extra parameters.
+
+### FILTER ELEMENTS (INDEXED)
+{{< fatecode >}}(indexed_filter [LAMBDA BOOL (INT X)] [X COLLECTION]){{< /fatecode >}}
+{{< fatecode >}}(indexed_filter [LAMBDA BOOL (INT X Y0 ... YN)] [X COLLECTION] [Y0 COMPUTATION*] ... [YN COMPUTATION*]){{< /fatecode >}}
+
+Returns a copy of `[INT X COLLECTION]` in which only the elements for which
+`<LAMBDA BOOL (INT X)>` (with `INT` being the element's index) returns `true`
+remain. If the lambda function needs extra parameters, use the second syntax,
+which adds those parameters at the end of the `(indexed_filter ...)` call. Note
+that the variable shorthand cannot be used for these extra parameters.
+
+### FOLD OVER COLLECTION
+{{< fatecode >}}(foldl [LAMBDA X (X Y)] [X COMPUTATION*] [Y COLLECTION]){{< /fatecode >}}
+{{< fatecode >}}(foldl [LAMBDA X (X Y Z0 ... ZN)] [X COMPUTATION*] [Y COLLECTION] [Z0 COMPUTATION*] ... [ZN COMPUTATION*]){{< /fatecode >}}
+{{< fatecode >}}(foldr [LAMBDA X (X Y)> [X COMPUTATION*] [Y COLLECTION]){{< /fatecode >}}
+{{< fatecode >}}(foldr [LAMBDA X (X Y Z0 ... ZN)] [X COMPUTATION*] [Y COLLECTION] [Z0 COMPUTATION*] ... [ZN COMPUTATION*]){{< /fatecode >}}
+
+Returns the result of iterating `<LAMBDA X (X Y)>` over `[Y COLLECTION]`, with
+`[X COMPUTATION*]` being the initial value. The direction of the iteration is
+by ascending index order when using `foldl`, and the opposite order when using
+`foldr`. Extra parameters for the lambda function can be passed as extra
+parameters of the call. Note that the variable shorthand cannot be used for
+those extra parameters, nor for the initial value.
diff --git a/content/fate_v1/computations/conditionals/_index.md b/content/fate_v1/computations/conditionals/_index.md
new file mode 100644
index 0000000..2953489
--- /dev/null
+++ b/content/fate_v1/computations/conditionals/_index.md
@@ -0,0 +1,54 @@
+---
+title: Conditionals
+---
+This page presents the computation operators that allow a choice depending on
+some condition. All possible returned values must be of the same type.
+
+### IF-ELSE
+{{< fatecode >}}(if_else [BOOL] [C0 = COMPUTATION] [C1 = COMPUTATION]){{< /fatecode >}}
+
+Returns `C0` is `[BOOL]` yields true, `C1` otherwise.
+
+### COND
+{{< fatecode >}}(cond ([B0 = BOOL] [C0 = COMPUTATION]) ... ([BN = BOOL] [CN = COMPUTATION])){{< /fatecode >}}
+
+Returns `<Ci>`, such that `<Bi>` is the first to hold true. If there is not such
+`Bi`, returns `[CN]`.
+
+### SWITCH
+{{< fatecode >}}(switch [T = COMPUTATION] ([V0 = COMPUTATION] [C0 = COMPUTATION]) ... ([VN = BOOL] [CN = COMPUTATION]) [D = COMPUTATION]){{< /fatecode >}}a
+
+Returns the first `Ci` such that `Vi` is equal to `T`. If there is not such
+`Vi`, returns `[D]`.
+
+## Examples
+{{< fatecode >}}(cond
+ ((false) (false))
+ ((false) (false))
+ ((true)
+ (cond
+ ((false) (false))
+ ((true) (not (is_member 3 test_list)))
+ ((true) (false))
+ )
+ )
+)
+{{< /fatecode >}}
+
+{{< fatecode >}}(switch 3
+ (0 (false))
+ (1 (false))
+ (3 (true))
+ (2 (false))
+ (false)
+)
+{{< /fatecode >}}
+
+{{< fatecode >}}(if_else (true)
+ (if_else (false)
+ (assert (false) FAILED: instruction ifelse E)
+ (set test_var (true))
+ )
+ (assert (false) FAILED: instruction ifelse F)
+)
+{{< /fatecode >}}
diff --git a/content/fate_v1/computations/cons/_index.md b/content/fate_v1/computations/cons/_index.md
new file mode 100644
index 0000000..5ece27b
--- /dev/null
+++ b/content/fate_v1/computations/cons/_index.md
@@ -0,0 +1,22 @@
+---
+title: Cons
+---
+Fate features a *construct* computation, making it possible to create an
+anonymous structure by creating pairs of computations. Unlike collections, these
+pairs do not have to be made of computations of the same type.
+
+### PAIRING
+{{< fatecode >}}(cons [C0 = COMPUTATION*] [C1 = COMPUTATION*]){{< /fatecode >}}
+
+Returns the value corresponding to a pair made of `[C0]` and `[C1]`. Note that
+the variable shorthand cannot be used for either parameter.
+
+### RETRIEVING THE FIRST ITEM
+{{< fatecode >}}(car [CONS]){{< /fatecode >}}
+
+Returns the value corresponding to the first item in the `[CONS]` pair.
+
+### RETRIEVING THE SECOND ITEM
+{{< fatecode >}}(cdr [CONS]){{< /fatecode >}}
+
+Returns the value corresponding to the second item in the `[CONS]` pair.
diff --git a/content/fate_v1/computations/lambda_functions/_index.md b/content/fate_v1/computations/lambda_functions/_index.md
new file mode 100644
index 0000000..35485a3
--- /dev/null
+++ b/content/fate_v1/computations/lambda_functions/_index.md
@@ -0,0 +1,30 @@
+---
+title: Lambda Functions
+---
+Lambda functions are values that correspond to a computation not yet performed.
+These can take arguments. Defining a lambda function returns the value that
+corresponds to the function itself, the `eval` computation must be used to
+obtain the value that the function computes.
+
+### DEFINITION
+{{< fatecode >}}(lambda (([T0 = TYPE] {S0 = String}) ... ([TN = TYPE] {SN = String})) [COMPUTATION]){{< /fatecode >}}
+
+Returns a lambda function taking `S0` ... `SN` of types `T0` ... `TN` as
+arguments and evaluating to `[COMPUTATION]`.
+
+### EVALUATION
+{{< fatecode >}}(eval [REFERENCE] [C0 = COMPUTATION] ... [CN = COMPUTATION]){{< /fatecode >}}
+
+Returns the result of evaluating the lambda function at `[REFERENCE]` given the
+parameters `C0` ... `CN`.
+
+## Examples
+{{< fatecode >}}(lambda ( (int i) )
+ (+ (var i) 1)
+)
+{{< /fatecode >}}
+
+{{< fatecode >}}(lambda ( (int i) )
+ (* (eval int_to_int (var i)) 2)
+)
+{{< /fatecode >}}
diff --git a/content/fate_v1/computations/references/_index.md b/content/fate_v1/computations/references/_index.md
new file mode 100644
index 0000000..ba5716a
--- /dev/null
+++ b/content/fate_v1/computations/references/_index.md
@@ -0,0 +1,18 @@
+---
+title: References
+---
+### VALUE ACCESS
+{{< fatecode >}}(at [ADDRESS]){{< /fatecode >}}
+
+Returns the variable at `[ADDRESS]`.
+
+### ALLOCATION
+{{< fatecode >}}(new [TYPE]){{< /fatecode >}}
+
+Returns the address of a new variable of type `[TYPE]`. Don't forget to call
+`free` on it once you're done.
+
+### ADDRESS
+{{< fatecode >}}(ptr [COMPUTATION VARIABLE]){{< /fatecode >}}
+
+Returns the address of `[COMPUTATION VARIABLE]`.
diff --git a/content/fate_v1/computations/rich_text/_index.md b/content/fate_v1/computations/rich_text/_index.md
new file mode 100644
index 0000000..7351a5c
--- /dev/null
+++ b/content/fate_v1/computations/rich_text/_index.md
@@ -0,0 +1,11 @@
+---
+title: Rich Text
+---
+### RICH TEXT
+{{< fatecode >}}(rich_text [TEXT]){{< /fatecode >}}
+
+### ADD TEXT EFFECT
+{{< fatecode >}}(add_text_effect ({String} [P0 = COMPUTATION] ... [PN = COMPUTATION]) [RICH TEXT]){{< /fatecode >}}
+
+### NEW LINE
+{{< fatecode >}}(newline){{< /fatecode >}}
diff --git a/content/fate_v1/declarations/_index.md b/content/fate_v1/declarations/_index.md
new file mode 100644
index 0000000..013d404
--- /dev/null
+++ b/content/fate_v1/declarations/_index.md
@@ -0,0 +1,5 @@
+---
+title: "Declarations"
+menuTitle: "Declarations"
+chapter: true
+---
diff --git a/content/fate_v1/declarations/events/_index.md b/content/fate_v1/declarations/events/_index.md
new file mode 100644
index 0000000..5493cd7
--- /dev/null
+++ b/content/fate_v1/declarations/events/_index.md
@@ -0,0 +1,18 @@
+---
+title: Events
+---
+Events are how a Fate narrative can communicate to the interpreter that
+something which cannot be expressed in Fate needs to be performed. The execution
+is paused until the event is resolved by the interpreter. To avoid mistakes, any
+event type must be declared before use.
+
+#### EVENT
+{{< fatecode >}}(declare_event_type {string} [C0 = TYPE] ... [CN = TYPE]){{< /fatecode >}}
+**Effect:** An event with the name `{string}` and taking parameters of types
+`[C0]`, ..., `[CN]` can be used.
+
+## Examples
+* `(declare_event_type user_string_input rich_text (ptr string))`
+* `(declare_event_type wait int)`
+* `(declare_event_type set_background_to string)`
+* `(declare_event_type rumble)`
diff --git a/content/fate_v1/declarations/files/_index.md b/content/fate_v1/declarations/files/_index.md
new file mode 100644
index 0000000..05c6836
--- /dev/null
+++ b/content/fate_v1/declarations/files/_index.md
@@ -0,0 +1,48 @@
+---
+title: File Management
+---
+Fate narratives have one main file, but this file can use the contents of other
+files, and these files in turn can also use the contents of other files. Three
+issues arise then: some things must be declared before they are used, nothing
+should be declared multiple times, and where are the files?
+
+The absolute path to each file is computed in order to detect whether it has
+already been loaded. The given paths are expected to be relative. They are then
+resolved by attempting access from the following, in order: the current file's
+directory; the include directories passed as parameter to the executable; the
+calling executable's directory.
+
+Dependency cycles will raise compiling errors.
+
+The first "instruction" on each file must be `(fate_version 1)`. Values cannot
+be placed before either, obviously.
+
+{{< fatecode >}}(require {string}){{< /fatecode >}}
+
+**Effect:** If the file at `{string}` has not yet been loaded, load it.
+
+{{< fatecode >}}(include {string}){{< /fatecode >}}
+
+**Effect:** Load the `{string}`, even if it has already been loaded.
+
+#### Examples
+* `(require bonus_sequence.fate)`
+* `(include types/plant.fate)`
+* `(require ../guild/merchants.fate)`
+* `(include ../what/../are/../you/../doing/../there.fate)`
+* `(require oh/../oh/../oh/../this_is_fine.fate)`
+
+Example of Fate file:
+{{< fatecode >}};;; A story of great importance
+(fate_version 1)
+
+(require include/events.fate)
+(require include/text_effects.fate)
+
+(require scenes/the_holiday_forest.fate)
+
+`Twas a long time ago... Longer now that it seems... In a place that can't be
+referenced here because I'm pretty sure the transcript is copyrighted.
+
+(jump_to not_the_tree_door_i_would_have_chosen)
+{{< /fatecode >}}
diff --git a/content/fate_v1/declarations/sequences/_index.md b/content/fate_v1/declarations/sequences/_index.md
new file mode 100644
index 0000000..8bdb30e
--- /dev/null
+++ b/content/fate_v1/declarations/sequences/_index.md
@@ -0,0 +1,113 @@
+---
+title: Sequences and Procedures
+---
+Sequences and procedures are the same thing. These are named lists of
+instructions and values, which can be called upon at any point where
+instructions can be used. They can take parameters.
+
+Procedures do not return values. It is however possible to emulate something
+similar, by passing a pointer as a parameter and storing a "return" value into
+it.
+
+These are also intended to be used to describe scenes.
+
+The execution of a sequence can be terminated by using the `(done)`
+instruction. The execution of the narrative can be terminated by using the
+`(end)` instruction.
+
+Any value not part of an instruction will simply be displayed when it is
+reached during the procedure's execution.
+
+Sequences can be used before their definition, the compiler will raise an error
+if the use ends up being incorrect.
+
+Execution of a sequence can be started in two ways: `(call sequence_name)` will
+execute the sequence then continue with the execution of the current
+instruction list; `(jump_to sequence_name)` will replace the current
+instruction list by the execution of the sequence. If one were to ignore
+variables, the `(jump_to sequence_name)` instruction is similar to performing
+`(call sequence_name) (done)`.
+
+{{< fatecode >}}(define_sequence {String} (([C0 = TYPE] {V0 = String}) ... ([CN = TYPE] {VN = String})) <I0 = INSTRUCTIONS|VALUE> ... <IM = INSTRUCTIONS|VALUE>){{< /fatecode >}}
+**Effect:** Defines the sequence `{String}`, with variables `V0` ... `VN` of types `C0` ...`CN` as parameters, and instructions `I0` ... `IM` as content.
+
+**Acceptable Aliases:** `declare_sequence`, `def_seq`, `define_procedure`, `declare_procedure`, `def_proc`.
+
+#### Examples
+{{< fatecode >}}(define_sequence in_your_room ()
+ (ifelse
+ (is_member visited_your_room progress)
+ (text_effect narrator
+ You room is still a mess. You don't have time to clean things up,
+ though.
+ )
+ (text_effect narrator
+ You room is a mess. You recall having been through every drawer while
+ preparing your bag yesterday. While still unclear on how you are
+ supposed to pack all the necessary things for what promises to be at
+ least a year-long journey inside a small backpack, you cannot avoid
+ but wasting more time contemplating the piles of items that didn't
+ make the cut.
+ )
+ )
+ (add visited_your_room progress)
+ (player_choice
+ (
+ ( Look for healing items )
+ (jump_to look_for_healing_items)
+ )
+ (
+ ( No time! Let's go adventuring! )
+ (jump_to leave_your_room)
+ )
+ )
+)
+{{< /fatecode >}}
+
+{{< fatecode >}}(define_sequence index_of_loop
+ (
+ ((ptr int) result_holder)
+ ((list int) collection)
+ (int target)
+ )
+ (local int collection_size)
+ (local int i)
+
+ (set collection_size (size collection))
+
+ (for (set i 0) (< (var i) (var collection_size)) (set i (+ (var i) 1))
+ (if (= (access collection (var i)) (var target))
+ (
+ (set (at result_holder) (var i))
+ (done)
+ )
+ )
+ )
+ (set (at result_holder) -1)
+)
+{{< /fatecode >}}
+
+
+{{< fatecode >}}(define_sequence index_of_jump
+ (
+ ((ptr int) result_holder)
+ ((list int) collection)
+ (int target)
+ (int i)
+ (int collection_size)
+ )
+ (ifelse (= (var i) (var collection_size))
+ (set (at result_holder) -1)
+ (ifelse (= (access collection (var i)) (var target))
+ (set (at result_holder) (var i))
+ (jump index_of_jump
+ (var result_holder)
+ (var collection)
+ (var target)
+ (+ (var i) 1)
+ (var collection_size)
+ )
+ )
+ )
+)
+{{< /fatecode >}}
diff --git a/content/fate_v1/declarations/text_effects/_index.md b/content/fate_v1/declarations/text_effects/_index.md
new file mode 100644
index 0000000..3bf7a08
--- /dev/null
+++ b/content/fate_v1/declarations/text_effects/_index.md
@@ -0,0 +1,31 @@
+---
+title: Text Effects
+---
+Text effects are attributes that can be given to rich text elements. The
+effects themselves can take parameters. To avoid errors that would be difficult
+to detect, Tonkadur expects text effects to be declared before being used.
+Note that multiple text effects can be applied to the same rich text elements,
+so there is no need to create text effects that combine other text effects.
+
+Two text effects cannot have the same name, even if their parameter types
+differ.
+
+Because text effects are handled by the interpreter, it is recommended to
+overlay their use by lambda functions. This way, each interpreter can simply
+expose its available text effects in a file, and the definition of the lambda
+functions can thus be changed according to which interpreter is used without
+having to go through the whole document. Furthermore, the name of text effects
+exposed by the interpreter might not match the name that would make the most
+sense to use within the narrative.
+
+### TEXT EFFECT
+{{< fatecode >}}(declare_text_effect {Identifier} [T0 = TYPE] ... [TN = TYPE]){{< /fatecode >}}
+Declares the text effect `{Identifier}`, with parameters of type `[T0]` ...
+`[TN]`.
+
+## Examples
+* `(declare_text_effect bold)`
+* `(declare_text_effect speaker string)`
+* `(declare_text_effect color int int int)`
+* `(declare_text_effect font string)`
+* `(declare_text_effect speaker_emotion string int)`
diff --git a/content/fate_v1/declarations/types/_index.md b/content/fate_v1/declarations/types/_index.md
new file mode 100644
index 0000000..9a3677f
--- /dev/null
+++ b/content/fate_v1/declarations/types/_index.md
@@ -0,0 +1,61 @@
+---
+title: Types
+---
+Fate is a strongly typed language.
+
+## Base Types
+There are a few base types already defined:
+
+* `int`: an integer, which is a number *without* fractional component (e.g. `-3`, `0`, `3`).
+* `float`: a number *with* a fractional component (e.g. `-3.14`, `0.0`, `3.9931`).
+* `bool`: a Boolean (i.e. `(true)` or `(false)`).
+* `string`: a list of characters, not including newlines (e.g. `bob`,
+ `something else`, `日本のもの`, or `الاشياء العربية`). This cannot include
+ computations: only hardcoded strings.
+
+* `text`: a list of computations, interpreted as text, which may have
+ attributes.
+
+Pointers are also available:
+* `(ptr [TYPE])`: a pointer to a memory element of type `[TYPE]` (e.g. `(ptr int)`, `(ptr (ptr string))`).
+If you are not familiar with pointers, a pointer is a value corresponding to an address containing a memory element.
+Accessing the value of the pointer yields the address, accessing the value pointed to by the value of the pointer yields the memory element.
+Pointers to pointers can be made, in which case that memory element is also an address to yet another memory element.
+Pointers still have to point to a definite type. Unlike in C, you cannot create a pointer to an unspecified type.
+
+Two collection types are available:
+* `(list [TYPE])`
+* `(set [COMPARABLE TYPE])`
+
+Lambda computations are available:
+* `(lambda <r = TYPE> (<a0 = TYPE> ... <an = TYPE>))` is a type corresponding
+ to a lambda function returning a value of type `r` and taking parameters of
+ types `a0` ... `an`.
+
+### Common Type Groupings
+* `[NUMBER]` corresponds to `int`, `float`.
+* `[COLLECTION]` corresponds to `(list [TYPE])` and `(set [COMPARABLE TYPE])`.
+* `[PRIMITIVE]` `int`, `float`, `bool`, `string`, `rich_text`.
+* `[COMPARABLE]` corresponds to `int`, `float`, `bool`, `string`, `rich_text`,
+ and `(ptr [TYPE])`. This indicates types for which operators such as `<` are
+ defined.
+
+## Defining Your Own Types
+
+### Aliasing
+{{< fatecode >}}(declare_alias_type [TYPE] {String}){{< /fatecode >}}.
+**Effect:** Declares the type `{String}`. If `[TYPE]` is not a `[PRIMITIVE]`,
+ `[TYPE]` and `{String}` are now two equivalent types. If `[TYPE]` is a
+ `[PRIMITIVE]`, `{String}` is a subtype of `[TYPE]`.
+
+### Structures
+{{< fatecode >}}(declare_structure_type {String} (<t0 = TYPE> {f0 = String}) ... (<tn = TYPE> {fn = String})){{< /fatecode >}}.
+
+## Examples
+
+{{< fatecode >}}(define_structure_type player
+ (creature creature)
+ ((list (ptr item)) inventory)
+ (int money)
+)
+{{< /fatecode >}}
diff --git a/content/fate_v1/declarations/variables/_index.md b/content/fate_v1/declarations/variables/_index.md
new file mode 100644
index 0000000..153135c
--- /dev/null
+++ b/content/fate_v1/declarations/variables/_index.md
@@ -0,0 +1,72 @@
+---
+title: Variables
+---
+Variables are what hold values. Each variable has a type, which cannot be
+changed.
+
+There are two variable scopes: local and global. A global variable can only be
+declared outside of any sequence. A local variable can also be declared within a
+sequence. Local variables can only be accessed within their context. In effect,
+a local variable declared outside of a sequence cannot be accessed in any
+sequence, and local variables cannot be accessed within lambda functions. Local
+variables can override global variables within their context.
+
+The sole exception to accessing a local variable outside its context is done
+through the use of pointers. Local variables live as long as the context
+that declared them does. Accessed one through a pointer past that point is
+likely to result in a runtime error and is, in any case, not to be done.
+
+Each sequence and lambda function defines its own context and thus does not
+share local variable with the others. Instructions which themselves contain
+instructions define hierarchies. Local variables defined within a hierarchical
+level can be accessed in that level and inner level, but are not shared with
+outer levels. For example:
+
+{{< fatecode >}}(if_else (var my_test)
+ (
+ (local int my_var) ;; my_var (a)
+ (set my_var 32)
+ )
+ (
+ ;; my_var (a) is not defined here.
+ (local int my_var) ;; my_var (b)
+ (set my_var 42)
+ (if (var my_other_test)
+ (
+ (local int my_other_var)
+ ;; Both my_other_var and my_var (b) are defined here
+ )
+ )
+ ;; only my_var (b) is defined here
+ )
+)
+{{< /fatecode >}}
+
+Generic instruction lists do not generate a new level of hierarchy:
+
+{{< fatecode >}}(
+ (local int my_var)
+)
+;; my_var is still defined.
+{{< /fatecode >}}
+
+### LOCAL VARIABLE
+{{< fatecode >}}(local [TYPE] {Identifier}){{< /fatecode >}}
+Declares the local variable `{Identifier}` of type `[TYPE]`.
+
+### GLOBAL VARIABLE
+{{< fatecode >}}(global [TYPE] {Identifier}){{< /fatecode >}}
+Declares the global variable `{Identifier}` of type `[TYPE]`.
+
+## Example
+{{< fatecode >}}(local string name_of_dog)
+
+(global (ptr int) index_of_result)
+
+;; Here is an amusing use of variables:
+(global int something_unexpected)
+(local int something_unexpected)
+;; something_unexpected will not be the same variable within processes (which
+;; will use the global variable) and outside of them (which will use the local
+;; variable). For code readability reasons, I do not recommend doing this.
+{{< /fatecode >}}
diff --git a/content/fate_v1/extensions/_index.md b/content/fate_v1/extensions/_index.md
new file mode 100644
index 0000000..01f7127
--- /dev/null
+++ b/content/fate_v1/extensions/_index.md
@@ -0,0 +1,4 @@
+---
+title: Extensions
+---
+This page not available yet, sorry.
diff --git a/content/fate_v1/instructions/_index.md b/content/fate_v1/instructions/_index.md
new file mode 100644
index 0000000..51066d1
--- /dev/null
+++ b/content/fate_v1/instructions/_index.md
@@ -0,0 +1,48 @@
+---
+title: Instructions
+---
+Instructions do not return values, but modify the memory in some way or
+interact with the interpreter. Computations are valid instructions, and will be
+automatically converted into `[TEXT]` to be displayed.
+
+### ASSERT
+{{< fatecode >}}(assert [BOOL] [TEXT]){{< /fatecode >}}
+
+Raises the exception `[TEXT]` to the interpreter if `[BOOL]` yields
+false.
+
+### DONE
+{{< fatecode >}}(done){{< /fatecode >}}
+
+Completes the execution of the current sequence.
+
+### END
+{{< fatecode >}}(end){{< /fatecode >}}
+
+Completes the execution of the script.
+
+### SET VALUE
+{{< fatecode >}}(set [REFERENCE] [COMPUTATION]){{< /fatecode >}}
+
+Gives the value `[COMPUTATION]` to `[REFERENCE]`.
+
+### VISIT SEQUENCE
+{{< fatecode >}}(visit {String} [C0 = COMPUTATION] ... [CN = COMPUTATION]){{< /fatecode >}}
+
+Visits the sequence named `{String}`, with `C0` ... `CN` as arguments. That
+sequence does not need to already have been defined. Visiting a sequence means
+that the execution of the current sequence continues once the visited sequence
+has completed.
+
+### JUMP TO SEQUENCE
+{{< fatecode >}}(jump_to {String} [C0 = COMPUTATION] ... [CN = COMPUTATION]){{< /fatecode >}}
+
+Jumps to the sequence named `{String}`, with `C0` ... `CN` as arguments. That
+sequence does not need to already have been defined. Jumping to a sequence means
+that the execution of the current sequence is replaced by that of the target
+sequence.
+
+### INSTRUCTION LIST
+{{< fatecode >}}([C0 = INSTRUCTION] ... [CN = INSTRUCTION]){{< /fatecode >}}
+
+Instruction corresponding to the execution of `[C0]` ... `[CN]` in order.
diff --git a/content/fate_v1/instructions/collections/_index.md b/content/fate_v1/instructions/collections/_index.md
new file mode 100644
index 0000000..8d646ee
--- /dev/null
+++ b/content/fate_v1/instructions/collections/_index.md
@@ -0,0 +1,72 @@
+---
+title: Collections
+---
+Fate supports two types of collections: `[LIST]`, which are basic, unordered
+lists; and `[SET]`, which are ordered lists, but only useable with
+`[COMPARABLE]` elements.
+
+### ADDING A MEMBER
+{{< fatecode >}}(add_element! [COMPUTATION*] [COLLECTION VAR]){{< /fatecode >}}
+
+Adds `[COMPUTATION*]` to `[COLLECTION VAR]`. If `[COLLECTION VAR]` is a
+`[LIST]`, the new member is added at the end of the list. Note that
+`[COMPUTATION*]` does not support use of the variable shorthand.
+
+### ADDING A MEMBER AT INDEX
+{{< fatecode >}}(add_element_at! [INT] [COMPUTATION*] [LIST VAR]){{< /fatecode >}}
+
+Adds `[COMPUTATION*]` to `[LIST VAR]` at index `[INT]`. If `[INT]` is less than
+0, the element is added at the start of the list, and if `[INT]` is greater or
+equal to the size of the list, the element is added at the end of the list. Note
+that `[COMPUTATION*]` does not support use of the variable shorthand.
+
+### ADDING MEMBERS
+{{< fatecode >}}(add_all_elements! [COLLECTION] [COLLECTION VAR]){{< /fatecode >}}
+
+Adds all the elements of `[COLLECTION]` to `[COLLECTION VAR]`. If
+`[COLLECTION VAR]` is a `[LIST]`, the new members are added at the end of the
+list.
+
+### EMPTYING COLLECTIONS
+{{< fatecode >}}(clear [COLLECTION]){{< /fatecode >}}
+
+Removes all members of `[COLLECTION]`.
+
+### REMOVING MEMBER
+{{< fatecode >}}(remove [COMPUTATION] [COLLECTION]){{< /fatecode >}}
+
+Removes the first member of `[COLLECTION]` equal to `[COMPUTATION]`.
+
+### REMOVING MEMBERS
+{{< fatecode >}}(remove_all [COMPUTATION] [COLLECTION]){{< /fatecode >}}
+
+Removes all instances of `[COMPUTATION]` from `[COLLECTION]`.
+
+### REMOVING AT INDEX
+{{< fatecode >}}(remove_at [INT] [COLLECTION]){{< /fatecode >}}
+
+Removes the element of `[COLLECTION]` at `[INT]`.
+
+### REVERSING LISTS
+{{< fatecode >}}(reverse [LIST]){{< /fatecode >}}
+
+Reverses the order of the members of `[LIST]`.
+
+### FILTER ELEMENTS
+{{< fatecode >}}(filter! <LAMBDA BOOL (X)> [X COLLECTION VAR]){{< /fatecode >}}
+{{< fatecode >}}(filter! <LAMBDA BOOL (X Y0 ... YN)> [X COLLECTION VAR] [Y0 COMPUTATION*] ... [YN COMPUTATION*]){{< /fatecode >}}
+Modifies `[X COLLECTION VAR]` so that only the elements for which
+`<LAMBDA BOOL (X)>` returns `true` remain. If the lambda function needs extra
+parameters, use the second syntax, which adds those parameters at the end of the
+`(filter! ...)` call. Note that the variable shorthand cannot be used for these
+extra parameters.
+
+### FILTER ELEMENTS (INDEXED)
+{{< fatecode >}}(indexed_filter! <LAMBDA BOOL (INT X)> [X COLLECTION VAR]){{< /fatecode >}}
+{{< fatecode >}}(indexed_filter! <LAMBDA BOOL (INT X Y0 ... YN)> [X COLLECTION VAR] [Y0 COMPUTATION*] ... [YN COMPUTATION*]){{< /fatecode >}}
+Modifies `[X COLLECTION VAR]` so that only the elements for which
+`<LAMBDA BOOL (INT X)>` (with the `INT` being the element's index) returns
+`true` remain. If the lambda function needs extra parameters, use the second
+syntax, which adds those parameters at the end of the `(indexed_filter! ...)`
+call. Note that the variable shorthand cannot be used for these extra
+parameters.
diff --git a/content/fate_v1/instructions/conditionals/_index.md b/content/fate_v1/instructions/conditionals/_index.md
new file mode 100644
index 0000000..e129b1b
--- /dev/null
+++ b/content/fate_v1/instructions/conditionals/_index.md
@@ -0,0 +1,27 @@
+---
+title: Conditionals
+---
+Allow the control of whether to execute instructions or not according to a
+computation. Every conditional branch defines its hierarchy level, from the
+local variables' point of view.
+
+### IF
+{{< fatecode >}}(if [BOOL] [INSTRUCTION]){{< /fatecode >}}
+
+Executes `[INSTRUCTION]` if, and only if, `[BOOL]` yields true.
+
+### IF-ELSE
+{{< fatecode >}}(if_else [BOOL] <IF_TRUE = INSTRUCTION> <IF_FALSE = INSTRUCTION>){{< /fatecode >}}
+
+Executes `<IF_TRUE>` if `[BOOL]` yields true, but `<IF_FALSE>` if it does not.
+
+### COND
+{{< fatecode >}}(cond ([C0 = BOOL] [I0 = INSTRUCTION]) ... ([CN = BOOL] [IN = INSTRUCTION])){{< /fatecode >}}
+
+Executes `[II]`, such that `[CI]` is the first listed boolean to yield true.
+
+### SWITCH
+{{< fatecode >}}(switch [T = COMPUTATION] ([C0 = COMPUTATION] [I0 = INSTRUCTION]) ... ([CN = COMPUTATION] [IN = INSTRUCTION]) [DEFAULT = INSTRUCTION]){{< /fatecode >}}
+
+Executes `[II]`, such that `[CI]` is the first listed computation to be equal
+to `[T]`. Executes `[DEFAULT]` if there is no such `[CI]`.
diff --git a/content/fate_v1/instructions/loops/_index.md b/content/fate_v1/instructions/loops/_index.md
new file mode 100644
index 0000000..03c0f3b
--- /dev/null
+++ b/content/fate_v1/instructions/loops/_index.md
@@ -0,0 +1,34 @@
+---
+title: Loops
+---
+Allow the repetition of a group of instructions according to a computation.
+Every loop body defines its hierarchy level, from the local variables' point of
+view.
+
+### WHILE
+{{< fatecode >}}(while [BOOL] [I0 = INSTRUCTION] ... [IM = INSTRUCTION]){{< /fatecode >}}
+
+Executes `[I0]` ... `[IM]` if, and as long as, `[BOOL]` yields true.
+
+### DO WHILE
+{{< fatecode >}}(do_while [BOOL] [I0 = INSTRUCTION] ... [IM = INSTRUCTION]){{< /fatecode >}}
+
+Executes `[I0]` ... `[IM]`, and does so again as long as, `[BOOL]` yields
+true.
+
+### FOR
+{{< fatecode >}}(for <pre = INSTRUCTION> [BOOL] <post = INSTRUCTION> [I0 = INSTRUCTION] ... [IM = INSTRUCTION]){{< /fatecode >}}
+
+Executes `<pre>`, then, if and as long as `[BOOL]` yields true, executes
+`[I0]` ... `[IM]` followed by `<post>`.
+
+### FOR EACH
+{{< fatecode >}}(foreach [COLLECTION] {String} [I0 = INSTRUCTION] ... [IM = INSTRUCTION]){{< /fatecode >}}
+
+Executes `[I0]` ... `[IM]` for each member of `[COLLECTION]`, in order. The current
+member is stored in a new local variable named `{String}`.
+
+### BREAK
+{{< fatecode >}}(break){{< /fatecode >}}
+
+Exits the current loop.
diff --git a/content/fate_v1/instructions/player_choices/_index.md b/content/fate_v1/instructions/player_choices/_index.md
new file mode 100644
index 0000000..a0dba20
--- /dev/null
+++ b/content/fate_v1/instructions/player_choices/_index.md
@@ -0,0 +1,31 @@
+---
+title: Player Choices
+---
+Player choices are the main way to interact with the user, by presenting them
+with a list of `[RICH TEXT]` choices, and executing a list of instructions
+associated to the choice they have made.
+
+### CHOICE OPTION
+{{< fatecode >}}([TEXT] [I0 = INSTRUCTION] ... [IN = INSTRUCTION]){{< /fatecode >}}
+
+Adds a choice showing `[RICH TEXT]` to the user, and executing `[I0]` ... `[IN]`
+if chosen.
+
+### CHOICE PROMPT
+{{< fatecode >}}(player_choice [C0 = CHOICE] ... [C1 = CHOICE]){{< /fatecode >}}
+
+Prompts the user to choose between `C0` ... `C1`. `[CHOICE]`. `[CHOICE]` is
+either an option as shown above, a [conditional](../conditionals), or a
+`for_each` (see [loops](../loops)) with `[CHOICE]` instead of `[INSTRUCTION]`.
+
+### INTEGER PROMPT
+{{< fatecode >}}(prompt_integer [INT REFERENCE] [MIN = INT] [MAX = INT] [TEXT]){{< /fatecode >}}
+
+Prompts the user for an integer between `[MIN]` and `[MAX]` by displaying the
+message `[TEXT]`. The result is stored in `[INT REFERENCE]`.
+
+### STRING PROMPT
+{{< fatecode >}}(prompt_string [STRING REFERENCE] [MIN = INT] [MAX = INT] [TEXT]){{< /fatecode >}}
+
+Prompts the user for a string of size between `[MIN]` and `[MAX]` by displaying
+the message `[TEXT]`. The result is stored in `[STRING REFERENCE]`.
diff --git a/content/fate_v1/instructions/references/_index.md b/content/fate_v1/instructions/references/_index.md
new file mode 100644
index 0000000..9beb132
--- /dev/null
+++ b/content/fate_v1/instructions/references/_index.md
@@ -0,0 +1,7 @@
+---
+title: References
+---
+### DE-ALLOCATION
+{{< fatecode >}}(free [POINTER]){{< /fatecode >}}
+
+Removes the memory element at `[POINTER]` from the memory.
diff --git a/content/images/discord.svg b/content/images/discord.svg
new file mode 100644
index 0000000..3d4cb8e
--- /dev/null
+++ b/content/images/discord.svg
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ height="533.33331"
+ width="466.06668"
+ version="1.1"
+ id="Layer_1"
+ viewBox="-26.25 -50 88.358475 199.99999"
+ sodipodi:docname="discord.svg"
+ inkscape:version="0.92.4 5da689c313, 2019-01-14">
+ <metadata
+ id="metadata1634">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs1632" />
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="958"
+ inkscape:window-height="528"
+ id="namedview1630"
+ showgrid="false"
+ fit-margin-top="0"
+ fit-margin-left="0"
+ fit-margin-right="-0.6"
+ fit-margin-bottom="0"
+ inkscape:pagecheckerboard="true"
+ inkscape:zoom="0.25833333"
+ inkscape:cx="193.98448"
+ inkscape:cy="-43.010726"
+ inkscape:window-x="961"
+ inkscape:window-y="20"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="Layer_1" />
+ <style
+ id="style41">.st0{fill:#fff}</style>
+ <path
+ id="path43"
+ d="m -0.11388706,33.9 c -5.70000004,0 -10.19999994,5 -10.19999994,11.1 0,6.1 4.5999999,11.1 10.19999994,11.1 5.69999996,0 10.20000006,-5 10.20000006,-11.1 0.1,-6.1 -4.5000001,-11.1 -10.20000006,-11.1 z m 36.50000006,0 c -5.7,0 -10.2,5 -10.2,11.1 0,6.1 4.6,11.1 10.2,11.1 5.7,0 10.2,-5 10.2,-11.1 0,-6.1 -4.5,-11.1 -10.2,-11.1 z"
+ class="st0"
+ inkscape:connector-curvature="0"
+ style="fill:#ffffff" />
+ <path
+ id="path45"
+ d="m 84.986113,-50 h -134 c -11.3,0 -20.5,9.2 -20.5,20.6 v 135.2 c 0,11.4 9.2,20.6 20.5,20.6 h 113.4 l -5.3,-18.5 12.8,11.9 12.1,11.2 21.499997,19 V -29.4 c 0,-11.4 -9.199997,-20.6 -20.499997,-20.6 z m -38.6,130.6 c 0,0 -3.6,-4.3 -6.6,-8.1 13.1,-3.7 18.1,-11.9 18.1,-11.9 -4.1,2.7 -8,4.6 -11.5,5.9 -5,2.1 -9.8,3.5 -14.5,4.3 -9.6,1.8 -18.4,1.3 -25.9000001,-0.1 -5.69999996,-1.1 -10.6,-2.7 -14.7,-4.3 -2.2999999,-0.9 -4.7999999,-2 -7.2999999,-3.4 -0.3,-0.2 -0.6,-0.3 -0.9,-0.5 -0.2,-0.1 -0.3,-0.2 -0.4,-0.3 -1.8,-1 -2.8,-1.7 -2.8,-1.7 0,0 4.8,8 17.4999999,11.8 -3,3.8 -6.7,8.3 -6.7,8.3 C -31.413887,79.9 -39.813887,65.4 -39.813887,65.4 c 0,-32.2 14.4,-58.3 14.4,-58.3 14.4,-10.8 28.0999999,-10.5 28.0999999,-10.5 l 1,1.2 C -14.313887,3 -22.613887,10.9 -22.613887,10.9 c 0,0 2.2,-1.2 5.9,-2.9 C -6.0138871,3.3 2.4861129,2 5.9861129,1.7 c 0.6,-0.1 1.1,-0.2 1.7,-0.2 6.1000001,-0.8 13.0000001,-1 20.2000001,-0.2 9.5,1.1 19.7,3.9 30.1,9.6 0,0 -7.9,-7.5 -24.9,-12.7 l 1.4,-1.6 c 0,0 13.7,-0.3 28.1,10.5 0,0 14.4,26.1 14.4,58.3 0,0 -8.5,14.5 -30.6,15.2 z"
+ class="st0"
+ inkscape:connector-curvature="0"
+ style="fill:#ffffff" />
+</svg>
diff --git a/content/images/github.svg b/content/images/github.svg
new file mode 100644
index 0000000..081fab1
--- /dev/null
+++ b/content/images/github.svg
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="11.493147mm"
+ height="11.209467mm"
+ viewBox="0 0 11.493147 11.209467"
+ version="1.1"
+ id="svg1567"
+ inkscape:version="0.92.4 5da689c313, 2019-01-14"
+ sodipodi:docname="github.svg">
+ <defs
+ id="defs1561" />
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="0.35"
+ inkscape:cx="293.14789"
+ inkscape:cy="-998.81676"
+ inkscape:document-units="mm"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ inkscape:pagecheckerboard="true"
+ fit-margin-top="0"
+ fit-margin-left="0"
+ fit-margin-right="0"
+ fit-margin-bottom="0"
+ inkscape:window-width="958"
+ inkscape:window-height="1059"
+ inkscape:window-x="961"
+ inkscape:window-y="20"
+ inkscape:window-maximized="0" />
+ <metadata
+ id="metadata1564">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(104.77634,126.6464)">
+ <g
+ id="g1028"
+ transform="matrix(0.35277777,0,0,-0.35277777,-99.030291,-126.6464)">
+ <path
+ d="m 0,0 c -8.995,0 -16.288,-7.293 -16.288,-16.29 0,-7.197 4.667,-13.302 11.14,-15.457 0.815,-0.149 1.112,0.354 1.112,0.786 0,0.386 -0.014,1.411 -0.022,2.77 -4.531,-0.984 -5.487,2.184 -5.487,2.184 -0.741,1.882 -1.809,2.383 -1.809,2.383 -1.479,1.01 0.112,0.99 0.112,0.99 1.635,-0.115 2.495,-1.679 2.495,-1.679 1.453,-2.489 3.813,-1.77 4.741,-1.353 0.148,1.052 0.568,1.77 1.034,2.177 -3.617,0.411 -7.42,1.809 -7.42,8.051 0,1.778 0.635,3.232 1.677,4.371 -0.168,0.412 -0.727,2.068 0.159,4.311 0,0 1.368,0.438 4.48,-1.67 1.299,0.362 2.693,0.542 4.078,0.548 1.383,-0.006 2.777,-0.186 4.078,-0.548 3.11,2.108 4.475,1.67 4.475,1.67 0.889,-2.243 0.33,-3.899 0.162,-4.311 1.044,-1.139 1.675,-2.593 1.675,-4.371 0,-6.258 -3.809,-7.635 -7.438,-8.038 0.585,-0.503 1.106,-1.497 1.106,-3.017 0,-2.177 -0.02,-3.934 -0.02,-4.468 0,-0.436 0.293,-0.943 1.12,-0.784 6.468,2.159 11.131,8.26 11.131,15.455 C 16.291,-7.293 8.997,0 0,0"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path1030"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+</svg>
diff --git a/content/images/reddit.svg b/content/images/reddit.svg
new file mode 100644
index 0000000..dd4332c
--- /dev/null
+++ b/content/images/reddit.svg
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ height="317.92969"
+ width="317.92773"
+ stroke-miterlimit="1.4142"
+ viewBox="-39.158565 -22.4785 89.913733 53.599369"
+ version="1.1"
+ id="svg2284"
+ sodipodi:docname="reddit.svg"
+ style="clip-rule:evenodd;fill-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:1.41419995"
+ inkscape:version="0.92.4 5da689c313, 2019-01-14">
+ <metadata
+ id="metadata2290">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs2288" />
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="958"
+ inkscape:window-height="528"
+ id="namedview2286"
+ showgrid="false"
+ inkscape:pagecheckerboard="true"
+ fit-margin-top="0"
+ fit-margin-left="0"
+ fit-margin-right="0"
+ fit-margin-bottom="0"
+ inkscape:zoom="0.73067701"
+ inkscape:cx="211.99214"
+ inkscape:cy="266.21581"
+ inkscape:window-x="961"
+ inkscape:window-y="20"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="svg2284" />
+ <path
+ style="fill:#ffffff;stroke-width:1"
+ d="M 5.7985782,-40.635958 A 44.957001,44.957001 0 0 0 -39.158565,4.3211838 44.957001,44.957001 0 0 0 5.7985782,49.278329 44.957001,44.957001 0 0 0 50.755169,4.3211838 44.957001,44.957001 0 0 0 5.7985782,-40.635958 Z m 18.7766088,17.81107 c 2.574999,0 4.667499,2.091948 4.667499,4.66695 0,2.576 -2.0925,4.668053 -4.667499,4.668053 -2.522,0 -4.559501,-1.98463 -4.667501,-4.45263 l -9.76419,-2.092366 -3.0043245,14.0560798 c 6.8669995,0.268001 13.0371745,2.359907 17.5431735,5.57890502 1.180001,-1.12699902 2.790343,-1.82391602 4.560341,-1.82391602 3.595002,0 6.544996,2.89699802 6.544996,6.544996 0,2.682001 -1.609149,4.9892 -3.862149,6.0092012 0.107001,0.643001 0.160738,1.340653 0.160738,1.984655 0,10.139 -11.749113,18.294392 -26.2341141,18.294392 -14.4849984,0 -26.2335599,-8.209392 -26.2335599,-18.294392 0,-0.698003 0.05274,-1.341654 0.160739,-1.984655 -2.254002,-1.0200012 -3.862704,-3.2730692 -3.862704,-5.9550682 0,-3.59499898 2.896997,-6.544996 6.544996,-6.544996 a 6.5883,6.5883 0 0 1 4.55979,1.82391602 C -8.4185833,-3.6187642 -2.1415118,-5.7107752 4.8324872,-5.9257742 L 8.1593955,-21.590901 c 0.052999,-0.321998 0.2142158,-0.589665 0.482214,-0.750665 0.215002,-0.160999 0.5369324,-0.21529 0.8589307,-0.16129 l 10.8899138,2.307236 c 0.751001,-1.556 2.360732,-2.629268 4.184733,-2.629268 z M -4.5014071,4.3211838 c -2.5760003,0 -4.668053,2.091948 -4.668053,4.666947 0,2.5750022 2.0920527,4.7210552 4.668053,4.6680532 2.5749991,0 4.66694716,-2.093051 4.66694716,-4.6680532 0,-2.574999 -2.09194806,-4.666947 -4.66694716,-4.666947 z m 20.5999711,0.05413 c -2.575,0 -4.666948,2.091948 -4.666948,4.666947 0,2.5750002 2.091948,4.6669482 4.666948,4.6669482 2.576,0 4.668052,-2.145948 4.668052,-4.6669482 0,-2.574999 -2.092052,-4.666947 -4.668052,-4.666947 z M -4.3948012,19.303032 c -0.3084996,0 -0.6174292,0.120249 -0.8589307,0.361247 -0.4819991,0.483 -0.4819991,1.233758 0,1.716759 3.1659996,3.164998 9.2818909,3.434065 11.1058888,3.434065 1.7700007,0 7.8863391,-0.215067 11.1053371,-3.434065 0.429,-0.483001 0.429,-1.233759 0,-1.716759 -0.483,-0.481999 -1.234309,-0.481999 -1.717307,0 -1.985,2.039003 -6.3300279,2.735874 -9.3880301,2.735874 -3.0579994,0 -7.3495789,-0.696871 -9.3885788,-2.735874 -0.2415016,-0.240998 -0.5498796,-0.361247 -0.8583793,-0.361247 z"
+ id="circle2278"
+ inkscape:connector-curvature="0" />
+</svg>
diff --git a/content/images/tonkadur_logo_black.svg b/content/images/tonkadur_logo_black.svg
new file mode 100644
index 0000000..3745257
--- /dev/null
+++ b/content/images/tonkadur_logo_black.svg
@@ -0,0 +1,97 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="51.232002mm"
+ height="16.4846mm"
+ viewBox="0 0 51.232002 16.4846"
+ version="1.1"
+ id="svg8"
+ inkscape:version="0.92.4 5da689c313, 2019-01-14"
+ sodipodi:docname="tonkadur_logo_black.svg">
+ <defs
+ id="defs2" />
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="2.8"
+ inkscape:cx="65.374105"
+ inkscape:cy="9.8673039"
+ inkscape:document-units="mm"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ fit-margin-top="0"
+ fit-margin-left="0"
+ fit-margin-right="0"
+ fit-margin-bottom="0"
+ inkscape:window-width="1918"
+ inkscape:window-height="1059"
+ inkscape:window-x="1"
+ inkscape:window-y="20"
+ inkscape:window-maximized="0" />
+ <metadata
+ id="metadata5">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(-61.119356,-51.9597)">
+ <flowRoot
+ xml:space="preserve"
+ id="flowRoot841"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:10.66666698px;line-height:125%;font-family:'Times New Roman';-inkscape-font-specification:'Times New Roman, ';letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ transform="scale(0.26458333)"><flowRegion
+ id="flowRegion843"><rect
+ id="rect845"
+ width="73.571426"
+ height="125"
+ x="574.28571"
+ y="174.66254" /></flowRegion><flowPara
+ id="flowPara847"></flowPara></flowRoot> <g
+ id="g930">
+ <text
+ id="text817"
+ y="63.331463"
+ x="67.892647"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:1.93140244px;line-height:125%;font-family:'Times New Roman';-inkscape-font-specification:'Times New Roman, ';letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.78100002;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:markers stroke fill"
+ xml:space="preserve"><tspan
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:15.45121956px;font-family:'Argos George';-inkscape-font-specification:'Argos George';fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.78100002;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:markers stroke fill"
+ y="63.331463"
+ x="67.892647"
+ id="tspan815"
+ sodipodi:role="line">onkadur</tspan></text>
+ <text
+ id="text924"
+ y="68.4189"
+ x="61.043156"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;line-height:125%;font-family:'Times New Roman';-inkscape-font-specification:'Times New Roman, ';letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ xml:space="preserve"><tspan
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:25.39999962px;font-family:'Argos George';-inkscape-font-specification:'Argos George';stroke-width:0.26458332px"
+ y="68.4189"
+ x="61.043156"
+ id="tspan922"
+ sodipodi:role="line">T</tspan></text>
+ </g>
+ </g>
+</svg>
diff --git a/content/images/tonkadur_logo_black_as_path.svg b/content/images/tonkadur_logo_black_as_path.svg
new file mode 100644
index 0000000..e09be31
--- /dev/null
+++ b/content/images/tonkadur_logo_black_as_path.svg
@@ -0,0 +1,117 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="51.232002mm"
+ height="16.4846mm"
+ viewBox="0 0 51.232002 16.4846"
+ version="1.1"
+ id="svg8"
+ inkscape:version="0.92.4 5da689c313, 2019-01-14"
+ sodipodi:docname="tonkadur_logo_black_as_path.svg">
+ <defs
+ id="defs2" />
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="2.8"
+ inkscape:cx="65.374105"
+ inkscape:cy="9.8673039"
+ inkscape:document-units="mm"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ fit-margin-top="0"
+ fit-margin-left="0"
+ fit-margin-right="0"
+ fit-margin-bottom="0"
+ inkscape:window-width="958"
+ inkscape:window-height="1059"
+ inkscape:window-x="961"
+ inkscape:window-y="20"
+ inkscape:window-maximized="0" />
+ <metadata
+ id="metadata5">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(-61.119356,-51.9597)">
+ <flowRoot
+ xml:space="preserve"
+ id="flowRoot841"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:10.66666698px;line-height:125%;font-family:'Times New Roman';-inkscape-font-specification:'Times New Roman, ';letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ transform="scale(0.26458333)"><flowRegion
+ id="flowRegion843"><rect
+ id="rect845"
+ width="73.571426"
+ height="125"
+ x="574.28571"
+ y="174.66254" /></flowRegion><flowPara
+ id="flowPara847" /></flowRoot> <g
+ id="g930">
+ <g
+ aria-label="onkadur"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:1.93140244px;line-height:125%;font-family:'Times New Roman';-inkscape-font-specification:'Times New Roman, ';letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.78100002;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:markers stroke fill"
+ id="text817">
+ <path
+ d="m 67.985354,60.488438 q 0,-1.220646 0.818915,-2.085914 0.818914,-0.88072 2.02411,-0.88072 1.189743,0 2.03956,0.865269 0.865269,0.865268 0.865269,2.055012 0,0.957975 -0.556244,1.745988 -0.818915,1.14339 -2.441293,1.14339 -1.251549,0 -2.008658,-0.772561 -0.741659,-0.772561 -0.741659,-2.070464 z m 2.750317,-2.379487 q -0.695305,0.09271 -1.035232,1.004329 -0.231768,0.618049 -0.231768,1.514219 0,0.88072 0.370829,1.452415 0.432635,0.664403 1.267,0.664403 0.710757,0 1.081586,-0.664403 0.293573,-0.525341 0.293573,-1.297902 0,-0.664403 -0.216317,-1.189744 -0.278122,-0.710756 -0.849817,-0.710756 -0.139061,0 -0.355378,0.123609 -0.216317,0.12361 -0.231768,0.12361 v -0.494439 q 0.293573,-0.216317 0.478987,-0.478988 -0.139061,-0.0309 -0.278122,-0.04635 -0.154512,-0.01545 -0.293573,0 z"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:15.45121956px;font-family:'Argos George';-inkscape-font-specification:'Argos George';fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.78100002;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:markers stroke fill"
+ id="path829" />
+ <path
+ d="m 74.352222,57.954438 q 0.09271,0 0.818915,-0.154512 0.50989,-0.108158 0.788012,-0.108158 0.169963,0 0.324476,0.231768 0.07726,0.12361 0.216317,0.370829 0.200865,-0.278122 0.834365,-0.448085 0.540793,-0.154512 0.973427,-0.154512 0.849817,0 0.927073,0.01545 0.648952,0.0618 0.648952,0.772561 v 2.348585 q 0,0.803464 0.417183,1.63783 0.0309,0.07726 0.556244,0.988878 h -1.375159 q -0.664402,0 -0.865268,-0.911622 -0.09271,-0.417183 -0.09271,-1.421513 v -0.803463 q 0.01545,-0.108158 0.01545,-0.278122 0.04635,-1.931402 -0.726208,-1.931402 -0.370829,0 -0.834366,0.169963 -0.618048,0.216317 -0.618048,0.571695 v 3.1675 q 0,0.772561 0.293573,1.251549 h -1.761439 q 0.12361,-0.772561 0.12361,-2.843024 0,-1.00433 -0.0309,-1.962305 -0.216317,-0.04635 -0.309024,-0.09271 -0.324476,-0.154512 -0.324476,-0.417183 z"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:15.45121956px;font-family:'Argos George';-inkscape-font-specification:'Argos George';fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.78100002;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:markers stroke fill"
+ id="path831" />
+ <path
+ d="m 81.382286,55.18867 q 0.849817,-0.525341 1.792342,-1.467866 l -0.169964,5.979622 q 0.478988,-0.478988 1.282451,-0.757109 0.231769,-0.07726 1.452415,-0.386281 0.664402,-0.247219 0.911622,-0.896171 0.540793,0.355378 0.540793,0.896171 0,0.339927 -0.37083,0.50989 -0.247219,0.07726 -0.788012,0.12361 -0.540793,0.0309 -0.741658,0.108159 0.834365,1.931402 1.220646,2.642158 0.200866,0.355378 0.880719,1.483317 -0.432634,0.06181 -0.957975,0.06181 -1.050683,0 -1.483317,-1.297902 -0.463537,-1.359708 -0.988878,-2.549452 -0.478988,0.139061 -0.927073,0.494439 0.01545,0.834366 0.01545,1.653281 0.0309,0.988878 0.154512,1.637829 h -1.77689 q 0.01545,-0.01545 0.200866,-0.602597 0.09271,-0.293574 0.09271,-0.463537 v -2.456744 q 0,-0.231768 0,-0.494439 0.01545,-0.293573 0.01545,-0.309024 0.01545,-3.383817 -0.355378,-3.909159 z"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:15.45121956px;font-family:'Argos George';-inkscape-font-specification:'Argos George';fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.78100002;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:markers stroke fill"
+ id="path833" />
+ <path
+ d="m 88.144366,60.565695 q 0,-1.205196 0.710756,-2.055013 0.726207,-0.865268 1.9005,-0.865268 0.216317,0 0.618049,0.07726 0.417183,0.07726 0.6335,0.07726 0.309024,0 0.417183,-0.154512 0.818914,0.370829 1.406061,0.571695 -0.24722,1.050683 -0.24722,2.394939 0,1.761439 0.432634,2.688512 -0.169963,-0.0309 -0.525341,-0.108158 -0.339927,-0.07726 -0.540793,-0.07726 -0.324475,0 -0.788012,0.09271 -0.911622,0.185415 -1.267,0.185415 -1.236098,0 -1.993207,-0.772561 -0.75711,-0.788012 -0.75711,-2.055012 z m 3.136598,-2.441293 q -0.865269,0 -1.313354,0.679854 -0.370829,0.571695 -0.370829,1.483317 0,1.328804 0.772561,2.039561 0.525341,0.494439 1.004329,0.494439 0.788012,0 0.788012,-0.973427 V 58.912414 Q 91.914464,58.448877 91.86811,58.387073 91.651793,58.124402 91.280964,58.124402 Z"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:15.45121956px;font-family:'Argos George';-inkscape-font-specification:'Argos George';fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.78100002;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:markers stroke fill"
+ id="path835" />
+ <path
+ d="m 100.17531,53.689902 q 0.21632,0.556244 0.20087,1.637829 -0.0155,0.618049 -0.0618,2.889378 -0.0618,2.14772 -0.0463,2.904829 0,0.185415 0.10816,0.788013 0.13906,0.834366 0.47899,1.328805 -0.71076,-0.12361 -1.313356,-0.12361 -0.417183,0 -1.174293,0.12361 -0.75711,0.108158 -1.097037,0.108158 H 97.08507 q -1.066134,0 -1.715086,-0.834366 -0.571695,-0.772561 -0.571695,-1.869597 0,-1.050683 0.556244,-1.977756 0.6335,-1.050683 1.622378,-1.050683 0.185415,0 0.262671,0.01545 0.370829,0.06181 0.896171,0.185414 0.448085,0.154513 0.757109,0.478988 v -0.741658 q 0.01545,-0.09271 0.01545,-0.216317 0.01545,-1.328805 -0.309025,-2.364037 0.417183,-0.309024 0.896171,-0.741658 0.262671,-0.24722 0.67985,-0.540793 z m -2.549448,4.511756 q -0.664402,0 -1.004329,0.741659 -0.262671,0.556243 -0.262671,1.313353 0,1.205195 0.24722,1.715086 0.355378,0.710756 1.282451,0.710756 0.50989,0 1.004329,-0.07726 v -3.553781 q 0,-0.38628 -0.463536,-0.6335 -0.401732,-0.216317 -0.803464,-0.216317 z"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:15.45121956px;font-family:'Argos George';-inkscape-font-specification:'Argos George';fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.78100002;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:markers stroke fill"
+ id="path837" />
+ <path
+ d="m 104.74332,57.84628 1.9314,0.0309 v 4.697171 q 0,0.401732 0.33993,0.741659 h -1.8696 v -0.293574 q 0,-0.216317 0.0155,-0.324475 0,-0.185415 -0.0155,-0.24722 l -0.58714,0.07726 q -0.20087,0.0309 -1.32881,0.571696 -0.44808,0.216317 -0.6335,0.216317 -0.78801,0 -0.78801,-0.679854 v -3.631037 q 0,-0.463536 -0.55624,-1.158841 h 1.63783 q 0.29357,0.417183 0.29357,0.679854 l -0.0309,3.801 q 0,0.293573 0.20086,0.293573 0.24722,-0.07726 1.01978,-0.386281 0.50989,-0.200866 0.86527,-0.200866 v -3.306561 q 0,-0.309024 -0.49444,-0.880719 z"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:15.45121956px;font-family:'Argos George';-inkscape-font-specification:'Argos George';fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.78100002;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:markers stroke fill"
+ id="path839" />
+ <path
+ d="m 109.94097,58.139853 q 0.64895,-0.448085 0.6953,-0.478988 0.50989,-0.293573 0.92708,-0.293573 0.78801,0 0.78801,0.772561 0,0.463537 -0.30903,0.741659 -0.30902,0.278122 -0.77256,0.278122 0.29358,-0.339927 0.29358,-0.540793 0,-0.169964 -0.20087,-0.278122 -0.18541,-0.108159 -0.38628,-0.108159 -0.67985,0 -1.03523,0.896171 -0.24722,0.6335 -0.24722,1.467866 0,0.88072 0.30902,1.591476 0.38628,0.865268 0.43264,1.14339 -1.28245,0 -1.63783,-0.231768 -0.46354,-0.309025 -0.46354,-1.436964 v -2.843024 q 0,-0.432634 -0.29357,-0.865269 -0.13906,-0.200865 -0.29358,-0.355378 0.35538,-0.04635 1.18975,-0.04635 h 0.27812 q 0.44809,0 0.55624,0.216317 0.10816,0.200866 0.16997,0.370829 z"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:15.45121956px;font-family:'Argos George';-inkscape-font-specification:'Argos George';fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.78100002;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:markers stroke fill"
+ id="path841" />
+ </g>
+ <g
+ aria-label="T"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;line-height:125%;font-family:'Times New Roman';-inkscape-font-specification:'Times New Roman, ';letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ id="text924">
+ <path
+ d="m 67.520156,52.3661 q 0.127,0 2.286,0.127 0.8636,0.0508 1.4224,0.0508 1.955799,0 3.860799,-0.5842 -0.1524,1.397 -1.2192,2.2606 -1.0668,0.8636 -2.489199,0.8636 -1.1938,0 -3.9116,-1.016 -2.7178,-1.0414 -3.81,-1.0414 -1.9304,0 -1.9304,1.9304 0,0.8128 0.6096,1.3716 0.3556,0.3302 1.3208,0.7874 -0.508,0.889 -0.7874,0.889 -1.0414,-0.3556 -1.4478,-1.143 -0.3048,-0.5842 -0.3048,-1.3716 0,-1.27 0.508,-1.9812 0.508,-0.7112 1.7018,-1.143 0.4064,-0.1524 1.524,-0.1524 1.1938,0 2.159,0.0762 0.1016,0 0.508,0.0762 z m -4.318,9.1694 q 0,-1.5494 0.9652,-3.81 1.0414,-2.3622 2.2352,-3.175 -0.9652,2.9718 -0.9652,4.2672 0,2.3622 1.1684,4.3942 1.7018,2.9972 5.1054,2.9972 0.635,0 1.549399,-0.3556 0.9398,-0.381 1.397,-0.4064 -0.8128,1.27 -2.565399,2.1336 -1.7272,0.8636 -3.302,0.8636 -1.778,0 -3.5306,-1.8288 -2.0574,-2.1336 -2.0574,-5.08 z"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:25.39999962px;font-family:'Argos George';-inkscape-font-specification:'Argos George';stroke-width:0.26458332px"
+ id="path844" />
+ </g>
+ </g>
+ </g>
+</svg>
diff --git a/content/images/tonkadur_logo_white.svg b/content/images/tonkadur_logo_white.svg
new file mode 100644
index 0000000..f17e213
--- /dev/null
+++ b/content/images/tonkadur_logo_white.svg
@@ -0,0 +1,98 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="51.232002mm"
+ height="16.4846mm"
+ viewBox="0 0 51.232002 16.4846"
+ version="1.1"
+ id="svg8"
+ inkscape:version="0.92.4 5da689c313, 2019-01-14"
+ sodipodi:docname="tonkadur_logo_white.svg">
+ <defs
+ id="defs2" />
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="2.8"
+ inkscape:cx="65.374106"
+ inkscape:cy="9.8673018"
+ inkscape:document-units="mm"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ fit-margin-top="0"
+ fit-margin-left="0"
+ fit-margin-right="0"
+ fit-margin-bottom="0"
+ inkscape:window-width="1918"
+ inkscape:window-height="1059"
+ inkscape:window-x="1"
+ inkscape:window-y="20"
+ inkscape:window-maximized="0" />
+ <metadata
+ id="metadata5">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(-61.119356,-51.9597)">
+ <flowRoot
+ xml:space="preserve"
+ id="flowRoot841"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:10.66666698px;line-height:125%;font-family:'Times New Roman';-inkscape-font-specification:'Times New Roman, ';letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ transform="scale(0.26458333)"><flowRegion
+ id="flowRegion843"><rect
+ id="rect845"
+ width="73.571426"
+ height="125"
+ x="574.28571"
+ y="174.66254" /></flowRegion><flowPara
+ id="flowPara847"></flowPara></flowRoot> <g
+ id="g930"
+ style="fill:#ffffff">
+ <text
+ id="text817"
+ y="63.331463"
+ x="67.892647"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:1.93140244px;line-height:125%;font-family:'Times New Roman';-inkscape-font-specification:'Times New Roman, ';letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.78100002;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:markers stroke fill"
+ xml:space="preserve"><tspan
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:15.45121956px;font-family:'Argos George';-inkscape-font-specification:'Argos George';fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.78100002;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:markers stroke fill"
+ y="63.331463"
+ x="67.892647"
+ id="tspan815"
+ sodipodi:role="line">onkadur</tspan></text>
+ <text
+ id="text924"
+ y="68.4189"
+ x="61.043156"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;line-height:125%;font-family:'Times New Roman';-inkscape-font-specification:'Times New Roman, ';letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ xml:space="preserve"><tspan
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:25.39999962px;font-family:'Argos George';-inkscape-font-specification:'Argos George';fill:#ffffff;stroke-width:0.26458332px"
+ y="68.4189"
+ x="61.043156"
+ id="tspan922"
+ sodipodi:role="line">T</tspan></text>
+ </g>
+ </g>
+</svg>
diff --git a/content/images/tonkadur_logo_white_as_path.svg b/content/images/tonkadur_logo_white_as_path.svg
new file mode 100644
index 0000000..04c3039
--- /dev/null
+++ b/content/images/tonkadur_logo_white_as_path.svg
@@ -0,0 +1,118 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="51.232002mm"
+ height="16.4846mm"
+ viewBox="0 0 51.232002 16.4846"
+ version="1.1"
+ id="svg8"
+ inkscape:version="0.92.4 5da689c313, 2019-01-14"
+ sodipodi:docname="tonkadur_logo_white_as_path.svg">
+ <defs
+ id="defs2" />
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="2.8"
+ inkscape:cx="65.374106"
+ inkscape:cy="9.8673018"
+ inkscape:document-units="mm"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ fit-margin-top="0"
+ fit-margin-left="0"
+ fit-margin-right="0"
+ fit-margin-bottom="0"
+ inkscape:window-width="1918"
+ inkscape:window-height="1059"
+ inkscape:window-x="1"
+ inkscape:window-y="20"
+ inkscape:window-maximized="0" />
+ <metadata
+ id="metadata5">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(-61.119356,-51.9597)">
+ <flowRoot
+ xml:space="preserve"
+ id="flowRoot841"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:10.66666698px;line-height:125%;font-family:'Times New Roman';-inkscape-font-specification:'Times New Roman, ';letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ transform="scale(0.26458333)"><flowRegion
+ id="flowRegion843"><rect
+ id="rect845"
+ width="73.571426"
+ height="125"
+ x="574.28571"
+ y="174.66254" /></flowRegion><flowPara
+ id="flowPara847" /></flowRoot> <g
+ id="g930"
+ style="fill:#ffffff">
+ <g
+ aria-label="onkadur"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:1.93140244px;line-height:125%;font-family:'Times New Roman';-inkscape-font-specification:'Times New Roman, ';letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.78100002;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:markers stroke fill"
+ id="text817">
+ <path
+ d="m 67.985354,60.488438 q 0,-1.220646 0.818915,-2.085914 0.818914,-0.88072 2.02411,-0.88072 1.189743,0 2.03956,0.865269 0.865269,0.865268 0.865269,2.055012 0,0.957975 -0.556244,1.745988 -0.818915,1.14339 -2.441293,1.14339 -1.251549,0 -2.008658,-0.772561 -0.741659,-0.772561 -0.741659,-2.070464 z m 2.750317,-2.379487 q -0.695305,0.09271 -1.035232,1.004329 -0.231768,0.618049 -0.231768,1.514219 0,0.88072 0.370829,1.452415 0.432635,0.664403 1.267,0.664403 0.710757,0 1.081586,-0.664403 0.293573,-0.525341 0.293573,-1.297902 0,-0.664403 -0.216317,-1.189744 -0.278122,-0.710756 -0.849817,-0.710756 -0.139061,0 -0.355378,0.123609 -0.216317,0.12361 -0.231768,0.12361 v -0.494439 q 0.293573,-0.216317 0.478987,-0.478988 -0.139061,-0.0309 -0.278122,-0.04635 -0.154512,-0.01545 -0.293573,0 z"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:15.45121956px;font-family:'Argos George';-inkscape-font-specification:'Argos George';fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.78100002;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:markers stroke fill"
+ id="path829" />
+ <path
+ d="m 74.352222,57.954438 q 0.09271,0 0.818915,-0.154512 0.50989,-0.108158 0.788012,-0.108158 0.169963,0 0.324476,0.231768 0.07726,0.12361 0.216317,0.370829 0.200865,-0.278122 0.834365,-0.448085 0.540793,-0.154512 0.973427,-0.154512 0.849817,0 0.927073,0.01545 0.648952,0.0618 0.648952,0.772561 v 2.348585 q 0,0.803464 0.417183,1.63783 0.0309,0.07726 0.556244,0.988878 h -1.375159 q -0.664402,0 -0.865268,-0.911622 -0.09271,-0.417183 -0.09271,-1.421513 v -0.803463 q 0.01545,-0.108158 0.01545,-0.278122 0.04635,-1.931402 -0.726208,-1.931402 -0.370829,0 -0.834366,0.169963 -0.618048,0.216317 -0.618048,0.571695 v 3.1675 q 0,0.772561 0.293573,1.251549 h -1.761439 q 0.12361,-0.772561 0.12361,-2.843024 0,-1.00433 -0.0309,-1.962305 -0.216317,-0.04635 -0.309024,-0.09271 -0.324476,-0.154512 -0.324476,-0.417183 z"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:15.45121956px;font-family:'Argos George';-inkscape-font-specification:'Argos George';fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.78100002;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:markers stroke fill"
+ id="path831" />
+ <path
+ d="m 81.382286,55.18867 q 0.849817,-0.525341 1.792342,-1.467866 l -0.169964,5.979622 q 0.478988,-0.478988 1.282451,-0.757109 0.231769,-0.07726 1.452415,-0.386281 0.664402,-0.247219 0.911622,-0.896171 0.540793,0.355378 0.540793,0.896171 0,0.339927 -0.37083,0.50989 -0.247219,0.07726 -0.788012,0.12361 -0.540793,0.0309 -0.741658,0.108159 0.834365,1.931402 1.220646,2.642158 0.200866,0.355378 0.880719,1.483317 -0.432634,0.06181 -0.957975,0.06181 -1.050683,0 -1.483317,-1.297902 -0.463537,-1.359708 -0.988878,-2.549452 -0.478988,0.139061 -0.927073,0.494439 0.01545,0.834366 0.01545,1.653281 0.0309,0.988878 0.154512,1.637829 h -1.77689 q 0.01545,-0.01545 0.200866,-0.602597 0.09271,-0.293574 0.09271,-0.463537 v -2.456744 q 0,-0.231768 0,-0.494439 0.01545,-0.293573 0.01545,-0.309024 0.01545,-3.383817 -0.355378,-3.909159 z"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:15.45121956px;font-family:'Argos George';-inkscape-font-specification:'Argos George';fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.78100002;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:markers stroke fill"
+ id="path833" />
+ <path
+ d="m 88.144366,60.565695 q 0,-1.205196 0.710756,-2.055013 0.726207,-0.865268 1.9005,-0.865268 0.216317,0 0.618049,0.07726 0.417183,0.07726 0.6335,0.07726 0.309024,0 0.417183,-0.154512 0.818914,0.370829 1.406061,0.571695 -0.24722,1.050683 -0.24722,2.394939 0,1.761439 0.432634,2.688512 -0.169963,-0.0309 -0.525341,-0.108158 -0.339927,-0.07726 -0.540793,-0.07726 -0.324475,0 -0.788012,0.09271 -0.911622,0.185415 -1.267,0.185415 -1.236098,0 -1.993207,-0.772561 -0.75711,-0.788012 -0.75711,-2.055012 z m 3.136598,-2.441293 q -0.865269,0 -1.313354,0.679854 -0.370829,0.571695 -0.370829,1.483317 0,1.328804 0.772561,2.039561 0.525341,0.494439 1.004329,0.494439 0.788012,0 0.788012,-0.973427 V 58.912414 Q 91.914464,58.448877 91.86811,58.387073 91.651793,58.124402 91.280964,58.124402 Z"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:15.45121956px;font-family:'Argos George';-inkscape-font-specification:'Argos George';fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.78100002;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:markers stroke fill"
+ id="path835" />
+ <path
+ d="m 100.17531,53.689902 q 0.21632,0.556244 0.20087,1.637829 -0.0155,0.618049 -0.0618,2.889378 -0.0618,2.14772 -0.0463,2.904829 0,0.185415 0.10816,0.788013 0.13906,0.834366 0.47899,1.328805 -0.71076,-0.12361 -1.313356,-0.12361 -0.417183,0 -1.174293,0.12361 -0.75711,0.108158 -1.097037,0.108158 H 97.08507 q -1.066134,0 -1.715086,-0.834366 -0.571695,-0.772561 -0.571695,-1.869597 0,-1.050683 0.556244,-1.977756 0.6335,-1.050683 1.622378,-1.050683 0.185415,0 0.262671,0.01545 0.370829,0.06181 0.896171,0.185414 0.448085,0.154513 0.757109,0.478988 v -0.741658 q 0.01545,-0.09271 0.01545,-0.216317 0.01545,-1.328805 -0.309025,-2.364037 0.417183,-0.309024 0.896171,-0.741658 0.262671,-0.24722 0.67985,-0.540793 z m -2.549448,4.511756 q -0.664402,0 -1.004329,0.741659 -0.262671,0.556243 -0.262671,1.313353 0,1.205195 0.24722,1.715086 0.355378,0.710756 1.282451,0.710756 0.50989,0 1.004329,-0.07726 v -3.553781 q 0,-0.38628 -0.463536,-0.6335 -0.401732,-0.216317 -0.803464,-0.216317 z"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:15.45121956px;font-family:'Argos George';-inkscape-font-specification:'Argos George';fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.78100002;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:markers stroke fill"
+ id="path837" />
+ <path
+ d="m 104.74332,57.84628 1.9314,0.0309 v 4.697171 q 0,0.401732 0.33993,0.741659 h -1.8696 v -0.293574 q 0,-0.216317 0.0155,-0.324475 0,-0.185415 -0.0155,-0.24722 l -0.58714,0.07726 q -0.20087,0.0309 -1.32881,0.571696 -0.44808,0.216317 -0.6335,0.216317 -0.78801,0 -0.78801,-0.679854 v -3.631037 q 0,-0.463536 -0.55624,-1.158841 h 1.63783 q 0.29357,0.417183 0.29357,0.679854 l -0.0309,3.801 q 0,0.293573 0.20086,0.293573 0.24722,-0.07726 1.01978,-0.386281 0.50989,-0.200866 0.86527,-0.200866 v -3.306561 q 0,-0.309024 -0.49444,-0.880719 z"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:15.45121956px;font-family:'Argos George';-inkscape-font-specification:'Argos George';fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.78100002;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:markers stroke fill"
+ id="path839" />
+ <path
+ d="m 109.94097,58.139853 q 0.64895,-0.448085 0.6953,-0.478988 0.50989,-0.293573 0.92708,-0.293573 0.78801,0 0.78801,0.772561 0,0.463537 -0.30903,0.741659 -0.30902,0.278122 -0.77256,0.278122 0.29358,-0.339927 0.29358,-0.540793 0,-0.169964 -0.20087,-0.278122 -0.18541,-0.108159 -0.38628,-0.108159 -0.67985,0 -1.03523,0.896171 -0.24722,0.6335 -0.24722,1.467866 0,0.88072 0.30902,1.591476 0.38628,0.865268 0.43264,1.14339 -1.28245,0 -1.63783,-0.231768 -0.46354,-0.309025 -0.46354,-1.436964 v -2.843024 q 0,-0.432634 -0.29357,-0.865269 -0.13906,-0.200865 -0.29358,-0.355378 0.35538,-0.04635 1.18975,-0.04635 h 0.27812 q 0.44809,0 0.55624,0.216317 0.10816,0.200866 0.16997,0.370829 z"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:15.45121956px;font-family:'Argos George';-inkscape-font-specification:'Argos George';fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.78100002;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:markers stroke fill"
+ id="path841" />
+ </g>
+ <g
+ aria-label="T"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;line-height:125%;font-family:'Times New Roman';-inkscape-font-specification:'Times New Roman, ';letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ id="text924">
+ <path
+ d="m 67.520156,52.3661 q 0.127,0 2.286,0.127 0.8636,0.0508 1.4224,0.0508 1.955799,0 3.860799,-0.5842 -0.1524,1.397 -1.2192,2.2606 -1.0668,0.8636 -2.489199,0.8636 -1.1938,0 -3.9116,-1.016 -2.7178,-1.0414 -3.81,-1.0414 -1.9304,0 -1.9304,1.9304 0,0.8128 0.6096,1.3716 0.3556,0.3302 1.3208,0.7874 -0.508,0.889 -0.7874,0.889 -1.0414,-0.3556 -1.4478,-1.143 -0.3048,-0.5842 -0.3048,-1.3716 0,-1.27 0.508,-1.9812 0.508,-0.7112 1.7018,-1.143 0.4064,-0.1524 1.524,-0.1524 1.1938,0 2.159,0.0762 0.1016,0 0.508,0.0762 z m -4.318,9.1694 q 0,-1.5494 0.9652,-3.81 1.0414,-2.3622 2.2352,-3.175 -0.9652,2.9718 -0.9652,4.2672 0,2.3622 1.1684,4.3942 1.7018,2.9972 5.1054,2.9972 0.635,0 1.549399,-0.3556 0.9398,-0.381 1.397,-0.4064 -0.8128,1.27 -2.565399,2.1336 -1.7272,0.8636 -3.302,0.8636 -1.778,0 -3.5306,-1.8288 -2.0574,-2.1336 -2.0574,-5.08 z"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:25.39999962px;font-family:'Argos George';-inkscape-font-specification:'Argos George';fill:#ffffff;stroke-width:0.26458332px"
+ id="path844" />
+ </g>
+ </g>
+ </g>
+</svg>
diff --git a/content/learn/01.start/_index.md b/content/learn/01.start/_index.md
new file mode 100644
index 0000000..1741772
--- /dev/null
+++ b/content/learn/01.start/_index.md
@@ -0,0 +1,43 @@
+---
+menuTitle: "Starting"
+title: "Writing a story in Fate"
+weight: 1
+---
+* Create a folder for your story. This is not mandatory, but helps keeping
+ track of the created files.
+* Open up your favorite text editor, and write in `main.fate`:
+
+{{< fatecode >}}(fate_version 1)
+Once upon a time, starting a story with these words wasn't considered
+a cliche. Starting in a tavern might also not be seen as very
+original. Having the main character be an street orphan, raised by
+some mysterious sage all to end up as a mercenary with an uncommonly
+strong sense of honor probably isn't going to lead to any praises for
+novelty either. Maybe you should drink to that.
+(newline)
+Or maybe you shouldn't. This isn't your first mug. Not your second
+either. Drinking to forget that you are a stereotypical hero isn't
+going to solve anything. Worse, the alcoholic trait is part of the
+image.
+(newline)
+As you contemplate your own pointless description, your gaze leaves
+what turns out to be an already empty glass in your hand and finds the
+barman.
+(end)
+{{< /fatecode >}}
+
+This is a very minimal story in Fate. Let's look at what is it made of:
+
+* The `(fate_version 1)` line must be at the top of every file. It is just
+ there to inform the compiler of the used language version. It has no effect on
+ the output.
+* The text is mostly printed out as-is: newlines, tabs and spaces are
+ considered to be a single space. No matter how many of them follow. This
+ makes indentation have no effect on the output text. Furthermore such
+ characters preceding text are ignored.
+* `(newline)` inserts a newline in the output.
+* `(end)` signals the end of the story. It needs to be there.
+
+With this, you know how to make a static, purely textual story in Fate. Our poor
+protagonist needs a refill, so we need to introduce
+[Player Choices](/learn/choices) next.
diff --git a/content/learn/02.choices/_index.md b/content/learn/02.choices/_index.md
new file mode 100644
index 0000000..a5ba4d7
--- /dev/null
+++ b/content/learn/02.choices/_index.md
@@ -0,0 +1,71 @@
+---
+menuTitle: "Player Choices"
+title: "Asking the Player"
+weight: 2
+---
+In [the previous step](/learn/start), we saw a minimal text story written in Fate.
+Now, we need to interact with the player.
+
+There are three ways to interact with the player:
+* Asking them to choose between options.
+* Prompting them for an integer.
+* Prompting them for a string.
+
+The last two require notions that haven't been introduced yet, so let's give
+the player a simple choice instead:
+
+**main.fate:**
+{{< fatecode >}}(fate_version 1)
+Once upon a time, starting a story with these words wasn't considered
+a cliche. Starting in a tavern might also not be seen as very
+original. Having the main character be an street orphan, raised by
+some mysterious sage all to end up as a mercenary with an uncommonly
+strong sense of honor probably isn't going to lead to any praises for
+novelty either. Maybe you should drink to that.
+(newline)
+Or maybe you shouldn't. This isn't your first mug. Not your second
+either. Drinking to forget that you are a stereotypical hero isn't
+going to solve anything. Worse, the alcoholic trait is part of the
+image.
+(newline)
+As you contemplate your own pointless description, your gaze leaves
+what turns out to be an already empty glass in your hand and finds the
+barman.
+
+(player_choice
+ (
+ ( Ask the barman for a refill )
+ Staring straight at the barman, you raise your glass and
+ proclaim:
+ (newline)
+ "This soon-to-be world savior needs more booze!"
+ )
+ (
+ ( Fall asleep )
+ Deciding to break away from the expected storyline, you promptly
+ fall asleep.
+ )
+ (
+ ( Resolve whether P=NP )
+ Sadly, the output for this choice would require some concepts
+ that haven't been introduced yet, so let's never mention it
+ again.
+ )
+)
+
+(end)
+{{< /fatecode >}}
+
+In this version, the player is able to interact with the story: once
+`player_choice` is reached, the output stops and the player is presented with
+options. Here, three choices are available. A choice is made of a label and a
+list of instructions. The label is the text which is displayed to player (for
+example `Fall asleep`). The list of instructions is what will be performed if
+that choice is selected. Putting text where instructions are expected simply
+outputs the text. In fact, all the content of the previous step was
+instructions. Once a choice has been made and the instructions have been
+performed, the story continues past the `player_choice` construct.
+
+But something critical is missing. Indeed, how can you get a refill without
+money? Just how much money does our hero have? Will it be enough to quench that
+terrible thirst? Let's [introduce variables](/learn/variables).
diff --git a/content/learn/03.variables/default.md b/content/learn/03.variables/default.md
new file mode 100644
index 0000000..6c2cdf4
--- /dev/null
+++ b/content/learn/03.variables/default.md
@@ -0,0 +1,90 @@
+---
+menuTitle: Variables
+title: "Adding Variables"
+weight: 3
+---
+In [the previous step](/learn/start), we introduced player choices. Dynamic
+content is here, but it is not going far without variables.
+
+Fate is a strongly typed language, meaning that variables **must** be assigned
+a precise type and cannot deviate from it.
+
+Variables have to be declared before being used. Let us keep things simple for
+now, and declare variables using the `local` instruction. The alternative is
+`global`. The difference between the two being about access from other
+contexts, something that is introduced in the next chapter.
+
+We are trying to add a variable that corresponds to money. An `int` is thus
+appropriate.
+
+**main.fate:**
+
+ (fate_version 1)
+
+ (local int hero_money)
+ (local int price_of_booze)
+
+ (set hero_money 42)
+ (set price_of_booze 12)
+
+ Once upon a time, starting a story with these words wasn't considered
+ a cliche. Starting in a tavern might also not be seen as very
+ original. Having the main character be an street orphan, raised by
+ some mysterious sage all to end up as a mercenary with an uncommonly
+ strong sense of honor probably isn't going to lead to any praises for
+ novelty either. Maybe you should drink to that.
+ (newline)
+ Or maybe you shouldn't. This isn't your first mug. Not your second
+ either. Drinking to forget that you are a stereotypical hero isn't
+ going to solve anything. Worse, the alcoholic trait is part of the
+ image.
+ (newline)
+ As you contemplate your own pointless description, your gaze leaves
+ what turns out to be an already empty glass in your hand and finds the
+ barman.
+
+ (player_choice
+ (
+ ( Ask the barman for a refill )
+ Staring straight at the barman, you raise your glass and
+ proclaim:
+ (newline)
+ "This soon-to-be world savior needs more booze!"
+ (newline)
+ The barman's lack of reaction is disappointing, but seeing the
+ beer being poured does help improve the mood.
+ (newline)
+ Satisfied, you hand the barman (var price_of_booze) copper coins.
+ (set hero_money
+ (- (var hero_money) (var price_of_booze))
+ )
+ )
+ (
+ ( Fall asleep )
+ Deciding to break away from the expected storyline, you promptly
+ fall asleep.
+ (newline)
+ ...
+ (newline)
+ Upon waking up, your hard-trained reflexes inform you that
+ someone stole all your money.
+ (set hero_money 0)
+ )
+ )
+
+ (end)
+
+* `(local int hero_money)` declares an `int` variable with the name
+ `hero_money`.
+* `(set hero_money 42)` sets the value of the `hero_money` variable to 42.
+* `(var price_of_booze)` returns the current value of the `price_of_booze`
+ variable.
+* `(- (var hero_money) (var price_of_booze))` returns the result of subtracting
+ the value of `price_of_booze` to the value of `hero_money`. All operators
+ use a prefixed form.
+
+`local`, `set`, `player_choice`, and `end`, are instructions. Instructions do
+not return any value. Thus, they do not add to the printed text.
+
+Having to continue the story from within the `player_choice` structure is going
+to get tedious very fast. Let's [introduce sequences](/learn/sequences).
diff --git a/content/learn/04.sequences/default.md b/content/learn/04.sequences/default.md
new file mode 100644
index 0000000..cecbff8
--- /dev/null
+++ b/content/learn/04.sequences/default.md
@@ -0,0 +1,123 @@
+---
+menuTitle: Sequences
+title: "Introducing Sequences"
+weight: 4
+---
+In [the previous step](/learn/variables), we introduced variables. The story is
+starting to have branches, but writing them from within a `player_choice`
+construct is awkward. To resolve this, *sequences* are introduced.
+
+Sequences are named lists of instructions. They do *not* have to be defined
+before being used, but the definition must be found at some point. Since
+instructions do not return any value, neither do sequences.
+
+Sequences define their own context, meaning that `local` variables from outside
+the sequence cannot be accessed and, conversely, `local` variables from the
+sequence cannot be accessed outside of it.
+
+Entering a sequence can be done in two ways:
+* By visiting, in which case the sequence is executed and the story continues.
+* By jumping, in which case the sequence replaces the current story execution.
+
+When in doubt, prefer visiting to jumping, as the latter is mainly intended for
+optimization purposes.
+
+Sequences can be entered again from themselves, making recursion possible.
+
+Sequences can take parameters.
+
+
+**main.fate:**
+
+ (fate_version 1)
+
+ (global int hero_money)
+
+ (set hero_money 42)
+
+ Once upon a time, starting a story with these words wasn't considered
+ a cliche. Starting in a tavern might also not be seen as very
+ original. Having the main character be an street orphan, raised by
+ some mysterious sage all to end up as a mercenary with an uncommonly
+ strong sense of honor probably isn't going to lead to any praises for
+ novelty either. Maybe you should drink to that.
+ (newline)
+ Or maybe you shouldn't. This isn't your first mug. Not your second
+ either. Drinking to forget that you are a stereotypical hero isn't
+ going to solve anything. Worse, the alcoholic trait is part of the
+ image.
+ (newline)
+ As you contemplate your own pointless description, your gaze leaves
+ what turns out to be an already empty glass in your hand and finds the
+ barman.
+
+ (player_choice
+ (
+ ( Ask the barman for a refill )
+ (visit get_a_refill)
+ )
+ (
+ ( Fall asleep )
+ (jump_to fall_asleep)
+ )
+ )
+
+ (define_sequence pay ( (int cost) )
+ (set hero_money
+ (- (var hero_money) (var cost))
+ )
+ )
+
+ (define_sequence get_a_refill ()
+ (local int price_of_booze)
+
+ (set price_of_booze 12)
+
+ Staring straight at the barman, you raise your glass and proclaim:
+ (newline)
+ "This soon-to-be world savior needs more booze!"
+ (newline)
+ The barman's lack of reaction is disappointing, but seeing the beer
+ being poured does help improve the mood.
+ (newline)
+ Satisfied, you hand the barman (var price_of_booze) copper coins.
+ (visit pay (var price_of_booze))
+ )
+
+ (define_sequence fall_asleep ()
+ Deciding to break away from the expected storyline, you promptly
+ fall asleep.
+ (newline)
+ ...
+ (newline)
+ Upon waking up, your hard-trained reflexes inform you that someone
+ stole all your money.
+ (set hero_money 0)
+ (newline)
+ This set-back was more than you could take. You give up on this
+ barely coherent story.
+ (end)
+ )
+
+ (end)
+
+* `(visit get_a_refill)` makes a visit to the sequence `get_a_refill`. Since
+ that sequence does not take parameters, none need to be provided.
+* `(jump_to fall_asleep)` stops the execution of the main instruction list and
+ proceeds to using the sequence `fall_asleep` instead. Here again, no
+ arguments are expected by `fall_asleep`. Notice how the `fall_asleep` sequence
+ ends with `(end)`: since there is no return from it, the original `(end)`
+ would not be reached and thus a new one is required to end the story.
+* `(visit pay (var price_of_booze))` makes a visit to the `pay` sequence, which
+ does require a parameter.
+* `(global int hero_money)` has replaced `(local int hero_money)`, because that
+ variable needs to be accessible from within the sequences.
+* `(local int price_of_booze)` has been moved to the `get_a_refill` sequence,
+ as there is no reason to have it be defined across the whole story.
+* The `pay` sequence cannot directly access the `price_of_booze` variable, as
+ it is `local` and from another sequence, hence the use of a parameter to
+ communicate the correct amount.
+
+With this, the `player_choice` have become much more readable. However, the file
+itself is starting to become hard to read. The solution is then to [split the
+content into multiple files](/learn/files).
diff --git a/content/learn/05.files/default.md b/content/learn/05.files/default.md
new file mode 100644
index 0000000..da78206
--- /dev/null
+++ b/content/learn/05.files/default.md
@@ -0,0 +1,113 @@
+---
+menuTitle: Files
+title: "Splitting into Multiple Files"
+weight: 5
+---
+In [the previous step](/learn/sequences), we introduced sequences. This made
+branching the story easier, but having many sequences in a file made the flow
+difficult to read. To resolve this, the content is going to be split into
+multiple files.
+
+By using `(require path_to_file)`, the content of `path_to_file` is explored,
+but only if that file has not already been explored.
+
+* Create a new file, `data.fate`, with the following content:
+
+ (fate_version 1)
+
+ (global int hero_money)
+
+ (set hero_money 42)
+
+* Create a new file, `actions.fate`, with the following content:
+
+ (fate_version 1)
+
+ (require data.fate)
+
+ (define_sequence pay ( (int cost) )
+ (set hero_money
+ (- (var hero_money) (var cost))
+ )
+ )
+
+* Create a new file, `get_a_refill.fate`, with the following content:
+
+ (fate_version 1)
+
+ (require actions.fate)
+
+ (define_sequence get_a_refill ()
+ (local int price_of_booze)
+
+ (set price_of_booze 12)
+
+ Staring straight at the barman, you raise your glass and proclaim:
+ (newline)
+ "This soon-to-be world savior needs more booze!"
+ (newline)
+ The barman's lack of reaction is disappointing, but seeing the beer
+ being poured does help improve the mood.
+ (newline)
+ Satisfied, you hand the barman (var price_of_booze) copper coins.
+ (visit pay (var price_of_booze))
+ )
+
+* Create a new file, `falling_asleep.fate`, with the following content:
+ (fate_version 1)
+
+ (require data.fate)
+
+ (define_sequence fall_asleep ()
+ Deciding to break away from the expected storyline, you promptly
+ fall asleep.
+ (newline)
+ ...
+ (newline)
+ Upon waking up, your hard-trained reflexes inform you that someone
+ stole all your money.
+ (set hero_money 0)
+ (newline)
+ This set-back was more than you could take. You give up on this
+ barely coherent story.
+ (end)
+ )
+
+**main.fate:**
+
+ (fate_version 1)
+
+ Once upon a time, starting a story with these words wasn't considered
+ a cliche. Starting in a tavern might also not be seen as very
+ original. Having the main character be an street orphan, raised by
+ some mysterious sage all to end up as a mercenary with an uncommonly
+ strong sense of honor probably isn't going to lead to any praises for
+ novelty either. Maybe you should drink to that.
+ (newline)
+ Or maybe you shouldn't. This isn't your first mug. Not your second
+ either. Drinking to forget that you are a stereotypical hero isn't
+ going to solve anything. Worse, the alcoholic trait is part of the
+ image.
+ (newline)
+ As you contemplate your own pointless description, your gaze leaves
+ what turns out to be an already empty glass in your hand and finds the
+ barman.
+
+ (player_choice
+ (
+ ( Ask the barman for a refill )
+ (visit get_a_refill)
+ )
+ (
+ ( Fall asleep )
+ (jump_to fall_asleep)
+ )
+ )
+
+ (require get_a_refill.fate)
+ (require falling_asleep.fate)
+
+ (end)
+
+With this, the story is much more easy to follow. Let's continue by looking
+at [the actually-not-scary-at-all pointers](/learn/pointers).
diff --git a/content/learn/06.pointers/default.md b/content/learn/06.pointers/default.md
new file mode 100644
index 0000000..a4108bb
--- /dev/null
+++ b/content/learn/06.pointers/default.md
@@ -0,0 +1,171 @@
+---
+menuTitle: Pointers
+title: "Addressing Pointers"
+weight: 6
+---
+In [the previous step](/learn/files), we split the story into multiple files
+to make it more readable. Now, we'll see pointers, because they were needed for
+two features that were glossed over in what was presented before:
+* Using sequences as imperative procedures.
+* Prompting the user for content.
+
+A pointer is a value that indicates a location in memory where some
+data is stored. This can be used as a value that will tell some instruction
+where to put data.
+
+Pointers have types. For example, `(ptr int)` is the type corresponding to
+pointers to `int` data.
+
+To compute a pointer to a variable `v`, simply write `(ptr v)`.
+
+Given a pointer `p`, the variable being pointed to can be referred to using
+`(at p)`.
+
+**data.fate:**
+
+ (fate_version 1)
+
+ (global int hero_money)
+ (global string hero_name)
+
+ (set hero_money 42)
+
+**get_a_refill.fate:**
+
+ (fate_version 1)
+
+ (require data.fate)
+ (require actions.fate)
+
+ (define_sequence lower_price_of_booze
+ (
+ ((ptr int) price_pointer)
+ (int decrease)
+ )
+ Great! The price of booze just lowered from (at price_pointer)
+ (set (at price_pointer)
+ (-
+ (at price_pointer)
+ (var decrease)
+ )
+ )
+ to (at price_pointer)!
+ )
+
+ (define_sequence get_a_refill ()
+ (local int price_of_booze)
+
+ (set price_of_booze 12)
+
+ Staring straight at the barman, you raise your glass and proclaim:
+ (newline)
+ "This soon-to-be world savior needs more booze!"
+ (newline)
+ The barman's lack of reaction is disappointing, but seeing the beer
+ being poured does help improve the mood.
+ (newline)
+ Satisfied, you hand the barman (var price_of_booze) copper coins.
+ (visit pay (var price_of_booze))
+ (newline)
+ The barman sighs, then asks:
+ (prompt_string (ptr hero_name) 2 64 What is your name, then, hero?)
+ (var hero_name)?
+ (newline)
+ The barman looks surprised.
+ (newline)
+ (visit lower_price_of_booze (ptr price_of_booze) 4)
+ (newline)
+ "I have heard of you, (var hero_name)," the barman exclaims, "I have
+ a quest for you!"
+ (newline)
+ It's your turn to sigh.
+ (newline)
+ The barman hands you a bag, and says:
+ (newline)
+ "Take this pre-payment and head to the smithy."
+ (newline)
+ )
+
+* `(prompt_string (ptr hero_name) 2 64 What is your name, then, hero?)` prompts
+ the player with `What is your name, then, hero?` and expects a string input
+ with a size between `2` and `64` characters. This input is stored at `(ptr
+ hero_name)`, which means that `hero_name` takes that value.
+* The `lower_price_of_booze` sequence shows how pointers can be used to modify
+ variables outside of a sequence's range.
+* `(var price_of_booze)` is equivalent to `(at (ptr price_of_booze))`.
+
+Our hero, who'll obviously end up being the lost heir of some royal family,
+should already have good equipment. It would be useful to have a character
+sheet, so [let's create one](/learn/structures).
+
+----
+
+## Unchanged Files
+**actions.fate:**
+
+ (fate_version 1)
+
+ (require data.fate)
+
+ (define_sequence pay ( (int cost) )
+ (set hero_money
+ (- (var hero_money) (var cost))
+ )
+ )
+
+**falling_asleep.fate:**
+
+ (fate_version 1)
+
+ (require data.fate)
+
+ (define_sequence fall_asleep ()
+ Deciding to break away from the expected storyline, you promptly
+ fall asleep.
+ (newline)
+ ...
+ (newline)
+ Upon waking up, your hard-trained reflexes inform you that someone
+ stole all your money.
+ (set hero_money 0)
+ (newline)
+ This set-back was more than you could take. You give up on this
+ barely coherent story.
+ (end)
+ )
+
+**main.fate:**
+
+ (fate_version 1)
+
+ Once upon a time, starting a story with these words wasn't considered
+ a cliche. Starting in a tavern might also not be seen as very
+ original. Having the main character be an street orphan, raised by
+ some mysterious sage all to end up as a mercenary with an uncommonly
+ strong sense of honor probably isn't going to lead to any praises for
+ novelty either. Maybe you should drink to that.
+ (newline)
+ Or maybe you shouldn't. This isn't your first mug. Not your second
+ either. Drinking to forget that you are a stereotypical hero isn't
+ going to solve anything. Worse, the alcoholic trait is part of the
+ image.
+ (newline)
+ As you contemplate your own pointless description, your gaze leaves
+ what turns out to be an already empty glass in your hand and finds the
+ barman.
+
+ (player_choice
+ (
+ ( Ask the barman for a refill )
+ (visit get_a_refill)
+ )
+ (
+ ( Fall asleep )
+ (jump_to fall_asleep)
+ )
+ )
+
+ (require get_a_refill.fate)
+ (require falling_asleep.fate)
+
+ (end)
diff --git a/content/learn/07.structures/default.md b/content/learn/07.structures/default.md
new file mode 100644
index 0000000..a87af08
--- /dev/null
+++ b/content/learn/07.structures/default.md
@@ -0,0 +1,201 @@
+---
+menuTitle: Structures
+title: "Structuring the Data"
+weight: 7
+---
+In [the previous step](/learn/pointers), we added pointers, which made it
+possible to change data from other contexts/sequences. As we add more and more
+data, it becomes clear that some structuring is needed.
+
+Structures are types. Types must be declared before being used. This also
+prevents recursive types.
+
+The fields of a structure are initialized at the same time as the structure.
+
+Fields of a structure can be accessed in two ways: using the
+`struct_var.field_name` notation, or the `(field struct_var field_name)` one.
+If `struct_ptr` is a pointer to a structure, `struct_ptr.field_name` will also
+work.
+
+To set the value of a structure's fields, one can use the `set` instruction or,
+to set multiple fields at once, the `set_fields!` one. Note that omitting the
+`!` at the end of `set_fields` is also valid Fate, but performs a computation
+instead of a instruction: the structure is not modified, but a copy with the
+modifications performed is returned.
+
+**data.fate:**
+
+ (fate_version 1)
+
+ (declare_structure weapon
+ (text name)
+ (int attack)
+ (int precision)
+ )
+
+ (declare_structure armor
+ (text name)
+ (int defense)
+ )
+
+ (declare_structure character
+ (string name)
+ (int money)
+ (weapon weapon)
+ (armor armor)
+ )
+
+ (global character hero)
+
+ (set_fields! hero.weapon
+ (name (text "Legendary" sword))
+ (attack 3)
+ (precision 50)
+ )
+
+ (set_fields! hero.armor
+ (name (text "Refined" attire))
+ (defense 1)
+ )
+
+ (set hero.money 42)
+
+* `(text "Refined" attire)` generates a `text` value containing a textual
+ representation of the values passed as parameter. `"Refined" attire` is, by
+ itself, a `string`, and thus incompatible with the `text` field without a
+ conversion taking place.
+* Because `hero_money` and `hero_name` have been removed in favor of a
+ structure, they should be replaced in the other files by `hero.money` and
+ `hero.name`.
+
+With this, it is time for our hero to get some proper gear, [let's see what
+collection is available at the smithy](/learn/collections).
+
+----
+
+## (Mostly) Unchanged Files
+
+**get_a_refill.fate:**
+
+ (fate_version 1)
+
+ (require data.fate)
+ (require actions.fate)
+
+ (define_sequence lower_price_of_booze
+ (
+ ((ptr int) price_pointer)
+ (int decrease)
+ )
+ Great! The price of booze just lowered from (at price_pointer)
+ (set (at price_pointer)
+ (-
+ (at price_pointer)
+ (var decrease)
+ )
+ )
+ to (at price_pointer)!
+ )
+
+ (define_sequence get_a_refill ()
+ (local int price_of_booze)
+
+ (set price_of_booze 12)
+
+ Staring straight at the barman, you raise your glass and proclaim:
+ (newline)
+ "This soon-to-be world savior needs more booze!"
+ (newline)
+ The barman's lack of reaction is disappointing, but seeing the beer
+ being poured does help improve the mood.
+ (newline)
+ Satisfied, you hand the barman (var price_of_booze) copper coins.
+ (visit pay (var price_of_booze))
+ (newline)
+ The barman sighs, then asks:
+ (prompt_string (ptr hero.name) 2 64 What is your name, then, hero?)
+ (var hero.name)?
+ (newline)
+ The barman looks surprised.
+ (newline)
+ (visit lower_price_of_booze (ptr price_of_booze) 4)
+ (newline)
+ "I have heard of you, (var hero.name)," the barman exclaims, "I have
+ a quest for you!"
+ (newline)
+ It's your turn to sigh.
+ (newline)
+ The barman hands you a bag, and says:
+ (newline)
+ "Take this pre-payment and head to the smithy."
+ (newline)
+ )
+
+**actions.fate:**
+
+ (fate_version 1)
+
+ (require data.fate)
+
+ (define_sequence pay ( (int cost) )
+ (set hero_money
+ (- (var hero.money) (var cost))
+ )
+ )
+
+**falling_asleep.fate:**
+
+ (fate_version 1)
+
+ (require data.fate)
+
+ (define_sequence fall_asleep ()
+ Deciding to break away from the expected storyline, you promptly
+ fall asleep.
+ (newline)
+ ...
+ (newline)
+ Upon waking up, your hard-trained reflexes inform you that someone
+ stole all your money.
+ (set hero.money 0)
+ (newline)
+ This set-back was more than you could take. You give up on this
+ barely coherent story.
+ (end)
+ )
+
+**main.fate:**
+
+ (fate_version 1)
+
+ Once upon a time, starting a story with these words wasn't considered
+ a cliche. Starting in a tavern might also not be seen as very
+ original. Having the main character be an street orphan, raised by
+ some mysterious sage all to end up as a mercenary with an uncommonly
+ strong sense of honor probably isn't going to lead to any praises for
+ novelty either. Maybe you should drink to that.
+ (newline)
+ Or maybe you shouldn't. This isn't your first mug. Not your second
+ either. Drinking to forget that you are a stereotypical hero isn't
+ going to solve anything. Worse, the alcoholic trait is part of the
+ image.
+ (newline)
+ As you contemplate your own pointless description, your gaze leaves
+ what turns out to be an already empty glass in your hand and finds the
+ barman.
+
+ (player_choice
+ (
+ ( Ask the barman for a refill )
+ (visit get_a_refill)
+ )
+ (
+ ( Fall asleep )
+ (jump_to fall_asleep)
+ )
+ )
+
+ (require get_a_refill.fate)
+ (require falling_asleep.fate)
+
+ (end)
diff --git a/content/learn/08.collections/default.md b/content/learn/08.collections/default.md
new file mode 100644
index 0000000..b4bae98
--- /dev/null
+++ b/content/learn/08.collections/default.md
@@ -0,0 +1,408 @@
+---
+menuTitle: Collections
+title: "Collections"
+weight: 8
+---
+In [the previous step](/learn/structures), we added structures, which made
+having some amounts of data more manageable. Still, what about when we need to
+have hundreds of elements? Collections are here to manage that.
+
+Fate has three types of collections:
+* Sets, which only contain a single instance of each element, can only be used
+ to store elements of one of the comparable types (`string`, `text`, `int`,
+ `float`, `bool`) and pointers. The elements are automatically sorted in
+ ascending order.
+* Lists, which can be made for one of any type.
+* Cons, which are pairs of two elements of any types.
+
+There are [quite a few computations](/fate_v1/computations/collections) and
+[instructions](/fate_v1/instructions/collections) available to handle
+collections.
+
+Let's add a new file, `smithy_inventory.fate`:
+ (fate_version 1)
+
+ (require data.fate)
+
+ (global (list (cons weapon int)) smithy_weapons)
+ (global (list (cons weapon int)) smithy_armors)
+
+ (add!
+ (cons
+ (set_fields (default weapon)
+ (name (text An Iron Rod))
+ (attack 10)
+ (precision 70)
+ )
+ 176
+ )
+ smithy_weapons
+ )
+ (add!
+ (cons
+ (set_fields (default weapon)
+ (name (text A Magnificient Brick))
+ (attack 6)
+ (precision 90)
+ )
+ 110
+ )
+ smithy_weapons
+ )
+
+ (add!
+ (cons
+ (set_fields (default armor)
+ (name (text A raincoat?!))
+ (defense 7)
+ )
+ 160
+ )
+ smithy_armors
+ )
+ (add!
+ (cons
+ (set_fields (default armor)
+ (name (text A nice cape))
+ (defense 3)
+ )
+ 50
+ )
+ smithy_armors
+ )
+
+We'll also need the actual smithy scene, so let's put in another file,
+`smithy.fate`.
+
+**NOTE:** Don't worry if it looks awful at the moment, the next chapters are
+going to introduce a lot of things to make it *much*, *much* easier to write.
+
+**smithy.fate:**
+
+ (fate_version 1)
+
+ (require smithy_inventory.fate)
+
+ (define_sequence visit_smithy ()
+ ;; This thing is going to show up every time, which isn't great.
+ As you approach the smithy, you notice that no one's there. All the
+ wares are out for selling. It's almost as if this story didn't need
+ more examples of lengthy dialogues.
+ (newline)
+ ;; We'll want to start here the next time we enter this sequence.
+ You have (var hero.money) coins.
+ (newline)
+ What will you look at?
+ (player_choice
+ (
+ ( Let's see the weapons )
+ (jump_to see_weapons)
+ )
+ (
+ ( Let's see the armors )
+ (jump_to see_armors)
+ )
+ (
+ ( Nothing, let's go back to the bar )
+ )
+ )
+ )
+
+ (define_sequence see_weapons ()
+ ;; We'll soon replace this mess with something way better.
+
+ (local text weapon_a_label)
+ (local text weapon_b_label)
+
+ (visit get_weapon_label
+ (access smithy_weapons 0)
+ (ptr weapon_a_label)
+ )
+ (visit get_weapon_label
+ (access smithy_weapons 1)
+ (ptr weapon_b_label)
+ )
+
+ (player_choice
+ (
+ ( (var weapon_a_label) )
+ (visit buy_weapon (access smithy_weapons 0))
+ (jump_to visit_smithy)
+ )
+ (
+ ( (var weapon_a_label) )
+ (visit buy_weapon (access smithy_weapons 1))
+ (jump_to visit_smithy)
+ )
+ (
+ ( Nevermind )
+ (jump_to visit_smithy)
+ )
+ )
+ )
+
+ (define_sequence see_armors ()
+ ;; We'll soon replace this mess with something way better.
+
+ (local text armor_a_label)
+ (local text armor_b_label)
+
+ (visit get_armor_label
+ (access smithy_armors 0)
+ (ptr armor_a_label)
+ )
+ (visit get_armor_label
+ (access smithy_armors 1)
+ (ptr armor_b_label)
+ )
+
+ (player_choice
+ (
+ ( (var armor_a_label) )
+ (visit buy_armor (access smithy_armors 0))
+ (jump_to visit_smithy)
+ )
+ (
+ ( (var armor_a_label) )
+ (visit buy_armor (access smithy_armors 1))
+ (jump_to visit_smithy)
+ )
+ (
+ ( Nevermind )
+ (jump_to visit_smithy)
+ )
+ )
+ )
+
+ ;; A terrible way to get labels
+ (define_sequence get_weapon_label
+ (
+ ((cons weapon int) weapon_offer)
+ ((ptr text) label)
+ )
+ (local weapon weapon)
+ (local int price)
+
+ (set weapon (car weapon_offer))
+ (set price (cdr weapon_offer))
+
+ (set (at label)
+ (
+ Buy "(var weapon.name)" \(attack: (var weapon.attack),
+ precision: (var weapon.precision)\) for (var price) coins.
+ )
+ )
+ )
+
+ ;; A terrible way to get labels
+ (define_sequence get_armor_label
+ (
+ ((cons armor int) armor_offer)
+ ((ptr text) label)
+ )
+ (local armor armor)
+ (local int price)
+
+ (set armor (car armor_offer))
+ (set price (cdr armor_offer))
+
+ (set (at label)
+ (
+ Buy "(var armor.name)" \(defense: (var armor.defense)\),
+ for (var price) coins.
+ )
+ )
+ )
+
+ (define_sequence buy_weapon ( ((cons weapon int) weapon) )
+ ;; We can't even deny a sell yet...
+ (set hero.weapon (car weapon))
+ Equipped (var hero.weapon.name).
+ (newline)
+ )
+
+ (define_sequence buy_armor ( ((cons armor int) armor) )
+ ;; We can't even deny a sell yet...
+ (set hero.armor (car armor))
+ Equipped (var hero.armor.name).
+ (newline)
+ )
+
+* `(list (cons weapon int))` indicates a list of `weapon` and `int` pairs.
+* `(add! something smithy_weapons)` adds `something` to the `smithy_weapons`
+ collection. Without the `!`, this would be a computation returning a copy of
+ `smithy_weapons` with the added weapon, but no modification of the
+ `smithy_weapons` collection itself would occur.
+* `(cons something something_else)` creates a pair with these two elements.
+* `(car weapon_offer)` returns the first element of the `weapon_offer` pair.
+* `(cdr weapon_offer)` returns the second element of the `weapon_offer` pair.
+
+Overall, the `smithy.fate` file is a mess. Let's start cleaning it up. We'll
+use loops, conditionals, and lambda functions to make it much cleaner. Let's
+start with the least expected one: [lambda functions](/learn/lambdas).
+
+----
+
+## Unchanged Files
+
+**data.fate:**
+
+ (fate_version 1)
+
+ (declare_structure weapon
+ (text name)
+ (int attack)
+ (int precision)
+ )
+
+ (declare_structure armor
+ (text name)
+ (int defense)
+ )
+
+ (declare_structure character
+ (string name)
+ (int money)
+ (weapon weapon)
+ (armor armor)
+ )
+
+ (global character hero)
+
+ (set_fields! hero.weapon
+ (name (text "Legendary" sword))
+ (attack 3)
+ (precision 50)
+ )
+
+ (set_fields! hero.armor
+ (name (text "Refined" attire))
+ (defense 1)
+ )
+
+ (set hero.money 42)
+
+**get_a_refill.fate:**
+
+ (fate_version 1)
+
+ (require data.fate)
+ (require actions.fate)
+
+ (define_sequence lower_price_of_booze
+ (
+ ((ptr int) price_pointer)
+ (int decrease)
+ )
+ Great! The price of booze just lowered from (at price_pointer)
+ (set (at price_pointer)
+ (-
+ (at price_pointer)
+ (var decrease)
+ )
+ )
+ to (at price_pointer)!
+ )
+
+ (define_sequence get_a_refill ()
+ (local int price_of_booze)
+
+ (set price_of_booze 12)
+
+ Staring straight at the barman, you raise your glass and proclaim:
+ (newline)
+ "This soon-to-be world savior needs more booze!"
+ (newline)
+ The barman's lack of reaction is disappointing, but seeing the beer
+ being poured does help improve the mood.
+ (newline)
+ Satisfied, you hand the barman (var price_of_booze) copper coins.
+ (visit pay (var price_of_booze))
+ (newline)
+ The barman sighs, then asks:
+ (prompt_string (ptr hero.name) 2 64 What is your name, then, hero?)
+ (var hero.name)?
+ (newline)
+ The barman looks surprised.
+ (newline)
+ (visit lower_price_of_booze (ptr price_of_booze) 4)
+ (newline)
+ "I have heard of you, (var hero.name)," the barman exclaims, "I have
+ a quest for you!"
+ (newline)
+ It's your turn to sigh.
+ (newline)
+ The barman hands you a bag, and says:
+ (newline)
+ "Take this pre-payment and head to the smithy."
+ (newline)
+ )
+
+**actions.fate:**
+
+ (fate_version 1)
+
+ (require data.fate)
+
+ (define_sequence pay ( (int cost) )
+ (set hero_money
+ (- (var hero.money) (var cost))
+ )
+ )
+
+**falling_asleep.fate:**
+
+ (fate_version 1)
+
+ (require data.fate)
+
+ (define_sequence fall_asleep ()
+ Deciding to break away from the expected storyline, you promptly
+ fall asleep.
+ (newline)
+ ...
+ (newline)
+ Upon waking up, your hard-trained reflexes inform you that someone
+ stole all your money.
+ (set hero.money 0)
+ (newline)
+ This set-back was more than you could take. You give up on this
+ barely coherent story.
+ (end)
+ )
+
+**main.fate:**
+
+ (fate_version 1)
+
+ Once upon a time, starting a story with these words wasn't considered
+ a cliche. Starting in a tavern might also not be seen as very
+ original. Having the main character be an street orphan, raised by
+ some mysterious sage all to end up as a mercenary with an uncommonly
+ strong sense of honor probably isn't going to lead to any praises for
+ novelty either. Maybe you should drink to that.
+ (newline)
+ Or maybe you shouldn't. This isn't your first mug. Not your second
+ either. Drinking to forget that you are a stereotypical hero isn't
+ going to solve anything. Worse, the alcoholic trait is part of the
+ image.
+ (newline)
+ As you contemplate your own pointless description, your gaze leaves
+ what turns out to be an already empty glass in your hand and finds the
+ barman.
+
+ (player_choice
+ (
+ ( Ask the barman for a refill )
+ (visit get_a_refill)
+ )
+ (
+ ( Fall asleep )
+ (jump_to fall_asleep)
+ )
+ )
+
+ (require get_a_refill.fate)
+ (require falling_asleep.fate)
+
+ (end)
diff --git a/content/learn/09.lambdas/default.md b/content/learn/09.lambdas/default.md
new file mode 100644
index 0000000..a2e6c24
--- /dev/null
+++ b/content/learn/09.lambdas/default.md
@@ -0,0 +1,366 @@
+---
+menuTitle: Lambda Functions
+title: "Lambda Functions"
+weight: 9
+---
+In [the previous step](/learn/collections), we added collections, which made
+having large amounts of data possible. We also ended up with a really ugly file,
+`smithy.fate`, which had way too much code to be readable. We'll start by
+removing the label generation sequences. Instead, we'll use lambda functions.
+
+A lambda function is computation description that can be stored for later use.
+It can also take parameters. Since it's a computation, it cannot alter the
+memory by itself, nor can it contain any instructions.
+
+**smithy.fate:**
+
+ (fate_version 1)
+
+ (require smithy_inventory.fate)
+
+ (global (lambda text ((cons weapon int))) get_weapon_offer_label)
+ (global (lambda text ((cons armor int))) get_armor_offer_label)
+
+ (set get_weapon_offer_label
+ (lambda
+ ( ((cons weapon int) offer) )
+ (let
+ (
+ (weapon (car offer))
+ (price (cdr offer))
+ )
+ (text
+ Buy "(var weapon.name)" \(attack: (var weapon.attack),
+ precision: (var weapon.precision)\) for (var price) coins.
+ )
+ )
+ )
+ )
+
+ (set get_armor_offer_label
+ (lambda
+ ( ((cons armor int) offer) )
+ (let
+ (
+ (armor (car offer))
+ (price (cdr offer))
+ )
+ (text
+ Buy "(var armor.name)" \(defense: (var armor.defense)\),
+ for (var price) coins.
+ )
+ )
+ )
+ )
+
+ (define_sequence visit_smithy ()
+ ;; This thing is going to show up every time, which isn't great.
+ As you approach the smithy, you notice that no one's there. All the
+ wares are out for selling. It's almost as if this story didn't need
+ more examples of lengthy dialogues.
+ (newline)
+ ;; We'll want to start here the next time we enter this sequence.
+ You have (var hero.money) coins.
+ (newline)
+ What will you look at?
+ (player_choice
+ (
+ ( Let's see the weapons )
+ (jump_to see_weapons)
+ )
+ (
+ ( Let's see the armors )
+ (jump_to see_armors)
+ )
+ (
+ ( Nothing, let's go back to the bar )
+ )
+ )
+ )
+
+ (define_sequence see_weapons ()
+ ;; Still can be improved.
+ (player_choice
+ (
+ ( (eval get_weapon_offer_label (access smithy_weapons 0)) )
+ (visit buy_weapon (access smithy_weapons 0))
+ (jump_to visit_smithy)
+ )
+ (
+ ( (eval get_weapon_offer_label (access smithy_weapons 1)) )
+ (visit buy_weapon (access smithy_weapons 1))
+ (jump_to visit_smithy)
+ )
+ (
+ ( Nevermind )
+ (jump_to visit_smithy)
+ )
+ )
+ )
+
+ (define_sequence see_armors ()
+ ;; Still can be improved.
+ (player_choice
+ (
+ ( (eval get_armor_offer_label (access smithy_armors 0)) )
+ (visit buy_armor (access smithy_armors 0))
+ (jump_to visit_smithy)
+ )
+ (
+ ( (eval get_armor_offer_label (access smithy_armors 1)) )
+ (visit buy_armor (access smithy_armors 1))
+ (jump_to visit_smithy)
+ )
+ (
+ ( Nevermind )
+ (jump_to visit_smithy)
+ )
+ )
+ )
+
+ (define_sequence buy_weapon ( ((cons weapon int) weapon) )
+ ;; We can't even deny a sell yet...
+ (set hero.weapon (car weapon))
+ Equipped (var hero.weapon.name).
+ (newline)
+ )
+
+ (define_sequence buy_armor ( ((cons armor int) armor) )
+ ;; We can't even deny a sell yet...
+ (set hero.armor (car armor))
+ Equipped (var hero.armor.name).
+ (newline)
+ )
+
+* `(lambda return_type (param_type0 param_type1 ...))` is the type corresponding
+ to a lambda function returning a value of type `return_type` and taking as
+ parameters values of types `param_type0`, `param_type1`, ...
+* `(eval variable_name param0 param1 ...)` computes and returns the result of
+ the lambda function stored in `variable_name` by giving it as parameter the
+ values `param0`, `param1`, ...
+* `(let ( (name0 val0) ... ) computation)` computes and returns `computation` as
+ if `name0` was a defined variable of value `val0`.
+
+Lambda functions are *very* useful. They can be used to manipulate lists in many
+ways. They can also be used to abstract away some complicated computation.
+
+This was a first step toward cleaning up `smithy.fate`. Next, we'll use
+[conditions](/learn/conditions) to improve things further.
+
+----
+
+## Unchanged Files
+
+**data.fate:**
+
+ (fate_version 1)
+
+ (declare_structure weapon
+ (text name)
+ (int attack)
+ (int precision)
+ )
+
+ (declare_structure armor
+ (text name)
+ (int defense)
+ )
+
+ (declare_structure character
+ (string name)
+ (int money)
+ (weapon weapon)
+ (armor armor)
+ )
+
+ (global character hero)
+
+ (set_fields! hero.weapon
+ (name (text "Legendary" sword))
+ (attack 3)
+ (precision 50)
+ )
+
+ (set_fields! hero.armor
+ (name (text "Refined" attire))
+ (defense 1)
+ )
+
+ (set hero.money 42)
+
+**get_a_refill.fate:**
+
+ (fate_version 1)
+
+ (require data.fate)
+ (require actions.fate)
+
+ (define_sequence lower_price_of_booze
+ (
+ ((ptr int) price_pointer)
+ (int decrease)
+ )
+ Great! The price of booze just lowered from (at price_pointer)
+ (set (at price_pointer)
+ (-
+ (at price_pointer)
+ (var decrease)
+ )
+ )
+ to (at price_pointer)!
+ )
+
+ (define_sequence get_a_refill ()
+ (local int price_of_booze)
+
+ (set price_of_booze 12)
+
+ Staring straight at the barman, you raise your glass and proclaim:
+ (newline)
+ "This soon-to-be world savior needs more booze!"
+ (newline)
+ The barman's lack of reaction is disappointing, but seeing the beer
+ being poured does help improve the mood.
+ (newline)
+ Satisfied, you hand the barman (var price_of_booze) copper coins.
+ (visit pay (var price_of_booze))
+ (newline)
+ The barman sighs, then asks:
+ (prompt_string (ptr hero.name) 2 64 What is your name, then, hero?)
+ (var hero.name)?
+ (newline)
+ The barman looks surprised.
+ (newline)
+ (visit lower_price_of_booze (ptr price_of_booze) 4)
+ (newline)
+ "I have heard of you, (var hero.name)," the barman exclaims, "I have
+ a quest for you!"
+ (newline)
+ It's your turn to sigh.
+ (newline)
+ The barman hands you a bag, and says:
+ (newline)
+ "Take this pre-payment and head to the smithy."
+ (newline)
+ )
+
+**actions.fate:**
+
+ (fate_version 1)
+
+ (require data.fate)
+
+ (define_sequence pay ( (int cost) )
+ (set hero_money
+ (- (var hero.money) (var cost))
+ )
+ )
+
+**falling_asleep.fate:**
+
+ (fate_version 1)
+
+ (require data.fate)
+
+ (define_sequence fall_asleep ()
+ Deciding to break away from the expected storyline, you promptly
+ fall asleep.
+ (newline)
+ ...
+ (newline)
+ Upon waking up, your hard-trained reflexes inform you that someone
+ stole all your money.
+ (set hero.money 0)
+ (newline)
+ This set-back was more than you could take. You give up on this
+ barely coherent story.
+ (end)
+ )
+
+**main.fate:**
+
+ (fate_version 1)
+
+ Once upon a time, starting a story with these words wasn't considered
+ a cliche. Starting in a tavern might also not be seen as very
+ original. Having the main character be an street orphan, raised by
+ some mysterious sage all to end up as a mercenary with an uncommonly
+ strong sense of honor probably isn't going to lead to any praises for
+ novelty either. Maybe you should drink to that.
+ (newline)
+ Or maybe you shouldn't. This isn't your first mug. Not your second
+ either. Drinking to forget that you are a stereotypical hero isn't
+ going to solve anything. Worse, the alcoholic trait is part of the
+ image.
+ (newline)
+ As you contemplate your own pointless description, your gaze leaves
+ what turns out to be an already empty glass in your hand and finds the
+ barman.
+
+ (player_choice
+ (
+ ( Ask the barman for a refill )
+ (visit get_a_refill)
+ )
+ (
+ ( Fall asleep )
+ (jump_to fall_asleep)
+ )
+ )
+
+ (require get_a_refill.fate)
+ (require falling_asleep.fate)
+
+ (end)
+
+**smithy_inventory.fate:**
+ (fate_version 1)
+
+ (require data.fate)
+
+ (global (list (cons weapon int)) smithy_weapons)
+ (global (list (cons weapon int)) smithy_armors)
+
+ (add!
+ (cons
+ (set_fields (default weapon)
+ (name (text An Iron Rod))
+ (attack 10)
+ (precision 70)
+ )
+ 176
+ )
+ smithy_weapons
+ )
+ (add!
+ (cons
+ (set_fields (default weapon)
+ (name (text A Magnificient Brick))
+ (attack 6)
+ (precision 90)
+ )
+ 110
+ )
+ smithy_weapons
+ )
+
+ (add!
+ (cons
+ (set_fields (default armor)
+ (name (text A raincoat?!))
+ (defense 7)
+ )
+ 160
+ )
+ smithy_armors
+ )
+ (add!
+ (cons
+ (set_fields (default armor)
+ (name (text A nice cape))
+ (defense 3)
+ )
+ 50
+ )
+ smithy_armors
+ )
diff --git a/content/learn/10.conditions/default.md b/content/learn/10.conditions/default.md
new file mode 100644
index 0000000..8a4f339
--- /dev/null
+++ b/content/learn/10.conditions/default.md
@@ -0,0 +1,402 @@
+---
+menuTitle: Conditionals
+title: "Expressing Conditions"
+weight: 10
+---
+In [the previous step](/learn/lambdas), we added lambda functions, which made
+it possible to store computation descriptions for later use. The `smithy.fate`
+is still a mess, and we couldn't handle the hero not having enough money for a
+purchase. Let's add conditions to our story.
+
+Fate has quite a few conditional constructs. `if_else`, `switch`, and `cond`
+can be used both as instruction and computation. `if` is only for instructions.
+* `if_else` selects between two options according to a given `bool` value.
+* `switch` has a list of options, each of which is associated to a value.
+ It selects the first listed option whose value is equal to the targeted
+ value. When used as a computation, a default option with no associated value
+ must be provided.
+* `cond` has a list of options, each of which is associated to a `bool`
+ computation. The first listed option for which the computation yields `(true)`
+ is chosen. In the case of a computation, the last option is chosen even as a
+ default value. With instructions, if no option has its condition satisfied,
+ nothing happens.
+* `if` is only for instructions, and applies its content only if the condition
+ is verified.
+
+All of these can be used within a `player_choice` to control what options are
+available.
+
+**smithy.fate:**
+
+ (fate_version 1)
+
+ (require smithy_inventory.fate)
+
+ (global (lambda text ((cons weapon int))) get_weapon_offer_label)
+ (global (lambda text ((cons armor int))) get_armor_offer_label)
+
+ (set get_weapon_offer_label
+ (lambda
+ ( ((cons weapon int) offer) )
+ (let
+ (
+ (weapon (car offer))
+ (price (cdr offer))
+ )
+ (text
+ Buy "(var weapon.name)" \(attack: (var weapon.attack),
+ precision: (var weapon.precision)\) for (var price) coins.
+ )
+ )
+ )
+ )
+
+ (set get_armor_offer_label
+ (lambda
+ ( ((cons armor int) offer) )
+ (let
+ (
+ (armor (car offer))
+ (price (cdr offer))
+ )
+ (text
+ Buy "(var armor.name)" \(defense: (var armor.defense)\),
+ for (var price) coins.
+ )
+ )
+ )
+ )
+
+ (global bool has_visited_smithy)
+
+ (set has_visited_smithy (false))
+
+ (define_sequence visit_smithy ()
+ (if (not (var has_visited_smithy))
+ As you approach the smithy, you notice that no one's there. All
+ the wares are out for selling. It's almost as if this story
+ didn't need more examples of lengthy dialogues.
+ (newline)
+ (set has_visited_smithy (true))
+ )
+ You have (var hero.money) coins.
+ (newline)
+ What will you look at?
+ (player_choice
+ (
+ ( Let's see the weapons )
+ (jump_to see_weapons)
+ )
+ (
+ ( Let's see the armors )
+ (jump_to see_armors)
+ )
+ (
+ ( Nothing, let's go back to the bar )
+ )
+ )
+ )
+
+ (define_sequence see_weapons ()
+ ;; Still can be improved.
+ (player_choice
+ (
+ ( (eval get_weapon_offer_label (access smithy_weapons 0)) )
+ (visit buy_weapon (access smithy_weapons 0))
+ (jump_to visit_smithy)
+ )
+ (
+ ( (eval get_weapon_offer_label (access smithy_weapons 1)) )
+ (visit buy_weapon (access smithy_weapons 1))
+ (jump_to visit_smithy)
+ )
+ (
+ ( Nevermind )
+ (jump_to visit_smithy)
+ )
+ )
+ )
+
+ (define_sequence see_armors ()
+ ;; Still can be improved.
+ (player_choice
+ (
+ ( (eval get_armor_offer_label (access smithy_armors 0)) )
+ (visit buy_armor (access smithy_armors 0))
+ (jump_to visit_smithy)
+ )
+ (
+ ( (eval get_armor_offer_label (access smithy_armors 1)) )
+ (visit buy_armor (access smithy_armors 1))
+ (jump_to visit_smithy)
+ )
+ (
+ ( Nevermind )
+ (jump_to visit_smithy)
+ )
+ )
+ )
+
+ (define_sequence buy_weapon ( ((cons weapon int) weapon) )
+ ;; We can't even deny a sell yet...
+ (local int money_after)
+
+ (set money_after (- (var hero.money) (cdr weapon)))
+
+ (if_else (< (var money_after) 0)
+ (
+ You can't afford that.
+ (newline)
+ You would need (abs (var money_after)) more coins.
+ )
+ (
+ (set hero.weapon (car weapon))
+ (set hero.money (var money_after))
+ Equipped (var hero.weapon.name).
+ )
+ )
+ (newline)
+ )
+
+ (define_sequence buy_armor ( ((cons armor int) armor) )
+ ;; We can't even deny a sell yet...
+ (local int money_after)
+
+ (set money_after (- (var hero.money) (cdr armor)))
+
+ (if_else (< (var money_after) 0)
+ (
+ You can't afford that.
+ (newline)
+ You would need (abs (var money_after)) more coins.
+ )
+ (
+ (set hero.armor (car armor))
+ (set hero.money (var money_after))
+ Equipped (var hero.armor.name).
+ )
+ )
+ (newline)
+ )
+
+
+This was a first step toward cleaning up `smithy.fate`. Next, we'll use
+[conditions](/learn/conditions) to improve things further.
+
+----
+
+## Unchanged Files
+
+**data.fate:**
+
+ (fate_version 1)
+
+ (declare_structure weapon
+ (text name)
+ (int attack)
+ (int precision)
+ )
+
+ (declare_structure armor
+ (text name)
+ (int defense)
+ )
+
+ (declare_structure character
+ (string name)
+ (int money)
+ (weapon weapon)
+ (armor armor)
+ )
+
+ (global character hero)
+
+ (set_fields! hero.weapon
+ (name (text "Legendary" sword))
+ (attack 3)
+ (precision 50)
+ )
+
+ (set_fields! hero.armor
+ (name (text "Refined" attire))
+ (defense 1)
+ )
+
+ (set hero.money 42)
+
+**get_a_refill.fate:**
+
+ (fate_version 1)
+
+ (require data.fate)
+ (require actions.fate)
+
+ (define_sequence lower_price_of_booze
+ (
+ ((ptr int) price_pointer)
+ (int decrease)
+ )
+ Great! The price of booze just lowered from (at price_pointer)
+ (set (at price_pointer)
+ (-
+ (at price_pointer)
+ (var decrease)
+ )
+ )
+ to (at price_pointer)!
+ )
+
+ (define_sequence get_a_refill ()
+ (local int price_of_booze)
+
+ (set price_of_booze 12)
+
+ Staring straight at the barman, you raise your glass and proclaim:
+ (newline)
+ "This soon-to-be world savior needs more booze!"
+ (newline)
+ The barman's lack of reaction is disappointing, but seeing the beer
+ being poured does help improve the mood.
+ (newline)
+ Satisfied, you hand the barman (var price_of_booze) copper coins.
+ (visit pay (var price_of_booze))
+ (newline)
+ The barman sighs, then asks:
+ (prompt_string (ptr hero.name) 2 64 What is your name, then, hero?)
+ (var hero.name)?
+ (newline)
+ The barman looks surprised.
+ (newline)
+ (visit lower_price_of_booze (ptr price_of_booze) 4)
+ (newline)
+ "I have heard of you, (var hero.name)," the barman exclaims, "I have
+ a quest for you!"
+ (newline)
+ It's your turn to sigh.
+ (newline)
+ The barman hands you a bag, and says:
+ (newline)
+ "Take this pre-payment and head to the smithy."
+ (newline)
+ )
+
+**actions.fate:**
+
+ (fate_version 1)
+
+ (require data.fate)
+
+ (define_sequence pay ( (int cost) )
+ (set hero_money
+ (- (var hero.money) (var cost))
+ )
+ )
+
+**falling_asleep.fate:**
+
+ (fate_version 1)
+
+ (require data.fate)
+
+ (define_sequence fall_asleep ()
+ Deciding to break away from the expected storyline, you promptly
+ fall asleep.
+ (newline)
+ ...
+ (newline)
+ Upon waking up, your hard-trained reflexes inform you that someone
+ stole all your money.
+ (set hero.money 0)
+ (newline)
+ This set-back was more than you could take. You give up on this
+ barely coherent story.
+ (end)
+ )
+
+**main.fate:**
+
+ (fate_version 1)
+
+ Once upon a time, starting a story with these words wasn't considered
+ a cliche. Starting in a tavern might also not be seen as very
+ original. Having the main character be an street orphan, raised by
+ some mysterious sage all to end up as a mercenary with an uncommonly
+ strong sense of honor probably isn't going to lead to any praises for
+ novelty either. Maybe you should drink to that.
+ (newline)
+ Or maybe you shouldn't. This isn't your first mug. Not your second
+ either. Drinking to forget that you are a stereotypical hero isn't
+ going to solve anything. Worse, the alcoholic trait is part of the
+ image.
+ (newline)
+ As you contemplate your own pointless description, your gaze leaves
+ what turns out to be an already empty glass in your hand and finds the
+ barman.
+
+ (player_choice
+ (
+ ( Ask the barman for a refill )
+ (visit get_a_refill)
+ )
+ (
+ ( Fall asleep )
+ (jump_to fall_asleep)
+ )
+ )
+
+ (require get_a_refill.fate)
+ (require falling_asleep.fate)
+
+ (end)
+
+**smithy_inventory.fate:**
+ (fate_version 1)
+
+ (require data.fate)
+
+ (global (list (cons weapon int)) smithy_weapons)
+ (global (list (cons weapon int)) smithy_armors)
+
+ (add!
+ (cons
+ (set_fields (default weapon)
+ (name (text An Iron Rod))
+ (attack 10)
+ (precision 70)
+ )
+ 176
+ )
+ smithy_weapons
+ )
+ (add!
+ (cons
+ (set_fields (default weapon)
+ (name (text A Magnificient Brick))
+ (attack 6)
+ (precision 90)
+ )
+ 110
+ )
+ smithy_weapons
+ )
+
+ (add!
+ (cons
+ (set_fields (default armor)
+ (name (text A raincoat?!))
+ (defense 7)
+ )
+ 160
+ )
+ smithy_armors
+ )
+ (add!
+ (cons
+ (set_fields (default armor)
+ (name (text A nice cape))
+ (defense 3)
+ )
+ 50
+ )
+ smithy_armors
+ )
diff --git a/content/learn/_index.md b/content/learn/_index.md
new file mode 100644
index 0000000..62706fc
--- /dev/null
+++ b/content/learn/_index.md
@@ -0,0 +1,8 @@
+---
+title: "Starting"
+menuTitle: "Learn"
+chapter: true
+---
+# Writing a story in Fate.
+This chapter provides an example of narrative written in Fate. Concepts are
+introduced progressively.
diff --git a/content/made_with_tonkadur/_index.md b/content/made_with_tonkadur/_index.md
new file mode 100644
index 0000000..4e1a654
--- /dev/null
+++ b/content/made_with_tonkadur/_index.md
@@ -0,0 +1,3 @@
+---
+title: Made with Tonkadur
+---
diff --git a/content/made_with_tonkadur/closed_source/_index.md b/content/made_with_tonkadur/closed_source/_index.md
new file mode 100644
index 0000000..5bb1e01
--- /dev/null
+++ b/content/made_with_tonkadur/closed_source/_index.md
@@ -0,0 +1,5 @@
+---
+title: Closed Source Games using Tonkadur
+menuTitle: Closed Source Games
+---
+!!!! This page **is** available, there's just nothing to list in there for now.
diff --git a/content/made_with_tonkadur/open_source/_index.md b/content/made_with_tonkadur/open_source/_index.md
new file mode 100644
index 0000000..0cc4bf9
--- /dev/null
+++ b/content/made_with_tonkadur/open_source/_index.md
@@ -0,0 +1,5 @@
+---
+menuTitle: Open Source Games
+title: Open Source Games using Tonkadur
+---
+!!!! This page **is** available, there's just nothing to list in there for now.
diff --git a/content/setup/_index.md b/content/setup/_index.md
new file mode 100644
index 0000000..1aad3fc
--- /dev/null
+++ b/content/setup/_index.md
@@ -0,0 +1,75 @@
+---
+title: "Setup"
+---
+# Setting Up Tonkadur
+There are two parts to set up: the compiler, and the interpreter. The compiler
+is provided and does not require any modification. The interpreter depends on
+the software you wish to integrate Tonkadur to. Examples of interpreters are
+available, but expect some modifications to be required. This should not prove
+to be difficult however, as the whole approach is design with the idea of
+keeping the interpreter small and simple.
+
+## Setting Up the Compiler
+
+### Installation
+**Dependencies:**
+* Java
+
+Download the latest release of Tonkadur on [this
+page](https://github.com/nsensfel/tonkadur/releases).
+
+### Use
+The Tonkadur compiler is invoked using `java -jar tonkadur.jar [option] <file>`.
+`java -jar tonkadur.jar` will yield the complete list of valid options.
+
+`<file>` corresponds to a Fate file. By default, the generated Wyrd file will
+have the same name with a suffix.
+
+## Setting Up the Interpreter
+It is recommended to look up existing interpreters. Not only might you be able
+to just use an existing one, but having examples of interpreters will help you
+create your own if you can't find one that fits your needs.
+
+**Known open source Wyrd interpreters:**
+* [nsensfel/tonkadur-python-interpreter](https://github.com/nsensfel/tonkadur-python-interpreter): A minimal Python3 interpreter, with JSON input.
+
+### Creating Your Own Interpreter
+If you end up needing to create your own interpreter, here are some clues on how
+to proceed.
+
+A Wyrd interpreter keeps track of:
+* **The Memory:** typically a mapping of strings to values. These values may be
+of any Wyrd type.
+* **The Program Counter:** an integer corresponding to the next Wyrd instruction
+to execute.
+* **Available Choices:** A list of `RICH_TEXT`.
+* **Last Chosen Choice:** Index of the last chosen choice.
+* **The Code:** A list of instructions.
+
+Additionally, the following can be kept track of:
+* **Types:** The default value for each type, making it easier to create new
+ memory elements of a given type.
+* **Allocated Data Counter:** The number of dynamically allocated memory
+ elements, making it easy to generate unique names for new memory elements.
+
+A few pitfalls:
+* **Copy values on assignment:** `(set_value a b)` does not make `a` become `b`,
+ but rather assigns a copy of the current value of `b` to `a`.
+* **Addresses may be already computed:** An `address` computation can take an
+ address as its `address` parameter. In other words, while in most cases an
+ `address` computation is a string that must be put in a list to become an
+ actual address, it can also sometimes already be a list and must then stay
+ unchanged.
+* **Beware of references:** When performing a computation that accesses memory
+ elements, be sure not to actually be returning the memory element itself after
+ it has been modified, but rather a modified copy of the memory element. This
+ is only problematic for memory elements whose type is modified by reference in
+ the interpreter's programming language. An example would be relative address
+ computation, which appends an element to a list. Computing a relative address
+ must not modify the base address, it only returns a list equivalent to the
+ base address but with an extra element.
+
+A set of tests can found on [this
+page](https://github.com/nsensfel/tonkadur/tree/master/data/tests), and will let
+you test your interpreter more easily. They have to be compiled to Wyrd first,
+however.
diff --git a/content/wyrd_v1/_index.md b/content/wyrd_v1/_index.md
new file mode 100644
index 0000000..4d902e2
--- /dev/null
+++ b/content/wyrd_v1/_index.md
@@ -0,0 +1,56 @@
+---
+menuTitle: Wyrd
+title: Wyrd (Version 1)
+---
+Wyrd is the language in which the narrative is given to the game engine. It is
+purposefully kept small and simple to facilitate porting Tonkadur to a new
+engine.
+
+The memory is seen as a table mapping strings to values. These values may also
+be tables. Thus a reference is a list of strings corresponding to a move from
+one table to the next.
+
+The program is a list of instructions. These instructions may use computations
+as parameters. They sometimes use hard-coded strings parameters as well.
+Instructions cannot take instructions as parameters. Instructions are not
+associated to any value.
+
+An integer, called _Program Counter_ is used to indicate the current
+instruction. In most cases, this integer is incremented by one after every
+instruction. There is an instruction to modify the value of the Program Counter,
+which allows conditional jumps and loops to be described.
+
+Computations are values and operations returning values. These are solely used
+as parameters of instructions. They do not alter memory (with one exception)
+and do not interact with the Program Counter in any way. An execution cannot be
+stopped during the evaluation of a computation: it is part of its parent
+instruction and is thus completed exactly when that instruction is performed.
+Computations may _read_ from the memory, as they may need to fetch the value
+associated with an address or traverse tables. All computations have a return
+type.
+
+Wyrd does not have the notion of sequence or that lambda functions. It does not
+even associate player choices with lists of actions. It's all done by carefully
+managing the Program Counter.
+
+Lambda functions are stored as an `INT` corresponding to a line in the program.
+
+## Types
+* `ADDRESS` (or `POINTER`, or `REFERENCE`), a list of `STRING` (note: not a
+ `STRING COLLECTION`).
+* `BOOL`. This should be changed to `BOOL` soon, for consistency's sake.
+* `[SOMETHING] COLLECTION`, table mapping `STRING` to `[SOMETHING]`.
+* `FLOAT`.
+* `INT`.
+* `RICH TEXT`, a list of `STRINGS` with attributes attached.
+* `STRING`.
+* `STRUCTURE` (or `DICTIONARY`), table mapping `STRING` to values of any type.
+* `{String}`, a hard-coded string.
+
+#### Aliases sometimes used to refer to types
+* `? ADDRESS`: an `ADDRESS` pointing to a particular type.
+* `BASE TYPE`: `INT`, `FLOAT`, `BOOL`, `STRING`.
+* `COMPARABLE`: `INT`, `FLOAT`, `BOOL`, `STRING`, `RICH TEXT`, `ADDRESS`.
+* `COLLECTION`: any `? COLLECTION`.
+* `COMPUTATION`: any type.
+* `NUMBER`: `INT` or `FLOAT`.
diff --git a/content/wyrd_v1/computations/_index.md b/content/wyrd_v1/computations/_index.md
new file mode 100644
index 0000000..028a82e
--- /dev/null
+++ b/content/wyrd_v1/computations/_index.md
@@ -0,0 +1,99 @@
+---
+title: Computations
+---
+This page presents all the computations that can be performed in Wyrd.
+Computations may access the current memory, but, with one exception, do not
+change it. The one exception is `(new t)`. All computations return values.
+The terms 'value' and 'computation' are interchangeable.
+
+## CONSTANT
+{{< fatecode >}}(const [BASE TYPE] {string}){{< /fatecode >}}
+Returns the `[BASE TYPE]` represented by `{string}`.
+
+## CAST
+{{< fatecode >}}(cast [COMPUTATION] [BASE TYPE]){{< /fatecode >}}
+Converts `[COMPUTATION]` to `[BASE TYPE]`, returns the result.
+
+Note:
+* Converting from `FLOAT` to `INT` returns `floor(v)`.
+* Converting from `BOOL` to `STRING` yields either `True` or `False`.
+
+The following must be supported:
+* `[FLOAT]` to `[FLOAT]`, `[INT]`, and `[STRING]`.
+* `[INT]` to `[FLOAT]`, `[INT]`, and `[STRING]`.
+* `[BOOL]` to `[BOOL]` and `[STRING]`.
+* `[STRING]` to `[BOOL]` (`true` and `false`), `[FLOAT]`, `[INT]`, and`[STRING]`.
+
+## IF-ELSE
+{{< fatecode >}}(if_else [BOOL] [C0 = COMPUTATION] [C1 = COMPUTATION]){{< /fatecode >}}
+Returns `C0` if `[BOOL]` holds _true_, `C1` otherwise. `C0` and `C1` both
+have the same type.
+
+## EQUALS
+{{< fatecode >}}(equals [C0 = COMPUTATION] [C1 = COMPUTATION]){{< /fatecode >}}
+Returns a `BOOL`, _true_ if `C0` and `C1` hold the same value. `C0` and `C1`
+are both of the same type.
+
+## MATHEMATICAL OPERATORS
+{{< fatecode >}}(divide [C0 = NUMBER] [C1 = NUMBER]){{< /fatecode >}}
+
+{{< fatecode >}}(minus [C0 = NUMBER] [C1 = NUMBER]){{< /fatecode >}}
+
+{{< fatecode >}}(plus [C0 = NUMBER] [C1 = NUMBER]){{< /fatecode >}}
+
+{{< fatecode >}}(power [C0 = NUMBER] [C1 = NUMBER]){{< /fatecode >}}
+
+{{< fatecode >}}(times [C0 = NUMBER] [C1 = NUMBER]){{< /fatecode >}}
+The operation returns a value of the same type as `C0` and `C1` (both `C0` and
+`C1` are also of the same type). Thus, `(divide C0 C1)` is an integer division
+(the remainder is discarded) if `C0` and `C1` are of type `INT`, and a standard
+division if they are of type `FLOAT`.
+
+{{< fatecode >}}(rand [C0 = INT] [C1 = INT]){{< /fatecode >}}
+Returns a random value between `C0` and `C1`, inclusive. Raises a runtime error
+if `C0 > C1`.
+
+## MATHEMATICAL COMPARISON
+{{< fatecode >}}(less_than [C0 = COMPARABLE] [C1 = COMPARABLE]){{< /fatecode >}}
+Returns a `[BOOL]` indicating if `C0` is strictly less than `C1`.
+`C0` and `C1` are both of the same type.
+
+## LOGICAL OPERATORS
+{{< fatecode >}}(and [C0 = BOOL] [C1 = BOOL]){{< /fatecode >}}
+
+{{< fatecode >}}(not [C0 = BOOL]){{< /fatecode >}}
+
+## SIZE
+{{< fatecode >}}(size [COLLECTION ADDRESS]){{< /fatecode >}}
+Returns the number of elements held by the collection at
+`[COLLECTION ADDRESS]`.
+
+## REFERENCES
+{{< fatecode >}}(address [COMPUTATION]){{< /fatecode >}}
+Returns an `ADDRESS` to the memory element at address `[COMPUTATION]`. Raises a
+runtime error if `[COMPUTATION]` is not a memory element.
+
+{{< fatecode >}}(relative_address <R0 = (COLLECTION|STRUCTURE) ADDRESS> [STRING]){{< /fatecode >}}
+Returns a `REFERENCE` to member `[STRING]` of `R0`.
+
+{{< fatecode >}}(value_of [ADDRESS]){{< /fatecode >}}
+Returns the value held at the memory location `[ADDRESS]`.
+
+{{< fatecode >}}(new [TYPE]){{< /fatecode >}}
+Returns an `[TYPE] ADDRESS` to a newly allocated memory element of
+type `[TYPE]`.
+
+## RICH TEXT
+{{< fatecode >}}(newline){{< /fatecode >}}
+Returns a `RICH TEXT` value corresponding to a newline.
+
+{{< fatecode >}}(rich_text [S0 = STRING] ... [SN = STRING]){{< /fatecode >}}
+Returns a single value `RICH TEXT` representing the elements `S0` ... `S1`.
+
+{{< fatecode >}}(add_rich_text_effect ({string} [V0 = COMPUTATION] ... [VN = COMPUTATION]) [RICH TEXT]){{< /fatecode >}}
+Returns a `RICH TEXT` value of `[RICH TEXT]` with the given effect enabled.
+
+## LAST USER CHOICE
+{{< fatecode >}}(get_last_user_choice){{< /fatecode >}}
+Returns the number corresponding to the option last chosen by the user in a
+`(resolve_choices)`, or `-1` if there is no such value.
diff --git a/content/wyrd_v1/extensions/_index.md b/content/wyrd_v1/extensions/_index.md
new file mode 100644
index 0000000..a21559c
--- /dev/null
+++ b/content/wyrd_v1/extensions/_index.md
@@ -0,0 +1,4 @@
+---
+title: Extensions
+---
+Not available in Version 1.
diff --git a/content/wyrd_v1/instructions/_index.md b/content/wyrd_v1/instructions/_index.md
new file mode 100644
index 0000000..9d43a5a
--- /dev/null
+++ b/content/wyrd_v1/instructions/_index.md
@@ -0,0 +1,75 @@
+---
+title: Instructions
+---
+This page presents all the instructions that can be performed in Wyrd.
+Instructions do not return values. With one exception, all instructions increase
+the Program Counter by 1.
+
+
+## ADD CHOICE
+{{< fatecode >}}(add_choice [RICH TEXT]){{< /fatecode >}}
+Adds a new option for the next `resolve_choices` instruction. The new option
+presents the player with `[RICH TEXT]`.
+
+## INTEGER PROMPT
+{{< fatecode >}}(prompt_integer [INT REFERENCE] [MIN = INT] [MAX = INT] [RICH TEXT]){{< /fatecode >}}
+
+Prompts the user for an integer between `[MIN]` and `[MAX]` by displaying the
+message `[RICH TEXT]`. The result is stored in `[INT REFERENCE]`.
+
+## STRING PROMPT
+{{< fatecode >}}(prompt_string [STRING REFERENCE] [MIN = INT] [MAX = INT] [RICH TEXT]){{< /fatecode >}}
+
+Prompts the user for a string of size between `[MIN]` and `[MAX]` by displaying
+the message `[RICH TEXT]`. The result is stored in `[STRING REFERENCE]`.
+
+
+## ASSERT
+{{< fatecode >}}(assert [BOOL] [RICH TEXT]){{< /fatecode >}}
+If `[BOOL]` isn't _true_, raise a runtime error containing `[RICH TEXT]`.
+
+
+## DISPLAY
+{{< fatecode >}}(display [RICH TEXT]){{< /fatecode >}}
+Displays `[RICH TEXT]` to the player.
+
+
+## END
+{{< fatecode >}}(end){{< /fatecode >}}
+Marks the end of the narration. Interrupts the execution.
+
+
+## EVENT CALL
+{{< fatecode >}}(event_call {string} [C0 = COMPUTATION] ... [CN = COMPUTATION]){{< /fatecode >}}
+Interrupts execution, informs the interpreter that the given event `{String}`
+was triggered with the parameters `C0 ... CN`.
+
+
+## REMOVE
+{{< fatecode >}}(remove [ADDRESS]){{< /fatecode >}}
+The memory at `[ADDRESS]` is freed.
+
+
+## RESOLVE CHOICES
+{{< fatecode >}}(resolve_choices){{< /fatecode >}}
+Present the player with all options that where added using `add_choice` since
+the last `resolve_choices`. The execution is paused and should be resumed by
+the interpreter setting the Program Counter according to the chosen option.
+
+
+## SET PC
+{{< fatecode >}}(set_pc [INT]){{< /fatecode >}}
+Sets the Program Counter to `[INT]`. The program counter is not automatically
+increased by 1 in this case.
+
+
+## SET VALUE
+{{< fatecode >}}(set_value [ADDRESS] [COMPUTATION]){{< /fatecode >}}
+Sets the memory pointed by `[ADDRESS]` to `[COMPUTATION]`.
+`[COMPUTATION]` is passed by value, not reference (i.e. no aliasing can occur
+without it being done explicitly through pointers).
+
+## INITIALIZE MEMORY ELEMENT
+{{< fatecode >}}(initialize [ADDRESS] [TYPE]){{< /fatecode >}}
+Initializes a memory element at `[ADDRESS]` with the default value for the type
+`[TYPE]`.
diff --git a/layouts/shortcodes/fatecode.html b/layouts/shortcodes/fatecode.html
new file mode 100644
index 0000000..77bd69c
--- /dev/null
+++ b/layouts/shortcodes/fatecode.html
@@ -0,0 +1,2 @@
+<!-- fatecode-->
+<pre><code class="language-scheme match-braces rainbow-braces line-numbers">{{.Inner}}</code></pre>
diff --git a/layouts/shortcodes/rawhtml.html b/layouts/shortcodes/rawhtml.html
new file mode 100644
index 0000000..b90bea2
--- /dev/null
+++ b/layouts/shortcodes/rawhtml.html
@@ -0,0 +1,2 @@
+<!-- raw html -->
+{{.Inner}}
diff --git a/static/css/prism.css b/static/css/prism.css
new file mode 100755
index 0000000..066264f
--- /dev/null
+++ b/static/css/prism.css
@@ -0,0 +1,321 @@
+/* PrismJS 1.22.0
+https://prismjs.com/download.html#themes=prism-tomorrow&languages=scheme&plugins=line-highlight+line-numbers+toolbar+copy-to-clipboard+match-braces */
+/**
+ * prism.js tomorrow night eighties for JavaScript, CoffeeScript, CSS and HTML
+ * Based on https://github.com/chriskempson/tomorrow-theme
+ * @author Rose Pritchard
+ */
+
+code[class*="language-"],
+pre[class*="language-"] {
+ color: #ccc;
+ background: none;
+ font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
+ font-size: 1em;
+ text-align: left;
+ white-space: pre;
+ word-spacing: normal;
+ word-break: normal;
+ word-wrap: normal;
+ line-height: 1.5;
+
+ -moz-tab-size: 4;
+ -o-tab-size: 4;
+ tab-size: 4;
+
+ -webkit-hyphens: none;
+ -moz-hyphens: none;
+ -ms-hyphens: none;
+ hyphens: none;
+
+}
+
+/* Code blocks */
+pre[class*="language-"] {
+ padding: 1em;
+ margin: .5em 0;
+ overflow: auto;
+}
+
+:not(pre) > code[class*="language-"],
+pre[class*="language-"] {
+ background: #2d2d2d;
+}
+
+/* Inline code */
+:not(pre) > code[class*="language-"] {
+ padding: .1em;
+ border-radius: .3em;
+ white-space: normal;
+}
+
+.token.comment,
+.token.block-comment,
+.token.prolog,
+.token.doctype,
+.token.cdata {
+ color: #999;
+}
+
+.token.punctuation {
+ color: #ccc;
+}
+
+.token.tag,
+.token.attr-name,
+.token.namespace,
+.token.deleted {
+ color: #e2777a;
+}
+
+.token.function-name {
+ color: #6196cc;
+}
+
+.token.boolean,
+.token.number,
+.token.function {
+ color: #f08d49;
+}
+
+.token.property,
+.token.class-name,
+.token.constant,
+.token.symbol {
+ color: #f8c555;
+}
+
+.token.selector,
+.token.important,
+.token.atrule,
+.token.keyword,
+.token.builtin {
+ color: #cc99cd;
+}
+
+.token.string,
+.token.char,
+.token.attr-value,
+.token.regex,
+.token.variable {
+ color: #7ec699;
+}
+
+.token.operator,
+.token.entity,
+.token.url {
+ color: #67cdcc;
+}
+
+.token.important,
+.token.bold {
+ font-weight: bold;
+}
+.token.italic {
+ font-style: italic;
+}
+
+.token.entity {
+ cursor: help;
+}
+
+.token.inserted {
+ color: green;
+}
+
+pre[data-line] {
+ position: relative;
+ padding: 1em 0 1em 3em;
+}
+
+.line-highlight {
+ position: absolute;
+ left: 0;
+ right: 0;
+ padding: inherit 0;
+ margin-top: 1em; /* Same as .prism’s padding-top */
+
+ background: hsla(24, 20%, 50%,.08);
+ background: linear-gradient(to right, hsla(24, 20%, 50%,.1) 70%, hsla(24, 20%, 50%,0));
+
+ pointer-events: none;
+
+ line-height: inherit;
+ white-space: pre;
+}
+
+ .line-highlight:before,
+ .line-highlight[data-end]:after {
+ content: attr(data-start);
+ position: absolute;
+ top: .4em;
+ left: .6em;
+ min-width: 1em;
+ padding: 0 .5em;
+ background-color: hsla(24, 20%, 50%,.4);
+ color: hsl(24, 20%, 95%);
+ font: bold 65%/1.5 sans-serif;
+ text-align: center;
+ vertical-align: .3em;
+ border-radius: 999px;
+ text-shadow: none;
+ box-shadow: 0 1px white;
+ }
+
+ .line-highlight[data-end]:after {
+ content: attr(data-end);
+ top: auto;
+ bottom: .4em;
+ }
+
+.line-numbers .line-highlight:before,
+.line-numbers .line-highlight:after {
+ content: none;
+}
+
+pre[id].linkable-line-numbers span.line-numbers-rows {
+ pointer-events: all;
+}
+pre[id].linkable-line-numbers span.line-numbers-rows > span:before {
+ cursor: pointer;
+}
+pre[id].linkable-line-numbers span.line-numbers-rows > span:hover:before {
+ background-color: rgba(128, 128, 128, .2);
+}
+
+pre[class*="language-"].line-numbers {
+ position: relative;
+ padding-left: 3.8em;
+ counter-reset: linenumber;
+}
+
+pre[class*="language-"].line-numbers > code {
+ position: relative;
+ white-space: inherit;
+}
+
+.line-numbers .line-numbers-rows {
+ position: absolute;
+ pointer-events: none;
+ top: 0;
+ font-size: 100%;
+ left: -3.8em;
+ width: 3em; /* works for line-numbers below 1000 lines */
+ letter-spacing: -1px;
+ border-right: 1px solid #999;
+
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+
+}
+
+ .line-numbers-rows > span {
+ display: block;
+ counter-increment: linenumber;
+ }
+
+ .line-numbers-rows > span:before {
+ content: counter(linenumber);
+ color: #999;
+ display: block;
+ padding-right: 0.8em;
+ text-align: right;
+ }
+
+div.code-toolbar {
+ position: relative;
+}
+
+div.code-toolbar > .toolbar {
+ position: absolute;
+ top: .3em;
+ right: .2em;
+ transition: opacity 0.3s ease-in-out;
+ opacity: 0;
+}
+
+div.code-toolbar:hover > .toolbar {
+ opacity: 1;
+}
+
+/* Separate line b/c rules are thrown out if selector is invalid.
+ IE11 and old Edge versions don't support :focus-within. */
+div.code-toolbar:focus-within > .toolbar {
+ opacity: 1;
+}
+
+div.code-toolbar > .toolbar .toolbar-item {
+ display: inline-block;
+}
+
+div.code-toolbar > .toolbar a {
+ cursor: pointer;
+}
+
+div.code-toolbar > .toolbar button {
+ background: none;
+ border: 0;
+ color: inherit;
+ font: inherit;
+ line-height: normal;
+ overflow: visible;
+ padding: 0;
+ -webkit-user-select: none; /* for button */
+ -moz-user-select: none;
+ -ms-user-select: none;
+}
+
+div.code-toolbar > .toolbar a,
+div.code-toolbar > .toolbar button,
+div.code-toolbar > .toolbar span {
+ color: #bbb;
+ font-size: .8em;
+ padding: 0 .5em;
+ background: #f5f2f0;
+ background: rgba(224, 224, 224, 0.2);
+ box-shadow: 0 2px 0 0 rgba(0,0,0,0.2);
+ border-radius: .5em;
+}
+
+div.code-toolbar > .toolbar a:hover,
+div.code-toolbar > .toolbar a:focus,
+div.code-toolbar > .toolbar button:hover,
+div.code-toolbar > .toolbar button:focus,
+div.code-toolbar > .toolbar span:hover,
+div.code-toolbar > .toolbar span:focus {
+ color: inherit;
+ text-decoration: none;
+}
+
+.token.punctuation.brace-hover,
+.token.punctuation.brace-selected {
+ outline: solid 1px;
+}
+
+.rainbow-braces .token.punctuation.brace-level-1,
+.rainbow-braces .token.punctuation.brace-level-5,
+.rainbow-braces .token.punctuation.brace-level-9 {
+ color: #E50;
+ opacity: 1;
+}
+.rainbow-braces .token.punctuation.brace-level-2,
+.rainbow-braces .token.punctuation.brace-level-6,
+.rainbow-braces .token.punctuation.brace-level-10 {
+ color: #0B3;
+ opacity: 1;
+}
+.rainbow-braces .token.punctuation.brace-level-3,
+.rainbow-braces .token.punctuation.brace-level-7,
+.rainbow-braces .token.punctuation.brace-level-11 {
+ color: #26F;
+ opacity: 1;
+}
+.rainbow-braces .token.punctuation.brace-level-4,
+.rainbow-braces .token.punctuation.brace-level-8,
+.rainbow-braces .token.punctuation.brace-level-12 {
+ color: #E0E;
+ opacity: 1;
+}
+
diff --git a/static/js/highlight.pack.js b/static/js/highlight.pack.js
new file mode 100755
index 0000000..2c9deb0
--- /dev/null
+++ b/static/js/highlight.pack.js
@@ -0,0 +1,9 @@
+/* PrismJS 1.22.0
+https://prismjs.com/download.html#themes=prism-tomorrow&languages=scheme&plugins=line-highlight+line-numbers+toolbar+copy-to-clipboard+match-braces */
+var _self="undefined"!=typeof window?window:"undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope?self:{},Prism=function(u){var c=/\blang(?:uage)?-([\w-]+)\b/i,n=0,_={manual:u.Prism&&u.Prism.manual,disableWorkerMessageHandler:u.Prism&&u.Prism.disableWorkerMessageHandler,util:{encode:function e(n){return n instanceof M?new M(n.type,e(n.content),n.alias):Array.isArray(n)?n.map(e):n.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/\u00a0/g," ")},type:function(e){return Object.prototype.toString.call(e).slice(8,-1)},objId:function(e){return e.__id||Object.defineProperty(e,"__id",{value:++n}),e.__id},clone:function t(e,r){var a,n;switch(r=r||{},_.util.type(e)){case"Object":if(n=_.util.objId(e),r[n])return r[n];for(var i in a={},r[n]=a,e)e.hasOwnProperty(i)&&(a[i]=t(e[i],r));return a;case"Array":return n=_.util.objId(e),r[n]?r[n]:(a=[],r[n]=a,e.forEach(function(e,n){a[n]=t(e,r)}),a);default:return e}},getLanguage:function(e){for(;e&&!c.test(e.className);)e=e.parentElement;return e?(e.className.match(c)||[,"none"])[1].toLowerCase():"none"},currentScript:function(){if("undefined"==typeof document)return null;if("currentScript"in document)return document.currentScript;try{throw new Error}catch(e){var n=(/at [^(\r\n]*\((.*):.+:.+\)$/i.exec(e.stack)||[])[1];if(n){var t=document.getElementsByTagName("script");for(var r in t)if(t[r].src==n)return t[r]}return null}},isActive:function(e,n,t){for(var r="no-"+n;e;){var a=e.classList;if(a.contains(n))return!0;if(a.contains(r))return!1;e=e.parentElement}return!!t}},languages:{extend:function(e,n){var t=_.util.clone(_.languages[e]);for(var r in n)t[r]=n[r];return t},insertBefore:function(t,e,n,r){var a=(r=r||_.languages)[t],i={};for(var l in a)if(a.hasOwnProperty(l)){if(l==e)for(var o in n)n.hasOwnProperty(o)&&(i[o]=n[o]);n.hasOwnProperty(l)||(i[l]=a[l])}var s=r[t];return r[t]=i,_.languages.DFS(_.languages,function(e,n){n===s&&e!=t&&(this[e]=i)}),i},DFS:function e(n,t,r,a){a=a||{};var i=_.util.objId;for(var l in n)if(n.hasOwnProperty(l)){t.call(n,l,n[l],r||l);var o=n[l],s=_.util.type(o);"Object"!==s||a[i(o)]?"Array"!==s||a[i(o)]||(a[i(o)]=!0,e(o,t,l,a)):(a[i(o)]=!0,e(o,t,null,a))}}},plugins:{},highlightAll:function(e,n){_.highlightAllUnder(document,e,n)},highlightAllUnder:function(e,n,t){var r={callback:t,container:e,selector:'code[class*="language-"], [class*="language-"] code, code[class*="lang-"], [class*="lang-"] code'};_.hooks.run("before-highlightall",r),r.elements=Array.prototype.slice.apply(r.container.querySelectorAll(r.selector)),_.hooks.run("before-all-elements-highlight",r);for(var a,i=0;a=r.elements[i++];)_.highlightElement(a,!0===n,r.callback)},highlightElement:function(e,n,t){var r=_.util.getLanguage(e),a=_.languages[r];e.className=e.className.replace(c,"").replace(/\s+/g," ")+" language-"+r;var i=e.parentElement;i&&"pre"===i.nodeName.toLowerCase()&&(i.className=i.className.replace(c,"").replace(/\s+/g," ")+" language-"+r);var l={element:e,language:r,grammar:a,code:e.textContent};function o(e){l.highlightedCode=e,_.hooks.run("before-insert",l),l.element.innerHTML=l.highlightedCode,_.hooks.run("after-highlight",l),_.hooks.run("complete",l),t&&t.call(l.element)}if(_.hooks.run("before-sanity-check",l),!l.code)return _.hooks.run("complete",l),void(t&&t.call(l.element));if(_.hooks.run("before-highlight",l),l.grammar)if(n&&u.Worker){var s=new Worker(_.filename);s.onmessage=function(e){o(e.data)},s.postMessage(JSON.stringify({language:l.language,code:l.code,immediateClose:!0}))}else o(_.highlight(l.code,l.grammar,l.language));else o(_.util.encode(l.code))},highlight:function(e,n,t){var r={code:e,grammar:n,language:t};return _.hooks.run("before-tokenize",r),r.tokens=_.tokenize(r.code,r.grammar),_.hooks.run("after-tokenize",r),M.stringify(_.util.encode(r.tokens),r.language)},tokenize:function(e,n){var t=n.rest;if(t){for(var r in t)n[r]=t[r];delete n.rest}var a=new i;return z(a,a.head,e),function e(n,t,r,a,i,l){for(var o in r)if(r.hasOwnProperty(o)&&r[o]){var s=r[o];s=Array.isArray(s)?s:[s];for(var u=0;u<s.length;++u){if(l&&l.cause==o+","+u)return;var c=s[u],g=c.inside,f=!!c.lookbehind,h=!!c.greedy,d=c.alias;if(h&&!c.pattern.global){var v=c.pattern.toString().match(/[imsuy]*$/)[0];c.pattern=RegExp(c.pattern.source,v+"g")}for(var p=c.pattern||c,m=a.next,y=i;m!==t.tail&&!(l&&y>=l.reach);y+=m.value.length,m=m.next){var k=m.value;if(t.length>n.length)return;if(!(k instanceof M)){var b,x=1;if(h){if(!(b=W(p,y,n,f)))break;var w=b.index,A=b.index+b[0].length,P=y;for(P+=m.value.length;P<=w;)m=m.next,P+=m.value.length;if(P-=m.value.length,y=P,m.value instanceof M)continue;for(var S=m;S!==t.tail&&(P<A||"string"==typeof S.value);S=S.next)x++,P+=S.value.length;x--,k=n.slice(y,P),b.index-=y}else if(!(b=W(p,0,k,f)))continue;var w=b.index,E=b[0],O=k.slice(0,w),L=k.slice(w+E.length),N=y+k.length;l&&N>l.reach&&(l.reach=N);var j=m.prev;O&&(j=z(t,j,O),y+=O.length),I(t,j,x);var C=new M(o,g?_.tokenize(E,g):E,d,E);m=z(t,j,C),L&&z(t,m,L),1<x&&e(n,t,r,m.prev,y,{cause:o+","+u,reach:N})}}}}}(e,a,n,a.head,0),function(e){var n=[],t=e.head.next;for(;t!==e.tail;)n.push(t.value),t=t.next;return n}(a)},hooks:{all:{},add:function(e,n){var t=_.hooks.all;t[e]=t[e]||[],t[e].push(n)},run:function(e,n){var t=_.hooks.all[e];if(t&&t.length)for(var r,a=0;r=t[a++];)r(n)}},Token:M};function M(e,n,t,r){this.type=e,this.content=n,this.alias=t,this.length=0|(r||"").length}function W(e,n,t,r){e.lastIndex=n;var a=e.exec(t);if(a&&r&&a[1]){var i=a[1].length;a.index+=i,a[0]=a[0].slice(i)}return a}function i(){var e={value:null,prev:null,next:null},n={value:null,prev:e,next:null};e.next=n,this.head=e,this.tail=n,this.length=0}function z(e,n,t){var r=n.next,a={value:t,prev:n,next:r};return n.next=a,r.prev=a,e.length++,a}function I(e,n,t){for(var r=n.next,a=0;a<t&&r!==e.tail;a++)r=r.next;(n.next=r).prev=n,e.length-=a}if(u.Prism=_,M.stringify=function n(e,t){if("string"==typeof e)return e;if(Array.isArray(e)){var r="";return e.forEach(function(e){r+=n(e,t)}),r}var a={type:e.type,content:n(e.content,t),tag:"span",classes:["token",e.type],attributes:{},language:t},i=e.alias;i&&(Array.isArray(i)?Array.prototype.push.apply(a.classes,i):a.classes.push(i)),_.hooks.run("wrap",a);var l="";for(var o in a.attributes)l+=" "+o+'="'+(a.attributes[o]||"").replace(/"/g,"&quot;")+'"';return"<"+a.tag+' class="'+a.classes.join(" ")+'"'+l+">"+a.content+"</"+a.tag+">"},!u.document)return u.addEventListener&&(_.disableWorkerMessageHandler||u.addEventListener("message",function(e){var n=JSON.parse(e.data),t=n.language,r=n.code,a=n.immediateClose;u.postMessage(_.highlight(r,_.languages[t],t)),a&&u.close()},!1)),_;var e=_.util.currentScript();function t(){_.manual||_.highlightAll()}if(e&&(_.filename=e.src,e.hasAttribute("data-manual")&&(_.manual=!0)),!_.manual){var r=document.readyState;"loading"===r||"interactive"===r&&e&&e.defer?document.addEventListener("DOMContentLoaded",t):window.requestAnimationFrame?window.requestAnimationFrame(t):window.setTimeout(t,16)}return _}(_self);"undefined"!=typeof module&&module.exports&&(module.exports=Prism),"undefined"!=typeof global&&(global.Prism=Prism);
+Prism.languages.scheme={comment:/;.*|#;\s*\((?:[^()]|\([^()]*\))*\)|#\|(?:[^#|]|#(?!\|)|\|(?!#)|#\|(?:[^#|]|#(?!\|)|\|(?!#))*\|#)*\|#/,string:{pattern:/"(?:[^"\\]|\\.)*"/,greedy:!0},symbol:{pattern:/'[^()#'\s]+/,greedy:!0},character:{pattern:/#\\(?:[ux][a-fA-F\d]+\b|[-a-zA-Z]+\b|\S)/,greedy:!0,alias:"string"},"lambda-parameter":[{pattern:/((?:^|[^'`#])\(lambda\s+)(?:[^|()'\s]+|\|(?:[^\\|]|\\.)*\|)/,lookbehind:!0},{pattern:/((?:^|[^'`#])\(lambda\s+\()[^()']+/,lookbehind:!0}],keyword:{pattern:/((?:^|[^'`#])\()(?:begin|case(?:-lambda)?|cond(?:-expand)?|define(?:-library|-macro|-record-type|-syntax|-values)?|defmacro|delay(?:-force)?|do|else|export|except|guard|if|import|include(?:-ci|-library-declarations)?|lambda|let(?:rec)?(?:-syntax|-values|\*)?|let\*-values|only|parameterize|prefix|(?:quasi-?)?quote|rename|set!|syntax-(?:case|rules)|unless|unquote(?:-splicing)?|when)(?=[()\s]|$)/,lookbehind:!0},builtin:{pattern:/((?:^|[^'`#])\()(?:abs|and|append|apply|assoc|ass[qv]|binary-port\?|boolean=?\?|bytevector(?:-append|-copy|-copy!|-length|-u8-ref|-u8-set!|\?)?|caar|cadr|call-with-(?:current-continuation|port|values)|call\/cc|car|cdar|cddr|cdr|ceiling|char(?:->integer|-ready\?|\?|<\?|<=\?|=\?|>\?|>=\?)|close-(?:input-port|output-port|port)|complex\?|cons|current-(?:error|input|output)-port|denominator|dynamic-wind|eof-object\??|eq\?|equal\?|eqv\?|error|error-object(?:-irritants|-message|\?)|eval|even\?|exact(?:-integer-sqrt|-integer\?|\?)?|expt|features|file-error\?|floor(?:-quotient|-remainder|\/)?|flush-output-port|for-each|gcd|get-output-(?:bytevector|string)|inexact\??|input-port(?:-open\?|\?)|integer(?:->char|\?)|lcm|length|list(?:->string|->vector|-copy|-ref|-set!|-tail|\?)?|make-(?:bytevector|list|parameter|string|vector)|map|max|member|memq|memv|min|modulo|negative\?|newline|not|null\?|number(?:->string|\?)|numerator|odd\?|open-(?:input|output)-(?:bytevector|string)|or|output-port(?:-open\?|\?)|pair\?|peek-char|peek-u8|port\?|positive\?|procedure\?|quotient|raise|raise-continuable|rational\?|rationalize|read-(?:bytevector|bytevector!|char|error\?|line|string|u8)|real\?|remainder|reverse|round|set-c[ad]r!|square|string(?:->list|->number|->symbol|->utf8|->vector|-append|-copy|-copy!|-fill!|-for-each|-length|-map|-ref|-set!|\?|<\?|<=\?|=\?|>\?|>=\?)?|substring|symbol(?:->string|\?|=\?)|syntax-error|textual-port\?|truncate(?:-quotient|-remainder|\/)?|u8-ready\?|utf8->string|values|vector(?:->list|->string|-append|-copy|-copy!|-fill!|-for-each|-length|-map|-ref|-set!|\?)?|with-exception-handler|write-(?:bytevector|char|string|u8)|zero\?)(?=[()\s]|$)/,lookbehind:!0},operator:{pattern:/((?:^|[^'`#])\()(?:[-+*%/]|[<>]=?|=>?)(?=[()\s]|$)/,lookbehind:!0},number:{pattern:RegExp(function(r){for(var e in r)r[e]=r[e].replace(/<[\w\s]+>/g,function(e){return"(?:"+r[e].trim()+")"});return r[e]}({"<ureal dec>":"\\d+(?:/\\d+)?|(?:\\d+(?:\\.\\d*)?|\\.\\d+)(?:e[+-]?\\d+)?","<real dec>":"[+-]?<ureal dec>|[+-](?:inf|nan)\\.0","<imaginary dec>":"[+-](?:<ureal dec>|(?:inf|nan)\\.0)?i","<complex dec>":"<real dec>(?:@<real dec>|<imaginary dec>)?|<imaginary dec>","<num dec>":"(?:#d(?:#[ei])?|#[ei](?:#d)?)?<complex dec>","<ureal box>":"[0-9a-f]+(?:/[0-9a-f]+)?","<real box>":"[+-]?<ureal box>|[+-](?:inf|nan)\\.0","<imaginary box>":"[+-](?:<ureal box>|(?:inf|nan)\\.0)?i","<complex box>":"<real box>(?:@<real box>|<imaginary box>)?|<imaginary box>","<num box>":"#[box](?:#[ei])?|(?:#[ei])?#[box]<complex box>","<number>":"(^|[\\s()])(?:<num dec>|<num box>)(?=[()\\s]|$)"}),"i"),lookbehind:!0},boolean:{pattern:/(^|[\s()])#(?:[ft]|false|true)(?=[()\s]|$)/,lookbehind:!0},function:{pattern:/((?:^|[^'`#])\()(?:[^|()'\s]+|\|(?:[^\\|]|\\.)*\|)(?=[()\s]|$)/,lookbehind:!0},identifier:{pattern:/(^|[\s()])\|(?:[^\\|]|\\.)*\|(?=[()\s]|$)/,lookbehind:!0,greedy:!0},punctuation:/[()']/};
+!function(){if("undefined"!=typeof self&&self.Prism&&self.document&&document.querySelector){var t,s=function(){if(void 0===t){var e=document.createElement("div");e.style.fontSize="13px",e.style.lineHeight="1.5",e.style.padding="0",e.style.border="0",e.innerHTML="&nbsp;<br />&nbsp;",document.body.appendChild(e),t=38===e.offsetHeight,document.body.removeChild(e)}return t},l=!0,a=0;Prism.hooks.add("before-sanity-check",function(e){var t=e.element.parentNode,n=t&&t.getAttribute("data-line");if(t&&n&&/pre/i.test(t.nodeName)){var i=0;g(".line-highlight",t).forEach(function(e){i+=e.textContent.length,e.parentNode.removeChild(e)}),i&&/^( \n)+$/.test(e.code.slice(-i))&&(e.code=e.code.slice(0,-i))}}),Prism.hooks.add("complete",function e(t){var n=t.element.parentNode,i=n&&n.getAttribute("data-line");if(n&&i&&/pre/i.test(n.nodeName)){clearTimeout(a);var r=Prism.plugins.lineNumbers,o=t.plugins&&t.plugins.lineNumbers;if(b(n,"line-numbers")&&r&&!o)Prism.hooks.add("line-numbers",e);else u(n,i)(),a=setTimeout(c,1)}}),window.addEventListener("hashchange",c),window.addEventListener("resize",function(){g("pre[data-line]").map(function(e){return u(e)}).forEach(v)})}function g(e,t){return Array.prototype.slice.call((t||document).querySelectorAll(e))}function b(e,t){return t=" "+t+" ",-1<(" "+e.className+" ").replace(/[\n\t]/g," ").indexOf(t)}function v(e){e()}function u(u,e,c){var t=(e="string"==typeof e?e:u.getAttribute("data-line")).replace(/\s+/g,"").split(",").filter(Boolean),d=+u.getAttribute("data-line-offset")||0,f=(s()?parseInt:parseFloat)(getComputedStyle(u).lineHeight),m=b(u,"line-numbers"),p=m?u:u.querySelector("code")||u,h=[];t.forEach(function(e){var t=e.split("-"),n=+t[0],i=+t[1]||n,r=u.querySelector('.line-highlight[data-range="'+e+'"]')||document.createElement("div");if(h.push(function(){r.setAttribute("aria-hidden","true"),r.setAttribute("data-range",e),r.className=(c||"")+" line-highlight"}),m&&Prism.plugins.lineNumbers){var o=Prism.plugins.lineNumbers.getLine(u,n),a=Prism.plugins.lineNumbers.getLine(u,i);if(o){var s=o.offsetTop+"px";h.push(function(){r.style.top=s})}if(a){var l=a.offsetTop-o.offsetTop+a.offsetHeight+"px";h.push(function(){r.style.height=l})}}else h.push(function(){r.setAttribute("data-start",n),n<i&&r.setAttribute("data-end",i),r.style.top=(n-d-1)*f+"px",r.textContent=new Array(i-n+2).join(" \n")});h.push(function(){p.appendChild(r)})});var i=u.id;if(m&&i){for(var n="linkable-line-numbers",r=!1,o=u;o;){if(b(o,n)){r=!0;break}o=o.parentElement}if(r){b(u,n)||h.push(function(){u.className=(u.className+" "+n).trim()});var a=parseInt(u.getAttribute("data-start")||"1");g(".line-numbers-rows > span",u).forEach(function(e,t){var n=t+a;e.onclick=function(){var e=i+"."+n;l=!1,location.hash=e,setTimeout(function(){l=!0},1)}})}}return function(){h.forEach(v)}}function c(){var e=location.hash.slice(1);g(".temporary.line-highlight").forEach(function(e){e.parentNode.removeChild(e)});var t=(e.match(/\.([\d,-]+)$/)||[,""])[1];if(t&&!document.getElementById(e)){var n=e.slice(0,e.lastIndexOf(".")),i=document.getElementById(n);if(i)i.hasAttribute("data-line")||i.setAttribute("data-line",""),u(i,t,"temporary ")(),l&&document.querySelector(".temporary.line-highlight").scrollIntoView()}}}();
+!function(){if("undefined"!=typeof self&&self.Prism&&self.document){var o="line-numbers",a=/\n(?!$)/g,e=Prism.plugins.lineNumbers={getLine:function(e,n){if("PRE"===e.tagName&&e.classList.contains(o)){var t=e.querySelector(".line-numbers-rows");if(t){var i=parseInt(e.getAttribute("data-start"),10)||1,r=i+(t.children.length-1);n<i&&(n=i),r<n&&(n=r);var s=n-i;return t.children[s]}}},resize:function(e){u([e])},assumeViewportIndependence:!0},t=function(e){return e?window.getComputedStyle?getComputedStyle(e):e.currentStyle||null:null},n=void 0;window.addEventListener("resize",function(){e.assumeViewportIndependence&&n===window.innerWidth||(n=window.innerWidth,u(Array.prototype.slice.call(document.querySelectorAll("pre."+o))))}),Prism.hooks.add("complete",function(e){if(e.code){var n=e.element,t=n.parentNode;if(t&&/pre/i.test(t.nodeName)&&!n.querySelector(".line-numbers-rows")&&Prism.util.isActive(n,o)){n.classList.remove(o),t.classList.add(o);var i,r=e.code.match(a),s=r?r.length+1:1,l=new Array(s+1).join("<span></span>");(i=document.createElement("span")).setAttribute("aria-hidden","true"),i.className="line-numbers-rows",i.innerHTML=l,t.hasAttribute("data-start")&&(t.style.counterReset="linenumber "+(parseInt(t.getAttribute("data-start"),10)-1)),e.element.appendChild(i),u([t]),Prism.hooks.run("line-numbers",e)}}}),Prism.hooks.add("line-numbers",function(e){e.plugins=e.plugins||{},e.plugins.lineNumbers=!0})}function u(e){if(0!=(e=e.filter(function(e){var n=t(e)["white-space"];return"pre-wrap"===n||"pre-line"===n})).length){var n=e.map(function(e){var n=e.querySelector("code"),t=e.querySelector(".line-numbers-rows");if(n&&t){var i=e.querySelector(".line-numbers-sizer"),r=n.textContent.split(a);i||((i=document.createElement("span")).className="line-numbers-sizer",n.appendChild(i)),i.innerHTML="0",i.style.display="block";var s=i.getBoundingClientRect().height;return i.innerHTML="",{element:e,lines:r,lineHeights:[],oneLinerHeight:s,sizer:i}}}).filter(Boolean);n.forEach(function(e){var i=e.sizer,n=e.lines,r=e.lineHeights,s=e.oneLinerHeight;r[n.length-1]=void 0,n.forEach(function(e,n){if(e&&1<e.length){var t=i.appendChild(document.createElement("span"));t.style.display="block",t.textContent=e}else r[n]=s})}),n.forEach(function(e){for(var n=e.sizer,t=e.lineHeights,i=0,r=0;r<t.length;r++)void 0===t[r]&&(t[r]=n.children[i++].getBoundingClientRect().height)}),n.forEach(function(e){var n=e.sizer,t=e.element.querySelector(".line-numbers-rows");n.style.display="none",n.innerHTML="",e.lineHeights.forEach(function(e,n){t.children[n].style.height=e+"px"})})}}}();
+!function(){if("undefined"!=typeof self&&self.Prism&&self.document){var i=[],l={},c=function(){};Prism.plugins.toolbar={};var e=Prism.plugins.toolbar.registerButton=function(e,n){var t;t="function"==typeof n?n:function(e){var t;return"function"==typeof n.onClick?((t=document.createElement("button")).type="button",t.addEventListener("click",function(){n.onClick.call(this,e)})):"string"==typeof n.url?(t=document.createElement("a")).href=n.url:t=document.createElement("span"),n.className&&t.classList.add(n.className),t.textContent=n.text,t},e in l?console.warn('There is a button with the key "'+e+'" registered already.'):i.push(l[e]=t)},t=Prism.plugins.toolbar.hook=function(a){var e=a.element.parentNode;if(e&&/pre/i.test(e.nodeName)&&!e.parentNode.classList.contains("code-toolbar")){var t=document.createElement("div");t.classList.add("code-toolbar"),e.parentNode.insertBefore(t,e),t.appendChild(e);var r=document.createElement("div");r.classList.add("toolbar");var n=i,o=function(e){for(;e;){var t=e.getAttribute("data-toolbar-order");if(null!=t)return(t=t.trim()).length?t.split(/\s*,\s*/g):[];e=e.parentElement}}(a.element);o&&(n=o.map(function(e){return l[e]||c})),n.forEach(function(e){var t=e(a);if(t){var n=document.createElement("div");n.classList.add("toolbar-item"),n.appendChild(t),r.appendChild(n)}}),t.appendChild(r)}};e("label",function(e){var t=e.element.parentNode;if(t&&/pre/i.test(t.nodeName)&&t.hasAttribute("data-label")){var n,a,r=t.getAttribute("data-label");try{a=document.querySelector("template#"+r)}catch(e){}return a?n=a.content:(t.hasAttribute("data-url")?(n=document.createElement("a")).href=t.getAttribute("data-url"):n=document.createElement("span"),n.textContent=r),n}}),Prism.hooks.add("complete",t)}}();
+!function(){if("undefined"!=typeof self&&self.Prism&&self.document)if(Prism.plugins.toolbar){var i=window.ClipboardJS||void 0;i||"function"!=typeof require||(i=require("clipboard"));var u=[];if(!i){var t=document.createElement("script"),e=document.querySelector("head");t.onload=function(){if(i=window.ClipboardJS)for(;u.length;)u.pop()()},t.src="https://cdnjs.cloudflare.com/ajax/libs/clipboard.js/2.0.0/clipboard.min.js",e.appendChild(t)}Prism.plugins.toolbar.registerButton("copy-to-clipboard",function(t){var e=document.createElement("button");e.textContent="Copy",e.setAttribute("type","button");var o=t.element;return i?n():u.push(n),e;function n(){var t=new i(e,{text:function(){return o.textContent}});t.on("success",function(){e.textContent="Copied!",r()}),t.on("error",function(){e.textContent="Press Ctrl+C to copy",r()})}function r(){setTimeout(function(){e.textContent="Copy"},5e3)}})}else console.warn("Copy to Clipboard plugin loaded before Toolbar plugin.")}();
+!function(){if("undefined"!=typeof self&&self.Prism&&self.document){var d={"(":")","[":"]","{":"}"},u={"(":"brace-round","[":"brace-square","{":"brace-curly"},f={"${":"{"},h=0,n=/^(pair-\d+-)(open|close)$/;Prism.hooks.add("complete",function(e){var t=e.element,n=t.parentElement;if(n&&"PRE"==n.tagName){var c=[];if(Prism.util.isActive(t,"match-braces")&&c.push("(","[","{"),0!=c.length){n.__listenerAdded||(n.addEventListener("mousedown",function(){var e=n.querySelector("code");Array.prototype.slice.call(e.querySelectorAll(".brace-selected")).forEach(function(e){e.classList.remove("brace-selected")})}),Object.defineProperty(n,"__listenerAdded",{value:!0}));var o=Array.prototype.slice.call(t.querySelectorAll("span.token.punctuation")),l=[];c.forEach(function(e){for(var t=d[e],n=u[e],c=[],r=[],s=0;s<o.length;s++){var a=o[s];if(0==a.childElementCount){var i=a.textContent;(i=f[i]||i)===e?(l.push({index:s,open:!0,element:a}),a.classList.add(n),a.classList.add("brace-open"),r.push(s)):i===t&&(l.push({index:s,open:!1,element:a}),a.classList.add(n),a.classList.add("brace-close"),r.length&&c.push([s,r.pop()]))}}c.forEach(function(e){var t="pair-"+h+++"-",n=o[e[0]],c=o[e[1]];n.id=t+"open",c.id=t+"close",[n,c].forEach(function(e){e.addEventListener("mouseenter",p),e.addEventListener("mouseleave",v),e.addEventListener("click",m)})})});var r=0;l.sort(function(e,t){return e.index-t.index}),l.forEach(function(e){e.open?(e.element.classList.add("brace-level-"+(r%12+1)),r++):(r=Math.max(0,r-1),e.element.classList.add("brace-level-"+(r%12+1)))})}}})}function e(e){var t=n.exec(e.id);return document.querySelector("#"+t[1]+("open"==t[2]?"close":"open"))}function p(){Prism.util.isActive(this,"brace-hover",!0)&&[this,e(this)].forEach(function(e){e.classList.add("brace-hover")})}function v(){[this,e(this)].forEach(function(e){e.classList.remove("brace-hover")})}function m(){Prism.util.isActive(this,"brace-select",!0)&&[this,e(this)].forEach(function(e){e.classList.add("brace-selected")})}}();