Random options, but one should always be first

Let’s say the PC is in a room with multiple paintings, coded as “some paintings” with a randomized description, rather than individual objects. I want the player to see one painting first, because it contains a clue; how can I ensure that that’s the first painting they see, but that that painting and all the other paintings are subsequently randomized? I’d been using a nested “one of”, like so -

The description is "You move close to one painting and look at [one of]the still life of a skull and goblet[or][one of]the Impressionist landscape[or]what seem to be arbitrary blotches of color[or]a portrait of a severe-looking woman[in random order][stopping]."

…but then I realized that this means they’ll never see the still life a second time. How do I make sure that it’s the first thing they see, but has a random chance of coming up after? (I also tried creating the still life as a separate painting and having the first “examine paintings” try examining the still life, but, same problem but worse.)

If need be I’ll do a fixed order, but randomness is fun.

There are a few ways of doing this. How about:

The description of the paintings is "You move close to one painting and look at the still life of a skull and goblet[randomize painting]."
To say randomize painting:
      Now the description of the paintings is "You move close to one painting and look at [one of]the still life of a skull and goblet[or]the Impressionist landscape[or]what seem to be arbitrary blotches of color[or]a portrait of a severe-looking woman[in random order]."

Yeah, I guess it did occur to me to just include a duplicate description of the plot-relevant painting in the randomized “one of” above! So, there’s no obvious way of doing this that I’m missing, it does have to be like that?

(Edit: Although I’d write it as “[one of][skull painting][or][one of][skull painting][or]an Impressionist landscape” etc. and then “To say skull painting…”)

How about “then at random”? That runs through all of the listed options in order first, then randomizes them (so you can make sure the player sees every painting before seeing any of them twice).

Yeah, I mentioned above that doing a fixed order was a possibility, but I like the idea of doing it randomly if possible. (The player doesn’t need to see any but the first one.)

This should always print the fixed-phrase first but then shuffle among the random-phrases:

[code]

say “[one of][fixed-phrase][or][random-phrase][stopping].”

To say fixed-phrase:
say “This is my fixed phrase”.

To say random-phrase:
say “[one of]This is random phrase 1[or]Here’s a second random phrase[or]This third phrase is also random[in random order]”.[/code]

If you want things to cycle back to the initial phrase, one way is to use a table.

[code]table of randstuff
rand-txt priority
“The first” 1
"The second’’ 2
“Any order” 3
“Any order again” 3

when play begins:
sort table of randstuff in random order;
sort table of randstuff in priority order;

to say my-rand-stuff:
increment rand-row;
choose row rand-row in table of randstuff;
say “[rand-txt entry]”;
if rand-row == number of rows in table of randstuff;
now rand-row is 0;
say “(this is the last one)”;

It’s possible to have another table that tracks how far you are in each random table, but that might be more than you want.

It seems like, for Inform 6, we could create an array and do the standard Fisher-Yates shuffle on elements 2…n instead of 1…n. That would take up a lot less code, but it would require Inform 6.

I found it to be an intriguing intellectual puzzle to try to achieve this, without repetitions, using just “[one of]” expressions.

The problem with the proposed solution:

        "[one of]A[or][one of]A[or]B[or]C[or]D[or]E[or]F[in random order][stopping]"

is of course that A might get printed twice in succession. To prevent that, we could move B into the branch containing A, and ensure that the B sub-branch is always taken before the A sub-branch.

I’m going to use Dialog syntax here, if you’ll bear with me, because the nesting can be visualized with indentation. The principles are the same as in Inform 7, including the “at random” vs. “purely at random” subtlety.

        (select)
            A
        (or)
            (select)
                (select) B (or) A (cycling)
            (or)
                C
            (or)
                D
            (or)
                E
            (or)
                F
            (at random)
        (stopping)

But now, in the long run, each of C, D, E, and F will appear twice as often as A and B. To adjust for that, we could use two branch slots, leading to a shared subroutine (this is bending my own rules) containing the actual B-A branch:

        (select)
            A
        (or)
            (select)
                (my subroutine)
            (or)
                (my subroutine)
            (or)
                C
            (or)
                D
            (or)
                E
            (or)
                F
            (at random)
        (stopping)

(my subroutine)
        (select) B (or) A (cycling)

But surely there must be a more elegant way to do it.

Here is a completely different approach: We divide all our options into two groups. Option A goes into the second group. Then we just ensure that the first choice, following the initial A, is taken from the first group:

        (select)
            A
        (or)
            (select)
                (select) D (or) E (or) F (at random)
            (or)
                (select) A (or) B (or) C (at random)
            (then purely at random)
        (stopping)

Eh, hopefully my elaborated non-placeholder-version descriptions imply sufficiently that more of the stuff is viewable if people want to see it for flavor.