"A Handy Kit" by Andrew Plotkin. The story headline is "An Inform 7 worked example". The release number is 2. The story description is "A reimplementation of the toolcase from Spider and Web. Contains some spoilers for the early parts of that game." Release along with the source text and a "Standard Helvetica" website. Chapter 1 - Setting up Use full-length room descriptions. When play begins: Say "A relaxing day at home, with nothing to do but play with your toys." The player carries the toolcase. The player carries a boring pebble. [An object-fiddling example should always have a neutral object to compare effects to.] [Changing the standard inventory listing.] This is the print wide inventory rule: say "You are carrying "; list the contents of the player, as a sentence, giving inventory information, tersely, including contents; say "." [Sure wish there was a way to do this without a procedural rule. Feature request filed.] Procedural rule: substitute the print wide inventory rule for the print standard inventory rule. [In a few (rare) cases, I want to handle "read" differently from "examining".] Reading is an action applying to one visible thing, requiring light. Understand the command "read" as something new. Understand "read [something]" as reading. Carry out reading something: try examining the noun. [I need to break up the standard "set [x] to [topic]" grammar into "set [x]" and "set [x] to [number]". Both of these need to be new actions.] Setting vaguely is an action applying to one thing. Dialing it to is an action applying to one thing and one number. Understand the command "set" as something new. Understand "set [something]" as setting vaguely. Understand "set [something] to [number]" as dialing it to. Understand the command "adjust" as something new. Understand "adjust [something]" as setting vaguely. Understand "adjust [something] to [number]" as dialing it to. Understand "turn [something] to [number]" as dialing it to. Understand "rotate [something] to [number]" as dialing it to. Check setting vaguely: instead say "You can't set that." Check dialing it to: instead say "You can't set that." [For fun, I decided to come up with a "one shot" facility -- a way to easily display a message the first time you come across something (but never again). This could be extended to handle "fire on Nth try", etc.] A oneshot is a kind of thing. A oneshot can be fired. To decide whether first trying (item - oneshot): if item is fired, decide no; now item is fired; decide yes. Chapter 2 - The Environs [This unimportant stuff declaration is my favorite part of the whole program.] Unimportant stuff is a kind of thing. Unimportant stuff is scenery. Instead of examining unimportant stuff, say "Nice, don't you think?" Instead of doing something other than examining or smelling unimportant stuff, say "For the sake of argument, let's say you'd rather play with your toolcase." [The smell system is straight from the "Art of Noise" example. But we add in perfume as a special case, because lots of things get perfumized at once. Having a perfumey object present summons the perfume cloud.] Understand the command "inhale" as "smell". A thing has a property called scent. The scent of a thing is usually "nothing". A thing can be perfumey. A thing can be perfumizable. Things are usually perfumizable. Unimportant stuff is never perfumizable. Scenery is always not perfumizable. Definition: a thing is scented if its scent is not "nothing". [but not if it's perfumey.] Instead of smelling a room (called locale): If a scented thing is in locale, say "You breathe in [the list of scented things in locale]."; otherwise say "The air is dead.". Rule for printing the name of something while smelling a room: say "[scent]" Instead of smelling something which is scented: say "You smell the [scent]." Instead of smelling something which is perfumey: say "It reeks of cheap perfume." Instead of smelling the toolcase when the toolcase is open and the toolcase encloses something perfumey: say "It reeks of cheap perfume." Instead of smelling the player when the player is perfumey: say "You've got cheap perfume all over you." [A cloud of perfume that hangs around after the stink bomb goes off. I can't make this a backdrop because I7 doesn't support condition-defined backdrops. Feature request filed.] The perfume cloud is scenery. Understand "nasty" or "reek" or "cheap" or "wave" as the perfume cloud. The scent of the perfume cloud is "lingering reek of perfume". Instead of examining the perfume cloud: try smelling the perfume cloud. The cloud-oneshot is a oneshot. Instead of doing something other than examining or smelling the perfume cloud, say "The reek is intangible[if first trying the cloud-oneshot]. (Never mind the distinct feeling that it is clawing at your soft palate.)[otherwise].[end if]". Every turn (this is the perfume backdrop rule): if a perfumey thing is touchable, move the perfume cloud to the location of the player; otherwise remove the perfume cloud from play. [The listening system is simpler, because only one thing in the game can make noise. Okay, except for the palms. Sorry.] Before listening to a room (called locale): if locale encloses the active relaxer, instead say "Gentle frog sounds fill the room." [And now, actual rooms.] The Arboretum is a room. "A nice place, if you do say so yourself who designed it. The scents of toxic Korean orchids blend with the rattling of the force-grown palms. An ivied arch to the north leads to your control center." The toxic Korean orchids are unimportant stuff in the Arboretum. Understand "orchid" or "flower" or "flowers" or "scent" as the orchids. The scent of the orchids is "thick, livid sweetness of orchids". The palm trees are unimportant stuff in the Arboretum. Understand "palms" or "tree" or "rattling" or "force-grown" as the palm trees. The ivied arch is scenery in the Arboretum. Understand "archway" as the ivied arch. Instead of entering the ivied arch, try going north. The Control Room is a room. It is north of the Arboretum. "The air is chill and dim beneath the high metal dome. Control panels stand here and there. To the south is an archway." The control panels are unimportant stuff in the Control Room. Understand "controls" as the control panels. The archway is scenery in the Control Room. Understand "arch" as the archway. Instead of entering the archway, try going south. Chapter 3 - Your Kit A tool is a kind of thing. The toolcase is an openable container. Understand "grey" or "gray" or "toolkit" or "case" or "tool case" as the toolcase. Understand "closed" as the toolcase when the toolcase is closed. Understand "open" as the toolcase when the toolcase is open. The description of the toolcase is "Your toolcase is a flat grey plastic form[if closed], which is closed.[otherwise], lined with shaped sponge foam. [contents of the toolcase]." [A phrase which shows what's in the case. Note that it does not end with a period/paragraph break. I wanted this to be usable as a string substitution inside a sentence.] To say contents of the toolcase: If the toolcase is closed begin; say "The toolcase is closed"; stop; end if; If the toolcase does not contain something, say "The toolcase is empty"; otherwise say "In the toolcase [is/are list of things in the toolcase]" [Same as above, but shorter, for use in an inventory listing] To say brief contents of the toolcase: If the toolcase is closed begin; say "a closed toolcase"; stop; end if; If the toolcase does not contain something, say "an empty toolcase"; otherwise say "a toolcase (in which [is/are list of things in the toolcase])" Instead of searching the toolcase, say "[contents of the toolcase]." The inventory listing of the toolcase is "[brief contents of the toolcase]". Instead of opening the toolcase when the toolcase is open: Say "The toolcase is already open." Report opening the toolcase when the toolcase does not contain something: Instead say "You open the toolcase, and find it empty." Report opening the toolcase: say "You open the toolcase. Inside [is/are list of things in the toolcase]."; if the toolcase encloses something perfumey begin; say "[conditional paragraph break]"; [This has to be broken up into two say phrases, due to a quirk of the paragraph machinery.] say "A wave of nasty perfume drifts out of the case."; end if; stop the action. A check inserting it into rule: If the second noun is the toolcase and the noun is not a tool, instead say "[The noun] won't fit in the case."; [I originally wrote the above this way: Instead of inserting something into the toolcase when the toolcase is open and the noun is not a tool: say "[The noun] won't fit in the case."; It's a toss-up which is nicer. The check rule doesn't have to have the "toolcase is open" exception, because the compiler inserts it after the "can't insert into closed containers" rule. On the other hand, you have to mess with "second noun".] [We have some foam padding, which is purely decorative.] The foam padding is part of the toolcase. Understand "shaped" or "sponge" as the foam padding. The description is "The toolcase is lined with foam padding, neatly shaped into hollows for the various tools that the case holds." Instead of taking the foam padding, say "The foam padding is part of the case." Instead of searching the foam padding, say "[contents of the toolcase]." Instead of inserting something into the foam padding, try inserting the noun into the toolcase. Rule for deciding the concealed possessions of the toolcase: if the toolcase is open then no; otherwise yes. [This conceals the foam padding when the case is closed. The tools aren't affected, because they wouldn't be visible anyway.] Chapter 4 - Rules for Connectable Stuff Color is a kind of value. The colors are black, red, purple, blue, green, yellow, orange, brown, and mauve. A module is a kind of tool. Understand "link" or "minus" as a module. A module has a color. Modules are usually mauve. Understand the color property as describing modules. A trigger is a kind of tool. Understand "link" or "plus" as a trigger. A trigger has a color. Triggers are usually black. Understand the color property as describing triggers. A remote is a kind of tool. A remote has a color. Remotes are usually black. Understand the color property as describing remotes. A thing can be connectable. A tool is usually connectable. [The connection between a trigger and a module is a reciprocal relation. This is slightly too broad, since this definition of the relation will permit connectivity between two triggers or two modules. We'll just have to be careful not to do that.] Connectivity relates one tool to another (called the partner). The verb to interface (it interfaces, they interface, they interfaced, it is interfaced, it is interfacing) implies the connectivity relation. Definition: a tool is connected if it interfaces something. [For the connection between a remote and a trigger, I decided to make two one-way relations, one defined in terms of the other. I had no particular reason for this.] Transmission relates one remote to one trigger. The verb to notify (it notifies, they notify) implies the transmission relation. Reception relates a trigger (called Y) to a remote (called X) when X notifies Y. The verb to attend (it attends, they attend) implies the reception relation. Contacting it with is an action applying to two things. Understand "touch [something] to [something]" as contacting it with. Understand "touch [something] on [something]" as contacting it with. Understand "touch [something] with [something]" as contacting it with (with nouns reversed). Understand "connect [something] to/on/onto/with/into [something]" as contacting it with. Understand the commands "link", "plug", "join", and "affix" as "connect". Understand the command "attach" as something new. Understand "attach [something] to/on/onto [something]" as contacting it with. Understand "tie [something] onto [something]" as tying it to. Instead of tying something (called X) to something (called Y), try contacting X with Y. Instead of putting a tool (called X) on a tool (called Y), try contacting X with Y. Detaching is an action applying to one thing. Understand "detach [something]" as detaching. Understand the commands "unlink", "unplug", "disconnect", and "free" as "detach". Detaching it from is an action applying to two things. Understand "detach [something] from [something]" as detaching it from. [Handy trick here. We want to modify the object's name in inventory listings and room descriptions (including sublists inside containers), but not during action commands. Solution: "while listing contents of some object". Note that "...of something" is not sufficient, because rooms are not "things"!] After printing the name of a module (called mod) while listing contents of some object: If mod interfaces something (called trig), say " (connected to [a trig])" Check contacting it with: If the second noun is connectable and the noun is not connectable, instead try contacting the second noun with the noun; if the noun is connectable, instead try connecting the noun with the second noun. Report contacting it with: instead say "Nothing happens." Report contacting it with when the noun is the second noun: instead say "You can't touch something to itself." This is the can't disconnect what isn't connected rule: if the noun is not connected, instead say "[The noun] isn't connected to anything." This is the can't disconnect what's connected elsewhere rule: if the noun is not the partner of the second noun, instead say "[The noun] is connected to [the partner of the noun], not to [the second noun]." [I really like expressing the conditions here with rules, like I've done. Sure, it's analogous to using subroutines in I6. But it's tidy.] Check detaching when the noun is a module: abide by the can't disconnect what isn't connected rule; instead try disconnecting the noun from the partner of the noun. Check detaching when the noun is a trigger: abide by the can't disconnect what isn't connected rule; instead try disconnecting the partner of the noun from the noun. Check detaching it from when the noun is a module: abide by the can't disconnect what isn't connected rule; abide by the can't disconnect what's connected elsewhere rule; instead try disconnecting the noun from the partner of the noun. Check detaching it from when the noun is a trigger: abide by the can't disconnect what isn't connected rule; abide by the can't disconnect what's connected elsewhere rule; instead try disconnecting the partner of the noun from the noun. Report detaching: instead say "There's no clear way to do that." Report detaching it from: instead say "There's no clear way to do that." [Connecting is a "fake action", in I6 terms; it isn't triggered by any player commands. It occurs only via a "try connecting..." phrase. I would have used an activity, except that an activity can apply to at most one thing.] Connecting it with is an action applying to two things. [I'm making this a general rule (no "when" clause) so that it sorts last in the rulebook of "check connecting it with". This may be a barbarism -- maybe I should name it and then say things like "the lockpick can't connect with itself rule is listed before the stuff can't connect with itself rule." For now, I won't bother.] Check connecting it with (this is the stuff can't self-connect rule): If the noun is the second noun, instead say "You can't connect something to itself." Report connecting it with: Say "Those don't connect." Check connecting it with when the noun is a trigger (this is the trigger connection check rule): If the noun is connected, instead say "[The noun] is already connected to [the partner]."; if the second noun is a trigger, instead say "You can't connect two positive links together."; if the second noun is a remote, instead carry out the complaining about no link on activity with the second noun; if the second noun is a connected module, instead say "[The second noun] is already connected to [the partner of the second noun]." Check connecting it with when the noun is a module (this is the module connection check rule): If the noun is connected, instead say "[The noun] is already connected to [the partner]."; if the second noun is a module, instead say "You can't connect two negative links together."; if the second noun is a remote, instead carry out the complaining about no link on activity with the second noun; if the second noun is a connected trigger, instead say "[The second noun] is already connected to [the partner of the second noun]."; if the second noun is a trigger, instead try connecting the second noun with the noun. Check connecting it with when the noun is a remote (this is the remote connection check rule): instead carry out the complaining about no link on activity with the noun. [This shouldn't have to be a procedural rule, but I couldn't get the "Rule X is listed after rule Y" declaration to work. Bug filed.] Procedural rule: Move the trigger connection check rule to after the stuff can't self-connect rule; move the module connection check rule to after the stuff can't self-connect rule; move the remote connection check rule to after the stuff can't self-connect rule. Carry out connecting when the noun is a trigger and the second noun is a module: Now the noun interfaces the second noun; relocate the second noun based on the noun; now the noun is part of the second noun; change the color of the noun to the color of the second noun; if something (called trans) notifies the noun, change the color of trans to the color of the second noun. Report connecting when the noun is a trigger and the second noun is a module: say "You connect [the noun] to [the second noun]. [The noun] turns [color of noun] to confirm the match"; if the noun attends something (called trans) begin; if the trans is visible, say ", and [the trans] turns [color of trans] as well"; end if; say ".[conditional paragraph break]"; if the noun is currently active begin; change the visible effect to zero; activate the second noun; end if; rule succeeds. [Another "fake action", parallel to connecting.] Disconnecting it from is an action applying to two things. Check disconnecting it from (this is the disconnection assertions rule): If the noun is not a module, instead say "(BUG) [The noun] is not a module!"; if the second noun is not a trigger, instead say "(BUG) [The second noun] is not a trigger!"; if the noun is not the partner of the second noun, instead say "(BUG) [The noun] and [the second noun] are not connected properly!"; if the second noun is not the partner of the noun, instead say "(BUG) [The second noun] and [the noun] are not connected properly!" Carry out disconnecting it from: now the noun is not interfaced by the second noun; now the player carries the second noun. Report disconnecting it from: Say "You disconnect [the noun], and take [the second noun] as it turns black again"; if the second noun attends something (called trans), if trans is visible, say ". [The trans] turns black as well"; say ".[conditional paragraph break]"; if the second noun is currently active begin; change the visible effect to zero; deactivate the noun; end if; rule succeeds. Instead of taking a trigger when the noun is connected: try taking the partner of the noun. Instead of dropping a trigger when the noun is connected: try dropping the partner of the noun. Report taking a module when the noun is connected: instead say "You take [the noun] (and [the partner of the noun] connected to it)." Report dropping a module when the noun is connected: instead say "You drop [the noun] (and [the partner of the noun] connected to it)." [I suffered some angst when trying to figure out how to implement this. Should it be an activity, a rule, a rulebook, or a phrase? I decided that I couldn't use a rule or rulebook, because I needed to pass in an argument. (You can't "follow" a rule/rulebook and provide an object for the rule to work on.) A phrase is suboptimal because the calling rule has to specify "rule fails". (Or am I wrong? I thought I tried it.) An activity seems to work, although I don't know why it's different from a phrase. I think an action would have worked too.] Complaining about no link on something is an activity. Rule for complaining about no link on something (called item): [The only way I could get a binding on the item's transmitter was this "if" statement.] if the item notifies something (called trig), say "[The item] doesn't have a link; it works through [the trig]."; otherwise say "[The item] doesn't have a link." To say tool status (item - tool): if the item is connected, say ", which is connected to [the partner]" To relocate (item - tool) based on (other item - tool): if the player carries the item or the player carries the other item begin; now the player carries the item; stop; end if; if the player encloses the other item begin; move item to the holder of the other item; stop; end if; if the player encloses the item begin; stop; end if; move item to the holder of the other item. Commanding on is an action applying to nothing. Understand "zap" as commanding on. Commanding off is an action applying to nothing. Understand "pow" as commanding off. Carry out commanding on: say "You say the keyword." Carry out commanding off: say "You say the keyword." [Activities used by the timer and voice triggers. (The other triggers are simple enough not to need it.) I originally used a fake action here, but that comes with baggage about reachability which I don't need. I just want some rules.] Engaging something is an activity. Disengaging something is an activity. [This is a half-clever trick. I need to keep track of whether remote activation produces any kind of visible effect. To do this, I sprinkle say "[effective]" substitutions into the various result messages. This substitution doesn't actually print anything; it just changes the visible effect variable.] The visible effect is a number that varies. To say effective: change visible effect to one. [Phrases which will define all module activity. The default values should not appear in final gameplay; they are placeholders for activity that I haven't written yet.] [Unfortunately, phrase precedence doesn't work right! (Bug filed.) I am working around this by having the activate/deactivate phrases trigger activities called activate-tmp/deactivate-tmp. The boolean argument "momentarily" will be shoved into a global variable. (An integer variable, since there are no boolean global variables.) I am not proud of this, but activity precedence works, so that's what I'm using.] To activate (item - module), momentarily: if momentarily, change momentarily-tmp-var to one; otherwise change momentarily-tmp-var to zero; carry out the activating-tmp activity with item. To deactivate (item - module): carry out the deactivating-tmp activity with item. Momentarily-tmp-var is a number that varies. To decide whether momentarily-tmp: If momentarily-tmp-var is zero, decide no; otherwise decide yes. To decide whether not momentarily-tmp: If momentarily-tmp-var is zero, decide yes; otherwise decide no. Activating-tmp something is an activity. Deactivating-tmp something is an activity. Rule for activating-tmp something (called item): if momentarily-tmp, say "[effective](BUG) [The item] activates momentarily."; otherwise say "[effective](BUG) [The item] activates." Rule for deactivating-tmp something (called item): say "[effective](BUG) [The item] deactivates." [Again, phrase precedence doesn't seem to be good enough to let me put rules on each item. So I'm doing this with a simple agglutinated "if" list.] To decide whether (item - thing) is currently active: if the item is the toggle switch and the toggle switch is on, decide yes; if the item is the voice module and the voice transmitter is on, decide yes; if the item is the timer and the timer is on, decide yes; decide no. Chapter 5 - Actual Tools [All of these tools say "...in the toolcase." I wanted to cut that out and use something less repetitive. I tried moving everything into the toolcase, with a "Repeat with item running through tools..." phrase at the beginning of play. That stuffed them in reverse order, though, and writing a "reverse order in container" routine would be ostentatious. So I went back to the way it is now.] Section - The Lockpick [The lockpick. Its functionality is not implemented in this sample.] The lockpick is a tool in the toolcase. Understand "pick" or "silver" or "rod" or "status" or "dot" as the lockpick. The description is "The pick is a silver rod the size of your ring finger -- not true silver, of course, nothing so easily scanned. It's splayed at one end into a flat disc of conductor-web matrix. The status dot is blue." Instead of touching or rubbing the lockpick, say "The rod is smooth and light, quick to pick up the heat of your fingers." The matrix disc is part of the lockpick. Understand "web" or "conductor" or "flat" or "disk" or "disc" or "lockpick matrix" or "lockpick disc" as the matrix disc. The description is "The lockpick widens at the top, ending in a coin-sized disc with the woven gleam of conductor-web matrix." Instead of touching or rubbing the matrix disc, say "The familiar weave slides across your thumb." The matrix disc is not perfumizable. The lockpick and the matrix disc are connectable. [I tried writing this as "Check connecting the lockpick with something: ..." but I can't seem to make that work.] Check connecting it with when the noun is the lockpick: if the second noun is the lockpick or the second noun is the matrix disc, instead say "The rod isn't flexible, you understand."; Report connecting it with when the noun is the lockpick: instead say "The pick does not react to [the second noun]." [Connection attempts with the matrix disc should be handled by the lockpick instead.] Check connecting it with when the noun is the matrix disc: instead try connecting the lockpick with the second noun. Section - Connectable Modules The bang tab is a purple module in the toolcase. Understand "small" or "cube" as the tab. The description is "It's a small [color] cube, which contains enough stabilized gel to make a satisfactory BANG noise. There's a minus link on one edge[tool status bang tab]." Rule for activating-tmp the bang tab: if the bang tab is visible begin; say "[effective][The bang tab] explodes with a satisfactory BANG[if the toolcase contains the bang tab], rattling the toolcase[end if]"; otherwise; if the toolcase contains the bang tab and the toolcase is closed and the toolcase is visible, say "[effective]BANG! [The toolcase] flies open as the tab explodes"; otherwise say "[effective]You hear a loud bang nearby"; end if; if the player encloses the bang tab, say ". You rub your numbed fingers"; say "."; if the toolcase contains the bang tab, now the toolcase is open; remove the bang tab from play The stink pack is a brown module in the toolcase. Understand "small" or "cone" as the stink pack. The description is "It's a small brown cone, covered with tiny pores. It [if stink pack is not expended]contains[otherwise]previously contained[end if] a pressurized capsule of nasty perfume. There's a minus link on one edge[tool status stink pack]." The stink pack can be expended. The stink pack is not expended. Rule for activating-tmp the stink pack: if the stink pack is expended, stop; now the stink pack is expended; if the stink pack is visible begin; say "[effective][The stink pack] hisses loudly, spraying perfume[if the toolcase contains the stink pack] out of the toolcase[otherwise] everywhere[end if]."; otherwise; if the toolcase contains the stink pack and the toolcase is closed and the toolcase is visible, say "[effective]You hear a loud hiss from inside [the toolcase]."; end if; [We want to perfumize everything in scope to the stink pack. The "can touch" relation handles this nicely, except that if the item is in the closed toolcase, it doesn't work right. (I think this is because the scope rules fail to understand the idea of being in a container -- they're written to deal with the scope of *people*, and people enter vehicles, not containers.) So we special-case the toolcase (har har), but otherwise use the natural I7 idiom.] if the toolcase contains the stink pack and the toolcase is closed begin; [I first wrote this as: repeat with item running through things enclosed by the toolcase begin; if the item is perfumizable, now the item is perfumey; end repeat; ...but that was making extra work for myself, wasn't it?] now each perfumizable thing which is enclosed by the toolcase is perfumey; otherwise; now each perfumizable thing which can be touched by the stink pack is perfumey; end if. Rule for deactivating-tmp the stink pack: stop. The minilamp is a yellow module in the toolcase. Understand "small" or "mini" or "lamp" or "torch" or "light" or "tube" or "lens" as the minilamp. The description is "It's a small yellow tube with a lens at one end[if minilamp is lit]; a beam of light shines out[end if]. There's a minus link on one edge of the tube[tool status minilamp]." [Handy trick here. We want to modify the object's name in inventory listings and room descriptions (including sublists inside containers), but not during action commands. Solution: "while listing contents of some object". Note that "...of something" is not sufficient, because rooms are not "things"!] Before printing the name of the minilamp while listing contents of some object: if the minilamp is lit, say "lit ". Rule for activating-tmp the minilamp: if not momentarily-tmp, now the minilamp is lit; if the minilamp is not visible, stop; if momentarily-tmp, say "[effective][The minilamp] glows for a moment, then goes out."; otherwise say "[effective][The minilamp] begins glowing." Rule for deactivating-tmp the minilamp: now the minilamp is unlit; if the minilamp is not visible, stop; say "[effective][The minilamp] goes dark." The sonic relaxer is an orange module in the toolcase. Understand "small" or "pyramid" as the relaxer. The description is "It's a small orange pyramid, traced with conductor matrix. [if relaxer is inactive]It is silent at the moment[otherwise]It is emitting relaxing frog-sounds[end if]. There's a minus link on one edge[tool status relaxer]." The relaxer can be either inactive or active. The relaxer is inactive. Instead of listening to the relaxer when the relaxer is active: say "Frog noises are coming from [the relaxer]." Instead of listening to the toolcase when the relaxer is active and the toolcase contains the relaxer: say "Frog noises are coming from [the toolcase]." Rule for activating-tmp the relaxer: if not momentarily-tmp, now the relaxer is active; let the producer be the relaxer; if the relaxer is in the toolcase and the toolcase is closed and the toolcase is visible, let the producer be the toolcase; if the producer is not visible, stop; if momentarily-tmp, say "[effective][The producer] emits a single croak."; otherwise say "[effective][The producer] begins playing a series of gentle frog croaks." Rule for deactivating-tmp the relaxer: now the relaxer is inactive; if the location of the player encloses the relaxer, say "[effective]The chorus of frog-noises ceases." After looking when the location of the player encloses the active relaxer: say "Gentle frog sounds fill the room." Section - Connectable Triggers The pushbutton is a trigger in the toolcase. Understand "push" or "button" or "box" as the pushbutton. The description is "It's a small [color] box with a button on one side and a plus link on the other[tool status pushbutton]." Instead of pushing or switching on the pushbutton: if the pushbutton is not connected, instead say "The link dot flashes green in confirmation, but as [the pushbutton] isn't linked to anything, that's all."; change the visible effect to zero; activate the partner of the pushbutton, momentarily; if the visible effect is zero, instead say "You press the button, but nothing happens." Instead of switching off the pushbutton, say "That's not something you can switch off." The toggle switch is a trigger in the toolcase. Understand "toggleswitch" or "toggle-switch" or "box" as the toggle. The description is "It's a small [color] box with a two-way toggle switch on one side, and a plus link on the other[tool status toggle]. The switch is [if toggle is off]off[otherwise]on[end if]." The toggle can be either off or on. The toggle is off. Instead of pushing or turning the toggle: if the toggle is on, try switching off the toggle; otherwise try switching on the toggle. Instead of switching on the toggle: if the toggle is on, instead say "The switch is already on."; change the toggle to on; say "You flip the [color] switch on. "; if the toggle is not connected, instead say "The link dot flashes green in confirmation, but as [the toggle] isn't linked to anything, that's all."; change the visible effect to zero; activate the partner of the toggle; if the visible effect is zero, instead say "There is no apparent effect." Instead of switching off the toggle: if the toggle is off, instead say "The switch is already off."; change the toggle to off; say "You flip the [color] switch off. "; if the toggle is not connected, instead say "The link dot flashes blue in confirmation, but as [the toggle] isn't linked to anything, that's all."; change the visible effect to zero; deactivate the partner of the toggle; if the visible effect is zero, instead say "There is no apparent effect." The timer is a trigger in the toolcase. Understand "dials" or "indicator" or "box" as the timer. The description is "It's a small [color] box with with two dials on one side, and a plus link on the other[tool status timer]. The status dot is [if on]green[otherwise]blue[end if]. [timer status]". Instead of reading the timer: say "[timer status]". Check turning when the noun is the timer: instead say "You can set the timer's green dial or its blue dial." Check setting vaguely when the noun is the timer: instead say "You can set the timer's green dial or its blue dial." Check dialing it to when the noun is the timer: instead say "You can set the timer's green dial or its blue dial." [The rule here: you can twiddle dials as you like; you don't get a countdown until you press the dial. If one dial is running, it's in the opposite state, and goes to the dial's state when the dial runs out. If you press the running dial, it stops (and the indicator vanishes.) If you press the non-running dial, it goes on, and you then get alternation. Press the non-running dial again, it shorts to that state of the alternation.] The timer can be either off or on. The timer is off. The timer can be neutral, switching, or alternating. The timer is neutral. The timer has a number called the setting. The setting of the timer is zero. The timer can be skipping this turn. The timer is not skipping this turn. To say timer status: if the on-dial is the same setting as the off-dial, say "Both the green and blue dials are set to [setting of on-dial]; "; otherwise say "The green dial is set to [setting of on-dial] and the blue dial to [setting of off-dial]; "; if the timer is switching, say "the [if on]blue[otherwise]green[end if] dial is lit. The"; if the timer is alternating, say "both dials are lit. The"; if the timer is neutral, say "the"; say " timer's indicator [if setting of timer is zero]is blank[otherwise]reads [setting of timer][end if]." Rule for engaging the timer: now the timer is on; change the visible effect to zero; if the timer is not connected and the timer is visible, instead say "The link dot goes green, but as [the timer] isn't linked to anything, that's all."; if the timer is connected, activate the partner of the timer; if the visible effect is zero and the timer is visible, instead say "The status dot goes green." Rule for disengaging the timer: now the timer is off; change the visible effect to zero; if the timer is not connected and the timer is visible, instead say "The link dot goes blue, but as [the timer] isn't linked to anything, that's all."; if the timer is connected, deactivate the partner of the timer; if the visible effect is zero and the timer is visible, instead say "The status dot goes blue." A dial-instance is a kind of thing. Understand "dial" as a dial-instances. Understand the color property as describing dial-instances. [I had some trouble here until I figured out the trick of using hyphenated terms for source-code names (which the player is unlikely to type), and then "understand" statements to parse player input. I did not, for example, want "dials" to be a valid descriptor of each dial -- the timer handles that.] Rule for printing the name of a dial-instance: say "[color] dial". A dial-instance is always not perfumizable. The on-dial and the off-dial are dial-instances which are part of the timer. A dial-instance has a number called the setting. The setting of a dial-instance is usually 1. A dial-instance has a color. The color of the on-dial is green. The color of the off-dial is blue. The description of a dial-instance is "[The item described] is set to [setting]." To decide which dial-instance is the current dial: if the timer is on, decide on the on-dial; otherwise decide on the off-dial. The timer-oneshot is a oneshot. [A one-time flag for explaining how the dials work.] Before setting vaguely or turning a dial-instance: instead say "The dial can be set from 1 to 20." Check dialing it to when the noun is a dial-instance: if the number understood is less than 1 or the number understood is greater than 20, instead try setting vaguely the noun; change the setting of the noun to the number understood; say "You set [the noun] to [the setting of the noun]"; if first trying the timer-oneshot, say ". (Press the dials to activate them.)"; otherwise say "."; stop. Instead of pushing a dial-instance (called this-dial) when timer is neutral: now the timer is switching; now the timer is skipping this turn; change the setting of the timer to the setting of this-dial; now the timer-oneshot is fired; say "[The this-dial] lights as you press it. The timer's indicator flashes to [setting of this-dial].[conditional paragraph break]"; if this-dial is the current dial begin; if this-dial is the on-dial begin; carry out the disengaging activity with the timer; otherwise; carry out the engaging activity with the timer; end if; end if. Instead of pushing a dial-instance (called this-dial) when timer is switching: if this-dial is the current dial begin; now the timer is alternating; say "[The this-dial] is now lit as well."; otherwise; now the timer is neutral; change the setting of the timer to zero; say "[The this-dial] goes out, and the timer's indicator goes blank."; end if. Instead of pushing a dial-instance (called this-dial) when timer is alternating: now the timer is neutral; change the setting of the timer to zero; say "Both dials go out, and the timer's indicator goes blank." [And the "daemon" procedure:] Every turn when the timer is not neutral: if the timer is skipping this turn begin; now the timer is not skipping this turn; stop; end if; decrease the setting of the timer by 1; if the setting of the timer is greater than zero begin; if the timer is visible, say "The timer changes to [setting of the timer]."; stop; end if; let this-dial be the current dial; if the timer is alternating begin; if the timer is visible, say "The timer's [this-dial] flashes once, and the indicator blinks to [setting of this-dial]. "; change the setting of the timer to the setting of this-dial; otherwise; now the timer is neutral; change the setting of the timer to zero; if the timer is visible, say "The timer reaches zero. "; end if; if the timer is on, carry out the disengaging activity with the timer; otherwise carry out the engaging activity with the timer; The radio module is a trigger in the toolcase. Understand "short" or "antenna" or "box" as the radio module. The description is "It's a small [color] box with a short antenna on one side and a plus link on the other[tool status radio module]." The voice module is a trigger in the toolcase. Understand "short" or "antenna" or "box" as the voice module. The description is "It's a small [color] box with a short antenna on one side and a plus link on the other[tool status voice module]." Section - Remotes for Triggers The key transmitter is a remote in the toolcase. Understand "trans" or "antenna" or "disk" or "disc" as the key transmitter. The description is "It's a small [color] disc with a key to press on one side, and a short antenna on the other." The key transmitter notifies the radio module. Instead of pushing or switching on the key transmitter: change the visible effect to zero; if the radio module is not connected and the radio module is visible, instead say "You press the transmitter key. [The radio module][apostrophe]s link dot flashes green in confirmation, but as it isn't linked to anything, that's all."; if the radio module is connected, activate the partner of the radio module, momentarily; if the visible effect is zero, instead say "You press the key, and the status dot flashes green, but you perceive no other effect." Instead of switching off the key transmitter, say "That's not something you can switch off." The voice transmitter is a remote in the toolcase. Understand "trans" or "antenna" or "audio" or "pickup" or "square" as the voice transmitter. The description is "It's a small [color] square with an audio pickup on one side, and a short antenna on the other. The status dot is [if on]green[otherwise]blue[end if]. The audio keywords are printed along one edge." The voice transmitter notifies the voice module. The voice transmitter can be either off or on. The voice transmitter is off. [These rules make the transmitter sensitive to bare "zap"/"pow" commands. I use "location encloses" test because no containers in this game are soundproof.] Instead of commanding on when the location encloses the voice transmitter: carry out the engaging activity with the voice transmitter. Instead of commanding off when the location encloses the voice transmitter: carry out the disengaging activity with the voice transmitter. Instead of asking the voice transmitter to try commanding on: carry out the engaging activity with the voice transmitter. Instead of asking the voice transmitter to try commanding off: carry out the disengaging activity with the voice transmitter. Before answering the player that: if the topic understood includes "zap", instead try commanding on; if the topic understood includes "pow", instead try commanding off. [There is no way in the current I7 system to make a non-person respond to commands: "voice transmitter, zap". Well, actually there is, but you have to declare the object to be an Inform library animate object -- not very obvious. So I'm leaving this out for now. Feature request filed.] Rule for engaging the voice transmitter when the voice transmitter is on: say "You say the keyword"; if the voice transmitter is visible, say ", but [the voice transmitter] is already on"; say "." Rule for disengaging the voice transmitter when the voice transmitter is off: say "You say the keyword"; if the voice transmitter is visible, say ", but [the voice transmitter] is already off"; say "." Rule for engaging the voice transmitter: change the voice transmitter to on; change the visible effect to zero; if the voice module is not connected and the voice module is visible, instead say "You say the keyword. [The voice module][apostrophe]s link dot flashes green in confirmation, but as it isn't linked to anything, that's all."; if the voice module is connected, activate the partner of the voice module; if the visible effect is zero, instead say "You say the keyword, and the status dot flashes green, but you perceive no other effect." Rule for disengaging the voice transmitter: change the voice transmitter to off; change the visible effect to zero; if the voice module is not connected and the voice module is visible, instead say "You say the keyword. [The voice module][apostrophe]s link dot flashes blue in confirmation, but as it isn't linked to anything, that's all."; if the voice module is connected, deactivate the partner of the voice module; if the visible effect is zero, instead say "You say the keyword, and the status dot flashes blue, but you perceive no other effect." The voice keywords are part of the voice transmitter. Understand "audio" or "keyword" or "word" or "words" as the keywords. The description is "The keywords for the voice transmitter are 'zap' to switch on, and 'pow' to switch off." The voice keywords is not perfumizable. ["are not" fails to compile here; bug filed.] Instead of doing something other than reading or examining the keywords, say "The keywords are only there as a reminder."