game behaves differently in IDE and release version (6L02)

Hello all,

This is a very specific bug in a very long game, but part of the problem is the difficulty of reproducing it, so I hope you’ll bear with me.

Some folks have pointed out that in Terminator they get a message every turn that says “You’ll have to say what compass direction to go in.” After some fiddling around, it appears that this message does not appear in the IDE, and does not appear when I release a testing version, but does appear when I release a version straight from the source code that I have in the IDE.

This naturally makes it very difficult for me to figure out where the bug is coming from, because any version in which I can run the debugging commands (like “rules”) doesn’t have the bug. (The bug itself is clearly coming from the “block vaguely going” rule running when it shouldn’t, but I don’t know what’s triggering it.)

The source code is here and the raw text is here. The extension “Multiple Actors” which I’m using can be found here and the other extensions it depends on are also on Github, except for Serial And Fix, which is the code in this post. I compiled using 6L02, though a quick scan of the bug tracker doesn’t reveal any obvious fixed bugs that could be causing it.

I have one “for release only” section, but I don’t see how it could be causing the bug, and in any case the testing release seems to include this section and doesn’t have the bug.

I’m sorry for the amount of effort it would take to try to track down this bug, but I’m at my wit’s end (admittedly not a long journey) and I really have no idea how this can be happening.

Matt

It’s way beyond my level of competence to try to diagnose this, but I can suggest a technique. Have you tried inserting old-fashioned print statements (oops, I mean “say” statements) manually into various blocks of code that may be running just before the offending rule? This may mean creating a personal temporary version of the Standard Rules, but that’s not hard to do. It might allow you to trace back through the code.

The other thought I have is, something in the not-for-release code is evidently bypassing the bug. You might be able to work backwards by eliminating bits of the debug-only code until the bug shows up.

Does the problem occur for everybody using the release build, or just some players? Your other post isn’t clear.

Also: can you post a package containing all your code and the extensions you’re using? I don’t want to go through a bunch of testing that winds up being different from what you’ve got.

zarf: Just saw your message on posting. I think the attached files should do it. [EDITED to actually attach the files.] The source file is “source.txt.” I’m compiling under 6L02.

I’m not sure whether the problem occurs for everyone. Looking at the transcripts I got it’s only in some of them but some (probably all) of the transcripts are of earlier versions of the game. I’ve only got feedback from one person who I know to be using the release build, and it’s happening for me with the release build.

Jim: Well, it’s not actually the for-release code (I don’t have any “not for release” code as such, unless it’s in an extension), because the for-release code shows up in the release-for-testing build and the bug doesn’t. So it’s somehow being bypassed by whatever allows “rules” and “actions” to be run in testing builds, or caused by whatever Inform does when it creates a release build rather than a testing build (or rather by some interaction of the code with the aforesaid).

Also the bug appears to be happening somewhere between the parser and the action generation. I put in this:

[code]First for supplying a missing noun:
say “Supplying a missing noun rules running on [the player’s command] for [the current action].”;
continue the activity.

This is the print action check rule:
say “The current action is [the current action].”

The print action check rule is listed before the declare everything initially unmentioned rule in the turn sequence rulebook.[/code]

and the output in the release build is:

…this at the first command prompt after an initial yes/no question, so there wasn’t a stray going nothing action left over from a previous turn. (In the IDE version I get “the current action is waiting” twice and then the final message, which is what I’m supposed to get.)

Which makes me think that maybe instead of the standard rules I’d need to be putting debug statements into the parser, and that’s not something I know how to do, or particularly want to learn.

Some of the extensions and kludges I use hack things up pretty bad, I guess, but why would they hack things up in release builds and not testing builds?
Terminator code and extensions.zip (37.5 KB)

I have not spent a lot of time on this – I spent today on that Quixe hack I mentioned in another thread. However, I have compiled your source in 6L02 and verified that the problem happens the way you say.

(It doesn’t compile in 6L38 due to a name clash. I expect it would be very quick to update for 6L38, but I am going to focus on 6L02 for this bug.)

A stack trace reveals that the errant message is printed from the ActionVariablesNotTypeSafe() call in ActionPrimitive(). ActionPrimitive() is one of the routines modified in “Multiple Actors.i7x” but I haven’t looked at the details yet. I will try to do that tomorrow.

This is Multiple Actors:

if ((meta) && (actorflag)) { ! Changed here. ACTION_PROCESSING_INTERNAL_RM('A',(+entry 1 of the multicommand actor list+)); new_line; FollowRulebook((+cancel metacommand rule+)); rv = RS_FAILS; }
This is the normal Actions.i6t:

if ((meta) && (actor ~= player)) { ACTION_PROCESSING_INTERNAL_RM('A', actor); new_line; rv = RS_FAILS; }
both in 6L02 and 6L38. That leaves open several possible avenues of investigation… Okay, I looked at it for about 20 minutes, which wasn’t enough, and I don’t have any more time right, now.

I’ve spent a little more time. I can see what’s happening, but not why.

After entering a command, the modified generate action rule is invoked once with all variables zero (action, noun, second, etc); and then again with the real action value. This happens in both the debug and release versions.

In the debug version, 0 is the debug “GLKLIST” action. It doesn’t actually execute. I’m not sure why not. (It’s not that keep_silent is set, I checked that.) But it gets past the “check for missing noun” test, which of course it passes, because that action takes no nouns.

In the release version, 0 is the “GO” action. Since there is no noun, it fails the “check for missing noun” test, and you see the error message.

So your answer is, something is triggering an extra action execution with bad data. This bug exists in all versions of your game, but it happens to only print an error message in the release version.

Aha! I never would have caught that!

It’s a stupid error on my part in the Multiple Actors extension. Once it’s parsed a list of names, I had it return from the parser routine. But the parser is only supposed to return when it’s successfully filled the parser_results struct. So the default zero values are left in there. I’ve changed it now to “jump ReType” instead, which is what is supposed to happen after printing an error message. It seems to work now.

EDIT: New version available here.

What is odd though is, why is it behaving differently in testing releases?

The parser uses several variables to return its results, and it starts out by zeroing them:

	cobj_flag = 0;
	parser_results-->ACTION_PRES = 0;
	parser_results-->NO_INPS_PRES = 0;
	parser_results-->INP1_PRES = 0;
	parser_results-->INP2_PRES = 0;
	meta = false;

This is sensible. If I typed “X BOOK” and then “JUMP”, the parser would not find a noun in the second sentence, and it makes more sense to reset it to 0 (nothing) than to leave it set to the book.

However, this also resets the action name to 0: the first action defined in the standard library. Usually this doesn’t matter because the parser will not return until it finds a verb, which will overwrite that. But due to a bug in my modified I6 code it would return early once it had found a list of actors. This meant that it would try to execute Action 0, with nothing as the noun, and nothing as the second noun.

In a testing version Action 0 is a debugging verb which doesn’t require a noun. But in a release version those debugging verbs are removed, and the first verb defined is the “going” action. When that action is called without a noun, it prints the error Matt was seeing, before my code gets a chance to intercept it.

I may be a layman, but I love all to watch all this sleuthing.

When digging into this, I used the unreleased debugger facility of Glulxe. Gonna have to release that at some point, I guess.

(Check out the “debugger” branch of both Glulxe and CheapGlk. Compile them together, using “-DVM_DEBUGGER=1” as an additional compiler flag for Glulxe. Requires “-lxml2” as well. No documentation. Sigh.)