Mantis Bug Tracker

View Issue Details Jump to Notes ] Issue History ] Print ]
IDProjectCategoryView StatusDate SubmittedLast Update
0000114Core InformActivitiespublic2010-06-23 21:302010-10-28 00:30
Assigned Tograham 
Platformx86OSWindowsOS VersionXP
Product Version6E59 
Target VersionFixed in Version6F95 
Summary0000114: Bad results and runtime errors from [one of]...[in random order] on Z-code (with solution?)
DescriptionLast year I began work on a small game which got mired in my own limitations as a non-programmer, but one of the problems seemed to be a case of me biting off more than z-code was meant to chew. It didn't occur to me that it was a _bug,_ per se, so, since it was non-critical, I simply replaced the code with something simpler, sighed, and moved on. The project continues to be mired in other, unrelated limitations on my part.

While working on an unrelated project in the newest release (6E59), I came across a passage in 26.2 of the Documentation which perked my interest:

(*) Bug fixed whereby nested bracketed compound phrases failed to be read
properly. It's often poor prose style to write messy phrases full of brackets
to disambiguate them, but it ought to work, and it seems that this long-standing
bug made Inform a little unpredictable here.

This reminded me of the problem I'd encountered and surgically removed from my little project. I honestly don't understand enough of the terminology to know if it's even _relevant_ to the problem, but it sounded kinda-sorta like it might be, so I brightened up and said "Okay, maybe I can try the much-cooler more complicated version in my game again ..." it was a snap to paste the other code back in from the archives, and the game once again compiled just fine, but with the same old problem in the resulting game file.

I'm reporting it now because now I suppose it _might_ be a bug. Or if not a bug, at least an example of just how ridiculously I can use nested brackets within other nested brackets within other nested brackets to do something that I could probably do better with Tables (as I normally do) or with Lists (except I don't understand Lists).

This is an isolated and trimmed version of the code from that project, which re-creates the problem.

However, the problem WITHIN the problem is that sometimes the game (both the original and this example code) compiles perfectly, with no apparent issues ... and sometimes it compiles broken, with problems immediately evident with a few strokes of the "EXAMINE BOOKS" command. This is why I suspect it may be a bug, because (A) Inform thinks it compiles just fine and (B) sometimes it works perfectly and (C) sometimes it just doesn't, despite consistent (A). **Multiple compiles may be necessary to the problem to manifest.**


When the problems arise, they arise in two flavors: (1) Fragments of text simply fail to appear, blank spaces instead. (2) explicit "Programming error:" warnings (in the IDE version of Frotz).

The problems do not seem to manifest in Glulx compiles, only z-code (but z8 is my target format for the project).

Presented with hopes that my (decidedly) poor style may be of some use to the I7, team, and with thanks for your efforts -- S. John
Minimal Source Text To Reproduce
When play begins, seed the random-number generator with 1234.

Home is a room.

Instead of waiting:
	repeat with N running from 1 to 72:
		say "[N] - ";
		say "[one of]a[or]b[or]c[or]d[or]e[or]f[or]g[or]h[or]i[or]j[or]k[or]l[or]m[or]n[or]o[or]p[or]q[or]r[or]s[or]t[in 
random order]."

Test me with "z".
TagsNo tags attached.
Effect(serious/mild) Game compiles but misbehaves
Attached Files

- Relationships

-  Notes
jmcgrew (administrator)
2010-06-23 21:53

The bug comes and goes only because it involves randomness: it's reproducible every time if you include "When play begins, seed the random-number generator with 1234." at the top. This appears to be a bug in the pseudorandom algorithm used by I7_SOO_SHU.
jmcgrew (administrator)
2010-06-23 22:07

I've edited down your sample code since it was wide enough to break the formatting of the page. The new sample demonstrates the error three times: no letter is printed on iteration 17 or 71, and three runtime errors appear on iteration 72. (This is under the I7 IDE on Windows; results may vary under other interpreters.)
Ghalev (reporter)
2010-06-23 22:18

Many thanks for testing this so rapidly, wow. I should also note that in the replacement version of the code, I still make heavy use of [one of]...[in random order]; the code is structurally identical, just with shorter lists of possibilities and less nested cross-referencing. So I'm not sure if there's some threshold I'm pushing past, because the simpler version has never struck a single error that I've seen, with hundreds of different compiles.
jmcgrew (administrator)
2010-06-23 22:44

This happens on OS X too: iterations 1 and 4 are blank, 5 and beyond give runtime errors.

I assume you marked this report private because you didn't want all the original source code to be public. Now that there's a simple test case, would you mind if I deleted that code from the revision history and made the report public?
Ghalev (reporter)
2010-06-23 22:53

That's correct, and yeah, provided the revision history is amended as you say, by all means make it public. I'm sorry I didn't know enough to boil it down any further and that you had to make the extra effort on my behalf.
EmacsUser (manager)
2010-06-25 09:44

Until a fix is incorporated into I7, you can patch the shuffle procedure with this code (a slightly edited version of I7_SOO_SHU):

