Quick multireplace question - when a numeric index exceeds number of value options listed

I have a quick Multireplace question that wasn’t resolved by the wiki.

Say that I’m using a numeric var to call a value from a multireplace set of values separated by pipes……

Here’s a place to start, the syntax note from the wiki:

Numeric example: @{(variable+1) Text if 0|Text if 1|Text if 2|Text if 3}

I gather the +1 there is really so coders used to the first value being 0 rather than 1 could operate with their patterns in place. But this stirred up some other ideas and questions.

But what if variable=3 ? And variable=4 ?

Here’s something likely foolish, but interesting to me. I’m looking to play around with a pretty aggressive set of multireplace inline tweaks in a “hub” block of text that is repeated that I want to coax into feeling really fresh and not flatten to “I’ve seen this before.” And one strategy could be to have multiple sets of inline insertions to call for flavor in addition to separate ones that are really functional.

What if you were using var as a counter to keep a reused block of text fresh with lots of inline insertions. But then what if the var goes beyond the number of options separated by pipes?

I was thinking of the toggling through variables option in twine, though in this case not as an interface thing, but as an experience where a label called more than once can toggle through a list of values and then go back to the first value after moving beyond the last value.

I thought of this studying Book of Hungry Names where you have to visit the trainers many times and Kyle has done so much magic to make that feel intentional and fresh every time you basically repeat the same label call.’

I can think of a bunch of external logic tests/fixes to call to keep my “index” call request cleaned of any problematic values, but this revealed that I don’t really know as much about multireplace as I thought, and am not sure what scenarios break a game! As with many things in ChoiceScript, there are my instincts to make it insanely complicated and maximalist, and then there are elegent coder strategies that crunch my 2k words of messiness down to like 10 lines of logic.

So this is a request for some help to learn some elegance! And the reward will be a technical study leaning into what I learn that I will submit at the end of the week for the NarraScope Game Jam! :slight_smile:

I suppose the main constraint with the multireplace vs. blocks of *if *elseif *else which are cumbersome but can handle unknown ranges of variables. Here are three ways off the top of my head you can use a counter to vary stuff in multireplace each time you visit (assuming you *create the values starting at 1 on the startup page):

Goes through each option in turn, moving to the next one each time you return to the hub.

*set cycle + 1
*if cycle > 4
 	*set cycle 1
You're @{cycle here|here again|back|here once more}


Pick a random option from the multireplace each time.

*rand random 1  4
The weather outside is @{random frightful|fine|delightful|inclement}.

Randomise Without Repeat
As above, but it doesn’t repeat the same thing twice.

*set storedrand random
*rand random 1  4
*label randloop
*if random = storedrand
	*rand random 1  4
	*goto randloop
The weather outside is @{random frightful|fine|delightful|inclement}.


Then your multireplace will fail the automated tests, and HG/CoG won’t publish it. Alas. As Joey noted, if/elseif/else have more versatility when you’re dealing with variables that resist confinement to a literal handful of values.

I suspect that unlike the *rand approaches, this one will actually fail the autotests… because if cycle can equal 5 in your game, however fleetingly, QT/RT will expect to see that as a possibility in multireplace.

If I’m right, you’d need something like this:

You're @{cycle here|here again|back|here once more|in a place the code should make it impossible to visit for long enough to see this message, but that's multireplace for you}
1 Like

I ran into a similar problem with randomtest with a variable I was convinced couldn’t go out of range. This is a snippet of code with comment from chapter 5 of Lies Under Ice:

*temp killcount 1
*set killcount + (deprivation / 10)
*set killcount round(killcount)
*if killcount > 8
	*set killcount 8
*if killcount = 0
	*set killcount 1
	*comment this shouldn't be possible as per above code but randomtest was complaining that it could be 0 for the @{} section
@{killcount one person ends|two people end|three people end|four people end|five people end|six people end|seven people end|eight people end} up dying.

Manually setting the value before the multireplace seemed to satisfy randomtest, but perhaps there was something else going on.

1 Like

You can use modulo to cycle through the options. You modulate the counter by the number of options. The counter must be on base 0. Try the code below.

*create counter 0

*label cycle_test

@{((counter modulo 3) + 1) text 1 | text 2 | text 3 } 

*set counter +1

*goto cycle_test

These suggestions are great! I think a simply cycling codeblock after each use should do it, as long as I make sure it is impossible to get a value beyond the range.

I’m really interested to see why Joey’s example from Lies Under Ice did indeed fail by hitting 0!

Oh, I suppose I should emphasize that I’m trying to AVOID random. My aim wasn’t to truly make things unpredictable as much as to cycle some things in and out of phase enough to just not feel that repetitive. These are for some “utility” reuses – and there is plenty of fresh text to land on before and after this, so I don’t think people will complain to much if they detect after a while that they are heading back through a familiar bit of prose.



I suspect looking at it fresh, that if deprivation could be a negative number then that would create the error. Ultimately it was an easy thing to workaround.

1 Like