the-infocom-files / zork1

Zork I: The Great Underground Empire
11 stars 3 forks source link

Drowning seems to happen too early in the Maintenance Room #36

Open eriktorbjorn opened 5 years ago

eriktorbjorn commented 5 years ago
>WAIT
Time passes...
The water level here is now up to your neck.
I'm afraid you have done drowned yourself.

So my head is still above the water. Why did I drown?

There are 13 messages before you drown:

The water level here is now up to your ankles.
The water level here is now up to your shin.
The water level here is now up to your shin.
The water level here is now up to your knees.
The water level here is now up to your knees.
The water level here is now up to your hips.
The water level here is now up to your hips.
The water level here is now up to your waist.
The water level here is now up to your waist.
The water level here is now up to your chest.
The water level here is now up to your chest.
The water level here is now up to your neck.
The water level here is now up to your neck.

The code for printing them:

<GLOBAL DROWNINGS
      <TABLE (PURE) "up to your ankles."
    "up to your shin."
    "up to your knees."
    "up to your hips."
    "up to your waist."
    "up to your chest."
    "up to your neck."
    "over your head."
    "high in your lungs.">>

<ROUTINE I-MAINT-ROOM ("AUX" HERE?)
     <SET HERE? <EQUAL? ,HERE ,MAINTENANCE-ROOM>>
     <COND (.HERE? <TELL "The water level here is now "> <TELL <GET
        ,DROWNINGS </ ,WATER-LEVEL 2>>> <CRLF>)>
     <SETG WATER-LEVEL <+ 1 ,WATER-LEVEL>>
     <COND (<NOT <L? ,WATER-LEVEL 14>>
        <MUNG-ROOM ,MAINTENANCE-ROOM
"The room is full of water and cannot be entered.">
        <QUEUE I-MAINT-ROOM 0>
        <COND (.HERE?
             <JIGS-UP
"I'm afraid you have done drowned yourself.">)>)
           (<AND <IN? ,WINNER ,INFLATED-BOAT>
             <EQUAL? ,HERE ,MAINTENANCE-ROOM ,DAM-ROOM ,DAM-LOBBY>>
        <JIGS-UP
"The rising water carries the boat over the dam, down the river, and over
the falls. Tsk, tsk.">)>
     <RTRUE>>

WATER-LEVEL is set to 1 when the water starts leaking, and is increased after the message. So when the first message is printed, it's 1. 1 / 2 is rounded down to 0. That's why the first message is only printed once.

The final message is printed when WATER-LEVEL is 13. After increasing it, it's no longer less than 14 and you're dead. 13 / 2 is rounded down to 6. The first element has index 0, so it prints the 7th element of the list ("up to your neck") both for level 12 and 13. So now we understand what happens.

So what about Mainframe Zork? It has the same list of messages, but the code is slightly different:

<PSETG DROWNINGS
      '["up to your ankles."
    "up to your shin."
    "up to your knees."
    "up to your hips."
    "up to your waist."
    "up to your chest."
    "up to your neck."
    "over your head."
    "high in your lungs."]>

<DEFINE MAINT-ROOM ("AUX" (MNT <SFIND-ROOM "MAINT">) (HERE? <==? ,HERE .MNT>) LEV)
    #DECL ((HERE?) <OR ATOM FALSE> (MNT) ROOM (LEV) FIX)
    <COND (<VERB? "C-INT">
           <SETG WATER-LEVEL!-FLAG <SET LEV <+ 1 ,WATER-LEVEL!-FLAG>>>
           <COND (<AND .HERE?
               <TELL "The water level here is now "
                 1
                 <NTH ,DROWNINGS <+ 1 </ .LEV 2>>>>>)>
           <COND (<G=? .LEV 16>
              <MUNG-ROOM .MNT
"The room is full of water and cannot be entered.">
              <CLOCK-INT ,MNTIN 0>
              <AND .HERE?
               <JIGS-UP "I'm afraid you have done drowned yourself.">>)>)>>

In Jeff Claar's C++ port, the first message you get is "up to your shin", and it's printed twice. The final message is "high in your lungs", which is also printed twice.

<NTH structured fix> "evaluates to the _fix_th element of structured. An error occurs if fix is less than 1 or greater than <LENGTH structured>." So apparently, in MDL the first element has index 1, not 0.

WATER-LEVEL!-FLAG is set to 1 when the leak starts. So for the first message, LEV will be 2. Divide by 2 and add 1, and that means the first printed message is the second one ("up to your shin"). The final message happens when LEV is 17. Both 16 and 17 will print the 9th message ("high in your lungs").

So Mainframe Zork seems buggy because it doesn't print the first message, and Zork I seems buggy because it doesn't print the two last messages.

If you ask me, you should get the "high in your lungs" message once and that's when you drown.

So what this all boils down to is that I think <NOT <L? ,WATER-LEVEL 14>> should be changed to <G? ,WATER-LEVEL 16>. With that change, I get:

>WAIT
Time passes...
The water level here is now over your head.

>WAIT
Time passes...
The water level here is now over your head.

>WAIT
Time passes...
The water level here is now high in your lungs.
I'm afraid you have done drowned yourself.

   ****  You have died  ****