the-infocom-files / ballyhoo

Ballyhoo
5 stars 4 forks source link

"PUT" command stops working after Rimshaw feels your head #11

Open eriktorbjorn opened 4 years ago

eriktorbjorn commented 4 years ago

This one has been bugging me for years:

>GIVE TICKET TO RIMSHAW
Rimshaw steps nearer, speaking in a very spiritual tone, "I can tell immediately
that you yourself possess great powers of transcendence. It is your eyes which
bespeak your affinity with those mysterious energies that choose to remain
unseen."

He punches your ticket and hands it back. "Whadda you want?"

>RIMSHAW, FEEL MY HEAD
Rimshaw the Incomparable places his fingertips on top of your skull and begins
going carefully over its hills and valleys, pausing occasionally for comment.
"Intelligence: I ascertain you play Infocom games. Personally I enjoyed
"Enchanter" ... Romance: A woman of mysterious beauty will soon come into your
life ... Travel: You will visit the Grand Canyon before the year is out."

With this, Rimshaw gives a perfunctory slap up the side of your head and says,
"End of Session."

>PUT MEAT IN BUCKET
Not in the least bit helpful.

In instead I do this, it keeps working:

>GIVE TICKET TO RIMSHAW
Rimshaw steps nearer, speaking in a very spiritual tone, "I can tell immediately
that you yourself possess great powers of transcendence. It is your eyes which
bespeak your affinity with those mysterious energies that choose to remain
unseen."

He punches your ticket and hands it back. "Whadda you want?"

>RIMSHAW, FEEL MY BUMPS
Rimshaw the Incomparable places his fingertips on top of your skull and begins
going carefully over its hills and valleys, pausing occasionally for comment.
"Intelligence: I ascertain you play Infocom games. Personally I enjoyed
"Enchanter" ... Romance: A woman of mysterious beauty will soon come into your
life ... Travel: You will visit the Grand Canyon before the year is out."

With this, Rimshaw gives a perfunctory slap up the side of your head and says,
"End of Session."

>PUT MEAT IN BUCKET
Done.

Very weird, considering "MY HEAD" and "MY BUMPS" should refer to the same object:

<OBJECT HEAD
        (IN GLOBAL-OBJECTS)
        (DESC "your head")
        (SYNONYM HEAD SKULL BUMP BUMPS) 
        (ADJECTIVE YOUR MY)
        (FLAGS NARTICLEBIT)
        (ACTION HEAD-F)>
eriktorbjorn commented 4 years ago

Other commands that work:

The problem seems to happen when "HEAD" is the third word.

Also:

>PUT MEAT IN BUCKET
Not in the least bit helpful.

>PUT THE LUMP OF MEAT IN THE BUCKET
Done.

The problem seems to be with IN-FRONT-FLAG, of all things. A feature which was probably intoduced in The Hitchhiker's Guide to the Galaxy, and was carried over to Ballyhoo, Nord and Bert and Border Zone. In The Hitchhiker's Guide to the Galaxy it's used for "PUT object IN FRONT OF object", and is set like this in PARSER:

                     ;"This COND added 8/7/84 for IN FRONT OF"
                     <COND (<AND <EQUAL? .VAL ,PR?IN>
                         <EQUAL? <GET ,P-LEXV
                                  <+ .PTR 2>>
                             ,W?FRONT>>
                        <SETG IN-FRONT-FLAG T>)
                       (<AND <EQUAL? .VAL ,PR?DOWN>
                         <EQUAL? <GET ,P-LEXV
                                  <+ .PTR 2>>
                             ,W?IN>
                         <EQUAL? <GET ,P-LEXV
                                  <+ .PTR 4>>
                             ,W?FRONT>>
                        <SETG IN-FRONT-FLAG T>)>

In Ballyhoo, I'm not yet sure exactly what it's used for, but is set like this in PARSER:

                     ;"This COND added 8/7/84 for IN FRONT OF"
                     <COND (<AND <EQUAL? .VAL ,PR?IN>
                         <EQUAL? <GET ,P-LEXV
                                  <+ .PTR 2>>
                             ,W?FRONT>>
                        <SETG IN-FRONT-FLAG T>)
                       (<OR <EQUAL? <GET ,P-LEXV
                                  <+ .PTR 2>>
                                 ,W?FRONT ,W?HEAD>
                            <EQUAL? <GET ,P-LEXV
                                  <+ .PTR 3>>
                             ,W?FRONT ,W?HEAD>
                        <EQUAL? <GET ,P-LEXV
                                  <+ .PTR 4>>
                                 ,W?FRONT ,W?HEAD>>
                        <SETG IN-FRONT-FLAG T>)
                       (<AND <EQUAL? .VAL ,PR?DOWN>
                         <EQUAL? <GET ,P-LEXV
                                  <+ .PTR 2>>
                             ,W?IN>
                         <EQUAL? <GET ,P-LEXV
                                  <+ .PTR 4>>
                             ,W?FRONT>>
                        <SETG IN-FRONT-FLAG T>)>

