A module for handling dynamic vocabulary on objects: dynamicVocab github repo.
This is intended to provide a mechanism for twiddling the vocabulary of objects at runtime, specifically when there’s the need for more customization that you can get out of adv3-native ThingState
.
This is the result of a refactor of dynamicThing module. That module provides both the low-level mechanics (methods for changing the vocabulary on objects) and the high-level interface stuff (how to programatically apply the changes due to in-game events).
The new module just provides the low-level methods. My plan is to do another module integrating the memoryEngine module via an interface to trigger vocabulary updates due to changes in in-game player knowledge.
USAGE
First you add theDynamicVocab
class as a mixin in a Thing
’s declaration:
// Declare an object whose vocabulary can be updated.
pebble: Thing, DynamicVocab '(small) (round) pebble' 'pebble'
"A small, round pebble. "
;
Then you declare one or more VocabCfg
instances. These have a vocabWords
property that uses exactly the same syntax as vocabWords
on a Thing
:
// Declare the dynamic part of the vocabulary.
alien: VocabCfg '(alien) artifact';
Having done that, you can add the additional vocabulary to the object via:
// Add the "alien" vocabulary to the pebble.
pebble.addVocab(alien);
Now something like >X ARTIFACT
or >X ALIEN ARTIFACT
will resolve to the pebble.
You can remove the additional vocabulary via:
// Remove the "alien" vocabulary to the pebble.
pebble.removeVocab(alien);
This is pretty trivial, and most of the (fairly short) code is devoted to making sure vocabulary is never removed when it shouldn’t be. For example, if you do something like:
// Create a couple VocabCfg instances.
alien = new VocabCfg('(alien) artifact');
weird = new VocabCfg('(weird) artifact');
// Add them to the pebble.
pebble.addVocab(alien); // >X ALIEN ARTIFACT now works
pebble.addVocab(weird); // >X WEIRD ARTIFACT now works
// Remove the "alien" vocabulary.
pebble.removeVocab(alien);
…then >X ARTIFACT
will still work, because the module will figure out that removeVocab(alien)
should only remove the adjective
“alien” and not the noun
“artifact”, because it’s still referred to by a different VocabCfg
. It will also avoid removing vocabulary that was on the Thing
declaration originally. In other words, you don’t have to worry about VocabCfg
vocabulary overlapping with vocabulary declared on the object elsewhere.
Additionally, by default an Unthing
sharing the VocabCfg
’s vocabulary will be created when the VocabCfg
is (or at preinit, if it’s declared in source). This means that >X ARTIFACT
will produce a “You see no artifact here.” response if the VocabCfg
hasn’t been applied to any objects, instead of a confusing “The word ‘artifact’ is not necessary in this story.” failure message.
All told it’s pretty simple, but there’s enough bookkeeping involved that it feels like it deserves to be its own thing.
And like I said I intend to add more of the “fancy” stuff (like DynamicThing
does)—providing message parameter substituions that can be used in object names, room titles, and so on—but I can also see uses cases for just using this as a slightly more flexible alternative to ThingState
.