One feature I’ve often wished for in Inform is the ability to take the transitive closure of a relation. That is, to take a relation R and make a new relation R+ that means “is recursively R”. If R is “X contains Y”, for example, then R+ would be “X contains Y, or X contains something that contains Y, and so on”.
Well, Dialog supports it! So what can we do with this?
Let’s establish a relation between puzzles: X requires Y if X cannot be solved until Y is solved. For example, you can’t unlock the door until you have the key; you can’t steal the diamonds until you’ve unlocked the door and have the cloak of invisibility.
(interface ($<Child requires $>Parent))
Now let’s take its transitive closure! X depends on Y if X requires Y, or X requires something that requires Y, and so on. The diamonds depend on the cloak, the door, and the key.
($Child depends on $Parent)
*($Child requires $Parent)
($Child depends on $Parent)
*($Child requires $Intermediate)
($Intermediate depends on $Parent)
Now we can check if a puzzle has any unsolved dependencies:
($Puzzle is missing dependencies)
*($Puzzle depends on $Other)
~(solved $Other)
And give this a more convenient name.
@(solvable $Puzzle)
~($Puzzle is missing dependencies)
Now, we can tell players which puzzles are solvable in their current state, to keep them from bashing their head against something that requires tools they don’t have!
(understand command [nudge])
(perform [nudge])
Currently, you’re equipped to handle:
(exhaust) {
*(puzzle $Puzzle)
~(solved $Puzzle)
(solvable $Puzzle)
(check $Puzzle is in room $Room)
(div @item) {
(bullet) (the $Puzzle)
(if) (current room $Room) (then)
in this room
(elseif) ($Room = []) (then)
%% Nothing - it’s not in any room
(elseif) ($Room is visited) (then)
in (the $Room)
(else)
in an unexplored room
(endif)
}
}
With just one utility predicate to make this cleaner.
(check $Obj is in room $Room)
($Obj is in room $Room) (or) ($Room = [])
Now, for every puzzle, you just define the conditions that will make it solved:
(puzzle #irondoor)
(solved #irondoor)
(#irondoor is unlocked)
(#irondoor requires #ironkey)
And voilà! How well does it work in practice? Well, you’ll see in this year’s ECTOCOMP!