| summaryrefslogtreecommitdiff |
diff options
| author | Nathanael Sensfelder <SpamShield0@MultiAgentSystems.org> | 2021-12-02 22:24:21 +0100 |
|---|---|---|
| committer | Nathanael Sensfelder <SpamShield0@MultiAgentSystems.org> | 2021-12-02 22:24:21 +0100 |
| commit | 0a32a8eeb98d5f3507edf5e303ae655f4b923c74 (patch) | |
| tree | 772d1793d7d1cdd323d598d144e1624699abcf36 /content | |
| parent | 0d2736d22ced1f9bf566192f8604f869e0f5c6b9 (diff) | |
Updating the documentation to match changes in Fate.
Diffstat (limited to 'content')
26 files changed, 1539 insertions, 758 deletions
diff --git a/content/_index.md b/content/_index.md index a082ffa..c97ad1a 100644 --- a/content/_index.md +++ b/content/_index.md @@ -17,8 +17,7 @@ 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) + (if_else (set: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. @@ -32,15 +31,13 @@ implications when it comes time to add support for it to your engine. make the cut. ) ) - (add visited_your_room progress) + (set:add! visited_your_room progress) (player_choice - ( - ( Look for healing items ) - (jump_to look_for_healing_items) + (option ( Look for healing items ) + (jump_to! look_for_healing_items) ) - ( - ( No time! Let's go adventuring! ) - (jump_to leave_your_room) + (option ( No time! Let's go adventuring! ) + (jump_to! leave_your_room) ) ) ) @@ -49,5 +46,7 @@ implications when it comes time to add support for it to your engine. ### Known alternatives * [Inkle's Ink](https://www.inklestudios.com/ink/). * [Yarn Spinner](https://yarnspinner.dev/). +* [Twine](https://twinery.org/). +* [Ren'Py](https://renpy.org/). * [DLG](https://github.com/iLambda/language-dlg). Nowhere near as popular as the -other two alternatives, but its approach shares more similarities with Tonkadur. +other alternatives, but its approach shares more similarities with Tonkadur. diff --git a/content/fate_v1/computations/addresses/_index.md b/content/fate_v1/computations/addresses/_index.md index aafd0f1..ae052ca 100644 --- a/content/fate_v1/computations/addresses/_index.md +++ b/content/fate_v1/computations/addresses/_index.md @@ -1,18 +1,27 @@ --- title: Addresses --- -### VALUE ACCESS -{{< fatecode >}}(at [ADDRESS]){{< /fatecode >}} -Returns the variable at `[ADDRESS]`. +Addresses are values that indicate where in the memory some other value is +located. They can thus be used to pass around an indication of where to modify +a value. + +### VALUE ACCESS +{{< fatecode >}}(at [address: (POINTER X)]){{< /fatecode >}} +Returns the `[X]` value at `[address]`. The returned value can act as a +reference. -### ALLOCATION -{{< fatecode >}}(new [TYPE]){{< /fatecode >}} +**Examples:** `(at my_ptr_var)`, `(at (ptr my_var))` -Returns the address of a new variable of type `[TYPE]`. Don't forget to call -`free` on it once you're done. +**Aliases:** `at`. ### ADDRESS -{{< fatecode >}}(ptr [COMPUTATION VARIABLE]){{< /fatecode >}} +{{< fatecode >}}(ptr [X]){{< /fatecode >}} Returns the address of `[COMPUTATION VARIABLE]`. + +**Examples:** `(ptr my_var)` + +**Aliases:** `address_of`, `addressof`, `addressOf`, `address`, `addr`, +`pointer_to`, `pointerto`, `pointerTo`, `pointer`, `ptr`, `reference_to`, +`referenceto`, `referenceTo`, `reference`, `ref`. diff --git a/content/fate_v1/computations/basics/_index.md b/content/fate_v1/computations/basics/_index.md index e8a8816..52b5e42 100644 --- a/content/fate_v1/computations/basics/_index.md +++ b/content/fate_v1/computations/basics/_index.md @@ -2,19 +2,44 @@ title: Computations weight: 2 --- -Computations are values. They may read from the memory, but do not modify it -(with a single exception). +Computations are values. They may read from the memory, but do not modify it. ### TEXT -{{< fatecode >}}(text [C0 = COMPUTATION] ... [CN = COMPUTATION]){{< /fatecode >}} +{{< fatecode >}}(text [C0: COMPUTATION]...[CN: COMPUTATION]){{< /fatecode >}} -Returns a `text` node containing the text representation of `C0` ... `CN`. +Returns a `text` value containing the text representation of `C0`...`CN`. + +**Examples:** `(text just a few strings)`, +`(text (string just a single string))`, `(text There are (+ 3 1) lights!)`, +`(text (text (text well...)))`. + +**Aliases:** `text`. ### 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}`. +applicable. In cases where no `text` or `string` value is expected, using +`{String}` instead of `(var {String})` will work as a shortcut. + +Structure members can be accessed by using `.` in `{String}`. Collection +(`list` or `set`) elements can be similarly accessed by their index. + +**Examples:** `(var my_list)`, `(var my_list.0)`, `(var my_list.0.name)`. + +**Aliases:** `var`, `variable`. + +### STRING +{{< fatecode >}}(string {String}){{< /fatecode >}} + +Returns a `string` value corresponding to `{String}`. This can be used +to disambiguate strings and variable names, as well as to create strings with +spaces. + +**Examples:** +`(string just a single string)`, `(string var0_is_not_a_var)` + +**Aliases:** `string`. ### SEQUENCE | PROCEDURE {{< fatecode >}}(sequence {String}){{< /fatecode >}} @@ -22,21 +47,42 @@ applicable. Structure members can be accessed by using `.` in `{String}`. Returns a `[SEQUENCE]` value corresponding to the sequence named `{String}`. Said sequence can be defined at a later point. +**Examples:** `(sequence the_cave)`, `(sequence end_credits)`. + +**Aliases:** `seq`, `sequence`. + + ### STRUCTURE FIELD ACCESS -{{< fatecode >}}{Structure Var Name}.{Field Name}{{< /fatecode >}} -{{< fatecode >}}(field {String} [STRUCTURE VAR]){{< /fatecode >}} +{{< fatecode >}}{Structure Variable Name}.{Field Name}{{< /fatecode >}} +{{< fatecode >}}(struct:field {String} [STRUCTURE]){{< /fatecode >}} -Accesses the `{String}` field of the structure `[STRUCTURE VAR]`. Using `.` to -access fields is recommended over the use of this operator. +Accesses the `{String}` field of the structure `[STRUCTURE]`. Using `.` to +access fields is recommended over the use of this operator when possible. The +returned value can act as a reference. + +**Examples:** `claude.health_points`, `(struct:field health_points jack)`, +`(struct:field stamina (car (list:pop_left character_list)))` + +**Aliases:** `struct:field`, `struct:get`, `struct:getfield`, +`struct:get_field`. -### STRUCTURE FIELD VALUE -{{< fatecode >}}(get_field {String} [STRUCTURE]){{< /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 >}} +{{< fatecode >}}(let + ( + ({V0: String} [C0: COMPUTATION]) + ... + ({VN: String} [CN: COMPUTATION]) + ) + [result: COMPUTATION] +){{< /fatecode >}} + +Defines a hierarchical level and local variables `V0` ... `VN` with values `C0` ... `CN`, and returns the value of `result`. + +**Examples:** + +**Aliases:** -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 >}} @@ -49,18 +95,28 @@ allowed: * `[BOOL]` to `[BOOL]` and `[STRING]`. * `[STRING]` to `[BOOL]` (`true` and `false`), `[FLOAT]`, `[INT]`, and`[STRING]`. +**Examples:** + +**Aliases:** + + ### RANDOM NUMBER -{{< fatecode >}}(rand [I0 = INT] [IN = INT]){{< /fatecode >}} +{{< fatecode >}}(rand [I0: INT] [IN: INT]){{< /fatecode >}} Returns a random number between `I0` and `IN` (inclusive). +**Examples:** + +**Aliases:** + + ## Basic Operators ### BOOL OPERATORS -{{< fatecode >}}(and [B0 = BOOL] ... [BN = BOOL]){{< /fatecode >}} +{{< fatecode >}}(and [B0: BOOL] ... [BN: BOOL]){{< /fatecode >}} Standard conjunction (minimum of 2 arguments). -{{< fatecode >}}(or [B0 = BOOL] ... [BN = BOOL]){{< /fatecode >}} +{{< fatecode >}}(or [B0: BOOL] ... [BN: BOOL]){{< /fatecode >}} Standard disjunction (minimum of 2 arguments). @@ -68,53 +124,58 @@ Standard disjunction (minimum of 2 arguments). Standard negation. -{{< fatecode >}}(implies [B0 = BOOL] [B1 = BOOL]){{< /fatecode >}} +{{< fatecode >}}(implies [B0: BOOL] [B1: BOOL]){{< /fatecode >}} Standard implication. -{{< fatecode >}}(one_in [B0 = BOOL] ... [BN = BOOL]){{< /fatecode >}} +{{< fatecode >}}(one_in [B0: BOOL] ... [BN: BOOL]){{< /fatecode >}} true if, and only if, exactly one of the operands is true. +**Examples:** + +**Aliases:** + + ### 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 >}} +{{< fatecode >}}(+ [N0: NUMBER] ... [NN: NUMBER]){{< /fatecode >}} Standard addition (minimum of 2 arguments). -{{< fatecode >}}(- [N0 = NUMBER] ... [NN = NUMBER]){{< /fatecode >}} +{{< fatecode >}}(- [N0: NUMBER] ... [NN: NUMBER]){{< /fatecode >}} Standard substraction (minimum of 2 arguments). -{{< fatecode >}}(* [N0 = NUMBER] ... [NN = NUMBER]){{< /fatecode >}} +{{< fatecode >}}(* [N0: NUMBER] ... [NN: NUMBER]){{< /fatecode >}} Standard multiplication (minimum of 2 arguments). -{{< fatecode >}}(/ [N0 = NUMBER] [N1 = NUMBER]){{< /fatecode >}} +{{< 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 >}} +{{< fatecode >}}(^ [N0: NUMBER] [N1: NUMBER]){{< /fatecode >}} Standard exponentiation. -{{< fatecode >}}(% [I0 = INT] [I1 = INT]){{< /fatecode >}} +{{< fatecode >}}(% [I0: INT] [I1: INT]){{< /fatecode >}} Standard modulo operation. -{{< fatecode >}}(min [N0 = NUMBER] ... [NN = NUMBER]){{< /fatecode >}} +{{< fatecode >}}(min [N0: NUMBER] ... [NN: NUMBER]){{< /fatecode >}} Lowest value among the operands. -{{< fatecode >}}(max [N0 = NUMBER] ... [NN = NUMBER]){{< /fatecode >}} +{{< fatecode >}}(max [N0: NUMBER] ... [NN: NUMBER]){{< /fatecode >}} Highest value among the operands. -{{< fatecode >}}(clamp [N0 = NUMBER] [N1 = NUMBER] [N2 = NUMBER]){{< /fatecode >}} +{{< fatecode >}}(clamp [N0: NUMBER] [N1: NUMBER] [N2: NUMBER]){{< /fatecode >}} Equivalent to `(max N0 (min N1 N2))`. @@ -123,23 +184,33 @@ Equivalent to `(max N0 (min N1 N2))`. Positive value of `[NUMBER]`. +**Examples:** + +**Aliases:** + + ### COMPARISON OPERATORS -{{< fatecode >}}(= [C0 = COMPUTATION] ... [CN = COMPUTATION]){{< /fatecode >}} +{{< fatecode >}}(= [C0: COMPUTATION] ... [CN: COMPUTATION]){{< /fatecode >}} True if, and only if, all operands are equal. -{{< fatecode >}}(< [C0 = COMPARABLE] [C1 = COMPARABLE]){{< /fatecode >}} +{{< fatecode >}}(< [C0: COMPARABLE] [C1: COMPARABLE]){{< /fatecode >}} True if, and only if, `C0` is strictly lower than `C1`. -{{< fatecode >}}(=< [C0 = COMPARABLE] [C1 = COMPARABLE]){{< /fatecode >}} +{{< 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 >}} +{{< fatecode >}}(> [C0: COMPARABLE] [C1: COMPARABLE]){{< /fatecode >}} True if, and only if, `C0` is strictly higher than `C1`. -{{< fatecode >}}(>= [C0 = COMPARABLE] [C1 = COMPARABLE]){{< /fatecode >}} +{{< fatecode >}}(>= [C0: COMPARABLE] [C1: COMPARABLE]){{< /fatecode >}} True if, and only if, `C0` is higher or equal to/than `C1`. + +**Examples:** + +**Aliases:** + diff --git a/content/fate_v1/computations/collections/_index.md b/content/fate_v1/computations/collections/_index.md index 80a4ead..584baef 100644 --- a/content/fate_v1/computations/collections/_index.md +++ b/content/fate_v1/computations/collections/_index.md @@ -2,151 +2,208 @@ title: Collections --- ### ACCESS -{{< fatecode >}}(access [INT] [COLLECTION|COLLECTION PTR]){{< /fatecode >}} +{{< fatecode >}}(list:access [INT] [LIST]){{< /fatecode >}} +{{< fatecode >}}(set:access [INT] [SET]){{< /fatecode >}} -Returns the value of the `[INT]`th element in `[COLLECTION|COLLECTION PTR]`. +Returns the value of the `[INT]`th element in the collection. ### ACCESS CONSTANT INDEX -{{< fatecode >}}[(COLLECTION|COLLECTION PTR) VAR].{Integer}{{< /fatecode >}} +{{< fatecode >}}[(LIST) VAR].{Integer}{{< /fatecode >}} +{{< fatecode >}}[(SET) VAR].{Integer}{{< /fatecode >}} -Returns a variable corresponding to the `[INT]`th element in -`[(COLLECTION|COLLECTION PTR) VAR]`. - -### ACCESS POINTER -{{< fatecode >}}(access_pointer [INT] [(COLLECTION|COLLECTION PTR) VAR]){{< /fatecode >}} - -Returns a pointer to the `[INT]`th element in `[(COLLECTION|COLLECTION PTR) -VAR]`. +Returns a variable corresponding to the `[INT]`th element in the collection. ### ADD ELEMENT AT -{{< fatecode >}}(add_element_at [INT] [COMPUTATION*] [LIST]){{< /fatecode >}} +{{< fatecode >}}(list: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. +that `[COMPUTATION*]` does not allow use of the variable shorthand if `[LIST]` +is a list of strings. ### ADD ELEMENT -{{< fatecode >}}(add_element [C0 = COMPUTATION*] ... [CN = COMPUTATION*] [COLLECTION]){{< /fatecode >}} +{{< fatecode >}}(list:add_element [C0 = COMPUTATION*] ... [CN = COMPUTATION*] [LIST]){{< /fatecode >}} +{{< fatecode >}}(set:add_element [C0 = COMPUTATION*] ... [CN = COMPUTATION*] [SET]){{< /fatecode >}} Returns a copy of `[COLLECTION]` with `C0` ... `CN` added. If `[COLLECTION]` is a `[LIST]`, then the elements are added at the end of the list, in order (meaning that `CN` will be the last element added). -Note that `[COMPUTATION*]` does not allow use of the variable shorthand. +Note that `[COMPUTATION*]` does not allow use of the variable shorthand if the +collection is a collection of strings. ### ADDING MEMBERS -{{< fatecode >}}(add_all_elements [C0 = COLLECTION] [C1 = COLLECTION]){{< /fatecode >}} +{{< fatecode >}}(list:add_all_elements [C0 = LIST|SET]+ [C1 = LIST]){{< /fatecode >}} +{{< fatecode >}}(set:add_all_elements [C0 = LIST|SET]+ [C1 = SET]){{< /fatecode >}} -Returns a copy of `[C1]`, with all the elements of `[C2]` added. If `[C1]` +Returns a copy of `[C1]`, with all the elements of `[C0]` added. If `[C1]` is a `[LIST]`, the new members are added at the end of the list. +As a shorthand, multiple `[C0]` can be specified. They will all be added in +order. + +### SUB-LIST +{{< fatecode >}}(list:sublist [start: INT] [end_before: INT] [LIST]){{< /fatecode >}} +{{< fatecode >}}(set:subset [start: INT] [end_before: INT] [SET]){{< /fatecode >}} + +Returns a copy of the collection in which only the elements with an index +higher or equal to `[start]` and strictly less than `[end_before]` are included. + +### SHUFFLE +{{< fatecode >}}(list:shuffle [LIST]){{< /fatecode >}} +{{< fatecode >}}(set:shuffle [SET]){{< /fatecode >}} + +Returns a list containing all the elements of the collection in a random order. + ### COUNT -{{< fatecode >}}(count [COMPUTATION*] [COLLECTION]){{< /fatecode >}} +{{< fatecode >}}(list:count [COMPUTATION*] [LIST]){{< /fatecode >}} +{{< fatecode >}}(set:count [COMPUTATION*] [SET]){{< /fatecode >}} -Returns the number of occurrences of `[COMPUTATION*]` in `[COLLECTION]`. -Note that `[COMPUTATION*]` does not allow use of the variable shorthand. +Returns the number of occurrences of `[COMPUTATION*]` in `[LIST]` or `[SET]`. +Note that `[COMPUTATION*]` does not allow use of the variable shorthand if +the collection is a collection of strings. ### INDEX OF -{{< fatecode >}}(index_of [COMPUTATION] [COLLECTION]){{< /fatecode >}} +{{< fatecode >}}(list:index_of [COMPUTATION] [LIST]){{< /fatecode >}} +{{< fatecode >}}(set:index_of [COMPUTATION] [SET]){{< /fatecode >}} -Returns the index of the first occurrence of `[COMPUTATION]` in `[COLLECTION]`, -starting at 0. +Returns the index of the first occurrence of `[COMPUTATION]` in `[LIST]` or +`[SET]`, starting at 0. ### IS MEMBER -{{< fatecode >}}(is_member [COMPUTATION] [COLLECTION]){{< /fatecode >}} +{{< fatecode >}}(list:is_member [COMPUTATION] [LIST]){{< /fatecode >}} +{{< fatecode >}}(set:is_member [COMPUTATION] [SET]){{< /fatecode >}} -Returns true if, and only if, `[COMPUTATION]` is in `[COLLECTION]`. +Returns true if, and only if, `[COMPUTATION]` is in `[LIST]` or `[SET]`. ### SIZE -{{< fatecode >}}(size [COLLECTION]){{< /fatecode >}} +{{< fatecode >}}(list:size [LIST]){{< /fatecode >}} +{{< fatecode >}}(set:size [SET]){{< /fatecode >}} -Returns the size (`[INT]`) of `[COLLECTION]`. +Returns the size (`[INT]`) of `[LIST]` or `[SET]`. ### IS EMPTY -{{< fatecode >}}(is_empty [COLLECTION]){{< /fatecode >}} +{{< fatecode >}}(list:is_empty [LIST]){{< /fatecode >}} +{{< fatecode >}}(set:is_empty [SET]){{< /fatecode >}} + +Returns true if, and only if `[LIST]` or `[SET]` is empty. + +### REMOVE ONE COPY +{{< fatecode >}}(list:remove [COMPUTATION*]+ [LIST]){{< /fatecode >}} +{{< fatecode >}}(set:remove [COMPUTATION*]+ [SET]){{< /fatecode >}} + +Returns a copy of the collection with one instance of `[COMPUTATION*]` having been removed. The variable shorthand cannot be used if the collection is a collection of strings. + +As a shorthand, multiple computations can be specified. They will all be removed +in order. + +### REMOVE ALL COPIES +{{< fatecode >}}(list:remove_each [COMPUTATION*]+ [LIST]){{< /fatecode >}} +{{< fatecode >}}(set:remove_each [COMPUTATION*]+ [SET]){{< /fatecode >}} + +Returns a copy of the collection with all instances of `[COMPUTATION*]` having been removed. The variable shorthand cannot be used if the collection is a collection of strings. + +As a shorthand, multiple computations can be specified. They will all be removed +from the list. + +### REMOVE ALL ALSO IN +{{< fatecode >}}(list:remove_all [removed: COLLECTION]+ [LIST]){{< /fatecode >}} +{{< fatecode >}}(set:remove_all [removed: COLLECTION]+ [SET]){{< /fatecode >}} + +Returns a copy of the collection with all elements of `[removed]` having been +removed. + +As a shorthand, multiple `[removed]` can be specified. Their elements will all +be removed. + +### REMOVE AT +{{< fatecode >}}(list:remove_at [INT] [LIST]){{< /fatecode >}} +{{< fatecode >}}(set:remove_at [INT] [SET]){{< /fatecode >}} + +Returns a copy of the collection with the element at index `[INT]` having been +removed. + +### PUSH ELEMENT +{{< fatecode >}}(list:push_left [COMPUTATION*] [LIST]){{< /fatecode >}} +{{< fatecode >}}(list:push_right [COMPUTATION*] [LIST]){{< /fatecode >}} +{{< fatecode >}}(set:push_left [COMPUTATION*] [SET]){{< /fatecode >}} +{{< fatecode >}}(set:push_right [COMPUTATION*] [SET]){{< /fatecode >}} + +Returns a list corresponding to the given `[LIST]` or `[SET]` to which the +`[COMPUTATION*]` has been added to the right (`push_right`) or the left +(`push_left`). + +### POP ELEMENT +TODO + +### PARTITION +TODO + +### PARTITION (INDEXED) +TODO -Returns true if, and only if `[COLLECTION]` is empty. +### SORT +TODO ### FILTER ELEMENTS -{{< fatecode >}}(filter [LAMBDA BOOL (X)] [X COLLECTION]){{< /fatecode >}} -{{< fatecode >}}(filter [LAMBDA BOOL (X Y0 ... YN)] [X COLLECTION] [Y0 COMPUTATION*] ... [YN COMPUTATION*]){{< /fatecode >}} +{{< fatecode >}}(list:filter [LAMBDA BOOL (X)] [X LIST]){{< /fatecode >}} +{{< fatecode >}}(set:filter [LAMBDA BOOL (X)] [X SET]){{< /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. +Returns a copy of `[X LIST]` or `[X SET]` in which only the elements for which +`[LAMBDA BOOL (X)]` returns `true` remain. ### 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 >}} +{{< fatecode >}}(list:indexed_filter [LAMBDA BOOL (INT X)] [X LIST]){{< /fatecode >}} +{{< fatecode >}}(set:indexed_filter [LAMBDA BOOL (INT X)] [X SET]){{< /fatecode >}} -Returns a copy of `[INT X COLLECTION]` in which only the elements for which +Returns a copy of `[X LIST]` or `[X SET]` 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. +remain. ### 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 >}} +{{< fatecode >}}(list:foldl [LAMBDA X (X Y)] [X COMPUTATION*] [Y LIST]){{< /fatecode >}} +{{< fatecode >}}(list:foldr [LAMBDA X (X Y)] [X COMPUTATION*] [Y LIST]){{< /fatecode >}} +{{< fatecode >}}(set:foldl [LAMBDA X (X Y)] [X COMPUTATION*] [Y SET]){{< /fatecode >}} +{{< fatecode >}}(set:foldr [LAMBDA X (X Y)] [X COMPUTATION*] [Y SET]){{< /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. +`foldr`. The variable shorthand cannot be used for the initial value if the +lambda function returns a string. ### MERGE COLLECTIONS -{{< fatecode >}}(merge_to_list [LAMBDA O (X Y)] [X COLLECTION] [Y COLLECTION]){{< /fatecode >}} -{{< fatecode >}}(merge_to_list [LAMBDA O (X Y Z0 ... ZN)] [X COLLECTION] [Y COLLECTION] [Z0 COMPUTATION*] ... [ZN COMPUTATION*]){{< /fatecode >}} -{{< fatecode >}}(merge_to_set [LAMBDA O (X Y)] [X COLLECTION] [Y COLLECTION]){{< /fatecode >}} -{{< fatecode >}}(merge_to_set [LAMBDA O (X Y Z0 ... ZN)] [X COLLECTION] [Y COLLECTION] [Z0 COMPUTATION*] ... [ZN COMPUTATION*]){{< /fatecode >}} -Merges two collections into either a list or a set. This version of merging -only continues as long as both collections have elements. Thus, extra elements -in either list are ignored. 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. +{{< fatecode >}}(list:merge [LAMBDA O (X Y)] [X LIST|X SET] [Y LIST|Y SET]){{< /fatecode >}} +{{< fatecode >}}(set:merge [LAMBDA O (X Y)] [X LIST|X SET] [Y LIST|Y SET]){{< /fatecode >}} +Merges two collections into either a list (`list:merge`) or a set +(`set:merge`). This version of merging only continues as long as both +collections have elements. Thus, extra elements in either list are ignored. ### SAFE-MERGE COLLECTIONS -{{< fatecode >}}(safe_merge_to_list [LAMBDA O (X Y)] [X COMPUTATION*] [X COLLECTION] [Y COMPUTATION*] [Y COLLECTION]){{< /fatecode >}} -{{< fatecode >}}(safe_merge_to_list [LAMBDA O (X Y Z0 ... ZN)] [X COMPUTATION*] [X COLLECTION] [Y COMPUTATION*] [Y COLLECTION] [Z0 COMPUTATION*] ... [ZN COMPUTATION*]){{< /fatecode >}} -{{< fatecode >}}(safe_merge_to_set [LAMBDA O (X Y)] [X COLLECTION] [X COMPUTATION*] [Y COLLECTION] [Y COMPUTATION*]){{< /fatecode >}} -{{< fatecode >}}(safe_merge_to_set [LAMBDA O (X Y Z0 ... ZN)] [X COLLECTION] [X COMPUTATION*] [Y COLLECTION] [Y COMPUTATION*] [Z0 COMPUTATION*] ... [ZN COMPUTATION*]){{< /fatecode >}} -Merges two collections into either a list or a set. This version of merging -continues as long as either collection has elements. Hence the extra two -parameters compared to the non-safe version: these correspond to the value used -for the lambda when a collection has ran out of elements but the other has not. -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. +{{< fatecode >}}(list:safe_merge [LAMBDA O (X Y)] [X LIST|X SET] [X COMPUTATION] [Y LIST|Y SET] [Y COMPUTATION]){{< /fatecode >}} +{{< fatecode >}}(set:safe_merge [LAMBDA O (X Y)] [X LIST|X SET] [X COMPUTATION] [Y LIST|Y SET] [Y COMPUTATION]){{< /fatecode >}} +Safely merges two collections into either a list (`list:safe_merge`) or a set +(`set:safe_merge`). This version of merging continues as long as either +collection has elements. If one of the two collections runs out of elements +before the other, it uses the provided default value (`[X COMPUTATION]` for the +first list, `[Y COMPUTATION]` for the second one). ### MERGE COLLECTIONS (INDEXED) -{{< fatecode >}}(indexed_merge_to_list [LAMBDA O (INT X Y)] [X COLLECTION] [Y COLLECTION]){{< /fatecode >}} -{{< fatecode >}}(indexed_merge_to_list [LAMBDA O (INT X Y Z0 ... ZN)] [X COLLECTION] [Y COLLECTION] [Z0 COMPUTATION*] ... [ZN COMPUTATION*]){{< /fatecode >}} -{{< fatecode >}}(indexed_merge_to_set [LAMBDA O (INT X Y)] [X COLLECTION] [Y COLLECTION]){{< /fatecode >}} -{{< fatecode >}}(indexed_merge_to_set [LAMBDA O (INT X Y Z0 ... ZN)] [X COLLECTION] [Y COLLECTION] [Z0 COMPUTATION*] ... [ZN COMPUTATION*]){{< /fatecode >}} -Merges two collections into either a list or a set, indicating the index of both -elements as first parameter for the lambda function. This version of merging -only continues as long as both collections have elements. Thus, extra elements -in either list are ignored and there is only one index passed as parameter for -the lambda function. 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. +{{< fatecode >}}(list:indexed_merge [LAMBDA O (INT X Y)] [X LIST|X SET] [Y LIST|Y SET]){{< /fatecode >}} +{{< fatecode >}}(set:indexed_merge [LAMBDA O (INT X Y)] [X LIST|X SET] [Y LIST|Y SET]){{< /fatecode >}} +Merges two collections into either a list (`list:merge`) or a set +(`set:merge`). This version of merging only continues as long as both +collections have elements. Thus, extra elements in either list are ignored. +The first parameter passed to the lambda function is the index of the element +in both collections. ### SAFE-MERGE COLLECTIONS (INDEXED) -{{< fatecode >}}(safe_indexed_merge_to_list [LAMBDA O (INT X INT Y)] [X COMPUTATION*] [X COLLECTION] [Y COMPUTATION*] [Y COLLECTION]){{< /fatecode >}} -{{< fatecode >}}(safe_indexed_merge_to_list [LAMBDA O (INT X INT Y Z0 ... ZN)] [X COMPUTATION*] [X COLLECTION] [Y COMPUTATION*] [Y COLLECTION] [Z0 COMPUTATION*] ... [ZN COMPUTATION*]){{< /fatecode >}} -{{< fatecode >}}(safe_indexed_merge_to_set [LAMBDA O (INT X INT Y)] [X COMPUTATION*] [X COLLECTION] [Y COMPUTATION*] [Y COLLECTION]){{< /fatecode >}} -{{< fatecode >}}(safe_indexed_merge_to_set [LAMBDA O (INT X INT Y Z0 ... ZN)] [X COMPUTATION*] [X COLLECTION] [Y COMPUTATION*] [Y COLLECTION] [Z0 COMPUTATION*] ... [ZN COMPUTATION*]){{< /fatecode >}} -Merges two collections into either a list or a set. This version of merging -continues as long as either collection has elements. Hence the extra two -parameters compared to the non-safe version: these correspond to the value used -for the lambda when a collection has ran out of elements but the other has not. -This is also the reason why two indices are given. The index given for a list -that has ran out of elements is equal the size of the list. -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. +{{< fatecode >}}(list:indexed_safe_merge [LAMBDA O (INT X INT Y)] [X LIST|X SET] [X COMPUTATION] [Y LIST|Y SET] [Y COMPUTATION]){{< /fatecode >}} +{{< fatecode >}}(set:indexed_safe_merge [LAMBDA O (INT X INT Y)] [X LIST|X SET] [X COMPUTATION] [Y LIST|Y SET] [Y COMPUTATION]){{< /fatecode >}} +Safely merges two collections into either a list (`list:safe_merge`) or a set +(`set:safe_merge`). This version of merging continues as long as either +collection has elements. If one of the two collections runs out of elements +before the other, it uses the provided default value (`[X COMPUTATION]` for the +first list, `[Y COMPUTATION]` for the second one). The first and third parameters +passed to the lambda function correspond to the index of the element in either +collection. It does not increase if the collection has no more elements and is +using the default value. diff --git a/content/fate_v1/computations/conditionals/_index.md b/content/fate_v1/computations/conditionals/_index.md index 7b65294..ee86b80 100644 --- a/content/fate_v1/computations/conditionals/_index.md +++ b/content/fate_v1/computations/conditionals/_index.md @@ -10,13 +10,22 @@ some condition. All possible returned values must be of the same type. Returns `C0` is `[BOOL]` yields true, `C1` otherwise. ### COND -{{< fatecode >}}(cond ([B0 = BOOL] [C0 = COMPUTATION]) ... ([BN = BOOL] [CN = COMPUTATION])){{< /fatecode >}} +{{< 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 +{{< 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]`. diff --git a/content/fate_v1/computations/lambda_functions/_index.md b/content/fate_v1/computations/lambda_functions/_index.md index 35485a3..7992b54 100644 --- a/content/fate_v1/computations/lambda_functions/_index.md +++ b/content/fate_v1/computations/lambda_functions/_index.md @@ -7,17 +7,26 @@ 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 >}} +{{< 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 >}} +{{< fatecode >}}(eval [LAMBDA O (C0 ... CN)] [C0 = COMPUTATION] ... [CN = COMPUTATION]){{< /fatecode >}} Returns the result of evaluating the lambda function at `[REFERENCE]` given the parameters `C0` ... `CN`. +### PARTIAL EVALUATION +{{< fatecode >}}(partial [LAMBDA O (C0 ... CN)] [C0 = COMPUTATION] ... [CM = COMPUTATION]){{< /fatecode >}} + +Returns a lambda function corresponding to the `[LAMBDA O (C0 ... CN)]` in which +the first M parameters have already been filled with `C0` ... `CM`. + ## Examples {{< fatecode >}}(lambda ( (int i) ) (+ (var i) 1) diff --git a/content/fate_v1/computations/text/_index.md b/content/fate_v1/computations/text/_index.md index b91a75f..4f6f520 100644 --- a/content/fate_v1/computations/text/_index.md +++ b/content/fate_v1/computations/text/_index.md @@ -9,3 +9,8 @@ title: Text ### NEW LINE {{< fatecode >}}(newline){{< /fatecode >}} + +### JOIN +{{< fatecode >}}(join_text [TEXT LIST|TEXT SET] [TEXT]){{< /fatecode >}} +Returns a text value corresponding to all elements of the text collection being +appended, with `[TEXT]` having been put in between each pair. diff --git a/content/fate_v1/extensions/_index.md b/content/fate_v1/extensions/_index.md new file mode 100644 index 0000000..e9a04ee --- /dev/null +++ b/content/fate_v1/extensions/_index.md @@ -0,0 +1,15 @@ +--- +title: Extensions +weight: 9 +--- + +{{< fatecode >}}(declare_extra_instruction {Identifier} [T0 = TYPE] ... [TN = TYPE]){{< /fatecode >}} +Declares an external instruction `{Identifier}` with parameters of type `[T0]` +... `[TN]`. + +{{< fatecode >}}(declare_extra_computation [R = TYPE] {Identifier} [T0 = TYPE] ... [TN = TYPE]){{< /fatecode >}} +Declares an external computation `{Identifier}` with parameters of type `[T0]` +... `[TN]` and returning a value of type `[R]`. + +{{< fatecode >}}(declare_extra_type {Identifier}){{< /fatecode >}} +Declares an external type. diff --git a/content/fate_v1/instructions/_index.md b/content/fate_v1/instructions/_index.md index 70e3987..1f28036 100644 --- a/content/fate_v1/instructions/_index.md +++ b/content/fate_v1/instructions/_index.md @@ -23,7 +23,7 @@ Completes the execution of the current sequence. Completes the execution of the script. ### SET VALUE -{{< fatecode >}}(set! [REFERENCE] [COMPUTATION]){{< /fatecode >}} +{{< fatecode >}}(set! [X REFERENCE] [X COMPUTATION]){{< /fatecode >}} Gives the value `[COMPUTATION]` to `[REFERENCE]`. @@ -39,7 +39,6 @@ once the visited sequence has completed. ### JUMP TO SEQUENCE {{< fatecode >}}(jump_to! {String} [C0 = COMPUTATION] ... [CN = COMPUTATION]){{< /fatecode >}} - {{< fatecode >}}(jump_to! [SEQUENCE] [C0 = COMPUTATION] ... [CN = COMPUTATION]){{< /fatecode >}} Jumps to the sequence named `{String}` (or stored in `[SEQUENCE]`), with `C0` @@ -48,6 +47,6 @@ 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 >}} +{{< fatecode >}}([C0 = INSTRUCTION] ... [CN = INSTRUCTION]){{< /fatecode >}} Instruction corresponding to the execution of `[C0]` ... `[CN]` in order. diff --git a/content/fate_v1/instructions/addresses/_index.md b/content/fate_v1/instructions/addresses/_index.md index 1b9cdc1..cf5143b 100644 --- a/content/fate_v1/instructions/addresses/_index.md +++ b/content/fate_v1/instructions/addresses/_index.md @@ -1,6 +1,12 @@ --- title: Addresses --- +### ALLOCATION +{{< fatecode >}}(allocate! [POINTER REFERENCE]){{< /fatecode >}} + +Set `[POINTER REFERENCE]` to the address of a new memory location of type +`[TYPE]`. Don't forget to call `free` on it once you're done. + ### DE-ALLOCATION {{< fatecode >}}(free! [POINTER]){{< /fatecode >}} diff --git a/content/fate_v1/instructions/collections/_index.md b/content/fate_v1/instructions/collections/_index.md index fb557c2..0922b3e 100644 --- a/content/fate_v1/instructions/collections/_index.md +++ b/content/fate_v1/instructions/collections/_index.md @@ -6,85 +6,133 @@ lists; and `[SET]`, which are ordered lists, but only useable with `[COMPARABLE]` elements. ### ADDING A MEMBER -{{< fatecode >}}(add_element! [C0 = COMPUTATION*] ... [CN = COMPUTATION*] [COLLECTION VAR]){{< /fatecode >}} +{{< fatecode >}}(list:add_element! [C0 = X COMPUTATION*] ... [CN = X COMPUTATION*] [X LIST REFERENCE]){{< /fatecode >}} +{{< fatecode >}}(set:add_element! [C0 = X COMPUTATION*] ... [CN = X COMPUTATION*] [X SET REFERENCE]){{< /fatecode >}} -Adds `C0` ... `CN` to `[COLLECTION VAR]`. If `[COLLECTION VAR]` is a `[LIST]`, -the new members are added at the end of the list, in order (meaning that the -list then ends with `CN`). Note that `[COMPUTATION*]` does not support use of -the variable shorthand. +Adds `C0` ... `CN` to the `[X LIST]` or `[X SET]` collection reference. If the +collection is a `[LIST]`, the new members are added at the end of the list, in +order (meaning that the list then ends with `CN`). Note that `[COMPUTATION*]` +does not support use of the variable shorthand if this is a collection of +strings or text. ### ADDING A MEMBER AT INDEX -{{< fatecode >}}(add_element_at! [INT] [COMPUTATION*] [LIST VAR]){{< /fatecode >}} +{{< fatecode >}}(list:add_element_at! [INT] [X COMPUTATION*] [X LIST REFERENCE]){{< /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. +Adds `[COMPUTATION*]` to `[X LIST REFERENCE]` 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 if this is a collection of string or text. ### ADDING MEMBERS -{{< fatecode >}}(add_all_elements! [COLLECTION] [COLLECTION VAR]){{< /fatecode >}} +{{< fatecode >}}(list:add_all_elements! [X COLLECTION] [X LIST REFERENCE]){{< /fatecode >}} +{{< fatecode >}}(set:add_all_elements! [X COLLECTION] [X SET REFERENCE]){{< /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. +Adds all the elements of `[COLLECTION]` to the `[X LIST]` or `[X SET]` +collection reference. In the case of `[X LIST]`, the new members are added at +the end of the list. ### EMPTYING COLLECTIONS -{{< fatecode >}}(clear! [COLLECTION]){{< /fatecode >}} +{{< fatecode >}}(list:clear! [LIST REFERENCE]){{< /fatecode >}} +{{< fatecode >}}(set:clear! [SET REFERENCE]){{< /fatecode >}} -Removes all members of `[COLLECTION]`. +Removes all members of the `[LIST]` or `[SET]` collection reference. ### REMOVING MEMBER -{{< fatecode >}}(remove! [COMPUTATION] [COLLECTION]){{< /fatecode >}} +{{< fatecode >}}(list:remove! [X COMPUTATION*] [X LIST REFERENCE]){{< /fatecode >}} +{{< fatecode >}}(set:remove! [X COMPUTATION*] [X SET REFERENCE]){{< /fatecode >}} -Removes the first member of `[COLLECTION]` equal to `[COMPUTATION]`. +Removes the first member of the `[X LIST]` or `[X SET]` collection reference +equal to `[COMPUTATION]`. Note that `[COMPUTATION*]` does not support use of +the variable shorthand if this is a collection of string or text. ### REMOVING MEMBERS -{{< fatecode >}}(remove_all! [COMPUTATION] [COLLECTION]){{< /fatecode >}} +{{< fatecode >}}(list:remove_all! [X COMPUTATION*] [X LIST REFERENCE]){{< /fatecode >}} +{{< fatecode >}}(set:remove_all! [X COMPUTATION*] [X SET REFERENCE]){{< /fatecode >}} -Removes all instances of `[COMPUTATION]` from `[COLLECTION]`. +Removes all values equal to `[COMPUTATION]` from the `[X LIST]` or `[X SET]` +collection reference. Note that `[COMPUTATION*]` does not support use of the +variable shorthand if this is a collection of string or text. ### REMOVING AT INDEX -{{< fatecode >}}(remove_at! [INT] [COLLECTION]){{< /fatecode >}} +{{< fatecode >}}(list:remove_at! [INT] [LIST REFERENCE]){{< /fatecode >}} +{{< fatecode >}}(set:remove_at! [INT] [SET REFERENCE]){{< /fatecode >}} -Removes the element of `[COLLECTION]` at `[INT]`. +Removes from the collection reference the element at index `[INT]`. ### REVERSING LISTS -{{< fatecode >}}(reverse! [LIST]){{< /fatecode >}} +{{< fatecode >}}(list:reverse! [LIST REFERENCE]){{< /fatecode >}} -Reverses the order of the members of `[LIST]`. +Reverses the order of the members of `[LIST REFERENCE]`. ### 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. +{{< fatecode >}}(list:filter! [LAMBDA BOOL (X)] [X LIST REFERENCE]){{< /fatecode >}} +{{< fatecode >}}(set:filter! [LAMBDA BOOL (X)] [X SET REFERENCE]){{< /fatecode >}} +Modifies the collection reference so that only the elements for which +`[LAMBDA BOOL (X)]` returns `true` remain. ### 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. - -### MERGE COLLECTIONS -{{< fatecode >}}(merge! [LAMBDA Y (X Y)] [X COLLECTION] [Y COLLECTION VAR]){{< /fatecode >}} -{{< fatecode >}}(merge! [LAMBDA Y (X Y Z0 ... ZN)] [X COLLECTION] [Y COLLECTION VAR] [Z0 COMPUTATION*] ... [ZN COMPUTATION*]){{< /fatecode >}} - - -### SAFE-MERGE COLLECTIONS -{{< fatecode >}}(safe_merge! [LAMBDA Y (X Y)] [X COMPUTATION*] [X COLLECTION] [Y COMPUTATION*] [Y COLLECTION VAR]){{< /fatecode >}} -{{< fatecode >}}(safe_merge! [LAMBDA Y (X Y Z0 ... ZN)] [X COLLECTION] [X COMPUTATION*] [Y COMPUTATION*] [Y COLLECTION VAR] [Z0 COMPUTATION*] ... [ZN COMPUTATION*]){{< /fatecode >}} - -### MERGE COLLECTIONS (INDEXED) -{{< fatecode >}}(indexed_merge! [LAMBDA Y (INT X Y)] [X COLLECTION] [Y COLLECTION VAR]){{< /fatecode >}} -{{< fatecode >}}(indexed_merge! [LAMBDA Y (INT X Y Z0 ... ZN)] [X COLLECTION] [Y COLLECTION VAR] [Z0 COMPUTATION*] ... [ZN COMPUTATION*]){{< /fatecode >}} - -### SAFE-MERGE COLLECTIONS (INDEXED) -{{< fatecode >}}(safe_indexed_merge! [LAMBDA Y (INT X INT Y)] [X COMPUTATION*] [X COLLECTION] [Y COMPUTATION*] [Y COLLECTION VAR]){{< /fatecode >}} -{{< fatecode >}}(safe_indexed_merge! [LAMBDA Y (INT X INT Y Z0 ... ZN)] [X COMPUTATION*] [X COLLECTION] [Y COMPUTATION*] [Y COLLECTION VAR] [Z0 COMPUTATION*] ... [ZN COMPUTATION*]){{< /fatecode >}} +{{< fatecode >}}(list:indexed_filter! [LAMBDA BOOL (INT X)] [X LIST REFERENCE]){{< /fatecode >}} +{{< fatecode >}}(set:indexed_filter! [LAMBDA BOOL (INT X)] [X SET REFERENCE]){{< /fatecode >}} +Modifies the collection reference so that only the elements for which +`[LAMBDA BOOL (INT X)]` returns `true` remain, with the `[INT]` value being the +index of the element in the collection. + +### SUBLIST +{{< fatecode >}}(list:sublist! [start_at = INT] [end_before = INT] [LIST REFERENCE]){{< /fatecode >}} +{{< fatecode >}}(set:sublist! [start_at = INT] [end_before = INT] [SET REFERENCE]){{< /fatecode >}} + +Only keep in the collection reference the elements with indexes equal or +greater than `[start_at]` and strictly lower than `[end_before]`. + +### SORT +{{< fatecode >}}(list:sort! [LAMBDA INT (X X)] [X LIST REFERENCE]){{< /fatecode >}} + +Reorders the elements of the list reference according to the `[LAMBDA]` +function. The resulting order is ascending. To compare two elements, the lambda +function should return: +- a negative number if the first argument is lower than the second. +- zero if the first argument is equal to the second. +- a non-null positive number otherwise. + +### SHUFFLE +{{< fatecode >}}(list:shuffle! [LIST REFERENCE]+){{< /fatecode >}} + +Randomly changes the order of the elements in `[LIST REFERENCE]`. As a +shorthand, multiple calls to the `list:shuffle!` instruction can be merged by +passing more lists as arguments. + +### PUSH ELEMENT +{{< fatecode >}}(list:push_right! [X COMPUTATION] [X LIST REFERENCE]){{< /fatecode >}} +{{< fatecode >}}(list:push_left! [X COMPUTATION] [X LIST REFERENCE]){{< /fatecode >}} + +Adds an element `[X]` at the start (`list:push_left`) or the end +(`list:push_right`) of a list reference. + +### POP ELEMENT +{{< fatecode >}}(list:pop_right! [X LIST REFERENCE] [X REFERENCE]){{< /fatecode >}} +{{< fatecode >}}(list:pop_left! [X LIST REFERENCE] [X REFERENCE]){{< /fatecode >}} +{{< fatecode >}}(set:pop_right! [X SET REFERENCE] [X REFERENCE]){{< /fatecode >}} +{{< fatecode >}}(set:pop_left! [X SET REFERENCE] [X REFERENCE]){{< /fatecode >}} + + +Removes and retrieves the element at the start (`pop_left`) or the end +(`pop_right`) of a list. The removed element is stored in `[X REFERENCE]`. + +### PARTITION +{{< fatecode >}}(list:partition! [LAMBDA BOOL (X)] [if_true = X LIST REFERENCE] [if_false = X LIST REFERENCE]){{< /fatecode >}} +{{< fatecode >}}(set:partition! [LAMBDA BOOL (X)] [if_true = X SET REFERENCE] [if_false = X SET REFERENCE]){{< /fatecode >}} + +Partitions a collection reference `[if_true]`, leaving in the collection all elements +for which the lambda function returns `(true)` and moving to the collection reference +`[if_false]` all elements for which the lambda function returns `(false)`. + +### PARTITION (INDEXED) +{{< fatecode >}}(list:partition! [LAMBDA BOOL (INT X)] [if_true = X LIST REFERENCE] [if_false = X LIST REFERENCE]){{< /fatecode >}} +{{< fatecode >}}(set:partition! [LAMBDA BOOL (INT X)] [if_true = X SET REFERENCE] [if_false = X SET REFERENCE]){{< /fatecode >}} + +Partitions a collection reference `[if_true]`, leaving in the collection all elements +for which the lambda function returns `(true)` and moving to the collection reference +`[if_false]` all elements for which the lambda function returns `(false)`. The first +argument given to the lambda function corresponds to the index of the element in +the collection (prior to the partitioning). diff --git a/content/fate_v1/instructions/conditionals/_index.md b/content/fate_v1/instructions/conditionals/_index.md index 39a51b3..f99a1cf 100644 --- a/content/fate_v1/instructions/conditionals/_index.md +++ b/content/fate_v1/instructions/conditionals/_index.md @@ -6,22 +6,36 @@ computation. Every conditional branch defines its hierarchy level, from the local variables' point of view. ### IF -{{< fatecode >}}(if [BOOL] [INSTRUCTION]){{< /fatecode >}} +{{< 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 >}} +{{< 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 >}} +{{< 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 >}} +{{< 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 index 5aa14ac..82acb28 100644 --- a/content/fate_v1/instructions/loops/_index.md +++ b/content/fate_v1/instructions/loops/_index.md @@ -6,24 +6,44 @@ Every loop body defines its hierarchy level, from the local variables' point of view. ### WHILE -{{< fatecode >}}(while [BOOL] [I0 = INSTRUCTION] ... [IM = INSTRUCTION]){{< /fatecode >}} +{{< 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 >}} +{{< 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 >}} +{{< 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 >}} +{{< 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}`. diff --git a/content/fate_v1/instructions/player_choices/_index.md b/content/fate_v1/instructions/player_choices/_index.md index 9ead97c..4b54789 100644 --- a/content/fate_v1/instructions/player_choices/_index.md +++ b/content/fate_v1/instructions/player_choices/_index.md @@ -6,17 +6,29 @@ with a list of `[TEXT]` choices, and executing a list of instructions associated to the choice they have made. ### CHOICE OPTION -{{< fatecode >}}(option [TEXT] [I0 = INSTRUCTION] ... [IN = INSTRUCTION]){{< /fatecode >}} +{{< fatecode >}}(option [TEXT] + [I0 = INSTRUCTION] + ... + [IN = INSTRUCTION] +){{< /fatecode >}} Adds a choice showing `[TEXT]` to the user, and executing `[I0]` ... `[IN]` if chosen. ### CHOICE PROMPT -{{< fatecode >}}(player_choice! [C0 = CHOICE] ... [C1 = CHOICE]){{< /fatecode >}} +{{< 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]`. +A special version of the `for` loop is also possible, as described below: + +### USER CHOICE - FOR +TODO ### INTEGER PROMPT {{< fatecode >}}(prompt_integer! [INT REFERENCE] [MIN = INT] [MAX = INT] [TEXT]){{< /fatecode >}} diff --git a/content/fate_v1/notations/_index.md b/content/fate_v1/notations/_index.md index a29a58b..eea96e2 100644 --- a/content/fate_v1/notations/_index.md +++ b/content/fate_v1/notations/_index.md @@ -15,18 +15,18 @@ Valid separators are spaces, tabs, and line returns. Having multiple separators between two elements is the same as having a single one. ### Comments -Comments are line without anything but any number of separators before `;;`. -Every that follows the `;;` on that line is considered to be a comment. +Every that follows a `;;` on a line is considered to be a comment. {{< fatecode >}};; You can comment here (fate_version 1) - ;; Separators before the ';;' are also okay. -something ;; This is not a comment, since the line contains something else. +something ;; This very sentence is also a comment. ;; Multi line ;; comments need a ';;' on ;; every line. (end) {{< /fatecode >}} +To write the `;;` string literal in fate, the syntax is `(2;)`. + ### Literals A literal is a hard-coded string. Basically, writing `42` corresponds to a literal of value `42`. A literal is any non-empty hard-coded string not @@ -43,6 +43,7 @@ Now, the rules about separators and parentheses being absent in literals is a bit problematic for strings. To remedy this: * Writing `(lp)` counts as writing the literal `(`. * Writing `(rp)` counts as writing the literal `)`. +* Writing `(2;)` counts as writing the literal `;;`. * Writing `(sp)` counts as writing the literal ` ` (space). Thus, you cannot write: @@ -53,10 +54,10 @@ But you can write: And it will be a bunch of `{STRING}` literals. ### Identifier -`{IDENTIFIER}`: Non-empty string literal without space characters, `.`, `)`, -or `(`. Line returns and tabs are considered to be space characters. Strings -that correspond to valid numbers (e.g. `42`) are likely to cause issues and -should thus be avoided. +`{IDENTIFIER}`: Non-empty string literal without space characters, `;`, `.`, +`)`, or `(`. Line returns and tabs are considered to be space characters. +Strings that correspond to valid numbers (e.g. `42`) are likely to cause issues +and should thus be avoided. Examples of valid identifiers: * {{< fatecode >}}i{{< /fatecode >}} @@ -65,7 +66,6 @@ Examples of valid identifiers: * {{< fatecode >}}80x9!{{< /fatecode >}} * {{< fatecode >}}pseudo::namespacing<$confusion>**a**{{< /fatecode >}} - ### Value `[INT]`: Computation (or literal) returning a value of type `INT`. Similarly, `[STRING]` would indicate the same for a value of type `STRING`. @@ -81,7 +81,8 @@ as the `[STRING]` literal `my_var`, and to get the value of a variable, you would need to write something like `(var my_var)`. `[STRING]` automatically implies `[STRING*]`. -If need be, `(string {STRING})` +If need be, `(string {STRING})` lets you specify that you want `{STRING}` to be +a string without any ambiguity. Examples of valid value: * Values for `[INT]`: diff --git a/content/learn/01.start/_index.md b/content/learn/01.start/_index.md index 1741772..a3a4225 100644 --- a/content/learn/01.start/_index.md +++ b/content/learn/01.start/_index.md @@ -23,7 +23,7 @@ image. 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) +(end!) {{< /fatecode >}} This is a very minimal story in Fate. Let's look at what is it made of: @@ -36,7 +36,7 @@ This is a very minimal story in Fate. Let's look at what is it made of: 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. +* `(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 diff --git a/content/learn/02.choices/_index.md b/content/learn/02.choices/_index.md index a5ba4d7..b61ce94 100644 --- a/content/learn/02.choices/_index.md +++ b/content/learn/02.choices/_index.md @@ -32,39 +32,34 @@ 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: +(player_choice! + (option ( 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. + (option ( 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. + (option ( 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) +(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 +`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. +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 diff --git a/content/learn/03.variables/default.md b/content/learn/03.variables/default.md index 3d0e962..d7fbc48 100644 --- a/content/learn/03.variables/default.md +++ b/content/learn/03.variables/default.md @@ -21,69 +21,64 @@ appropriate. {{< fatecode >}}(fate_version 1) (local int hero_money) -(local int price_of_booze) +(local int price_of_booze 12) -(set hero_money 42) -(set price_of_booze 12) +(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. +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. +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. +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: +(player_choice! + (option ( 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. + The barman's lack of reaction is disappointing, but seeing the beer being + poured does improve your mood. (newline) Satisfied, you hand the barman (var price_of_booze) copper coins. - (set hero_money - (- (var hero_money) (var price_of_booze)) - ) + (set! hero_money (- hero_money price_of_booze)) ) - ( - ( Fall asleep ) - Deciding to break away from the expected storyline, you promptly - fall asleep. + (option ( 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) + Upon waking up, your hard-trained reflexes inform you that someone stole + all your money. + (set! hero_money 0) ) ) -(end) +(end!) {{< /fatecode >}} * `(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. + `hero_money`. This variable takes the default value for its type. +* `(local int price_of_booze 12)` declares an `int` variable with the name + `price_of_booze`. This variable takes the value `12`. +* `(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 +* `(- hero_money 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. + use a prefixed form. Because there is no ambiguity about `hero_money` and + `price_of_booze` being strings, it is not necessary to write + `(- (var hero_money) (var price_of_booze))`. -`local`, `set`, `player_choice`, and `end`, are instructions. Instructions do +`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 diff --git a/content/learn/04.sequences/default.md b/content/learn/04.sequences/default.md index 8b56ee7..874b14b 100644 --- a/content/learn/04.sequences/default.md +++ b/content/learn/04.sequences/default.md @@ -4,7 +4,7 @@ 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` +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 @@ -31,94 +31,86 @@ Sequences can take parameters. {{< fatecode >}}(fate_version 1) -(global int hero_money) +(global int hero_money 42) -(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. +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. +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) +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! + (option ( Ask the barman for a refill ) + (visit! get_a_refill) ) - ( - ( Fall asleep ) - (jump_to fall_asleep) + (option ( Fall asleep ) + (jump_to! fall_asleep) ) ) (define_sequence pay ( (int cost) ) - (set hero_money - (- (var hero_money) (var cost)) - ) + (set! hero_money (- hero_money cost)) ) (define_sequence get_a_refill () (local int price_of_booze) - (set price_of_booze 12) + (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. + The barman's lack of reaction is disappointing, but seeing the beer being + poured does improve your mood. (newline) Satisfied, you hand the barman (var price_of_booze) copper coins. - (visit pay (var price_of_booze)) + (visit! pay price_of_booze) ) (define_sequence fall_asleep () - Deciding to break away from the expected storyline, you promptly - 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) + 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) + This set-back was more than you could handle. You give up on this barely + coherent story. + (end!) ) -(end) +(end!) {{< /fatecode >}} -* `(visit get_a_refill)` makes a visit to the sequence `get_a_refill`. Since +* `(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 +* `(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)` + 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. +* `(visit! pay price_of_booze)` makes a visit to the `pay` sequence, and the + compiler infers that `price_of_booze` is a variable whose value should be + passed as parameter. `(visit! pay (var price_of_booze))` would make that explicit. +* `(global int hero_money 42)` 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). +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 index 06b6436..0829db1 100644 --- a/content/learn/05.files/default.md +++ b/content/learn/05.files/default.md @@ -15,9 +15,7 @@ but only if that file has not already been explored. {{< fatecode >}}(fate_version 1) -(global int hero_money) - -(set hero_money 42) +(global int hero_money 42) {{< /fatecode >}} * Create a new file, `actions.fate`, with the following content: @@ -27,10 +25,9 @@ but only if that file has not already been explored. (require data.fate) (define_sequence pay ( (int cost) ) - (set hero_money - (- (var hero_money) (var cost)) - ) + (set! hero_money (- hero_money cost)) ) + {{< /fatecode >}} * Create a new file, `get_a_refill.fate`, with the following content: @@ -42,17 +39,17 @@ but only if that file has not already been explored. (define_sequence get_a_refill () (local int price_of_booze) - (set price_of_booze 12) + (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. + poured does improve your mood. (newline) Satisfied, you hand the barman (var price_of_booze) copper coins. - (visit pay (var price_of_booze)) + (visit! pay price_of_booze) ) {{< /fatecode >}} @@ -69,11 +66,11 @@ but only if that file has not already been explored. (newline) Upon waking up, your hard-trained reflexes inform you that someone stole all your money. - (set hero_money 0) + (set! hero_money 0) (newline) - This set-back was more than you could take. You give up on this barely + This set-back was more than you could handle. You give up on this barely coherent story. - (end) + (end!) ) {{< /fatecode >}} @@ -81,6 +78,9 @@ but only if that file has not already been explored. {{< fatecode >}}(fate_version 1) +(require get_a_refill.fate) +(require falling_asleep.fate) + 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 @@ -94,21 +94,16 @@ anything. Worse, the alcoholic trait is part of the image. 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) +(player_choice! + (option ( Ask the barman for a refill ) + (visit! get_a_refill) ) - ( - ( Fall asleep ) - (jump_to fall_asleep) + (option ( Fall asleep ) + (jump_to! fall_asleep) ) ) -(require get_a_refill.fate) -(require falling_asleep.fate) - -(end) +(end!) {{< /fatecode >}} With this, the story is much more easy to follow. Let's continue by looking diff --git a/content/learn/06.pointers/default.md b/content/learn/06.pointers/default.md index 8432b3e..82a5733 100644 --- a/content/learn/06.pointers/default.md +++ b/content/learn/06.pointers/default.md @@ -24,11 +24,10 @@ Given a pointer `p`, the variable being pointed to can be referred to using **data.fate:** {{< fatecode >}}(fate_version 1) -(global int hero_money) +(global int hero_money 42) (global string hero_name) - -(set hero_money 42) {{< /fatecode >}} + **get_a_refill.fate:** {{< fatecode >}}(fate_version 1) @@ -41,11 +40,8 @@ Given a pointer `p`, the variable being pointed to can be referred to using (int decrease) ) Great! The price of booze just lowered from (at price_pointer) - (set (at price_pointer) - (- - (at price_pointer) - (var decrease) - ) + (set! (at price_pointer) + (- (at price_pointer) decrease) ) to (at price_pointer)! ) @@ -53,25 +49,24 @@ Given a pointer `p`, the variable being pointed to can be referred to using (define_sequence get_a_refill () (local int price_of_booze) - (set price_of_booze 12) + (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. + poured does improve your mood. (newline) Satisfied, you hand the barman (var price_of_booze) copper coins. - (visit pay (var price_of_booze)) - (newline) + (visit! pay price_of_booze) The barman sighs, then asks: - (prompt_string (ptr hero_name) 2 64 What is your name, then, hero?) + (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) + (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!" @@ -85,7 +80,7 @@ Given a pointer `p`, the variable being pointed to can be referred to using ) {{< /fatecode >}} -* `(prompt_string (ptr hero_name) 2 64 What is your name, then, hero?)` prompts +* `(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. @@ -106,10 +101,9 @@ sheet, so [let's create one](/learn/structures). (require data.fate) (define_sequence pay ( (int cost) ) - (set hero_money - (- (var hero_money) (var cost)) - ) + (set! hero_money (- hero_money cost)) ) + {{< /fatecode >}} **falling_asleep.fate:** @@ -125,17 +119,20 @@ sheet, so [let's create one](/learn/structures). (newline) Upon waking up, your hard-trained reflexes inform you that someone stole all your money. - (set hero_money 0) + (set! hero_money 0) (newline) - This set-back was more than you could take. You give up on this barely + This set-back was more than you could handle. You give up on this barely coherent story. - (end) + (end!) ) {{< /fatecode >}} **main.fate:** {{< fatecode >}}(fate_version 1) +(require get_a_refill.fate) +(require falling_asleep.fate) + 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 @@ -149,19 +146,14 @@ anything. Worse, the alcoholic trait is part of the image. 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) +(player_choice! + (option ( Ask the barman for a refill ) + (visit! get_a_refill) ) - ( - ( Fall asleep ) - (jump_to fall_asleep) + (option ( Fall asleep ) + (jump_to! fall_asleep) ) ) -(require get_a_refill.fate) -(require falling_asleep.fate) - -(end) +(end!) {{< /fatecode >}} diff --git a/content/learn/07.structures/default.md b/content/learn/07.structures/default.md index 8e2dede..fa6f17e 100644 --- a/content/learn/07.structures/default.md +++ b/content/learn/07.structures/default.md @@ -17,47 +17,52 @@ Fields of a structure can be accessed in two ways: using the 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 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. +The name of user-defined types are expected to start with `#`. This ensures +backward compatibility if a type with a similar name is introduced in a future +(non-major) version of Fate. A warning will be raised during compilation if this +convention is not upheld. + **data.fate:** {{< fatecode >}}(fate_version 1) -(declare_structure weapon +(declare_structure #weapon (text name) (int attack) (int precision) ) -(declare_structure armor +(declare_structure #armor (text name) (int defense) ) -(declare_structure character +(declare_structure #character (string name) (int money) - (weapon weapon) - (armor armor) + (#weapon weapon) + (#armor armor) ) -(global character hero) +(global #character hero) -(set_fields! hero.weapon +(struct:set_fields! hero.weapon (name (text "Legendary" sword)) (attack 3) (precision 50) ) -(set_fields! hero.armor +(struct:set_fields! hero.armor (name (text "Refined" attire)) (defense 1) ) -(set hero.money 42) +(set! hero.money 42) {{< /fatecode >}} * `(text "Refined" attire)` generates a `text` value containing a textual @@ -87,11 +92,8 @@ collection is available at the smithy](/learn/collections). (int decrease) ) Great! The price of booze just lowered from (at price_pointer) - (set (at price_pointer) - (- - (at price_pointer) - (var decrease) - ) + (set! (at price_pointer) + (- (at price_pointer) decrease) ) to (at price_pointer)! ) @@ -99,25 +101,24 @@ collection is available at the smithy](/learn/collections). (define_sequence get_a_refill () (local int price_of_booze) - (set price_of_booze 12) + (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. + poured does improve your mood. (newline) Satisfied, you hand the barman (var price_of_booze) copper coins. - (visit pay (var price_of_booze)) - (newline) + (visit! pay price_of_booze) The barman sighs, then asks: - (prompt_string (ptr hero.name) 2 64 What is your name, then, hero?) + (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) + (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!" @@ -137,14 +138,12 @@ collection is available at the smithy](/learn/collections). (require data.fate) (define_sequence pay ( (int cost) ) - (set hero_money - (- (var hero.money) (var cost)) - ) + (set! hero.money (- hero.money cost)) ) + {{< /fatecode >}} **falling_asleep.fate:** - {{< fatecode >}}(fate_version 1) (require data.fate) @@ -157,17 +156,21 @@ collection is available at the smithy](/learn/collections). (newline) Upon waking up, your hard-trained reflexes inform you that someone stole all your money. - (set hero.money 0) + (set! hero.money 0) (newline) - This set-back was more than you could take. You give up on this barely + This set-back was more than you could handle. You give up on this barely coherent story. - (end) + (end!) ) {{< /fatecode >}} **main.fate:** {{< fatecode >}}(fate_version 1) +(require get_a_refill.fate) +(require falling_asleep.fate) + + 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 @@ -181,19 +184,14 @@ anything. Worse, the alcoholic trait is part of the image. 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) +(player_choice! + (option ( Ask the barman for a refill ) + (visit! get_a_refill) ) - ( - ( Fall asleep ) - (jump_to fall_asleep) + (option ( Fall asleep ) + (jump_to! fall_asleep) ) ) -(require get_a_refill.fate) -(require falling_asleep.fate) - -(end) +k(end!) {{< /fatecode >}} diff --git a/content/learn/08.collections/default.md b/content/learn/08.collections/default.md index 34310f3..57463e0 100644 --- a/content/learn/08.collections/default.md +++ b/content/learn/08.collections/default.md @@ -24,12 +24,12 @@ Let's add a new file, `smithy_inventory.fate`: (require data.fate) -(global (list (cons weapon int)) smithy_weapons) -(global (list (cons weapon int)) smithy_armors) +(global (list (cons #weapon int)) smithy_weapons) +(global (list (cons #armor int)) smithy_armors) -(add! +(list:add! (cons - (set_fields (default weapon) + (struct:set_fields (default #weapon) (name (text An Iron Rod)) (attack 10) (precision 70) @@ -38,9 +38,9 @@ Let's add a new file, `smithy_inventory.fate`: ) smithy_weapons ) -(add! +(list:add! (cons - (set_fields (default weapon) + (struct:set_fields (default #weapon) (name (text A Magnificient Brick)) (attack 6) (precision 90) @@ -50,19 +50,16 @@ Let's add a new file, `smithy_inventory.fate`: smithy_weapons ) -(add! +(list:add! (cons - (set_fields (default armor) + (struct:set_fields (default #armor) (name (text A raincoat?!)) (defense 7) ) 160 ) - smithy_armors -) -(add! (cons - (set_fields (default armor) + (struct:set_fields (default #armor) (name (text A nice cape)) (defense 3) ) @@ -75,8 +72,9 @@ Let's add a new file, `smithy_inventory.fate`: 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. +**IMPORTANT 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:** {{< fatecode >}}(fate_version 1) @@ -93,17 +91,14 @@ going to introduce a lot of things to make it *much*, *much* easier to write. You have (var hero.money) coins. (newline) What will you look at? - (player_choice - ( - ( Let's see the weapons ) - (jump_to see_weapons) + (player_choice! + (option ( Let's see the weapons ) + (jump_to! see_weapons) ) - ( - ( Let's see the armors ) - (jump_to see_armors) + (option ( Let's see the armors ) + (jump_to! see_armors) ) - ( - ( Nothing, let's go back to the bar ) + (option ( Nothing, let's go back to the bar ) ) ) ) @@ -114,29 +109,26 @@ going to introduce a lot of things to make it *much*, *much* easier to write. (local text weapon_a_label) (local text weapon_b_label) - (visit get_weapon_label - (access smithy_weapons 0) + (visit! get_weapon_label + (list:access 0 smithy_weapons) (ptr weapon_a_label) ) - (visit get_weapon_label - (access smithy_weapons 1) + (visit! get_weapon_label + smithy_weapons.1 (ptr weapon_b_label) ) - (player_choice - ( - ( (var weapon_a_label) ) - (visit buy_weapon (access smithy_weapons 0)) - (jump_to visit_smithy) + (player_choice! + (option ( (var weapon_a_label) ) + (visit! buy_weapon smithy_weapons.0) + (jump_to! visit_smithy) ) - ( - ( (var weapon_a_label) ) - (visit buy_weapon (access smithy_weapons 1)) - (jump_to visit_smithy) + (option ( (var weapon_b_label) ) + (visit! buy_weapon (list:access 1 smithy_weapons)) + (jump_to! visit_smithy) ) - ( - ( Nevermind ) - (jump_to visit_smithy) + (option ( Nevermind ) + (jump_to! visit_smithy) ) ) ) @@ -147,29 +139,26 @@ going to introduce a lot of things to make it *much*, *much* easier to write. (local text armor_a_label) (local text armor_b_label) - (visit get_armor_label - (access smithy_armors 0) + (visit! get_armor_label + smithy_armors.0 (ptr armor_a_label) ) - (visit get_armor_label - (access smithy_armors 1) + (visit! get_armor_label + smithy_armors.1 (ptr armor_b_label) ) - (player_choice - ( - ( (var armor_a_label) ) - (visit buy_armor (access smithy_armors 0)) - (jump_to visit_smithy) + (player_choice! + (option ( (var armor_a_label) ) + (visit! buy_armor smithy_armors.0) + (jump_to! visit_smithy) ) - ( - ( (var armor_a_label) ) - (visit buy_armor (access smithy_armors 1)) - (jump_to visit_smithy) + (option ( (var armor_b_label) ) + (visit! buy_armor smithy_armors.1) + (jump_to! visit_smithy) ) - ( - ( Nevermind ) - (jump_to visit_smithy) + (option ( Nevermind ) + (jump_to! visit_smithy) ) ) ) @@ -177,19 +166,19 @@ going to introduce a lot of things to make it *much*, *much* easier to write. ;; A terrible way to get labels (define_sequence get_weapon_label ( - ((cons weapon int) weapon_offer) + ((cons #weapon int) weapon_offer) ((ptr text) label) ) - (local weapon weapon) + (local #weapon weapon) (local int price) - (set weapon (car weapon_offer)) - (set price (cdr weapon_offer)) + (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. + (set! (at label) + (text + Buy "(var weapon.name)" (lp)attack: (var weapon.attack), + precision: (var weapon.precision)(rp) for (var price) coins. ) ) ) @@ -197,90 +186,98 @@ going to introduce a lot of things to make it *much*, *much* easier to write. ;; A terrible way to get labels (define_sequence get_armor_label ( - ((cons armor int) armor_offer) + ((cons #armor int) armor_offer) ((ptr text) label) ) - (local armor armor) + (local #armor armor) (local int price) - (set armor (car armor_offer)) - (set price (cdr armor_offer)) + (set! armor (car armor_offer)) + (set! price (cdr armor_offer)) - (set (at label) - ( - Buy "(var armor.name)" \(defense: (var armor.defense)\), + (set! (at label) + (text + Buy "(var armor.name)" (lp)defense: (var armor.defense)(rp), for (var price) coins. ) ) ) -(define_sequence buy_weapon ( ((cons weapon int) weapon) ) +(define_sequence buy_weapon ( ((cons #weapon int) weapon) ) ;; We can't even deny a sell yet... - (set hero.weapon (car weapon)) + (set! hero.weapon (car weapon)) Equipped (var hero.weapon.name). (newline) ) -(define_sequence buy_armor ( ((cons armor int) armor) ) +(define_sequence buy_armor ( ((cons #armor int) armor) ) ;; We can't even deny a sell yet... - (set hero.armor (car armor)) + (set! hero.armor (car armor)) Equipped (var hero.armor.name). (newline) ) {{< /fatecode >}} +Now, add `(require smithy.fate)` at the start of the **get_a_refill.fate** +file, then add `(visit! visit_smithy)` at the end of the `get_a_refill` +sequence, so that our hero indeed goes to visit this great shop. + * `(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. +* `(list: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. You can + have multiple `something` to add to the same list in the same `list:add` call. +* `(list:access 0 my_list)` gets you the first element of `my_list`. If the + index is a constant, it is preferable to write `my_list.0` instead. * `(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 +## (Mostly) Unchanged Files **data.fate:** {{< fatecode >}}(fate_version 1) -(declare_structure weapon +(declare_structure #weapon (text name) (int attack) (int precision) ) -(declare_structure armor +(declare_structure #armor (text name) (int defense) ) -(declare_structure character +(declare_structure #character (string name) (int money) - (weapon weapon) - (armor armor) + (#weapon weapon) + (#armor armor) ) -(global character hero) +(global #character hero) -(set_fields! hero.weapon +(struct:set_fields! hero.weapon (name (text "Legendary" sword)) (attack 3) (precision 50) ) -(set_fields! hero.armor +(struct:set_fields! hero.armor (name (text "Refined" attire)) (defense 1) ) -(set hero.money 42) +(set! hero.money 42) {{< /fatecode >}} **get_a_refill.fate:** @@ -288,6 +285,7 @@ start with the least expected one: [lambda functions](/learn/lambdas). (require data.fate) (require actions.fate) +(require smithy.fate) (define_sequence lower_price_of_booze ( @@ -295,11 +293,8 @@ start with the least expected one: [lambda functions](/learn/lambdas). (int decrease) ) Great! The price of booze just lowered from (at price_pointer) - (set (at price_pointer) - (- - (at price_pointer) - (var decrease) - ) + (set! (at price_pointer) + (- (at price_pointer) decrease) ) to (at price_pointer)! ) @@ -307,25 +302,24 @@ start with the least expected one: [lambda functions](/learn/lambdas). (define_sequence get_a_refill () (local int price_of_booze) - (set price_of_booze 12) + (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. + poured does improve your mood. (newline) Satisfied, you hand the barman (var price_of_booze) copper coins. - (visit pay (var price_of_booze)) - (newline) + (visit! pay price_of_booze) The barman sighs, then asks: - (prompt_string (ptr hero.name) 2 64 What is your name, then, hero?) + (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) + (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!" @@ -336,6 +330,7 @@ start with the least expected one: [lambda functions](/learn/lambdas). (newline) "Take this pre-payment and head to the smithy." (newline) + (visit! visit_smithy) ) {{< /fatecode >}} @@ -345,10 +340,9 @@ start with the least expected one: [lambda functions](/learn/lambdas). (require data.fate) (define_sequence pay ( (int cost) ) - (set hero_money - (- (var hero.money) (var cost)) - ) + (set! hero.money (- hero.money cost)) ) + {{< /fatecode >}} **falling_asleep.fate:** @@ -364,17 +358,20 @@ start with the least expected one: [lambda functions](/learn/lambdas). (newline) Upon waking up, your hard-trained reflexes inform you that someone stole all your money. - (set hero.money 0) + (set! hero.money 0) (newline) - This set-back was more than you could take. You give up on this barely + This set-back was more than you could handle. You give up on this barely coherent story. - (end) + (end!) ) {{< /fatecode >}} **main.fate:** {{< fatecode >}}(fate_version 1) +(require get_a_refill.fate) +(require falling_asleep.fate) + 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 @@ -388,19 +385,14 @@ anything. Worse, the alcoholic trait is part of the image. 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) +(player_choice! + (option ( Ask the barman for a refill ) + (visit! get_a_refill) ) - ( - ( Fall asleep ) - (jump_to fall_asleep) + (option ( Fall asleep ) + (jump_to! fall_asleep) ) ) -(require get_a_refill.fate) -(require falling_asleep.fate) - -(end) +(end!) {{< /fatecode >}} diff --git a/content/learn/09.lambdas/default.md b/content/learn/09.lambdas/default.md index 91d5660..8119639 100644 --- a/content/learn/09.lambdas/default.md +++ b/content/learn/09.lambdas/default.md @@ -17,35 +17,36 @@ memory by itself, nor can it contain any instructions. (require smithy_inventory.fate) -(global (lambda text ((cons weapon int))) get_weapon_offer_label) -(global (lambda text ((cons armor int))) get_armor_offer_label) +;; Maybe it would be better to put this in a different file, but oh well... +(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 +(set! get_weapon_offer_label (lambda - ( ((cons weapon int) offer) ) + ( ((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. + Buy "(var weapon.name)" (lp)attack: (var weapon.attack), + precision: (var weapon.precision)(rp) for (var price) coins. ) ) ) ) -(set get_armor_offer_label +(set! get_armor_offer_label (lambda - ( ((cons armor int) offer) ) + ( ((cons #armor int) offer) ) (let ( (armor (car offer)) (price (cdr offer)) ) (text - Buy "(var armor.name)" \(defense: (var armor.defense)\), + Buy "(var armor.name)" (lp)defense: (var armor.defense)(rp), for (var price) coins. ) ) @@ -62,71 +63,64 @@ memory by itself, nor can it contain any instructions. You have (var hero.money) coins. (newline) What will you look at? - (player_choice - ( - ( Let's see the weapons ) - (jump_to see_weapons) + (player_choice! + (option ( Let's see the weapons ) + (jump_to! see_weapons) ) - ( - ( Let's see the armors ) - (jump_to see_armors) + (option ( Let's see the armors ) + (jump_to! see_armors) ) - ( - ( Nothing, let's go back to the bar ) + (option ( 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) + ;; We'll improve it further once we get to loops. + + (player_choice! + (option ( (eval get_weapon_offer_label smithy_weapons.0) ) + (visit! buy_weapon 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) + (option ( (eval get_weapon_offer_label smithy_weapons.1) ) + (visit! buy_weapon smithy_weapons.1) + (jump_to! visit_smithy) ) - ( - ( Nevermind ) - (jump_to visit_smithy) + (option ( 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) + ;; We'll improve it further once we get to loops. + + (player_choice! + (option ( (eval get_armor_offer_label smithy_armors.0) ) + (visit! buy_armor 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) + (option ( (eval get_armor_offer_label smithy_armors.1) ) + (visit! buy_armor smithy_armors.1) + (jump_to! visit_smithy) ) - ( - ( Nevermind ) - (jump_to visit_smithy) + (option ( 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)) +(define_sequence buy_weapon ( ((cons #weapon int) weapon) ) + ;; We still can't even deny a sell... + (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)) +(define_sequence buy_armor ( ((cons #armor int) armor) ) + ;; We still can't even deny a sell... + (set! hero.armor (car armor)) Equipped (var hero.armor.name). (newline) ) @@ -154,38 +148,38 @@ This was a first step toward cleaning up `smithy.fate`. Next, we'll use **data.fate:** {{< fatecode >}}(fate_version 1) -(declare_structure weapon +(declare_structure #weapon (text name) (int attack) (int precision) ) -(declare_structure armor +(declare_structure #armor (text name) (int defense) ) -(declare_structure character +(declare_structure #character (string name) (int money) - (weapon weapon) - (armor armor) + (#weapon weapon) + (#armor armor) ) -(global character hero) +(global #character hero) -(set_fields! hero.weapon +(struct:set_fields! hero.weapon (name (text "Legendary" sword)) (attack 3) (precision 50) ) -(set_fields! hero.armor +(struct:set_fields! hero.armor (name (text "Refined" attire)) (defense 1) ) -(set hero.money 42) +(set! hero.money 42) {{< /fatecode >}} **get_a_refill.fate:** @@ -193,6 +187,7 @@ This was a first step toward cleaning up `smithy.fate`. Next, we'll use (require data.fate) (require actions.fate) +(require smithy.fate) (define_sequence lower_price_of_booze ( @@ -200,11 +195,8 @@ This was a first step toward cleaning up `smithy.fate`. Next, we'll use (int decrease) ) Great! The price of booze just lowered from (at price_pointer) - (set (at price_pointer) - (- - (at price_pointer) - (var decrease) - ) + (set! (at price_pointer) + (- (at price_pointer) decrease) ) to (at price_pointer)! ) @@ -212,25 +204,24 @@ This was a first step toward cleaning up `smithy.fate`. Next, we'll use (define_sequence get_a_refill () (local int price_of_booze) - (set price_of_booze 12) + (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. + poured does improve your mood. (newline) Satisfied, you hand the barman (var price_of_booze) copper coins. - (visit pay (var price_of_booze)) - (newline) + (visit! pay price_of_booze) The barman sighs, then asks: - (prompt_string (ptr hero.name) 2 64 What is your name, then, hero?) + (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) + (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!" @@ -241,6 +232,7 @@ This was a first step toward cleaning up `smithy.fate`. Next, we'll use (newline) "Take this pre-payment and head to the smithy." (newline) + (visit! visit_smithy) ) {{< /fatecode >}} @@ -250,9 +242,7 @@ This was a first step toward cleaning up `smithy.fate`. Next, we'll use (require data.fate) (define_sequence pay ( (int cost) ) - (set hero_money - (- (var hero.money) (var cost)) - ) + (set! hero.money (- hero.money cost)) ) {{< /fatecode >}} @@ -269,17 +259,20 @@ This was a first step toward cleaning up `smithy.fate`. Next, we'll use (newline) Upon waking up, your hard-trained reflexes inform you that someone stole all your money. - (set hero.money 0) + (set! hero.money 0) (newline) - This set-back was more than you could take. You give up on this barely + This set-back was more than you could handle. You give up on this barely coherent story. - (end) + (end!) ) {{< /fatecode >}} **main.fate:** {{< fatecode >}}(fate_version 1) +(require get_a_refill.fate) +(require falling_asleep.fate) + 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 @@ -293,21 +286,16 @@ anything. Worse, the alcoholic trait is part of the image. 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) +(player_choice! + (option ( Ask the barman for a refill ) + (visit! get_a_refill) ) - ( - ( Fall asleep ) - (jump_to fall_asleep) + (option ( Fall asleep ) + (jump_to! fall_asleep) ) ) -(require get_a_refill.fate) -(require falling_asleep.fate) - -(end) +(end!) {{< /fatecode >}} **smithy_inventory.fate:** @@ -315,12 +303,12 @@ out to be an already empty glass in your hand and finds the barman. (require data.fate) -(global (list (cons weapon int)) smithy_weapons) -(global (list (cons weapon int)) smithy_armors) +(global (list (cons #weapon int)) smithy_weapons) +(global (list (cons #armor int)) smithy_armors) -(add! +(list:add! (cons - (set_fields (default weapon) + (struct:set_fields (default #weapon) (name (text An Iron Rod)) (attack 10) (precision 70) @@ -329,9 +317,9 @@ out to be an already empty glass in your hand and finds the barman. ) smithy_weapons ) -(add! +(list:add! (cons - (set_fields (default weapon) + (struct:set_fields (default #weapon) (name (text A Magnificient Brick)) (attack 6) (precision 90) @@ -341,19 +329,16 @@ out to be an already empty glass in your hand and finds the barman. smithy_weapons ) -(add! +(list:add! (cons - (set_fields (default armor) + (struct:set_fields (default #armor) (name (text A raincoat?!)) (defense 7) ) 160 ) - smithy_armors -) -(add! (cons - (set_fields (default armor) + (struct:set_fields (default #armor) (name (text A nice cape)) (defense 3) ) diff --git a/content/learn/10.conditions/default.md b/content/learn/10.conditions/default.md index 0b449b4..9125a14 100644 --- a/content/learn/10.conditions/default.md +++ b/content/learn/10.conditions/default.md @@ -23,155 +23,150 @@ can be used both as instruction and computation. `if` is only for instructions. * `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 +All of these can be used within a `player_choice!` to control what options are available. +Let's start our changes by checking if this is the player's first visit to the +smithy, as there is no need to give a detailed description of the place if it +is not. We can also use conditions to check if the player is able to purchase +items: + **smithy.fate:** {{< fatecode >}}(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) +;; Maybe it would be better to put this in a different file, but oh well... +(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 +(set! get_weapon_offer_label (lambda - ( ((cons weapon int) offer) ) + ( ((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. + Buy "(var weapon.name)" (lp)attack: (var weapon.attack), + precision: (var weapon.precision)(rp) for (var price) coins. ) ) ) ) -(set get_armor_offer_label +(set! get_armor_offer_label (lambda - ( ((cons armor int) offer) ) + ( ((cons #armor int) offer) ) (let ( (armor (car offer)) (price (cdr offer)) ) (text - Buy "(var armor.name)" \(defense: (var armor.defense)\), + Buy "(var armor.name)" (lp)defense: (var armor.defense)(rp), for (var price) coins. ) ) ) ) -(global bool has_visited_smithy) - -(set has_visited_smithy (false)) +(global bool has_visited_smithy (false)) (define_sequence visit_smithy () - (if (not (var has_visited_smithy)) + (if (not 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)) + (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) + (player_choice! + (option ( Let's see the weapons ) + (jump_to! see_weapons) ) - ( - ( Let's see the armors ) - (jump_to see_armors) + (option ( Let's see the armors ) + (jump_to! see_armors) ) - ( - ( Nothing, let's go back to the bar ) + (option ( 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) + ;; We'll improve it further once we get to loops. + + (player_choice! + (option ( (eval get_weapon_offer_label smithy_weapons.0) ) + (visit! buy_weapon 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) + (option ( (eval get_weapon_offer_label smithy_weapons.1) ) + (visit! buy_weapon smithy_weapons.1) + (jump_to! visit_smithy) ) - ( - ( Nevermind ) - (jump_to visit_smithy) + (option ( 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) + ;; We'll improve it further once we get to loops. + + (player_choice! + (option ( (eval get_armor_offer_label smithy_armors.0) ) + (visit! buy_armor 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) + (option ( (eval get_armor_offer_label smithy_armors.1) ) + (visit! buy_armor smithy_armors.1) + (jump_to! visit_smithy) ) - ( - ( Nevermind ) - (jump_to visit_smithy) + (option ( Nevermind ) + (jump_to! visit_smithy) ) ) ) -(define_sequence buy_weapon ( ((cons weapon int) weapon) ) - ;; We can't even deny a sell yet... +(define_sequence buy_weapon ( ((cons #weapon int) weapon) ) (local int money_after) - (set money_after (- (var hero.money) (cdr weapon))) + (set! money_after (- hero.money (cdr weapon))) - (if_else (< (var money_after) 0) + (if_else (< money_after 0) ( You can't afford that. (newline) - You would need (abs (var money_after)) more coins. + You would need (abs money_after) more coins. ) ( - (set hero.weapon (car weapon)) - (set hero.money (var money_after)) + (set! hero.weapon (car weapon)) + (set! hero.money money_after) Equipped (var hero.weapon.name). ) ) (newline) ) -(define_sequence buy_armor ( ((cons armor int) armor) ) - ;; We can't even deny a sell yet... +(define_sequence buy_armor ( ((cons #armor int) armor) ) (local int money_after) - (set money_after (- (var hero.money) (cdr armor))) + (set! money_after (- hero.money (cdr armor))) - (if_else (< (var money_after) 0) + (if_else (< money_after 0) ( You can't afford that. (newline) - You would need (abs (var money_after)) more coins. + You would need (abs money_after) more coins. ) ( - (set hero.armor (car armor)) - (set hero.money (var money_after)) + (set! hero.armor (car armor)) + (set! hero.money money_after) Equipped (var hero.armor.name). ) ) @@ -179,9 +174,126 @@ available. ) {{< /fatecode >}} +To showcase a use of `cond`, we'll add some checks that tell the player how well +they did: + +**main.fate:** +{{< fatecode >}}(fate_version 1) + +(require get_a_refill.fate) +(require falling_asleep.fate) + +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! + (option ( Ask the barman for a refill ) + (visit! get_a_refill) + ) + (option ( Fall asleep ) + (jump_to! fall_asleep) + ) +) + +;; Let's analyze how well the player did +(cond + ((> hero.weapon.attack 7) + Your feel ready to strike down any challenge. + ) + ((>= hero.armor.defense 7) + Your feel invincible. + ) + ((>= hero.money 50) + You feel good about having spent your coins sparingly. + ) + ((true) + You feel like you wasted your evening. + ) +) +(end!) +{{< /fatecode >}} + +Lastly, we can have an example of `switch` by having the barman react to certain +hero names. Note that `The barman looks surprised` corresponds to the default +branch of that switch. + +**get_a_refill.fate:** +{{< fatecode >}}(fate_version 1) + +(require data.fate) +(require actions.fate) +(require smithy.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) 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 improve your mood. + (newline) + Satisfied, you hand the barman (var price_of_booze) copper coins. + (visit! pay price_of_booze) + The barman sighs, then asks: + (prompt_string! (ptr hero.name) 2 64 What is your name, then, hero?) + "(var hero.name)?" + (newline) + (switch hero.name + (Fred + You brace for the inevitable mockery. + ) + (Link + You show the back of your hand to the barman. + ) + ((string Lancelot of Camelot) + You place halves of a coconut shell on the bar. + ) + 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) + (visit! visit_smithy) +) +{{< /fatecode >}} This was a first step toward cleaning up `smithy.fate`. Next, we'll use -[conditions](/learn/conditions) to improve things further. +[loops](/learn/loops) to improve things further. ---- @@ -190,38 +302,39 @@ This was a first step toward cleaning up `smithy.fate`. Next, we'll use **data.fate:** {{< fatecode >}}(fate_version 1) -(declare_structure weapon +(declare_structure #weapon (text name) (int attack) (int precision) ) -(declare_structure armor +(declare_structure #armor (text name) (int defense) ) -(declare_structure character +(declare_structure #character (string name) (int money) - (weapon weapon) - (armor armor) + (#weapon weapon) + (#armor armor) ) -(global character hero) +(global #character hero) -(set_fields! hero.weapon +(struct:set_fields! hero.weapon (name (text "Legendary" sword)) (attack 3) (precision 50) ) -(set_fields! hero.armor +(struct:set_fields! hero.armor (name (text "Refined" attire)) (defense 1) ) -(set hero.money 42) +(set! hero.money 200) + {{< /fatecode >}} **get_a_refill.fate:** @@ -229,6 +342,7 @@ This was a first step toward cleaning up `smithy.fate`. Next, we'll use (require data.fate) (require actions.fate) +(require smithy.fate) (define_sequence lower_price_of_booze ( @@ -236,11 +350,8 @@ This was a first step toward cleaning up `smithy.fate`. Next, we'll use (int decrease) ) Great! The price of booze just lowered from (at price_pointer) - (set (at price_pointer) - (- - (at price_pointer) - (var decrease) - ) + (set! (at price_pointer) + (- (at price_pointer) decrease) ) to (at price_pointer)! ) @@ -248,25 +359,24 @@ This was a first step toward cleaning up `smithy.fate`. Next, we'll use (define_sequence get_a_refill () (local int price_of_booze) - (set price_of_booze 12) + (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. + poured does improve your mood. (newline) Satisfied, you hand the barman (var price_of_booze) copper coins. - (visit pay (var price_of_booze)) - (newline) + (visit! pay price_of_booze) The barman sighs, then asks: - (prompt_string (ptr hero.name) 2 64 What is your name, then, hero?) + (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) + (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!" @@ -277,7 +387,9 @@ This was a first step toward cleaning up `smithy.fate`. Next, we'll use (newline) "Take this pre-payment and head to the smithy." (newline) + (visit! visit_smithy) ) + {{< /fatecode >}} **actions.fate:** @@ -286,9 +398,7 @@ This was a first step toward cleaning up `smithy.fate`. Next, we'll use (require data.fate) (define_sequence pay ( (int cost) ) - (set hero_money - (- (var hero.money) (var cost)) - ) + (set! hero.money (- hero.money cost)) ) {{< /fatecode >}} @@ -305,17 +415,20 @@ This was a first step toward cleaning up `smithy.fate`. Next, we'll use (newline) Upon waking up, your hard-trained reflexes inform you that someone stole all your money. - (set hero.money 0) + (set! hero.money 0) (newline) - This set-back was more than you could take. You give up on this barely + This set-back was more than you could handle. You give up on this barely coherent story. - (end) + (end!) ) {{< /fatecode >}} **main.fate:** {{< fatecode >}}(fate_version 1) +(require get_a_refill.fate) +(require falling_asleep.fate) + 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 @@ -329,21 +442,17 @@ anything. Worse, the alcoholic trait is part of the image. 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) +(player_choice! + (option ( Ask the barman for a refill ) + (visit! get_a_refill) ) - ( - ( Fall asleep ) - (jump_to fall_asleep) + (option ( Fall asleep ) + (jump_to! fall_asleep) ) ) -(require get_a_refill.fate) -(require falling_asleep.fate) +(end!) -(end) {{< /fatecode >}} **smithy_inventory.fate:** @@ -351,12 +460,12 @@ out to be an already empty glass in your hand and finds the barman. (require data.fate) -(global (list (cons weapon int)) smithy_weapons) -(global (list (cons weapon int)) smithy_armors) +(global (list (cons #weapon int)) smithy_weapons) +(global (list (cons #armor int)) smithy_armors) -(add! +(list:add! (cons - (set_fields (default weapon) + (struct:set_fields (default #weapon) (name (text An Iron Rod)) (attack 10) (precision 70) @@ -365,9 +474,9 @@ out to be an already empty glass in your hand and finds the barman. ) smithy_weapons ) -(add! +(list:add! (cons - (set_fields (default weapon) + (struct:set_fields (default #weapon) (name (text A Magnificient Brick)) (attack 6) (precision 90) @@ -377,19 +486,16 @@ out to be an already empty glass in your hand and finds the barman. smithy_weapons ) -(add! +(list:add! (cons - (set_fields (default armor) + (struct:set_fields (default #armor) (name (text A raincoat?!)) (defense 7) ) 160 ) - smithy_armors -) -(add! (cons - (set_fields (default armor) + (struct:set_fields (default #armor) (name (text A nice cape)) (defense 3) ) diff --git a/content/learn/11.loops/default.md b/content/learn/11.loops/default.md new file mode 100644 index 0000000..26aa949 --- /dev/null +++ b/content/learn/11.loops/default.md @@ -0,0 +1,457 @@ +--- +menuTitle: Loops +title: "Doing Things Over and Over" +weight: 11 +--- +[The previous step](/learn/conditions) introduced conditions, making it +possible to change the flow of execution according to the value of variables. +In this step, we look at loops, which will make instructions be executed a +certain number time depending on a condition, or just for each element of a +collection. + +Fate offers the following loop constructs: +* `while`, to execute instructions if and as many time as a condition is + verified. +* `do_while`, to execute instructions at least once, then as many time as a + condition is verified. +* `for`, a loop that has pre-instructions, a condition to verify before each + execution of the main body, the main body of instructions itself, then + post-instructions, which are executed before checking the condition. +* `for_each`, a loop that executes for each member of a collection. + +The `for_each` loops can also be used within a `player_choice!` to control what +options are available. + +Let's change how armors and weapons are displayed to the player: + +**smithy.fate:** +{{< fatecode >}}(fate_version 1) +(require smithy_inventory.fate) + +;; Maybe it would be better to put this in a different file, but oh well... +(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)" (lp)attack: (var weapon.attack), + precision: (var weapon.precision)(rp) 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)" (lp)defense: (var armor.defense)(rp), + for (var price) coins. + ) + ) + ) +) + +(global bool has_visited_smithy (false)) + +(define_sequence visit_smithy () + (if (not 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! + (option ( Let's see the weapons ) + (jump_to! see_weapons) + ) + (option ( Let's see the armors ) + (jump_to! see_armors) + ) + (option ( Nothing, let's go back to the bar ) + ) + ) +) + +(define_sequence see_weapons () + (player_choice! + (foreach smithy_weapons weapon + (option ( (eval get_weapon_offer_label weapon) ) + (visit! buy_weapon weapon) + ) + ) + (option ( Nevermind ) ) + ) + (jump_to! visit_smithy) +) + +(define_sequence see_armors () + ;; Not as good as a for_each in this case, but let's use a for to show how + ;; it can be done. + + (player_choice! + (for + ( (i 0) ) + (< i (list:size smithy_armors)) + ( (i (+ i 1)) ) + + (option ( (eval get_armor_offer_label (list:access i smithy_armors)) ) + (visit! buy_armor (list:access i smithy_armors)) + ) + ) + (option ( Nevermind ) ) + ) + (jump_to! visit_smithy) +) + +(define_sequence buy_weapon ( ((cons #weapon int) weapon) ) + (local int money_after) + + (set! money_after (- hero.money (cdr weapon))) + + (if_else (< money_after 0) + ( + You can't afford that. + (newline) + You would need (abs money_after) more coins. + ) + ( + (set! hero.weapon (car weapon)) + (set! hero.money money_after) + Equipped (var hero.weapon.name). + ) + ) + (newline) +) + +(define_sequence buy_armor ( ((cons #armor int) armor) ) + (local int money_after) + + (set! money_after (- hero.money (cdr armor))) + + (if_else (< money_after 0) + ( + You can't afford that. + (newline) + You would need (abs money_after) more coins. + ) + ( + (set! hero.armor (car armor)) + (set! hero.money money_after) + Equipped (var hero.armor.name). + ) + ) + (newline) +) +{{< /fatecode >}} + +Let's also look at a loop not within a `player_choice!` construct. We'll have +the player try to count sheeps: + +**falling_asleep.fate:** +{{< fatecode >}}(fate_version 1) +(require data.fate) + +(global (list string) affirmative_messages) + +(list:add! + Indeed. + (string Sounds about right.) + Yes. + Agreed. + (string That's correct.) + True. + Undoubtedly. + Certainly. + (string Without a doubt.) + Correct. + Affirmative. + affirmative_messages +) + +(global (lambda string ()) get_affirmative_message + (lambda () + (list:access + (rand 0 (- (list:size affirmative_messages) 1)) + affirmative_messages + ) + ) +) + +(define_sequence count_sheeps () + (local int sheeps 0) + + You start imagining some pasture with no sheeps. + + (while (< sheeps 100) + (local int player_guess) + (local int new_sheeps (rand 1 20)) + + (if_else (= new_sheeps 1) + ( A single sheep appears. ) + ( (var new_sheeps) sheeps appear. ) + ) + + (set! sheeps (+ sheeps new_sheeps)) + + (prompt_integer! (ptr player_guess) 0 120 How many sheeps are there now?) + + (if_else (= sheeps player_guess) + (eval get_affirmative_message) + ( + No. It was (var sheeps), you're pretty sure. The doubt wakes you up. + (newline) + (break!) + ) + ) + (newline) + ) +) + +(define_sequence fall_asleep () + Deciding to break away from the expected storyline, you attempt to fall + asleep. It's not easy, though. Maybe counting sheeps would help? + + (visit! count_sheeps) + (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 handle. You give up on this barely + coherent story. + (end!) +) +{{< /fatecode >}} + +[The next step of this tutorial](/learn/going_deeper) goes deeper into all the +concepts that were already explored. + +---- + +## Unchanged Files + +**data.fate:** +{{< fatecode >}}(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) + +(struct:set_fields! hero.weapon + (name (text "Legendary" sword)) + (attack 3) + (precision 50) +) + +(struct:set_fields! hero.armor + (name (text "Refined" attire)) + (defense 1) +) + +(set! hero.money 200) + +{{< /fatecode >}} + +**get_a_refill.fate:** +{{< fatecode >}}(fate_version 1) + +(require data.fate) +(require actions.fate) +(require smithy.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) 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 improve your mood. + (newline) + Satisfied, you hand the barman (var price_of_booze) copper coins. + (visit! pay price_of_booze) + The barman sighs, then asks: + (prompt_string! (ptr hero.name) 2 64 What is your name, then, hero?) + "(var hero.name)?" + (newline) + (switch hero.name + (Fred + You brace for the inevitable mockery. + ) + (Link + You show the back of your hand to the barman. + ) + ((string Lancelot of Camelot) + You place halves of a coconut shell on the bar. + ) + 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) + (visit! visit_smithy) +) +{{< /fatecode >}} + +**actions.fate:** +{{< fatecode >}}(fate_version 1) + +(require data.fate) + +(define_sequence pay ( (int cost) ) + (set! hero.money (- hero.money cost)) +) +{{< /fatecode >}} + +**main.fate:** +{{< fatecode >}}(fate_version 1) + +(require get_a_refill.fate) +(require falling_asleep.fate) + +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! + (option ( Ask the barman for a refill ) + (visit! get_a_refill) + ) + (option ( Fall asleep ) + (jump_to! fall_asleep) + ) +) + +;; Let's analyze how well the player did +(cond + ((> hero.weapon.attack 7) + Your feel ready to strike down any challenge. + ) + ((>= hero.armor.defense 7) + Your feel invincible. + ) + ((>= hero.money 50) + You feel good about having spent your coins sparingly. + ) + ((true) + You feel like you wasted your evening. + ) +) +(end!) +{{< /fatecode >}} + +**smithy_inventory.fate:** +{{< fatecode >}}(fate_version 1) + +(require data.fate) + +(global (list (cons #weapon int)) smithy_weapons) +(global (list (cons #armor int)) smithy_armors) + +(list:add! + (cons + (struct:set_fields (default #weapon) + (name (text An Iron Rod)) + (attack 10) + (precision 70) + ) + 176 + ) + smithy_weapons +) +(list:add! + (cons + (struct:set_fields (default #weapon) + (name (text A Magnificient Brick)) + (attack 6) + (precision 90) + ) + 110 + ) + smithy_weapons +) + +(list:add! + (cons + (struct:set_fields (default #armor) + (name (text A raincoat?!)) + (defense 7) + ) + 160 + ) + (cons + (struct:set_fields (default #armor) + (name (text A nice cape)) + (defense 3) + ) + 50 + ) + smithy_armors +) +{{< /fatecode >}} |


