the-infocom-files / amfv

A Mind Forever Voyaging
5 stars 2 forks source link

"ASK LIBRARIAN FOR ACCOUNT" doesn't work #9

Open eriktorbjorn opened 4 years ago

eriktorbjorn commented 4 years ago

In release 79, you can ask the librarian for an account. The exact message depends on the year, but it can look like this:

>LOOK
Main Library
This is the main branch of the Rockvil Public Library system, crowded but quiet.
The librarian is standing near the card catalog. The only exit is southeast.

>ASK LIBRARIAN FOR ACCOUNT
The librarian has you fill out several forms. After filing them, she whispers
that your card should arrive in the mail within a month.

In the version here, it doesn't work:

>ASK LIBRARIAN FOR ACCOUNT
[You'll have to be more specific.]

In fact, I get this for all three preserved versions of the source code.

The problem seems to be this bit in MOBY-FIND:

     '<PROG ()
     <REPEAT ()
         <COND (<AND ;<SET FOO <META-LOC .OBJ T>>
                 <NOT <IN? .OBJ ,ROOMS>>
                 <SET FOO <THIS-IT? .OBJ>>>
            <SET FOO <OBJ-FOUND .OBJ .TBL>>)>
         <COND (<IGRTR? OBJ ,MUSEUM-ENTRANCE>
            <RETURN>)>>>)

In the official release, MUSEUM-ENTRANCE is object 609 which is the last object in the game.

In the ZILF-compiled version, MUSEUM-ENTRANCE is object 341, and ROCKVIL-CENTRE is the last object. If I change MOBY-FIND to use ROCKVIL-CENTRE instead it works, but I'm not suggesting that as the way to fix it. Just as an indication that I'm probably on the right track.

I have a feeling that this will lead to many similar bugs down the line...

eriktorbjorn commented 4 years ago

Here's what I've been able to find about MOBY-FIND:

Zork I-III, Deadline and Starcross do not have this routine at all. If they do have similar functionality, it's called something else.

In most games, MOBY-FIND loops through the contents of the ROOMS object.

In Hollywood Hijinx and Wishbringer (both the original and the Solid Gold) version, MOBY-FIND loops through object 1 to DUMMY-OBJECT. This is an object defined in misc.zil with the comment "NOTE: This object MUST be the FIRST one defined (for MOBY-FIND)!". I wasn't able to find any bugs related to this in the original release of Wishbringer. I haven't tested the other two yet.

A Mind Forever Voyaging, as mentioned above, hard-codes MUSEUM-ENTRANCE as being the last object.

In many of the later games (starting with Ballyhoo, I think, but not including every game after that), MOBY-FIND loops from object 1 to LAST-OBJECT. This is a constant defined as 0 in the source code, but usually with a comment that "ZILCH should stick the # of the last object here".

Starting with Sherlock, things start getting a bit too different for me to easily compare things.

So this change works for me:

diff --git a/parser.zil b/parser.zil
index 7ada990..b68908d 100644
--- a/parser.zil
+++ b/parser.zil
@@ -1284,6 +1284,8 @@ the words in the last clause"
               <SETG P-ADJ <>>
               <RTRUE>>>

+<CONSTANT LAST-OBJECT 0> ;"ZILCH should stick the # of the last object here"
+
 <ROUTINE MOBY-FIND (TBL "AUX" (OBJ 1) LEN FOO NAM ADJ)
   <SET NAM ,P-NAM>
   <SET ADJ ,P-ADJ>
@@ -1301,7 +1303,7 @@ the words in the last clause"
                             <NOT <IN? .OBJ ,ROOMS>>
                             <SET FOO <THIS-IT? .OBJ>>>
                        <SET FOO <OBJ-FOUND .OBJ .TBL>>)>
-                <COND (<IGRTR? OBJ ,MUSEUM-ENTRANCE>
+                <COND (<IGRTR? OBJ ,LAST-OBJECT>
                        <RETURN>)>>>)
        (T              ;"ZIL case"
         '<PROG ()

Perhaps the same thing should also be applied to Wishbringer and Hollywood Hijinx?

eriktorbjorn commented 4 years ago

This also appears to be why "BUY SOY PATTY" doesn't work in the 2071 Foodville, unless you already have the soy patty.

eriktorbjorn commented 4 years ago

Yet another bug caused by this is that you can't attempt to buy a newspaper at the Drug Store. Or for that matter, trying to buy a newspaper where none is available.

eriktorbjorn commented 4 years ago

Yet another bug caused by this is that you can't buy a glass of water at the restaurants.

eriktorbjorn commented 4 years ago

Another bug caused by this is that "FOLLOW OFFICIAL" doesn't work after talking to the government official. (Though I just noticed that V-FOLLOW doesn't actually check who you a trying to follow when FOLLOW-FLAG is 9...)

eriktorbjorn commented 4 years ago

That you can't "WAIT FOR PEOPLE" on the rooftop in Part 3 of the game is probably caused by this, but I haven't actually verified it. (Other than seeing that "WAIT FOR PEOPLE" produce a different default response if I fix the bug.)

taradinoc commented 4 years ago

+1 for patching MOBY-FIND to use LAST-OBJECT instead of hardcoding an assumption.

I'm not sure why the objects are numbered the way they are in the original build. For example, the objects MORNING-START, MORNING-END, EVENING-START, and EVENING-END are defined together and used together, but the numbers are nowhere near sequential. It seems to be stable across releases, though... my guess is the numbers were assigned by walking through a hash table.

eriktorbjorn commented 4 years ago

If we take the PAX USB Drive (http://www.ifwiki.org/index.php/PAX_USB_Drive) as canon (I don't think I had even heard of it before today), there is a file there (game-zil.doc) that talks about object numbering:

<ORDER-OBJECTS? how> tells ZILCH to generate object numbers in a particular order; normally they're generated at random. This can be helpful if, for example, you have a lot of tables of rooms; if all rooms have an object number that's less than 255, you can put them in byte tables rather than word tables. The `how' argument is one of: ROOMS-FIRST (rooms will have small object numbers); ROOMS-LAST (rooms will have big object numbers); DEFINED (object numbers will be assigned in the order the objects were defined); anything else is at random.

(Emphasis added.)

So I guess that answers why they're ordered the way they are in the original: It's random. (But your explanation seems good too. :-)