I7 - new example: Secret Reagents

It’s a bit lengthy, but I think this demonstrates a bit more Inform 7 syntax that was (in many cases) maddening for me to get right. My particular bugbear is when the error messages seem to agree that the code is perfect but somehow not applicable for unknown reasons (“in any context I can find”).

If you cut and paste to try it out, remember that tables have to be tab-character delimited.

"Secret Reagents" by Ed Halley

Part 1 - Defining Reagents and Vessels

When play begins: say "This is an Inform 7 example that provides some basic support for pouring and blending ingredients in vessels.  Unlike other examples, makes a very simple semantic quantity system instead of numeric quantities and capacities."

Section 1 - Reagent Definitions

Table of Reagents
[these are all the possible non-thing pourable values; water and muck are special]
Reagent		Taste	Flavor
water		  1		 "boring"
juice		  1		 "sour"
syrup		  1		 "extremely sweet"
honey		  1		 "sticky sweet"
tea			 1		 "soothing"
lemonade	  1		 "refreshingly sweet"
soda		   1		 "stimulating"
cocoa		  1		 "warming"
soup		   1		 "invigorating"
sugar		  1		 "crunchy sweet"
powder		 0
jasmine		0
seeds		  0
oil			 0
dirt			0
mulch		  0
soil			0
grit			0
mud		    0
sprouts		0
muck		   0

A reagent is a kind of value. The reagents are defined by the Table of Reagents.

Table of Recipes
[if not listed, water+anything=itself, anything+itself=itself, otherwise muck]
Basic		Added		Result
water		dirt		 mud
water		sugar		syrup
syrup		juice		lemonade
dirt		 mulch		soil
water		powder	  cocoa
water		jasmine	 tea
tea		  honey		tea
soil		 seeds		sprouts

Section 2 - Vessel Definitions

A vessel is a kind of thing. A vessel is either empty, partly-full, mostly-full or full. A vessel is usually empty. A vessel has a reagent called current reagent. The current reagent of a vessel is usually water.

Understand "look in [a vessel]" as examining.

Instead of examining a vessel (called the item):
	if the item is empty begin;
		say "[The item] is empty, but for a tiny bit of [current reagent of item] at the bottom.";
	otherwise;
		say "[The item] is [vessel condition of item] of [current reagent of item].";
	end if.

Filling up something is an activity.
Rule for filling up something (called the item):
	if the item is full begin;
		say "[The item] overflows.";
	otherwise;
		if the item is mostly-full, change the item to full;
		if the item is partly-full, change the item to mostly-full;
		if the item is empty, change the item to partly-full;
		say "[The item] fills until it is [vessel condition of item] of [current reagent of item].";
	end if.

Emptying out something is an activity.
Rule for emptying out a vessel (called the item):
	if the item is partly-full, change the item to empty;
	if the item is mostly-full, change the item to partly-full;
	if the item is full, change the item to mostly-full.

Section 3 - Drinking from a Vessel

Definition: a vessel is yummy if the taste of its current reagent is 1.
[cannot say 'if no flavor entry...' because empty table cells get defaults when used to define values]

Understand "drink from [a vessel]" as drinking.

Instead of drinking a vessel (called the item):
	if the item is empty begin;
		say "[The item] is already empty.";
	otherwise;
		if the item is not yummy begin;
			say "That would not taste very good.";
		otherwise;
			carry out the emptying out activity with the item;
			say "You drink from [the item] until it is [vessel condition of item].";
			say "That was [flavor of the current reagent of the item].";
		end if;
	end if.

Section 4 - Pouring from Vessel to Vessel or Mixing Reagents

Pouring it into is an action applying to two things.
Understand "put [a vessel] in/into/on/onto [a vessel]" as pouring it into.
Understand "pour [something] in/into/on/onto [something]" as pouring it into.
Understand "drain [something] in/into/on/onto [something]" as pouring it into.
Understand "fill [something] from/with [something]" as pouring it into (with nouns reversed).
Check pouring it into:
	if the noun is not a vessel, say "You can't pour [the noun]." instead;
	if the noun is empty, say "[The noun] is empty." instead;
	if the second noun is not a vessel, say "You can't pour anything into [the second noun]." instead;
	if the noun is the second noun, say "You can't pour that into itself." instead;
	if the second noun is full, say "[The second noun] is already full." instead.

