Here’s how I would lay out my approach!
First, I’m going to make two traits: (liquid source $) and (liquid container $). A liquid source can provide an unlimited supply of liquid; a liquid container can, well…contain a liquid.
Since we want each container to hold no more than one liquid, but each liquid can be held by several containers, we need a relation of one liquid to various containers. Dialog’s relation handling isn’t as advanced as Inform 7’s, but this sort of relation is easy: we make a per-object variable ($ is filled with $). This will be used for both our sources and our containers.
In other words, we’re not going to have our actual liquid objects on-stage—instead they’ll be abstract off-stage objects, like #north or #heldby, which only matter when they appear in properties of on-stage things. All actions will actually be performed on the sources instead.
This means we’ll want sources to have appropriate synonyms:
(dict (liquid source $Obj))
($Obj is filled with $Liquid)
*(dict $Liquid)
And we’ll want our containers to show what they’re full of:
(name (liquid container $Obj))
~($Obj is filled with $)
empty (real name $Obj)
(name (liquid container $Obj))
($Obj is filled with $Liquid)
(name $Liquid) (no space) -filled (real name $Obj)
(after [examine (liquid container $Obj)])
($Obj is filled with $Liquid)
(par) (It $Obj) (is $Obj) currently full of (name $Liquid) .
With a bit of extra machinery to clear up parsing and printing. It’s unfortunate that we need to bring in a new (real name $) predicate here, but Dialog’s standard library is not good at inserting adjectives in front of object names.
(dict (liquid container $Obj))
%% First, add “water filled”
($Obj is filled with $Liquid)
*(dict $Liquid)
filled
%% Then, add “water-filled”
(collect words)
(name $Liquid)
(into $Name)
(append $Name [-filled] $Tmp)
(join words $Tmp into $Compound)
$Compound
(an (liquid container $Obj))
~($Obj is filled with $) (just) %% “Empty” starts with a vowel
(an (liquid container $Obj))
($Obj is filled with $Liquid)
(just) (an $Liquid) %% Otherwise it depends on the liquid’s name
The efficiency of this (dict $) trickery is not great. It would probably be better just to give each liquid a (name-filled $) property that prints “water-filled”, “oil-filled”, etc. That would also let us say “hydrogen peroxide-filled” instead of “hydrogenperoxide-filled”. Actually, let’s do that.
(dict (liquid container $Obj))
($Obj is filled with $Liquid)
filled (name-filled $Liquid)
Much better!
For the purposes of this scenario, I’m going to have liquid containers count as liquid sources when full. In other words, you can pour water from a bucket into a bottle and still have water left in the bucket.
(liquid source $Container)
*(liquid container $Container)
($Container is filled with $)
And since I mentioned drinking:
(potable (liquid source $Obj))
($Obj is filled with $Liquid)
(potable $Liquid)
There we go! Plenty of traits. Next up: actions!