Development history of Finto in 2014


New: unvisited?, moved from the game "La bleko de l' ŝargú".

Change: clearer comments separate the inner and application parts of the code; more code is moved to the application interface, in order to make the application more powerful. Other simple changes and corrections.

2014-02-17 (start of version A-06)

The narrative syntax needs a new rewrite, in order to make everything easier for the authors. The goal is to let keywords in the printed text, though the current Forth-like words will be provided as well.

In order to separate keywords from the surrounding text, parsing is needed. If the Forth interpreter is used, the link must start with a separated word.

A new free-text syntax was inspired by the word [", recently written for Galope,

An Asciidoctor-like link syntax, with the word <<, would look like this:

  |" Narrative inspired by one
  << ~original_narrative, book>> I just forgot. "|

A parsing word ~node-name, could be automatically created by node:.

But parsing a single character is easier and faster than parsing the final ">>". A simpler alternative could be:

  {" Narrative insipired by one
  { ~original_narrative book} I just forgot "}

Using the Forth interpreter creates a problem: how to know if the link has to be printed after an space or not?:

  {" Narrative insipired by one
  "{ ~original_narrative book}" I just forgot "}

An additional word could be defined for every case, e.g. the word "{, or use the flags and checks that already solved the same problem in Fendo's parser. But since the only markups are links, it seems easier to write a character-by-character parser, that searches for "{" and "}". This makes the syntax easier for the writer, because no extra spaces are needed. Also, synonyms could be specified:

  {" Narrative insipired by one
  "{ ~original_narrative book|publication|text}" I just forgot "}

Anyway, all kernel words that provide the manipulation of keywords have been renamed with clear names. The actual markup can be implemented with alias:

' enter_node alias ->
' node_keyword alias ^
' node_keyword+ alias ^^
' .node_keyword alias .^
' .node_keyword+ alias .^^
' global_keyword alias +^
' global_keyword+ alias +^^

Possible alternative:

' enter_node alias ~>
' node_keyword alias ^
' node_keyword+ alias ^+
' .node_keyword alias .^
' .node_keyword+ alias .^+
' global_keyword alias *^
' global_keyword+ alias *^+

New: node fields seconds+ and commands+; node and global counters of seconds and commands.


Alternative markups. The better one seems to be the following one:

' enter_node alias }>
' node_keyword alias }
' node_keyword+ alias }+
' .node_keyword alias }.
' .node_keyword+ alias }.+
' global_keyword alias }*
' global_keyword+ alias }*+

false [if]

  \ ............................
  \ Usage example

  s" help" {help }*  \ global keyword
  s" sos" }*+  \ global extra keyword

  s" south" {celler } s" s" }+  \ two invisible keywords

  \ Text with two printed keywords to the same node:
  t" Her" s" home" {house }. t" is a little"
  s" house." }.+

  {node-id }>  \ go to a node


Change: .node_keywords and .global_keywods simplified

Problem: vocs and order crashes when is used in unclear conditions. After a lot of testing, it was clear the problem had nothing to do with Finto. The bug was found and fixed in .

New: First working version of ~", to provide the following syntax, with keywords in narrative text:

  ~" The lonely ~street street.
  You see your ~house house,
  the general ~store store,
  and the ~saloon saloon. "~

All markups will be provided as optional addons.


New: Nodes use their own wordlist. Now node? simply uses search-list. New words to manage the wordlists order.

Fix: (node:) finally uses the lodge space thanks to the new word lodge-address-value written for the Galope's lodge module.

New: :node::

: :node:  ( "name" -- )
  \ Create a new node and start its definition.
  \ Usage examples:
  \   :node: ~node-id  ( definition )  ;node
  \   secondary :node: ~node-id  ( definition )  ;node
  node: execute-latest :node

Fix: :node is not immediate anymore.

Improvement: ~" now recognizes the markup for paragraphs, and the string used is configurable.


Fix: A missing dup in enter_node caused the node code to be executed without its id on the stack.

New: First try to implement latest_node, a value to hold the id of the previous node, primary or secondary. So far previous_node holds the previous primary node only. A new approach is required about the tasks of primary and secondary nodes, because currently there's no way, beside using ordinary Forth variables, to know the latest secondary node.

Fix: After a lot of debugging, a bug was fixed: nodes were created with lodge-address-value, so they returned the absolute address of its data space in the lodge; the problem was the lodge address is variable because allocated. The solution was to create the nodes with lodge-value, so they return the lodge offset, and change the data interface of the node structure in order to convert the offset to the current absolute address.

Improvement: Now one word can be used to define all nodes, no matter if their ids have been created or not. This makes it easier to write the interactive fiction. :node and :node: are removed and combined into node:. The old node: is renamed node:

: node?  ( ca len -- xt true | false )
  \ Is a string a node-id?
  nodes_wid search-wordlist
: name>node  ( "node-id" -- node )
  \ Parse a node-id and return its value. 
  \ If the parsed node-id has not been created before, create it.
  >in @ >r parse-name r> >in !
  node? if  execute  else  node execute-latest  then
: node:  ( "node-id" -- )
  \ Start the definition of a node.
  \ If the node-id has not been created before, create it.
  \ Usage examples:
  \   node: ~node-id  ( definition )  ;node
  \   secondary node: ~node-id  ( definition )  ;node
  name>node dup :noname  ( node node xt colon-sys ) colon-sys>r
  [:node] ( node )  postpone literal  secondary? @
  if    postpone (:secondary_node) secondary? off
  else  postpone (:primary_node)
  then  r>colon-sys  ( colon-sys )


First tries for saving and restoring a game:

secondary node: ~save
  \ xxx todo choose filename
  lodge @ /lodge @ s" ~/forth/lpda/" unslurp-file
  | t" [Saved.]"
node: ~load
  \ xxx todo choose filename
  s" ~/forth/lpda/" slurp-file lodge @ swap move
  ~" | [Loaded. Press any key to continue were you saved.] "~
  key drop  print_page  previous_node ~>

But there are two problems:

First, the execution tokens of the nodes, stored in the lodge, are absolute! That makes it impossible to restore a game in a different Gforth session. A lookup table will solve this.

Second, in order to continue the game, the node that was the current one when the save command was invoqued, must be executed again after the loading. This means some things may be different, depending on what the node actually does at the start. There's now solution for this.


New: Execution tokens of the nodes are stored in a table. This table has been implemented as a lodge. The Galope's "lodge-colon" module makes it possible to create several lodge buffers.


Change: The code that restores saved sessions has been rewritten. Now the sessions list is not a text file that must be read line by line, but a Forth source file ready to be included; it creates the session filenames keywords.


New: The code to save and restore sessions is finished but not fully tested. Only two interface words are required by the user application: load_session and save_session.


Change: The string parsed by ~" ends with a double quote, not with "" "~ "".

Fix: The this value failed in nested nodes, because it was updated at run-time, at the end of every node. The solution was to convert it to an immediate word that compiles the id of the node being compiled. A new variable, [node] was created to hold the id (;node) and the words that call it had to be modified.


Same little changes in the source format.