ScottKit (compile/decompile Scott Adams game files)

Another question about the Howarth games: Feasibility Experiment has counters for the lion and dragon’s patience. They tick down in those creatures’ presence, and when they hit zero, you die.

However, those counters are never initialized anywhere, which means they start at zero. Is this correct—that is, do the lion and dragon actually kill you on the first turn? Or are these counters getting their initial values in some non-standard way?

Similarly, in Wizard of Akryz, there’s some code to make the spectacles fall off after three turns if the chain isn’t attached, and they shatter if you try to pick them up in the dark. But either that code isn’t finished, or my decompiler is doing something wrong.

(automatic)
	~(carried #spectacles-worn)
	
	(swap counter with counter 01)
	(now) (counter = 3)
	(swap counter with counter 01)

(automatic)
	(carried #spectacles-worn)
	~(chain attached to spectacles)
	
	(swap counter with counter 01)
	(decrease counter by 1)

Presumably after this there should be some code to check if counter 01 has hit zero, and then to swap it back after. But there just…isn’t.

So: does this code actually function in the game (meaning the problem is in my decompiler)? I can’t tell if Howarth is using the format in a non-standard way, or if he’s just using structures that Adams didn’t so my decompiler was never tested on them.

This is the same snippet decompiled with ScottKit

occur when !carried worn
	select_counter 1
	set_counter 3
	select_counter 1

occur when carried worn and !flag 4
	select_counter 1
	dec_counter
	continue

occur 0% when counter_eq 0
	destroy worn
	drop Spectacles
	print "The Spectacles have fallen off!"
	continue

occur 0%
	select_counter 1
	look

Are you missing decompiling the continue?

Guess you need a part after what you showed above, like:

(automatic)
	(carried #spectacles-worn)
	~(chain attached to spectacles)
    (counter == 0)
	
	(destroy worn)
	(drop spectacles)
    ...

I have not tested the game in any interpreter, but my guess is that ScottFree handles it correctly.

1 Like

Both ScottFree and the original (C64) interpreter print “I see nothing special”.

1 Like

I tested these briefly in ScottFree, and it seems that the lion will kill you immediately if you are not carrying the shield, otherwise it will never attack. The dragon will always kill you after three turns.

1 Like

The converter should work fine with Brian Howarth’s games – his games used the exactly same DAT format as the Scott Adams games.

Yes, the glasses stuff seems to be working in ScottFree, as well as the original ZX Spectrum and Commodore 64 interpreters.

As long as your interpreter handles the light timer properly. These games do not replace the lamp item with its turned-off version, so if the interpreter does not look out for this, the result will be a second, unlit, burned-out lamp appearing while the player is still holding the lit lamp.

EDIT: It turns out most of the Mysterious Adventures do not create a “burned-out light source” object, but simply rely on the interpreter removing the light source when the timer runs out. Which in a standards-compliant interpreter simply means that the light will keep on shining even after running out.

Not sure which Mysterious games actually use a lamp, though.

1 Like

Hmm, then somehow my decompiler is missing this specific continue. I wonder what’s weird about this one?

Oh this was something I was only dimly aware of, so thanks for bringing it up.

The ScottFree and ASFD interpreters have a -p option, called PREHISTORIC_LAMP, which makes the standard light source disappear when the timer runs out. I assumed this was for some very old/rare games, but it seems to be what the Brian Howarth games require.

I’ve looked at the decompilation of some of his games, especially #1 and #2, and they definitely assume that the light object will go away when the timer runs out.

Some of his other games just seem buggy, and don’t handle flag 16 at all, even though they have lamps which you can turn on/off and a timer which can run out.

I think this case is difficult for interpreters, there is no obvious way to detect a Brian Howarth game from a Scott Adams game. ASFD and ScottFree punt the decision to the user via that-p option. Perhaps the best they can do is detect when an item is the “off” version of the standard light source, and prevent both items ending up in the world at the same time?

2 Likes

The Dialog decompiler tracks which flags are used in the game’s code, so in theory, it could detect that flag 16 is never checked, and add in an extra daemon that removes the light source object when that flag is set. Would that accomplish the right behavior?

1 Like

Which games are these, if you don’t mind me asking?

I’d like to eventually compile a list of exactly which games need non-standard handling of the light source item and darkness flag.

According to the Dialog decompilations, 1, 2, and 6 check flag 16, 3 has no lamp timer, and all the rest use the lamp timer but don’t check flag 16.

(But the Dialog decompiler has been having some issues with the Howarth games, so take this with a grain of salt.)

1 Like

Thanks! I wonder if the games expect the interpreter to handle darkness, by looking at the light timer value in the header, bypassing the need to set flag 16 at all.

Yeah, I’m really not sure. I’m really surprised that we see (for example) 6 check flag 16 but 5 doesn’t, and so on.

Right, the difference is that some games (i.e. 1, 2, and 6) create “burned out” light source objects, and thus need to check flag 16 in order to create them at the right moment, while the rest of the games are content with just letting the light source object (always number 9) disappear, which the Howarth interpreter does automatically when the light timer reaches zero.

EDIT: If I’m not mistaken, the TI-99/4A interpreter also removes the light source object (9) from play automatically when the light timer runs out.

EDIT 2: There is a comment in the original ScottFree source about how “Brian Howarth games seem to use [a light timer of] -1 for forever”, but as far as I can tell the original interpreter still counts this (16-bit) value down, and simply doesn’t expect the player to last 32767 turns.

1 Like

Hmmm. So the Dialog translation happens in two stages: first it decompiles the DAT file, then it translates the decompiled code into Dialog. And this is what I get when I dump the raw decompilation.

Daemon 100%
	~CARRIED Spectacles (worn) (I9)
		SWAP_COUNTER C1
		SET_COUNTER #3
		SWAP_COUNTER C1
Daemon 100%
	CARRIED Spectacles (worn) (I9)
	~FLAG F4
		SWAP_COUNTER C1
		DEC_COUNTER 
		CONTINUE 
Continuation
	EQ #0
		DESTROY Spectacles (worn) (I9)
		DROP Strange Spectacles (I11)
		MESSAGE "The Spectacles have fallen off!" (M60)
		CONTINUE 
Continuation
		SWAP_COUNTER C1
		LOOK 

Which means the continuation is being decompiled, but it’s not being translated properly. This is going to be a headache…

But now there’s even more proof the problem is on my end. So hopefully I can fix this and post the Howarth Dialog versions soon!

1 Like

Aha! Found the problem. Howarth sometimes uses a CONTINUE opcode inside a continuation. This doesn’t actually do anything—once a single CONTINUE opcode has been encountered, the interpreter will keep executing continuations until it finds the next non-continuation action—but it confused the Dialog translator into resetting some internal variables too early, and the result was any continuations with a CONTINUE in them disappearing into the aether.

(automatic)
	(carried #spectacles-worn)
	~(chain attached to spectacles)
	
	(swap counter with spectacles falling off timer)
	(decrease counter by 1)
	%% 2 continuations attached
	
	(if)
		(counter = 0)
		
		(remove #spectacles-worn)
		(move #strange-spectacles to location)
		The Spectacles have fallen off! (line)
	(then) (endif)
	
	(if)
		(swap counter with spectacles falling off timer)
		(show room)
	(then) (endif)

Much better! I’ll redo all the other Howarth games too.

4 Likes

I just checked the disassembly of some TI-99/4A games (some by Scott Adams, some home-brew) and they usually check for flag 16 and swap two items, or explicitly destroy the lamp, just like the Scott Adams interpreter would do. So I think that the TI-99/4A interpreter does not automatically remove the lamp item.

These disassemblies were made by my defy tool, which is in the same repository as my unstitch tool which disassembles the text-based (DAT) format. If somebody wants a copy of these disassemblies, PM me.

I haven’t tested it in an emulator, but I think the author’s intent of a very high value is that the lamp will never run out, and so an interpreter should follow that intent.

What should the threshold be? Looking at the disassemblies, 10000 appears quite often, that would be my choice.

Link to unstitch: Andrew Apted / unstitch · GitLab

1 Like

I’ve got another headache for you, a little bug that slipped my mind until now.

The get opcode may “abort” the current action when the player is at their inventory limit, but the specific action should still succeed. In your Dialog translation, the get can make an action (the query implementing it) fail, so Dialog will try other matching actions, but that is incorrect behavior.

My specifications don’t do a great job at explaining this, and it’s something I haven’t been 100% sure of until recently. I plan to update the specs soon and clarify this, plus add some information about the Brian Howarth lamp behavior discussed here.

2 Likes