So I'm guessing what happens it that "RIMSHAW, FEEL MY HEAD" meant that W?HEAD was still in the P-LEXV buffer, and "PUT MEAT IN BUCKET" wasn't long enough to overwrite it with words from the new command. That's why "RIMSHAW, FEEL HEAD" and "RIMSHAW, FEEL MY YOUR HEAD" worked. The first one was probably short enough that W?HEAD was overwritten by the next command, and the second one was probably long enough that W?HEAD wasn't left in the critical spot.

eriktorbjorn commented 4 years ago

I forgot to say that it's PRE-PUT that prints the error message by calling V-DIG:

           (,IN-FRONT-FLAG
        <V-DIG>)

Anyway it's possible to reproduce the bug without even involving Rimshaw:

>PUT KEY IN BUCKET
Done.

>EXAMINE HEAD HEAD HEAD HEAD
[There were too many nouns in that sentence.]

>PUT MEAT IN BUCKET
Useless. Utterly useless.
eriktorbjorn commented 4 years ago

IN-FRONT-FLAG is checked in the following places:

So I'm guessing the parser checks for the word "HEAD" go catch things like "GO TO HEAD OF LINE", or something like that.

eriktorbjorn commented 4 years ago

Anyway, I guess it should check that there actually are words to look ahead to before checking what they are. But I don't know enough about the parser to suggest exactly how to accomplish this.

Either that or the conditions should be a bit more precise. The second one in particular seems rather fuzzy.

There's also an earlier case in PARSER, but I don't know what that's about, and it isn't what was triggered here:

                  <COND (<AND <G? ,P-LEN 0>
                      <EQUAL? <GET ,P-LEXV <+ .PTR ,P-LEXELEN>>
                          ,W?OF>
                      <0? .VAL>
                      <NOT <EQUAL? .WRD ,W?ALL ,W?ONE ,W?A>>
                      <NOT <EQUAL? .WRD ,W?BOTH>>>
                      <COND (<EQUAL? .WRD ,W?FRONT ,W?HEAD>
                         <SETG IN-FRONT-FLAG T>)>)
eriktorbjorn commented 4 years ago

Another thing that appears to be the same bug:

>PUT TICKET UNDER FRONT
The ticket disappears under the plywood and moments later a secret panel in the
old sideshow front slides open.

>EAST
As you enter, a blue haze of smoke stings your eyeballs.

Blue Room
In the far corner of this tented enclosure a thick, undulating cloud of smoke
hovers over a poker game. Straight across from you a tight-jawed dealer stands
over a blackjack table covered with a green floor-length tablecloth.

Your ticket lies here.

The spring-loaded secret panel slides shut.

>PLAY BLACKJACK
Useless. Utterly useless.

If I use another word than "FRONT":

>PUT TICKET UNDER PLYWOOD
The ticket disappears under the plywood and moments later a secret panel in the
old sideshow front slides open.

>EAST
As you enter, a blue haze of smoke stings your eyeballs.

Blue Room
In the far corner of this tented enclosure a thick, undulating cloud of smoke
hovers over a poker game. Straight across from you a tight-jawed dealer stands
over a blackjack table covered with a green floor-length tablecloth.

Your ticket lies here.

The spring-loaded secret panel slides shut.

>PLAY BLACKJACK
[Specify an amount of money, such as: BET 75 CENTS, or BET $1.50.]

This is because "PLAY BLACKJACK" is implemented like this in BLACKJACK-F:

     <COND (<VERB? PLAY>
        <PERFORM ,V?PUT-ON ,GLOBAL-MONEY ,TABLE>
        <RTRUE>)

"PUT TICKET UNDER FRONT" sets the IN-FRONT-FLAG, so the PUT-ON action is handled by the PRE-PUT routine, just as described above. The main difference is that this time the bug is triggered by the word "FRONT" instead of "HEAD".

eriktorbjorn commented 4 years ago

Here's yet another way of triggering the bug. The V-PUT-ON command has a special case for "PUT MASK ON HEAD"

     <COND (<OR <PRSI? ,ME>
            <AND <PRSI? ,HEAD>
                 <PRSO? ,MASK>>>
        <PERFORM ,V?WEAR ,PRSO>
        <RTRUE>)

Again, IN-FRONT-FLAG gets set and the command is caught in PRE-PUT.