Using *rand in a choice

@Sinnie Yes

And do you want to prevent any of the original 5 names being picked the next time?

@Sinnie If that’s possible to code, then yeah

It is. But it’s cumbersome.

1 Like

Oof. Maybe not then lol

Don’t give up hope - nearly there :slight_smile:

Try this:

*temp var1
*rand number_1 1 20

*if number_1 = 1
    *set var1 "Arthur"
*if number_1 = 2
    *set var1 "Alice"

And so on. Do this 5 times for 5 different random numbers. Like this:

*temp var2
*rand number_2 1 20

*if (number_2 = 1) and (number_1 != 1)
    *set var2 "Arthur"
*if (number_2 = 1) and (number_1 = 1)
    *set number_2 2

*if (number_2 = 2) and (number_1 != 2)
    *set var2 "Alice"
*if (number_2 = 2) and (number_1 = 2)
    *set number_2 3

It’ll take a while. If you need me to make the whole thing, just ask and I’ll give all of the code for it.

It is possible, but it would require a lot of coding for 5 of 20 options.

Here is a quick example of choosing 2 options out of 3:

*create human_name1 "Arthur"
*create human_name2 "Alice"
*create human_name3 "Christopher"

*create rand1 0
*create rand2 0
*create name1 "name1"
*create name2 "name2"

*rand rand1 1 3
*label second_rand
*rand rand2 1 3
*if rand1=rand2
  *goto second_rand

*if rand1=1
  *set name1 "${human_name1}"
*if rand1=2
  *set name1 "${human_name2}"
*if rand1=3
  *set name1 "${human_name3}"
*if rand2=1
  *set name2 "${human_name1}"
*if rand2=2
  *set name2 "${human_name2}"
*if rand2=3
  *set name2 "${human_name3}"

*fake_choice
  #${name1}
  #${name2}

For 5 from 20, you probably would require to use some *gosub to check if names are repeated.

1 Like

Instead of using rand, why not split it into a couple of pages of names, with a “see more” option to go between them?

@dillpickle1996, OK, assumining I have understood what you are looking for correctly, this should cover you.
This will give 5 name options, then if you re-roll the names you get a new list of 5 names without repeating the list.
If you re-roll again it will exit as there are no names left (can make it reset to the beginning if you want).

*create human_name ""

*create human_name_1 "Arthur"
*create human_name_2 "Alice"
*create human_name_3 "Christopher"
*create human_name_4 "Beatrice"
*create human_name_5 "Frederick"
*create human_name_6 "Elizabeth"
*create human_name_7 "James"
*create human_name_8 "Grace"
*create human_name_9 "Louis"
*create human_name_10 "Matilda"

*create human_name_picked_1 false
*create human_name_picked_2 false
*create human_name_picked_3 false
*create human_name_picked_4 false
*create human_name_picked_5 false
*create human_name_picked_6 false
*create human_name_picked_7 false
*create human_name_picked_8 false
*create human_name_picked_9 false
*create human_name_picked_10 false

*create names_left 5


*create Option_1 0
*create Option_2 0
*create Option_3 0
*create Option_4 0
*create Option_5 0

*label RerollTheNames

*label Option_1_reroll
*rand Option_1 1 10
*if human_name_picked[Option_1] = true
    *goto Option_1_reroll
*set human_name_picked[Option_1] true

*label Option_2_reroll
*rand Option_2 1 10
*if (Option_2 = Option_1)
    *goto Option_2_reroll
*if human_name_picked[Option_2] = true
    *goto Option_2_reroll
*set human_name_picked[Option_2] true

*label Option_3_reroll
*rand Option_3 1 10
*if ((Option_3 = Option_1) or (Option_3 = Option_2))
    *goto Option_3_reroll
*if human_name_picked[Option_3] = true
    *goto Option_3_reroll
*set human_name_picked[Option_3] true

*label Option_4_reroll
*rand Option_4 1 10
*if ((Option_4 = Option_1) or ((Option_4 = Option_2) or (Option_4 = Option_3)))
    *goto Option_4_reroll
*if human_name_picked[Option_4] = true
    *goto Option_4_reroll
*set human_name_picked[Option_4] true

*label Option_5_reroll
*rand Option_5 1 10
*if (((Option_5 = Option_1) or (Option_5 = Option_2)) or ((Option_5 = Option_3) or (Option_5 = Option_4)))
    *goto Option_5_reroll
*if human_name_picked[Option_5] = true
    *goto Option_5_reroll
*set human_name_picked[Option_5] true

*choice
    #Pick name ${human_name[Option_1]}
        *set human_name human_name[Option_1]
        You picked ${human_name}
        *finish
    #Pick name ${human_name[Option_2]}
        *set human_name human_name[Option_2]
        You picked ${human_name}
        *finish
    #Pick name ${human_name[Option_3]}
        *set human_name human_name[Option_3]
        You picked ${human_name}
        *finish
    #Pick name ${human_name[Option_4]}
        *set human_name human_name[Option_4]
        You picked ${human_name}
        *finish
    #Pick name ${human_name[Option_5]}
        *set human_name human_name[Option_5]
        You picked ${human_name}
        *finish
    #Reroll the names
        *if names_left = 0
            There are no more names to pick
            *finish
        *set names_left - 5
        *goto RerollTheNames    