Include (-
[ I7_SOO_ALTERNATE_SHU oldval count sd ct v i j s ssd scope cc base;
base = count+1;
v = oldval%base; oldval = oldval/base; ct = oldval%base; sd = oldval/base;
if (count > 32) return I7_SOO_PAR(oldval, count);
if (count <= 1) v = count;
else {
!print "^In v=", v, " ct=", ct, " sd=", sd, "^";
cc = base*base;
!print "Scope = ", scope, "^";
if (sd == 0) { sd = random(scope); ct=0; }
for (i=0:i<count:i++) I7_SOO_SHUF->i = i;
ssd = sd;
for (i=0:i<count-1:i++) {
j = (sd)%(count-i)+i; sd = (sd*31973)+17; if (sd<0) sd=-sd;
s = I7_SOO_SHUF->j; I7_SOO_SHUF->j = I7_SOO_SHUF->i; I7_SOO_SHUF->i = s;
!for (i=0:i<count:i++) print I7_SOO_SHUF->i, " "; print "^";
v = (I7_SOO_SHUF->ct)+1;
ct++; if (ct >= count) { ct = 0; ssd = 0; }
!print "Out v=", v, " ct=", ct, " ssd=", ssd, "^";
!print "Return ", v + ct*base + ssd*base*base, "^";
return v + ct*base + ssd*base*base;
To say in random order -- ending say_one_of with marker I7_SOO_ALTERNATE_SHU:
(- {-close-brace} -).
jmcgrew (administrator)
2010-06-25 10:47

Looks like you only changed "scope"? I don't know how that works, or if it's a general solution, but it does fix this test case.
EmacsUser (manager)
2010-06-25 11:41

Sorry, I should have commented on that. I7_SOO_SHU looks like it's meant to save memory, because it's packing three integers into one word: the current permutation as an LCG seed (sd/ssd), the number of things already said out of the current permutation (ct), and the alternative chosen last (v). The seed can only grow so big, or else the word in which everything is packed overflows, making the packed word negative, corrupting the seed, or both. (The packed word should not be negative because it's split into parts with %, which is sensitive to sign.) Scope is the limit on the seed.

I couldn't figure out what the previous computation of scope was intending, but the computation in the patch will find a safe bound: base*base*(MAX_POSITIVE_NUMBER/base/base) might be smaller than the max positive number (due to flooring), but it will never be larger.

So, this should be a general solution.
Ghalev (reporter)
2010-06-25 13:25

Fantastic; thanks so much.
EmacsUser (manager)
2010-06-26 19:03
edited on: 2010-06-26 19:04

Ach, the bound should guarantee that base*base*scope is <emph>strictly</emph> less than MAX_POSITIVE_NUMBER, and the line ought to read:

scope = (MAX_POSITIVE_NUMBER-1)/cc;

Fortunately, no possible value of cc evenly divides the MAX_POSITIVE_NUMBER for the Z-machine or the one for Glulx. So the two computations are equivalent on the targets that Inform currently supports. The latter would be better for human consumption though.

graham (administrator)
2010-09-03 14:24

Many thanks; this fix has been incorporated into I7_SOO_SHU for the next build.

- Issue History
Date Modified Username Field Change
2010-06-23 21:30 Ghalev New Issue
2010-06-23 21:53 jmcgrew Note Added: 0000143
2010-06-23 21:53 jmcgrew Status new => confirmed
2010-06-23 22:07 jmcgrew Note Added: 0000144
2010-06-23 22:07 jmcgrew Summary Nested Brackety Thingies causing "Programming Error" in compiled game (z-code only) => Bad results and runtime errors from [one of]...[in random order] on Z-code
2010-06-23 22:07 jmcgrew Steps to Reproduce Updated View Revisions
2010-06-23 22:18 Ghalev Note Added: 0000145
2010-06-23 22:44 jmcgrew Note Added: 0000146
2010-06-23 22:53 Ghalev Note Added: 0000147
2010-06-23 22:55 jmcgrew Bug Revision Dropped: Minimal Source Text To Reproduce: 0000074
2010-06-23 22:56 jmcgrew View Status private => public
2010-06-25 09:44 EmacsUser Note Added: 0000153
2010-06-25 10:47 jmcgrew Note Added: 0000154
2010-06-25 10:47 jmcgrew Summary Bad results and runtime errors from [one of]...[in random order] on Z-code => Bad results and runtime errors from [one of]...[in random order] on Z-code (with solution?)
2010-06-25 11:41 EmacsUser Note Added: 0000155
2010-06-25 13:25 Ghalev Note Added: 0000156
2010-06-26 19:03 EmacsUser Note Added: 0000163
2010-06-26 19:04 EmacsUser Note Edited: 0000163 View Revisions
2010-09-03 14:24 graham Note Added: 0000499
2010-09-03 14:24 graham Status confirmed => resolved
2010-09-03 14:24 graham Resolution open => fixed
2010-09-03 14:24 graham Assigned To => graham
2010-10-25 21:14 jmcgrew Fixed in Version => 6F95
2010-10-28 00:30 jmcgrew Status resolved => closed

Copyright © 2000 - 2010 MantisBT Group
Powered by Mantis Bugtracker