Coffee disambiguation (Dialog example)
From IFWiki
To do our disambiguating, we partly rely on the predicate (heads $), which effectively tells the program, "If disambiguating, ignore all names except these."
As helpful as this is, the real star of our show is (unlikely $), which allows us to not only prioritize our cupful of coffee but also make some versatile code that can disambiguate in a variety of contexts.
(story title) Coffee Disambiguation Example (story author) Karona (story noun) for IFWiki (current player #player) #kitchen (name *) Test Kitchen (room *) (look *) This test kitchen is very clean. It's so clean, it hardly has anything in it. The living room is to the south. (#urn is #in *) (#mug is #in *) (from * go #south to #room) #urn (name *) coffee urn (heads *) urn %% We use the item trait to make it possible to take an object: (item *) (container *) (descr *) The urn is large, round, and heavy. It has to be large to hold the endless supply of coffee inside it. Perhaps you'd like to pour some into a mug? (appearance *) You see (a *) here. (#supply is #in *) %% We override the standard library response. (prevent [empty *]) (#supply is #in *) You can't empty the urn. (unlikely [pour $ into *]) (#supply is #in *) #supply (name *) endless supply of coffee (an *) (potable *) (descr *) Hello, tall, dark, and endless. (before [pour *]) (#player is in room $Room) (#mug is in room $Room) ~(#mug is #heldby #player) (first try [take #mug]) (unlikely [drink/taste *]) (* is in room $Room) (#cupful is in room $Room) (prevent [drink *]) How rude! Use a mug! (prevent [pour * into $Container]) ~($Container = #mug) You can't pour coffee into that. (prevent [pour * into $Container]) (#cupful is #in $Container) ($Container = #mug) But the mug is full! (perform [pour * into #mug]) Using the urn, you fill the mug with hot coffee. (now)(#cupful is #in #mug) (unlikely [smell *]) (* is in room $Room) (#cupful is in room $Room) (perform [smell *]) Smells good. Endlessly good. #mug (name *) coffee mug (heads *) mug (item *) (container *) (descr *) The mug has the phrase "WORLD'S BEST EXAMPLE CODER" prominently on the outside. The inside of the mug is (if)(#cupful is #in *)(then) full of coffee. (else) empty. (endif) (appearance *) You see (a *) here. (instead of [fill *]) (#player is in room $Room) (#supply is in room $Room) (try [pour #supply into *]) (instead of [drink *]) *($Stuff is #in *) (potable $Stuff) (try [drink $Stuff]) (prevent [pour *]) (#player is in room $Room) ~(* is in room $Room) But you don't have a mug! #cupful (name *) cupful of coffee (potable *) (descr *) The coffee in the mug looks quite drinkable. (prevent [pour * into $Container]) ~($Container = #urn) You can't pour the cupful of coffee into that. (prevent [pour * into #urn]) (#player is in room $Room) (#urn is in room $Room) The supply of coffee is already endless. (prevent [empty (container $Container)]) (* is #in $Container) That would be a waste of perfectly good coffee! (prevent [empty (container $Container)]) ~(* is #in $Container) ~(#supply is #in $Container) (The $Container) is already empty! (perform [smell *]) Smells good. A cupful of good. (perform [drink *]) You drink the mug of coffee. Aaah. The satisfaction. (now)(#cupful is nowhere) #room (name *) Living Room (room *) (look *) This pleasant living room is ever-so-lightly furnished with a coffee table. A kitchen can be found to the north. (from * go #north to #kitchen) (#player is #in *) (#table is #in *) #table (name *) coffee table (heads *) table %% We make the table a supporter -- and not an actor supporter -- to allow %% objects to be put on the table without allowing the PC to get on the table: (supporter *) (descr *) The coffee table is a modern piece of furniture with metal legs and a square glass top. %% We put general code after specific code. %% Liquids %% We define all things that are potable (and thus our #supply and our #cupful) %% to be liquids. Our code would work if we excluded this out and instead used %% the predicate (potable $) pervasively, but the author might want to add other %% liquids later, and using predicates in generic code is good practice. (liquid $Stuff) *(potable $Stuff) (grammar [pour [single] [into in] [single]] for [pour $ into $]) (grammar [fill [single] with [single]] for [pour $ into $] reversed) (instead of [pour $Obj into $Container]) *($Stuff is #in $Obj) (liquid $Stuff) (try [pour $Stuff into $Container]) %% When actual coffee is in scope, we do not want the parser to understand POUR %% COFFEE to be about the coffee table, the urn, or the mug. Declaring "table", %% "urn", and "mug" to be heads (as we did above) would be sufficient, but here %% we include versatile code that will handle liquids the author might include %% later. (unlikely [pour ~(liquid $Object)]) (prevent [pour $ into $Object]) ~(container $Object) (The $Object) is not a container. (prevent [pour $Object into $]) ~(potable $Object) (The $Object) is not a liquid. %% If there is an ambiguity, we assume that the player does not want to pour a %% liquid into the container that already holds it. (unlikely [pour $Liquid into $Object]) ($Liquid is #in $Object) (unlikely [pour $ into $Object]) ~(container $Object) (unlikely [pour $Object into $]) ~(liquid $Object) (grammar [pour [single]] for [pour $]) (unlikely [pour $Object]) ~(liquid $Object) (instead of [pour $Obj]) *($Liquid is #in $Obj) (liquid $Liquid) (try [pour $Liquid]) (instead of [pour $Stuff]) (#player is in room $Room) (#mug is in room $Room) (try [pour $Stuff into #mug]) (prevent [pour $Object]) ~(liquid $Object) (The $Object) is not a liquid. (grammar [fill [single]] for [fill $]) (grammar [empty [single]] for [empty $]) %% Potable (unlikely [drink/taste ~(potable $Object)]) %% We divert TASTE to DRINK but only if the object is potable. (instead of [taste (potable $Object)]) (try [drink $Object])