@armadillidium - Yeah, I wondered that too. I just wanted to see if I could figure it out.

8 Likes

I like the

*if rand1 = rand2
    *goto second_rand

The problem is that code makes the player go back. There is a code to make you just vist then return, but I forgot what it is.

edit:
:thinking: sorry, not sure this is actually an issue.

Not exactly. This part of code will go back and randomize again authomatically. The player won’t have to do anything manually.

But it should be repeated several times if you need more than 2 names to be shown. Actually, @Sinnie’s code works better on this issue.

1 Like

Thank you so much!!

1 Like

I can’t remember what it’s called in choice script and can’t find it on the wiki to reference to, but the:
Variable1_name[Variable2_name] or ${variable1_name[variable2_name]}
is incredibly useful for this sort of thing. For anyone not familiar with what it does…

Variable2 is a number, and by adding it in [square brackets] to the end of another variable (variable1) we actually append that number prefixed by an underscore. So in my code above, we have:

human_name[Option_1]

Option_1 is a number (random from 1-10) - let’s say that number was 8, and so our code becomes:

human_name_8

Thus we pull the value of the variable ‘human_name_8’

In this way we can generate a pool of ‘human_name_x’ (as many as you like).
You update the random number generator for the maximum number of names in the pool.
It then pulls the name of whichever random number you generate and puts it in as the choice.

We then use the same method to ‘lock off’ that choice from appearing again.
By dynamically changing the ‘human_name_picked_x’ variable for that name being set to true.

It allows you to iterate through lists more elegantly with less code.

@dillpickle1996 - did that do everything you needed? Do you understand how to add in the extra names (I just did 10 because it was quicker).

4 Likes

I think you got your answer, but here’s my implementation with all 20 names if you’re interested. And they’re non-repeating as well.

*comment NAMES _____________________
*temp mc_name ""
*temp names_displayed_count 0

*temp tchoice_name_1 "Arthur"
*temp tchoice_name_1_wasShown false
*temp tchoice_name_2 "Alice"
*temp tchoice_name_2_wasShown false
*temp tchoice_name_3 "Christopher"
*temp tchoice_name_3_wasShown false
*temp tchoice_name_4 "Beatrice"
*temp tchoice_name_4_wasShown false
*temp tchoice_name_5 "Frederick"
*temp tchoice_name_5_wasShown false
*temp tchoice_name_6 "Elizabeth"
*temp tchoice_name_6_wasShown false
*temp tchoice_name_7 "James"
*temp tchoice_name_7_wasShown false
*temp tchoice_name_8 "Grace"
*temp tchoice_name_8_wasShown false
*temp tchoice_name_9 "Louis"
*temp tchoice_name_9_wasShown false
*temp tchoice_name_10 "Matilda"
*temp tchoice_name_10_wasShown false
*temp tchoice_name_11 "Nicholas"
*temp tchoice_name_11_wasShown false
*temp tchoice_name_12 "Penolope"
*temp tchoice_name_12_wasShown false
*temp tchoice_name_13 "Richard"
*temp tchoice_name_13_wasShown false
*temp tchoice_name_14 "Sophie"
*temp tchoice_name_14_wasShown false
*temp tchoice_name_15 "Shiloh"
*temp tchoice_name_15_wasShown false
*temp tchoice_name_16 "Quinn"
*temp tchoice_name_16_wasShown false
*temp tchoice_name_17 "Emerson"
*temp tchoice_name_17_wasShown false
*temp tchoice_name_18 "Marlowe"
*temp tchoice_name_18_wasShown false
*temp tchoice_name_19 "Rory"
*temp tchoice_name_19_wasShown false
*temp tchoice_name_20 "Rowan"
*temp tchoice_name_20_wasShown false

*comment CHOICES ___________________
*temp tchoice_option_1 ""
*temp tchoice_option_2 ""
*temp tchoice_option_3 ""
*temp tchoice_option_4 ""
*temp tchoice_option_5 ""


*comment FUNCTION CALL _____________
*comment The randomizer function must be called in the preceding page to which it's used, otherwise ChoiceScript will randomize again every time the player visits the stats page and comes back or closes the app and opens again. This would cause a problem in the way this implementation was coded, locking the player in an infinite loop.
*gosub populate_name_choice
*page_break

*comment Insert your text here.

*label name_choice
*choice
	# ${tchoice_option_1}
		*set mc_name tchoice_option_1
		*goto confirm_name
	# ${tchoice_option_2}
		*set mc_name tchoice_option_2
		*goto confirm_name
	# ${tchoice_option_3}
		*set mc_name tchoice_option_3
		*goto confirm_name
	# ${tchoice_option_4}
		*set mc_name tchoice_option_4
		*goto confirm_name
	# ${tchoice_option_5}
		*set mc_name tchoice_option_5
		*goto confirm_name
	*if (names_displayed_count <= 15) 
		# Reroll names
			*gosub populate_name_choice
			*goto name_choice
	*else
		# Reset names
			*gosub reset_names
			*gosub populate_name_choice
			*goto name_choice

