the-infocom-files / trinity

Trinity
24 stars 5 forks source link

"EXAMINE WINGS" sometimes fails if only one of the boots is winged #93

Open eriktorbjorn opened 4 years ago

eriktorbjorn commented 4 years ago
>PUT EMERALD IN GREEN BOOT
You press the emerald into the toe of the green boot. As you watch, the green
leather closes around the jewel and absorbs it like melting wax.

A shudder of ecstasy ripples up and down the length of the boot. It begins to
glow with raw energy, brighter and brighter, until you shield your eyes from the
glare.

When you peek again, a tiny pair of wings has sprouted out of the heel.

[Your score just went up by 1 point. The total is now 65 out of 100.]

>EXAMINE RED BOOT
The boot is exceedingly well-made, and colored bright red. A small recess is
visible at the toe's tip.

>EXAMINE WINGS
You can't see that here.

>EXAMINE WINGS
The boot is exceedingly well-made, and colored bright green. A pair of miniature
wings sprouts from the heel.

So I had to "EXAMINE WINGS" twice for it to work. Here's what happens.

Both RBOOT and GBOOT always has "WINGS" as one of their synonyms, so "EXAMINE WINGS" matches both boots. To help disambiguate, objects can define a GENERIC routine that can make the decision. So both boots define GENERIC-BOOT-F as theirs.

Like many other such routines in Trinity, this one is set up to prefer whatever "it" is referring to:

     <COND (<EQUAL? ,P-IT-OBJECT ,RBOOT ,GBOOT>
        <RETURN ,P-IT-OBJECT>)

So it returns RBOOT, even though the red boot doesn't yet have any wings, and RBOOT-F gets to handle the action:

     <COND (<BAD-BOOT-PART? ,RBOOT>
        <RFATAL>)>

The BAD-BOOT-PART? makes sure you can't refer to the recess when the boot has wings, and not to the wings unless the boot has them. The CHILLY flag indicates that the boot has wings:

           (<AND <NOT <IS? .BOOT ,CHILLY>>
             <NOUN-USED? ,W?WING ,W?WINGS>>
        <CANT-SEE-ANY>
        <RTRUE>)

The CANT-SEE-ANY routine will set P-IT-OBJECT to NOT-HERE-OBJECT, so the second time I examined the boots it made it through to this part of GENERIC-BOOT-F:

           (<OR <EQUAL? ,P-NAM ,W?WINGS ,W?WING>
            <EQUAL? ,P-XNAM ,W?WINGS ,W?WING>>
        <COND (<IS? ,RBOOT ,CHILLY>
               <COND (<IS? ,GBOOT ,CHILLY>
                  <RFALSE>)>
               <RETURN ,RBOOT>)
              (<IS? ,GBOOT ,CHILLY>
               <RETURN ,GBOOT>)>
        <REFERRING>
        <RETURN ,NOT-HERE-OBJECT>)

That is, if only one boot is winged it will pick that one. Otherwise, it will give up and the parser will ask you which one you meant.

Changing it to something like this seems to work:

diff --git a/things.zil b/things.zil
index f6039d1..d1afd83 100644
--- a/things.zil
+++ b/things.zil
@@ -6618,22 +6618,24 @@ You curse and fume at the stupid, flimsy " D ,PRSI
        (GENERIC GENERIC-BOOT-F)
        (ACTION GBOOT-F)>

-<ROUTINE GENERIC-BOOT-F (TABLE "AUX" LEN)
+<ROUTINE GENERIC-BOOT-F (TABLE "AUX" LEN (OBJ <>))
         <COND (<EQUAL? ,P-IT-OBJECT ,RBOOT ,GBOOT>
-               <RETURN ,P-IT-OBJECT>)
-              (<OR <EQUAL? ,P-NAM ,W?BOOTS ,W?PAIR>
+               <SET OBJ ,P-IT-OBJECT>)>
+        <COND (<OR <EQUAL? ,P-NAM ,W?BOOTS ,W?PAIR>
                    <EQUAL? ,P-XNAM ,W?BOOTS ,W?PAIR>>
                <RETURN ,RBOOT>)
               (<OR <EQUAL? ,P-NAM ,W?WINGS ,W?WING>
                    <EQUAL? ,P-XNAM ,W?WINGS ,W?WING>>
                <COND (<IS? ,RBOOT ,CHILLY>
                       <COND (<IS? ,GBOOT ,CHILLY>
-                             <RFALSE>)>
+                             <RETURN .OBJ>)>
                       <RETURN ,RBOOT>)
                      (<IS? ,GBOOT ,CHILLY>
                       <RETURN ,GBOOT>)>
                <REFERRING>
                <RETURN ,NOT-HERE-OBJECT>)
+              (.OBJ
+               <RETURN .OBJ>)
               (T
                <RFALSE>)>>

The idea here is: