@Pluie, thanks for the bug reports! I’ll take a look.
As for synthesizing input from output, I agree with your list of obstacles, and would like to add the fact that most queries only return the first match. This is such a central design element of the language that it’s hard for me to imagine a Dialog program that avoids it entirely.
That being said, the language is very amenable to opportunistic static analysis, as one would use in an optimizing compiler. For instance, traits like (item $)
or (openable $)
tend to be defined using simple, straightforward rules, and the compiler is generally able to reduce them to per-object flags.
Here’s an example of opportunistically “running the program backwards”: The compiler analyzes the (dict $)
predicate for each object, and figures out what words can come out. The result is inverted into a word-to-object lookup table, which speeds up the in-game parser. To do this, the compiler must explore every branch of the decision tree, and e.g. look at what happens both if a dynamic predicate succeeds and if it fails.
But the whole operation needs to be approximate. It needs to stop recursion early, for instance, because the base case could depend on a dynamic predicate. And words like “open” and “closed” would both show up as potential output from the dict rules of every openable object. So words like these have to be eliminated from the result, to prevent the table from growing ridiculously large. Therefore, if the player types “open closed”, the game would still have to enumerate every object in scope, and weed out all but the openable, closed ones. But in most cases, like “open safe”, the game only needs to consider a handful of objects, and then weed out the ones that are out of scope.
That optimization improves parsing speed significantly on old hardware, and it wouldn’t be possible in a language where everything by default is stored dynamically on the heap, and updated imperatively. Dialog still allows the programmer to put everything in dynamic storage, in which case the optimization doesn’t work. But because the language encourages a declarative programming style, most programs end up being transparent enough for this kind of analysis.
@cpb, path-finding is already part of the standard library. It currently uses a variant of Dijkstra’s algorithm, although I’ve been meaning to replace it with a breadth-first search (because the edges don’t have weights). This can be done using ordinary forward-links. But in other places, the map-connection predicate is indeed queried “backwards”. To provide reasonable default behaviour for commands like “enter the red door”, the library needs to figure out in what direction there’s a link to the indicated door object, and then redirect to the action for going in that direction.