the-infocom-files / bureaucracy

Bureaucracy
8 stars 2 forks source link

PICK-NEXT sometimes prints garbage #15

Open eriktorbjorn opened 1 year ago

eriktorbjorn commented 1 year ago
>KISS DOOR
There's no point in doing that.

>KISS DOOR
That would be pointless.

>KISS DOOR
That's a pointless thing to do.

>KISS DOOR
ghis gdn gsusk.

What I'm doing here is triggering repeated calls to the WASTE-OF-TIME routine:

<DEFINE WASTE-OF-TIME ()
     <TELL PNEXT ,POINTLESS ,PERIOD>
     T>

<CONSTANT POINTLESS
    <TABLE (LENGTH PATTERN (BYTE [REST WORD])) #BYTE 0
     "There's no point in doing that"
     "That would be pointless"
     "That's a pointless thing to do">>

The PNEXT token is defined in TELL-TOKENS as:

             PNEXT *         <PRINT-PICK-NEXT .X>

The PRINT-PICK-NEXT routine is defined simply as:

<DEFINE PRINT-PICK-NEXT (TBL)
  <TELL <PICK-NEXT .TBL>>>

Which finally leads us to the subject matter of PICK-NEXT:

"PICK-NEXT expects an LTABLE (length=number of strings), with an extra
byte after the length that's initially 0."

<DEFINE PICK-NEXT (TBL "AUX" CNT:FIX STR)
         <SET CNT <GETB .TBL 2>>
         <SET STR <ZGET <REST .TBL 3> .CNT>>
         <COND (<G=? <SET CNT <+ .CNT 1>> <ZGET .TBL 0>:FIX>
                <SET CNT 0>)>
         <PUTB .TBL 2 .CNT>
         .STR>

When I asked in the Facebook group, the general consensus was that there is a bug in this routine, and not - as I had first thought - a bug in the way ZILF handles tables. So fixing it would be the simplest solution. However, disassembling (with txd) the released version of the game suggests that the routine was originally the same as in e.g. Trinity:

"PICK-NEXT expects an LTABLE of strings, with an initial element of 2."

<ROUTINE PICK-NEXT (TBL "AUX" CNT STR)
         <SET CNT <GET .TBL 1>>
         <SET STR <GET .TBL .CNT>>
         <INC CNT>
         <COND (<G? .CNT <GET .TBL 0>>
                <SET CNT 2>)>
         <PUT .TBL 1 .CNT>
         <RETURN .STR>>

In that game, WASTE-OF-TIME is defined as:

<ROUTINE WASTE-OF-TIME ()
         <TELL <PICK-NEXT ,POINTLESS> ,PERIOD>
         <RTRUE>>

<GLOBAL POINTLESS:TABLE
        <LTABLE 2
         "There's no point in doing that"
         "That would be pointless"
         "That's a pointless thing to do">>

So it would probably be more historically correct to revert to this implementation of PICK-NEXT, and change every table defined for it to match the expected format. The downside of that is that this is not a very small list.

I found these by searching for "LENGTH PATTERN". Some tables contain more than one sub-table.

Simply change "TABLE (LENGTH PATTERN (BYTE [REST WORD])) to "LTABLE 2". This is probably what I will be doing for the remainder of the testing.

eriktorbjorn commented 1 year ago

Here is an untested version of the patch I'm going to use. Where possible I have used the code formatting from Trinity. The resulting data file is 20 bytes larger than before. I don't think that will be a problem.

pick-next.txt

eriktorbjorn commented 1 year ago

Oops, found a bug in my patch. (I accidentally kept COULDNTS as a TABLE instead of an LTABLE.) Here's a new version:

pick-next-2.txt