Invalid values for time in V3 games

A couple days ago, @eriktorbjorn pointed out that Infocom’s “Cutthroats” does something strange with the in-game time at the status line. If you’re wearing your watch, you’ll see the current time. If not, something else. With most Infocom terps: for Apple II, C64, CP/M, DOS, and Macintosh; you’ll see Time: 99:99 pm. For the Amiga interpreter, you’ll see Time: 3:99 pm. This is also what Frotz and Jzip do. Going through the source code to “Cutthroats”, we see this:

<ROUTINE WATCH-UPDATE ()
	 <COND (<IN? ,WATCH ,PLAYER>
		<SETG MOVES ,WATCH-MOVES>
		<SETG SCORE ,WATCH-SCORE>)
	       (T
		<SETG MOVES 99>
		<SETG SCORE 111>)>>

For V3, time is encoded with the moves representing minutes and score representing hours. Here, if you’re not wearing the watch, the hour is set to 111. Then, in the interpreter, this is checked and if the hours are invalid, then subtract 12 and you get 99. Here’s a snippet of the assembly code to an Infocom interpreter for the Tandy Color Computer:

	; PRINT TIME (HOURS)

PTIME:	LDA	TEMP+1
	BNE	PTIME1		; 00 IS REALLY 24
	LDA	#24
PTIME1:	CMPA	#12
	BLE	PTIME2		; IF HOURS IS GREATER THAN 12,
	SUBA	#12		; CONVERT TO 12-HOUR TIME
	STA	TEMP+1
PTIME2:	JSR	NUMBER		; SHOW HOURS VALUE
	LDA	#$3A		; ASCII COLON

If the hour is greater than 12, the interpreter assumes that 24-hour notation is used, and so subtracts 12. The author of “Cutthroats” obviously was aware of this behavior and used it to create a sensible “invalid” value.

Here’s what Frotz has always done for the time in a V3 game:

zword hours = (global1 + 11) % 12 + 1;

That performs the conversion of 24-hour to am/pm correctly, rather than the quick-and-dirty approach Infocom used and results in 3 instead of 99. Clearly the Amiga interpreter did this too. I don’t know how this would be discovered to this depth without the availability of the ZIL code of Infocom’s games.

So, I’ll alter the Frotz core to check if “Cutthroats” is being played and to return what the implementors expected.

This was first reported at https://gitlab.com/DavidGriffith/frotz/issues/187

4 Likes

Note that the handling of am/pm and time reduction is inconsistent - the code in Frotz (and Jzip) just checks if hours>12 to use pm (same thing the CoCo assembly does). The z-machine standard is not rally helpful, saying in section 8.2.3.2:

For “time games”: the time, in the form hours:minutes (held in the second and third globals). The time may be given on a 24-hour clock or the number of hours may be reduced modulo 12 (but if so, “AM” or “PM” should be appended). Either way the player should be able to see the difference between 4am and 4pm, for example. The hours global may be assumed to be in the range 0 to 23 and the minutes global in the range 0 to 59.

Seems to me the best thing to do is to follow Infocom’s practice and if anything is conditional it should be if machine type is Amiga (but in this case more testing is needed to see how am/pm is handled there).

if anything is conditional it should be if machine type is Amiga (but in this case more testing is needed to see how am/pm is handled there).

Note that the list of interpreters I made for the bug report was not intended to be exhaustive in any way. It was just the DOS version, plus any version that I could find an run from The Internet Archive. According to my notes, what I saw was:

TIME: 99:99 PM     (Apple II)
Time: 99:99 PM     (C64)
Time: 99:99 pm     (CP/M, DOS, Macintosh)
Time:  3:99 pm     (Amiga)

What did surprise me the most was that the Macintosh and Amiga versions behaved differently, because it suggests that they were not directly based on each other despite being for the same CPU. I wonder what the Atari ST version did…

By the way, Cutthroats seems to be the only canonical test case for displaying an invalid time in the status line. As far as I know the only V3 games to display time are Cutthroats, Deadline, Moonmist, Suspect, Wishbringer and The Witness.

As far as I can tell, in all except Cutthroats SCORE will always be in the range 0-23 and MOVES will always be in the range 0-59. They will always reflect the actual in-game time.

In Cutthroats, the status line reflects your watch and has nothing to do with the actual in-game time. As long as you’re carrying the watch, SCORE will always be in the range 0-11 (if you examine the watch you are told that “The AM/PM indicator never did work.”) and MOVES will always be in the range 0-59. The watch will stop if you don’t wind it, and you can set it to any time you like. If you’re not carrying the watch, SCORE is set to 111 and MOVES to 99 as described above.