Carry out pouring it into:
	let S be muck;
	let A be the current reagent of the noun;
	let B be the current reagent of the second noun;
	if the second noun is empty, let B be the A;
	if A is B, let S be the A;
	if A is not B begin;
		repeat through the Table of Recipes begin;
			if the Added entry is the A and the Basic entry is the B, let S be the result entry;
			if the Added entry is the B and the Basic entry is the A, let S be the result entry;
		end repeat;
	end if;
	if S is muck and A is water then let S be B;
	if S is muck and B is water then let S be A;
	change the current reagent of the second noun to S;
	carry out the emptying out activity with the noun;
	carry out the filling up activity with the second noun.

A bottle and a mug and a cup and a pitcher and a kettle and a pot and a tank and a bin and a packet are kinds of vessels.

Section 5 - Pouring Vessel into Drain and Filling Vessel from Faucet

[Currently we do not support stopping up the drain of the sink; the sink is not a vessel.]

A drain is a kind of thing. A drain is usually scenery.
A faucet is a kind of thing. A faucet is usually scenery.
A sink is a kind of container. A sink is usually scenery. A drain is part of every sink. A faucet is part of every sink. A tub is a kind of sink.

Instead of pouring when the noun is a sink or the noun is a faucet:
	if the second noun is not a vessel begin;
		say "You cannot fill [the second noun] from [the noun].";
	otherwise;
		if the second noun is full begin;
			say "[The noun] is already full.";
		otherwise;
			[mixing recipes can only be done from vessel to vessel, consider it a game challenge]
			if the current reagent of the second noun is not water begin;
				say " (Emptying [the second noun] first.)[line break]";
				change the vessel condition of the second noun to empty;
			end if;
			change the current reagent of the second noun to water;
			carry out the filling up activity with the second noun;
		end if;
	end if.

Instead of pouring when the second noun is a sink or the second noun is a drain:
	if the noun is not a vessel begin;
		say "You cannot pour [the noun] into [the second noun].";
	otherwise;
		if the noun is empty begin;
			say "[The noun] is already empty.";
		otherwise;
			carry out the emptying out activity with the noun;
			say "You pour [the noun] down [the second noun] until it is [vessel condition of the noun].";
		end if;
	end if.

Part 2 - Trial Run Using Vessels and Reagents

Section 1 - The Laboratory

The Kitchen is a room.

In the Kitchen is a closed openable container called a fridge.
In the fridge is a bottle called a Coke bottle. The current reagent of the bottle is soda. The bottle is full.

In the Kitchen is a pitcher. The current reagent of the pitcher is oil. The pitcher is mostly-full.
In the Kitchen is a pot. The current reagent of the pot is dirt. The pot is partly-full.
In the Kitchen is a vessel called a sack. The current reagent of the sack is mulch. The sack is full.
In the Kitchen is a mug.
In the Kitchen is a kettle.
In the Kitchen is a sink.
In the Kitchen is a packet called a seed packet. The current reagent of the seed packet is seeds. The packet is partly-full.

In the Kitchen is a packet called a teabag. The current reagent of the teabag is jasmine. The packet is mostly-full.

Section 2 - Some Experiments

Test fridge with "pour pitcher in fridge / fill pitcher from fridge".

Test bottle with "open fridge / get bottle / x bottle / drink from bottle / pour bottle in sink / drink bottle".

Test pot with "x pot / x sack / pour sack in pot / pour seed packet into pot".

Test sink with "x pitcher / drink from pitcher / empty pitcher in sink / fill pitcher from sink / x pitcher".

Test faucet with "x mug / put teabag in mug / fill mug from sink / x mug / damn".

Test me with "x mug / put teabag in mug / fill kettle from sink / pour kettle into mug / drink from mug".

Let me know if you try it out, expand on it, bang your head in frustration on it, or find a bug you can fix.

After some play testing, I wanted to expand this so the player could refer to vessels by their current reagent.

This compiles:

Understand "[a reagent]" as a vessel.

But it lets the player refer to any vessel in the vicinity by any reagent word, whether the vessel has that current reagent or not.

I expected these would not work but I’ve tried the following anyway. There appears to be no conditions allowed.

Understand "[current reagent]" as a vessel.
Understand "[current reagent of any vessel]" as a vessel.
Understand "[a reagent]" as a vessel when the reagent is the current reagent of the object in question.

Edit:

Understand the current reagent property as describing a vessel.

I should read more documentation.