*label confirm_name
Your name is ${mc_name}

Is that correct?

*choice
	# Yes!
		*goto continue_story
	# No, let me choose again.
		*goto name_choice

*label continue_story
*comment Continue the story from here.
...

*finish

*label populate_name_choice
*temp loop_count 1
*temp random_name_index 0
*label populate_name_choice_loop_start
*rand random_name_index 1 20
*label has_name_been_displayed_already?
*if (tchoice_name[random_name_index]["wasShown"])
	*set random_name_index +1
	*if (random_name_index > 20)
		*set random_name_index 1
	*looplimit 100
	*goto has_name_been_displayed_already?
*set tchoice_option[loop_count] tchoice_name[random_name_index]
*set tchoice_name[random_name_index]["wasShown"] true
*set names_displayed_count +1
*if (loop_count < 5)
	*set loop_count +1
	*looplimit 100
	*goto populate_name_choice_loop_start
*return

*label reset_names
*set names_displayed_count 0
*set tchoice_name_1_wasShown false
*set tchoice_name_2_wasShown false
*set tchoice_name_3_wasShown false
*set tchoice_name_4_wasShown false
*set tchoice_name_5_wasShown false
*set tchoice_name_6_wasShown false
*set tchoice_name_7_wasShown false
*set tchoice_name_8_wasShown false
*set tchoice_name_9_wasShown false
*set tchoice_name_10_wasShown false
*set tchoice_name_11_wasShown false
*set tchoice_name_12_wasShown false
*set tchoice_name_13_wasShown false
*set tchoice_name_14_wasShown false
*set tchoice_name_15_wasShown false
*set tchoice_name_16_wasShown false
*set tchoice_name_17_wasShown false
*set tchoice_name_18_wasShown false
*set tchoice_name_19_wasShown false
*set tchoice_name_20_wasShown false
*return

I used tchoice instead of choice because ChoiceScript does not allow for variables to start with the word “choice”.

4 Likes

This discussion is also relevant: Non repeatable strings (code example here) You can create a random shuffle of 20 names, show 5 and then another 5.

1 Like

Using a shuffled array is nice because you don’t need variables to track whether a name was seen before; the shuffling ensures you see everything once, in a random order.

You’ve already gotten your answer, but I thought I’d share my crack at it just for fun:

*create name ""

*label name_randomizer
*temp offset 0
*temp human_name_1 "Arthur"
*temp human_name_2 "Alice"
*temp human_name_3 "Christopher"
*temp human_name_4 "Beatrice"
*temp human_name_5 "Frederick"
*temp human_name_6 "Elizabeth"
*temp human_name_7 "James"
*temp human_name_8 "Grace"
*temp human_name_9 "Louis"
*temp human_name_10 "Matilda"
*temp human_name_11 "Nicholas"
*temp human_name_12 "Penolope"
*temp human_name_13 "Richard"
*temp human_name_14 "Sophie"
*temp human_name_15 "Shiloh"
*temp human_name_16 "Quinn"
*temp human_name_17 "Emerson"
*temp human_name_18 "Marlowe"
*temp human_name_19 "Rory"
*temp human_name_20 "Rowan"
*gosub shuffle_array "human_name" 20


*label name_choice
What is your name?
*fake_choice
  #${human_name[1+offset]}
    *set name human_name[1+offset]
  #${human_name[2+offset]}
    *set name human_name[2+offset]
  #${human_name[3+offset]}
    *set name human_name[3+offset]
  #${human_name[4+offset]}
    *set name human_name[4+offset]
  #${human_name[5+offset]}
    *set name human_name[5+offset]
  #Show me more
    *if (offset < 15)
      *set offset + 5
      *goto name_choice
    *else
      You've seen all the names. Rerolling...
      *goto name_randomizer
Your name is ${name}?
*fake_choice
  #No, let me pick again.
    *goto name_choice
  #Yes.
    *finish


*label shuffle_array
*params array array_length
*temp i 1
*temp j 0
*label shuffle_array_loop
*if (i < array_length)
  *rand j i array_length
  *if (j != i)
    *temp val_i {(array&"_")&"${i}"}
    *set {(array&"_")&"${i}"} {(array&"_")&"${j}"}
    *set {(array&"_")&"${j}"} val_i
  *set i + 1
  *goto shuffle_array_loop
*return
8 Likes

Wow, this is a piece of art. 14 lines for the core logic. Very compact and reusable. I like the way you used redirection to sort any given array. Well done!

Two minor suggestions:

  • you can skip the test j!=i and always swap even if they are equal
  • if you do *temp prefix (array&"_") then you can do simply *set {prefix&i} {prefix&j} (more readable)
2 Likes

Agree - that’s a level of logic I hadn’t considered for iterating through a list. Very clever.

This topic was automatically closed 24 hours after the last reply. If you want to reopen your WiP, contact the moderators.