The only other V3 games I can remember where the status line reflect an in-game object rather than the actual game time are Planetfall and Stationfall. If you’re not carrying the chronometer the status line will show “0” as the time (I noticed earlier today that this actually causes a slight status line glitch in the Solid Gold version of Planetfall), and in Planetfall you can stop the chronometer by pouring acid on it.

2 Likes

I decided to alter behavior for Cutthroats because the author made an assumption about the interpreters wherein the Amiga interpreter clearly behaved contrary to the assumption. I can see this being either an accident or a case of “not ideal, but acceptable.”.

I don’t know if it has any significance, but according to The Infocom Fact Sheet, Cutthroats predates the Amiga interpreter. So the assumption came first, I guess.

Have you noticed with which interpreters this glitch with Gold Planetfall happens?

Have you noticed with which interpreters this glitch with Gold Planetfall happens?

I assumed it was all of them, since it looks like a coding error. The UPDATE-STATUS-LINE function doesn’t redraw the entire status line, only the parts it thinks have changed. This is how it updates the moves and score:

	 <COND (<G? ,WIDTH 74>
		<CURSET 1 58>
		<TELL N ,SCORE " ">  ;"for 110 to 80 score bug"
		<CURSET 1 70>
		<TELL N ,MOVES>)
	       (T
		<DIROUT ,D-TABLE-ON ,SL-TABLE>
		<TELL N ,SCORE "/" N ,MOVES " ">
		<DIROUT ,D-TABLE-OFF>
		<CURSET 1 <- ,WIDTH <+ <GET ,SL-TABLE 0> 1>>>
		<TELL N ,SCORE "/" N ,MOVES " ">)>

So, if I understand it correctly, it draws an extra space in case the score is decreased to make it shorter than before. (I don’t think that happens in Planetfall, so it may be a leftover from some other game.) But it doesn’t account for the moves (actually the time) going from a 4-digit number to a 1-digit number. So if you drop the chronometer, the first digit of the time becomes a 0 and the other three remain “frozen”.

I think quality control must have suffered a bit in Infocom’s final years. I’ve stumbled over annoying bugs in three of the five “Solid Gold” titles that weren’t present in the original releases:

  • In Planetfall, you can’t push the up and down elevator buttons if you are carrying the diary that was added as an in-game object for the Solid Gold version. Apparently the parser thinks you mean the button on the diary.
  • In Leather Goddesses of Phobos, you can push the orange and purple buttons even if you are nowhere near the barge.
  • In Wishbringer, you never run out of time. After 5 pm the “TIME” command will simply tell you that you have a negative number of hours and minutes left to complete your delivery.

Time to upgrade the Infocom bug list, seems…

(yes, the joke is intentional…)

Best regards from Italy,
dott. Piergiorgio.
^------ no, I have only one heart :wink:

I don’t think this is correct. It’s just that a single integer value is used to keep track of the hours, but the statusline clock needs to show 1-2 digits for the hour PLUS an AM/PM indicator. So 13 is used to represent 1 PM etc. To print a time after 12:59 PM, the interpreter needs to subtract 12 from the hours before printing the value.

Isn’t that what I said? What we have here are different ports of the Z-machine behaving differently. The big question, I think, is “Which way is correct? Amiga or pre-Amiga?”.

What I mean is: The interpreter doesn’t need to assume anything about notation. There is only one way to represent 3:00 PM which the interpreter can understand, and that’s by setting the hours to 15 and minutes to 0.

Anyway, I think the fact that Cutthroats expects the terp to work this way is important. I have therefore changed the behaviour of Ozmoo to match this. I wasn’t aware of the issue before you brought it up here, so thanks for the heads-up.

The whole affair of the interpreter handling the clock display is weird, which I suppose is why it’s done differently after V3.

So, the “correct” way to handle 24-to-12 is “wrong” for V3 and a note to that effect should go in the new standard?

Of course, for all Z-machine versions other than v3, the terp doesn’t care about time.

For v3, yes, I think it makes sense to say terps should work in a way that makes the time 111:nn display as “99:nn PM” since Cutthroats is part of the canonical story files and that’s clearly how the imps who wrote it expected a terp to work.

1 Like

I reversed the idiosyncrasy fix for Cutthroats in Frotz and redid the time display to match how the COCO source does it. This will be in the 2.52 release.

I’m guessing the reason Infocom did it like this was because doing it the Right Way would have been too taxing for the very limited machines upon which a V3 interpreter was expected to run. When the V3 interpreter for the Amiga was written, the author either was unaware of this detail or forgot.

1 Like