Randomizing Lists

Talon
22 Jul 2017, 03:07

An odd question.
Is there a randomize list function in quest?

The effect i'm trying to do is this, when players start the game they can select a scenario, this will start a timer that ever 3 minutes will have an event happen randomly, (Stored in a string list) I would like to make it so the same even string can't be used again. I was thinking one way would be to remove item 1 from the list before it triggered again, then hopefully randomizing the list so the next time the event in position one is triggered it would be something with no risk of repeating?


DarkLizerd
22 Jul 2017, 03:42

Yes! Here is how I did it for my Wumpus V3.0 game:
// randomize the room names
player.N1 = Split(" 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,16,17,18,19,20", ",")
for (a, 1, 20) {
I = GetRandomInt(1,20)
N = stringListItem (player.N1, I)
list remove (player.N1, N)
list add (player.N1, N)
}
The for loop will run for 20 loops, to randomize it more, run it longer.
What this will do is select a random number, "I" in the list "player.N1" and save it as "N".
Then it will delete that entry, then add it "N" back to the end of the list.
IE:
player.N1 = Split(" 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,16,17,18,19,20", ",")
I=6
The 6th item is deleted, then added back to the end so:
player.N1 = Split(" 0, 1, 2, 3, 4, 5, 7, 8, 9,10,11,12,13,14,15,16,17,18,19,20, 6", ",")
then loop again...
I=15
The 15th item is deleted "16" then adder to the end so:
player.N1 = Split(" 0, 1, 2, 3, 4, 5, 7, 8, 9,10,11,12,13,14,15,17,18,19,20, 6, 16", ",")
and so on...


hegemonkhan
22 Jul 2017, 06:09

(filler to get my edited post updated)


very nice code Dark Lizard!

(quest should have this as a built-in Function: it has sorting list Functions but no 'scramble/randomizing' Functions for lists)
(we should let Pixie know, and he can add it into the next version of quest)


if you just don't want to repeat an item in the list (but without removing that item), we can use a part of Dark Lizard's code to do it:

player.N1 = Split(" 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,16,17,18,19,20", ",")
last_index_number_integer_variable = ListCount (player.N1) - 1
for (a, 0, list_count_integer_variable) {
I = GetRandomInt(a, list_count_integer_variable)
N = stringListItem (player.N1, I)
// then do whatever with 'n' (your item from the list)

// though one caveat: each time, if the min item isn't randomly selected, it misses out from ever being selected (unless you do this Function over again repeatedly: each time you run the function it resets, but during the function scripting itself, if the min item isn't randomly selected, it won't be selected for this function run)


to avoid the above issue/caveat, the easiest code design is to just remove the randomly selected item from the list (after you do the desired action on that item), and if you want to preserve the list, you can just make a copy-temporary list, which you remove the items from, and thus, not touching the original list, keeping all of its items.


The Pixie
22 Jul 2017, 06:15

It was in the last version!
http://docs.textadventures.co.uk/quest/functions/pickonestring.html

Though it does not remove it from the list. Here is DL's modified loop:

player.N1 = Split(" 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,16,17,18,19,20", ",")
while (ListCount(player.N1) > 0) {
  N = PickOneString (player.N1)
  list remove (player.N1, N)
  msg ("Picked " + N)
}

Note that N is a string.


hegemonkhan
22 Jul 2017, 06:20

oops, Pixie already has it, in his latest version (I'm still using old v550, so not aware of what was added in v560 and now v570 is current? v580 isn't out yet, right?), my bad.


DarkLizerd
22 Jul 2017, 06:35

I didn't randomize "0" because my rooms were numbered 1 to 20...
I needed "0" as a place holder.


hegemonkhan
22 Jul 2017, 06:42

HK edit:

oops (wasn't paying enough attention to your post), as you already know the below, you were just excluding your 'room_0' intentionally from the random selection of your room list. So, ignore the below.


we're using the '0:zero' because the list's index numbering (which is used to reference/get the item in the list), starts at '0:zero'

our code design is a bit different from your, so that's why we're using the '0:zero'

my_list = split ("red, blue, yellow", ";")

first_item_in_the_list = StringListItem (my_list, 0)
// first_item_in_the_list = "red"

second_item_in_the_list = StringListItem (my_list, 1)
// second_item_in_the_list = "blue"

third_item_in_the_list = StringListItem (my_list, 2)
// second_item_in_the_list = "yellow"

fourth_item_in_the_list = StringListItem (my_list, 3)
// ERROR, there is no 4th item in the list!

so, the last index number is: ListCount (LIST) - 1


HK edit 2:

last_index_number_of_list = ListCount (my_list) - 1
random_index_number_within_bounds_of_list = GetRandomInt (0, last_index_number_of_list)
random_item_from_list = StringListItem (my_list, random_index_number_within_bounds_of_list)
msg (random Item_from_list)
// output: (one of these: red or blue or yellow)

you can combine as a single line too (if you prefer, but you got to make sure you got the correct number of matching, left-right, parenthesis and that they're in the right locations too):

random_item_from_list = StringListItem (my_list, GetRandomInt (0, ListCount (my_list) - 1))
msg (random_item_from_list)
// output: (one of these: red or blue or yellow)


Talon
22 Jul 2017, 16:29

looks like some interesting stuff to try out, modified the code somewhat to suit my needs, since I only needed it to take one entry at a time, and not preserve the list I also pre built the list as an attribute, and did a simple (ListCount(player.N1) > 0) to provide a way for the function to show it was out of possibles..

My biggest challenge in adjusting the code was a huge overlook... i was resetting the list each time with the split command since i was avoiding the loop

The end result looks like it'll work fine, thank you all for such illumination on the basic concept of what i needed to do.


hegemonkhan
22 Jul 2017, 17:00

yep, that's a common mistake by lots of people, hehe, just try to remember to have those VARIABLES outside-of/before-the looping scripting, for example using the 'while' (loop) Function

terminator_boolean_variable = false // you do not want such 'creation/setting' variables as this/these to be within the looping scripting below

while (not terminator_boolean_variable) { // while terminator_boolean_variable = false // while (FALSE)
  msg ("hi")
  if (RandomChance (50)) { // if (TRUE)
    terminator_boolean_variable = true
  }
}

// -----------------------------------------

msg ("How many times do you want to display 'hi' ??? (Type in a positive number)")
get input {
  if (IsInt (result) and ToInt (result) > 0) {

     // -----------------------------------------------------

    // you do not want such 'creation/setting' variables as these to be within the looping scripting below:

    input_integer_variable = ToInt (result)
    count_integer_variable = 0 

    // ----------------------------------------------------------

    while (not count_integer_variable = input_integer_variable) { // while 'count_integer_variable' is less than 'input_integer_variable' // while (FALSE)
      msg ("hi")
      count_integer_variable = count_integer_variable + 1
    }
  } else {
    msg ("wrong input, try again")
  }
}