Yep! A plist is just a list that goes [key1 value1 key2 value2 key3 value3 ...] in order to represent a dictionary. And Dialog is so good at manipulating lists that we can get all the normal dictionary operations we could want, in just ten lines of code!
First, (plist $ key $ has value $) looks up the value corresponding to a particular key. (Bonus: if you use this as a multi-dict, a multi-query will get you every value corresponding to it!)
Second, (plist $ without $ is $) removes a key from the dictionary completely.
And finally, (plist $ with $ updated to $ is $) first removes a key, then inserts that key again with a new value. In other words, this is our update operation.
These three operations are all O(n), while adding a new key is O(1), which isn’t great efficiency (something like Python can do them all in O(1)!), but it’s not terrible either. On the order of magnitude we’re talking about, there’s no noticeable delay.
The benefit of plists, then, is you can stick 'em in global variables and update them when needed. In Wise-Woman’s Dog, a plist mapped recipients to a number of goats; in Stage Fright, it mapped staked objects to the number of turns left on their timer; and now in this competition, it maps alien words to lists of human words (probably English, but who knows?) supplied by the player.
(Plists were probably not the right tool for the job in Stage Fright, because at most two things can be staked at a time. But I couldn’t see a better solution and I was under time pressure, so plists were Good Enough.)
Exactly! Access predicates are macros that expand to their contents during compilation. Everyone who’s coded in Dialog has probably used one:
@($Obj is $Rel $Parent)
*($Obj has parent $Parent)
*($Obj has relation $Rel)
This means that (#dog is #in #car) actually expands to (#dog has parent #car) (#dog has relation #in). But this expansion can happen anywhere: as a top-level rule (declaring the initial state of the world), as a query (checking that state), or as a (now) statement (updating that state). This means the main use for access predicates is to create aliases for properties and flags, like making ($Obj is closed) mean ~($Obj is open).
But…
There’s also a significantly MORE powerful use of access predicates, which I believe nobody except Linus has ever used, and then only for one purpose in the standard library. This is how rules for (grammar $ for $) are converted into an efficient form for the parser.
Because you see, access predicates can match literal values at compile-time. Only literals—objects, numbers, dictionary words, and list literals—but that’s still immensely powerful. It means that:
(word assigner #tablet [ejebro ghazeva qroghod])
Is converted at compile-time into:
(#tablet bears @ejebro)
(word assigner #tablet [ghazeva qroghod])
Which is converted into:
(#tablet bears @ejebro)
(#tablet bears @ghazeva)
(word assigner #tablet [qroghod])
And finally:
(#tablet bears @ejebro)
(#tablet bears @ghazeva)
(#tablet bears @qroghod)
In other words, I can declare a rule like (tablet reads [ejebro ghazeva qroghod]), and have the compiler convert it automatically into:
(#tablet has text [ejebro ghazeva qroghod])
(#tablet bears @ejebro)
(#tablet bears @ghazeva)
(#tablet bears @qroghod)
The first rule here is then used in the game to actually print the inscription when you examine an object, while the other three are used to establish a relation between objects and words, that I can then query to determine which objects a certain word appears on! Since all the heavy lifting is done at compile-time, I can very efficiently search up (for example) a list of all words that appear on examined objects, without having to do any list searches at run-time.
I’m pretty sure Linus built this feature into the compiler specifically to implement the (grammar $ for $) system in pure library code, and I don’t know if it’s ever been touched by anyone who hasn’t dug deep into the guts of the compiler to figure out what’s going on. But if part of this competition is to show off the power of Dialog, I’m going to pull out the deep esoteric lore!
If my esteemed competitor is going to make double updates, then clearly I need to make triple ones!