[I7] Tweaking [one of]

This feels ticky-tacky but I’m wondering about how to inform a player when he has reached the end of a

[one of] [in random order]

loop, e.g if there is a good built-in command. The code I have below seems awkward. Am I just being lazy and have I gotten too comfortable with/demanding of the “one of” structure? Or can I tighten things up?

[code]“responses” by andrew

when play begins:
sort the table of silly-responses in random order;

room 1 is a room.

response-num is a number that varies.

the button is a thing in room 1.

check pushing button:
increment response-num;
choose row response-num in table of silly-responses;
say “[thingo entry]”;
if response-num is number of rows in table of silly-responses:
now response-num is 0;
say " (Note: you have [one of][or]once again [stopping]cycled through all the things the button does.)";
the rule succeeds;

table of silly-responses
thingo
“Woo!”
“Yay!”
“Rah!”
“Bzz!”
“Pff!”[/code]

More importantly, are there any extensions I may’ve overlooked that handle more detailed message randomization?

If you want to use the ‘one of … or … in random order’ phrase, I suppose the number of alternative responses will be known in advance. Then you could do essentially the same thing as above but without reading the responses from a table.

[code]room 1 is a room.

response-num is a number that varies.

the button is a thing in room 1.

report pushing the button:
increment response-num;
say “[one of]Woo[or]Yay[or]Rah[or]Bzz[or]Pff[in random order]!”;
if response-num is 5:
say “(Note: you have [one of][or]once again [stopping]cycled through all the things the button does.)[line break]”;
now response-num is 0;
stop the action.[/code]

That looks good, thanks! I was concerned about having a bunch of counting variables to track (e.g. if I added something to the one of/or, I’d need to remember to increment response-num)

This also seems easily modifiable to add flexibility for, say,

  • 1st 2x, game-important stuff when you push the button
  • after that, semi-random stuff/jokes/flavor after that.

Which would’ve been the next part of my question.

That particular case can be handled by a nested “one of” clause, although it’s not the clearest way to code.

say “[one of]Clue 1.[or]Clue 2.[or][one of]Joke 1.[or]Joke 2.[or]Joke 3.[at random][stopping]”;

As you get into more complicated structures, I think it’s worth using a more verbose structure. The shortcuts are shortcuts.

Ooh, I didn’t see that! I assumed that since nested ifs didn’t work, nested one of’s didn’t either. So I never even tried it to see if it gave an error.

Hooray for losing a blind spot.

And yeah, it’s easy to get spoiled by Inform’s shortcuts. I also tend not to look for extensions etc that’ll make life easier–but at some point, yeah, you just have to sit down and know when to code. And by you I mean me.

How about something like this?

[spoiler][code]“Test”

Include (-

[ I7_SOO_PAR oldval count; if (count <= 1) return count; return random(count); ];
[ I7_SOO_RAN oldval count v; if (count <= 1) return count;
v = oldval; while (v == oldval) v = random(count); return v; ];
[ I7_SOO_STI oldval count v; if (oldval) return oldval; return I7_SOO_PAR(oldval, count); ];
[ I7_SOO_CYC oldval count; oldval++; if (oldval > count) oldval = 1; return oldval; ];
[ I7_SOO_STOP oldval count; oldval++; if (oldval > count) oldval = count; return oldval; ];
[ I7_SOO_TAP oldval count tn rn c; if (count <= 1) return count; tn = count*(count+1)/2;
rn = random(tn); for (c=1:c<=count:c++) { rn = rn - c; if (rn<=0) return (count-c+1); } ];
[ I7_SOO_TRAN oldval count; if (oldval<count) return oldval+1;
return count + 1 + I7_SOO_RAN(oldval%(count+1), count); ];
[ I7_SOO_TPAR oldval count; if (oldval<count) return oldval+1;
return count + 1 + I7_SOO_PAR(oldval%(count+1), count); ];

Array I7_SOO_SHUF->32;

[ I7_SOO_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 = basebase;
scope = (MAX_POSITIVE_NUMBER-1)/cc;
!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=", sd, “^”;
!print "Return ", v + ctbase + ssdbasebase, “^”;
!print " [Base = ", base, " Oldval = ", oldval, " Count = ", count, " V = ", v, " CT = ", ct, " SSD = ", sd, " Return ", v + ct
base + ssdbasebase, "] ";
if (ct == 0) {
(+ finish state +) = true;
}
else {
(+ finish state +) = false;
}
return v + ctbase + ssdbase*base;
];

-) instead of “Say One Of” in “Printing.i6t”.

Finish state is a truth state that varies.

The Testing Room is A Room. The description of the testing room is “Number [one of]one[or]two[or]three[or]four[in random order][if finish state is true]. You have reached the end[end if].”.[/code][/spoiler]

Hope this helps.

It may take time to wrap my head around it, but that seems optimally flexible.

I (still) want to learn I6 and this code is a great example/encouragement of how to do stuff where I’m not quite pleased with my I7 code–how it looks or how flexible it is.

I guess so, although you can overdo it at times. I’ve sometimes spend hours trying to get something to work using I6 only to realise that I could have done it much simpler in I7.