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: