I was first interested in Interactive Fiction back in the 80’s, and also had a basic understanding of object-oriented programming at the time.
Whether you’re writing ZIL, or TADS, or something else, it is common to put your behaviors in three different places:
- The verb (which typically encodes a prepositional phrase as well -
#putOn,#putIn,#openWith, etc) - The direct object, which might check the verb and a possible indirect object via “before” and “after” handlers
- The indirect object, as above
So for example, if you had a weird verb that only made sense in one place, it would be easier to put all the logic in the verb’s handler directly. It can check for valid combinations it cares about and issue failures on the rest.
Common actions like taking or dropping will likely have logic spread across many different objects “before” and “after” handlers.
Something I was wondering about way back in the day, and just crossed my brain again for the first time in many years, is a concept of a tuple. Specifically, you’d want a way to “intercept” a particular combination of verb/object/indirectObject without having to modify any specific verb, before, or after handler.
I guess the first question is… maybe, who cares? Just put the logic wherever it makes the most sense. Plenty of frameworks already seem to work this way.
But I wonder if anybody has tried to formalize this already in an existing authoring language? Just realized even a “tuple” might not be enough, since the location might matter too, but I feel like that could be just part of the logic that runs when the tuple fires.
The main advantage I can see is that it gives you a way to define specialized behavior (typically from new verbs) without having to either:
- Add a bunch of new special cases to the verb handler
- Add more code to the before or after functions of an object or indirect object.
At some point it might just be syntactic sugar? Specifying a tuple separately at an appropriate place in the code could be exactly identical to adding that logic to the verb handler directly
(in the case below, assume the parser has already determined that both the object and indirect object are available to the player)
routine OpenWith [directObject indirectObject] {
if (directObject == canOfTuna && indirectObject == canOpener) {
canOfTuna.open = true;
print_ret "The cat comes bolting into the room, expecting dinner!"
}
.... other logic ...
}
tuple #openWith,canOfTuna,canOpener {
canOfTuna.open = true;
print_ret "The cat comes bolting into the room, expecting dinner!";
}
Whether the language physically inserts the equivalent of the first block when it encounters the second, or it records a list of object pairs associated with each verb and walks that implicitly is an implementation detail.
I’m just wondering if having this level of separation makes sense or not?
Thanks,
-Dave