Liquids and Liquid Containers

Hi there, I’m (reasonably) new to TADS3 and have been working my way through Eric Eve’s Learning TADS3 to get a handle on the basics. It’s been going well but I’ve hit a bit of a roadblock concerning liquids. This is partly a technical question, partly an IF style and writing question.
I checked the reference and didn’t find a designated liquid class, so I created a simple custom object that has a custom description and some scripts to handle when something is poured into it. There are a few problems with this, mostly relating to object phrasing:

  • A container would be the logical choice but I don’t know of a way to control the manner an object would be handled, or how to control quantities (how much water a liquid container can carry, how much is taken from a source etc.) that fits into the OO model TADS3 uses.
  • Transitive operators like “drink” and “pour out” now refer to the vessel rather than the contents; so “drink canteen” is a bit cumbersome when you probably want “drink from canteen” or “drink water”
  • I can’t think of a good verb for collecting water from one source into a vessel that isn’t another vessel. “Pour water into glass” would be fine if you were carrying, say, a carafe, but if it’s a running tap, a waterfall, or a puddle on the ground I can’t find an easy choice. Even if I can use a regular container, “Put water into glass” isn’t good either.

This is all still new to me, so apologies if this is a trivial question. I have many others…
Thanks for reading!

Liquids and ropes are among the hardest things to implement in parser-based IF. Searching for “liquid” in “Learning T3” took me straight to the discussion of multi-methods on p. 323. I’ve never used this technique, but it may be worth investigating.

A more straightforward way to remap a player command from the liquid in the vessel to the vessel itself (or vice-versa) would be with replaceAction(). This is discussed on p. 105.

There are several verbs a player might use. ‘fill glass’ (when the tap is already flowing), ‘fill glass with water’ (ditto), or ‘fill glass from tap’ (which should cause the tap to be turned on automatically) would be natural. ‘put water in glass’ is also natural. The point is not to decide for the player what command reads well to your ear – the point is to allow the player to use as many different commands as you can think of, even commands that seem a little weird.

Once the water is in the glass, you need to handle ‘drink water’, ‘drink from glass’, and ‘drink water from glass’, at minimum. With ‘quaff’, ‘imbibe’, ‘sip’, ‘guzzle’, and ‘consume’ as synonyms for ‘drink’, I suppose.

The easiest way to handle quantities is not to. The glass would have an isFull property, which you set to either true or nil in your code, and test in a check() rule. If isFull is true, then ‘fill glass’ should respond, ‘The glass is already full’ in the check() for dobjFor(Fill). And so forth. It’s a lot of work … no way around it.

Steve Breslin together with contributors did a t3liquid extension long time ago. I don’t know whatever it is finished since it is not published on IF archive (several extensions of this author are on archive), but I’ve found a repository on SourceForge: and some discusion!topic/ (Hey, even Jim participated in the discussion!) I’ve never used it, but it seems to be centered around mixing liquids and simulating outcomes such as color and so on. It has a class for a liquid and liquid container and if not directly applicable, it could be a good source of inspiration, because it is throughfully commented.

Thanks for both messages! Both the advice and the library have been invaluable, and I might try and still find a solution but may just use it if it all ends up being too difficult. The mixing part of the library is something I had barely even considered, and sounds like an excellent component to inventory-based puzzles.

It’s interesting you mention rope, I had just come up with an equally cumbersome solution to that problem when I ran into this one (I replace the item with a custom fixture I add and remove from various parts of the environment, inelegant but seems to work). Thanks again for everyone’s help!