Having a character respond "Randomly" from a list of answers

Okay so first I know there is not such thing as random in computers, that's why randomly is in quotes. Any way what I want to do is have a character do an action or something like that then run a script it a list of responses to give one of, but the character can do that action multiple times each time having one of a the responses selected from the list.
So as an related example a guy I know has in his game a scene where the player is knocking on a person's door, and the person in question refuses to answer, so the player has to be persistent and harass them till they answer. Now from what I understand he has it so there are a list of responses to knocking he has scripted and when the player knocks it choose from any of the responses to reply, and after a number of turns the person is scripted to finally answer the door. I like this however since the script choose from any of the listed answers you can get the same one multiple times in a row, and I don't like that.

So what I want to do is similar with you getting responses from the scripted list each turn for lets say ten turns then the character is forced to answer the door. However to prevent the player from getting the same response more then once I want to change the scripts each turn the player knocks the script chooses one response for that turn then removes it from the list so next time it has to choose another so by turn nine there is only one possible response. I do know how to script it so a player gets a different response specifically for that turn, like this one for turn one, this one for turn two, but I rather it be choose at ramrod so the order of the responses changes each play through.

Any ideas oh how to do that?


I have my Wumpus game where I randomized the names of the 20 rooms.
But, to prevent the same name from coming up twice, I made a list of names, removed one at random and put it at the end of the list, then kept doing this for 30 times.
You could use that to randomize the list, then, remove the first one each time the person knocked.
Then, when you run out of responses, the NPC opens the door.

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, 30) {
        I = GetRandomInt(1,20)
        N = stringListItem (player.N1, I)
        list remove (player.N1, N)
        list add (player.N1, N)
      }

OR... randomly remove all but the last one, then for the last response, the NPC opens the door...
One more idea, have 3 responses for when the NPC opens the door...


responses = NewStringList()
list add (responses, "Nothing happens.")
list add (responses, "No one answers.")
list add (responses, "Time passes.")
// You can add however many you choose.
response = PickOneString(responses)
msg(response)

So, if I had a door you could knock on, and I wanted to print a random response until the fourth knock, I'd make this the door's "knock on" verb's script:

firsttime{
  this.knocks = 0
}
if (this.knocks < 5){
  this.knocks = this.knocks + 1
  if (this.knocks < 4){
    responses = NewStringList()
    list add (responses, "Nothing happens.")
    list add (responses, "No one answers.")
    list add (responses, "Time passes.")
    // You can add however many you choose.
    response = PickOneString(responses)
    msg(response)
  }
  else if (this.knocks = 4) {
    msg("Someone opens the door.")
    this.isopen = true
  }
}
else {
  msg ("You've already done this bit!")
}

http://docs.textadventures.co.uk/quest/using_lists.html


EDIT

I started writing this, then my oven timer beeped...

I came back, finished it up and posted it. Now I see DL's post, which will work just as well as this one (if not better).


I don't understand how any of those helps me do what I want. I can't see where in those codes it removes the response from the list once it's run?


Here's a script for the knock command/verb/etc that might do what you want. If I'm understanding you right:

firsttime {
  this.responses = Split("You knock, but nothing happens;You hear someone moving about inside the house, but they don't answer the door;A voice screams “Go away you little punk!”;You thought you heard someone coming to the door, but it was just the wind;more responses here")
}
if (ListCount(this.responses) > 0) {
  my_response = PickOneString (this.responses)
  msg (my_response)
  list remove (this.responses, my_response)
}
else {
  msg ("Finally, the door opens")
}

However to prevent the player from getting the same response more then once I want to change the scripts each turn the player knocks the script chooses one response for that turn then removes it from the list so next time it has to choose another so by turn nine there is only one possible response.

Whoops! I didn't notice this bit. mrangel's got you covered though!


// put this in the room first enter...
player.N1 = Split("No answer, Go away, I gave at the office, I've got a gun!", ",")
   // add this to the "knock on door" command
       // this select a random one from the list
        I = GetRandomInt(1,4) // I thing there is a list count command that will tell you how many are in the list.
   // if the list count=0 then exit this and have the NPC open the door
        N = stringListItem (player.N1, I)
   msg (N) // tell the player this responce
     // this removes item # I from the list
        list remove (player.N1, N)
      }

(filler for getting my edited post, updated/posted)


finishing-up (and expanding/explaining my adjustments/examples to) DL's code:

// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

// put the below code line in the room first enter:

// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

player.example_stringlist_attribute = Split ("No answer;Go away;I gave at the office;I've got a gun!", ";")

// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

// add all of the rest of the code lines below to the "knock on door" command:

// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

// get the list count (number of items in the list):

list_count_integer_variable = ListCount (player.example_stringlist_attribute)

// get the last index number (the last item's indicator/reference) of the list (lists' items start at ZERO, not one, and so):

last_index_number_integer_variable = list_count_integer_variable - 1

// get a viable (within the list's range/scope) randomly selected index number:

viable_randomly_selected_index_number_integer_variable = GetRandomInt (0, last_index_number_integer_variable)

// get a viable (within the list's range/scope) randomly selected list item (a String Value, as we're using a String List Attribute):

viable_randomly_selected_stringlist_item_string_variable = StringListItem (player.example_stringlist_attribute, viable_randomly_selected_index_number_integer_variable)

// if the list count=0 then exit this and have the NPC open the door:

if (list_count_integer_variable = 0) {

  // example scripts below:

  // NAME_OF_DOOR_OR_EXIT.locked = false
  // NAME_OF_DOOR_OR_EXIT.isopen = true

  // player.parent = NAME_OF_DESTINATION_ROOM_OBJECT
  // or (the 'helper' Script/Function below, which is doing the code line above for you, hence why it's called a 'helper' Script/Function --- programming terminology):
  // MoveObject (player, NAME_OF_DESTINATION_ROOM_OBJECT)

} else {

  // tell the player this response:

  msg (viable_randomly_selected_stringlist_item_string_variable)

  // this removes the randomly selected item (a String Value) from the string list:

  list remove (player.example_stringlist_attribute, viable_randomly_selected_stringlist_item_string_variable)

}

I think HK might get in the Guinness World Records for viable_randomly_selected_stringlist_item_string_variable. (Hehehe)

I'm just kidding. HK uses long variable names, but that just makes it easy to decipher the code.


oh, that's not that long a name/label for HK... as he can make them much longer... lol

HK uses the names of things as his comments/instructions, hehe

(it's a pain to read, but if you read it, you can follow right along, knowing exactly what's being done, lol)


if you read it, you can follow right along, knowing exactly what's being done,

Very true! (I just edited my last post to add that bit at the same moment you posted this.)


And yet, I started out in Basic where every letter counted to take up memory...
Ever try to program a game on a computer with 4K of ram???


Ever try to program a game on a computer with 4K of ram???

Nope :p My first game was on the Commodore 16.
Theoretically 16k… but after loading the system and the BASIC interpreter, you get the startup message:

 COMMODORE BASIC V3.5 12277 BYTES FREE

READY.

(All caps too. Because there's a lowercase font, but it saves memory by having only one of them in memory at any time)


high efficiency (not human usable) vs human usable (low efficiency) :D

(this is why everything that can be done, aka not critical: life-death and/or compactness: having limited physical space, is done with high level languages)

it's amazing the games they could make with limited memory/space (probably some of the best game makers on those early gaming consoles/systems, like NES/SNES, and etc)


So far the second one from Dark lizard is the only one I got to work, and it does for the first two times I use the command then I get this error
Error running script: Error evaluating expression 'stringListItem (player.N1, I)': StringListItem: index 3 is out of range for this list (2 items, last index is 1)
How do I fix this?
Here is the original code he gave
``
// put this in the room first enter...
player.N1 = Split("No answer, Go away, I gave at the office, I've got a gun!", ",")
// add this to the "knock on door" command
// this select a random one from the list
I = GetRandomInt(1,4) // I thing there is a list count command that will tell you how many are in the list.
// if the list count=0 then exit this and have the NPC open the door
N = stringListItem (player.N1, I)
msg (N) // tell the player this responce
// this removes item # I from the list
list remove (player.N1, N)
}


I = GetRandomInt(1,4) // I thing there is a list count command that will tell you how many are in the list.

When there are less than 4 items, there is a chance that the random number will select an entry not on the list...
Change it to
I = GetRandomInt(1,ListCount(player.N1))


Okay I tried that and got this error
Error running script: Error evaluating expression 'stringListItem (player.N1, I)': StringListItem: index 2 is out of range for this list (2 items, last index is 1)
So doesn't seemed to have changed anything?


@ Thickar:

here's an extensive step-by-step/example-by-example detailed explanation/guide on fully understanding and using lists:

create ("example_object")

example_object.example_stringlist_attribute = NewStringList ()
list add (example_object.example_stringlist_attribute, "red")
list add (example_object.example_stringlist_attribute, "blue")
list add (example_object.example_stringlist_attribute, "yellow")

// string list item 1:
// input (key: index number): 0
// output (value): "red"

// string list item 2:
// input (key: index number): 1
// output (value): "blue"

// string list item 3:
// input (key: index number): 2
// output (value): "yellow"

// string list item 4:
// ERROR! (there is no 4th item in the 'example_object.example_stringlist_attribute' list: you are going outside/beyond of the 'example_object.example_stringlist_attribute' list, an 'out of bounds' ERROR, and into the next memory segment of data, and this is a big no no, as it scrambles up all of your stored data in memory, and hence the error to protect/block this from happening)

// (computer memory is literally just a long line of 'boxes', holding their address/location and whatever data, which are segmented, and can be further/sub-segment by you, too. Computer memory is literally just a single very long list/array of its addresses and data, that is segmented up into smaller sub lists/arrays)

string_variable = StringListItem (example_object.example_stringlist_attribute, 0)
msg (string_variable)
// display output: red

string_variable = StringListItem (example_object.example_stringlist_attribute, 1)
msg (string_variable)
// display output: blue

string_variable = StringListItem (example_object.example_stringlist_attribute, 2)
msg (string_variable)
// display output: yellow

string_variable = StringListItem (example_object.example_stringlist_attribute, 3)
msg (string_variable)
// ERROR ('out of bounds' ERROR: there is no 4th item in the 'example_object.example_stringlist_attribute' list)

--------

quantity of items in a list:

list_count_integer_variable = ListCount (example_object.example_stringlist_attribute)

because a list's first item is given the index number of 0 (and not 1), its last item's index number is: ListCount (LIST) - 1

as seen by my list above, it has 3 items (0="red", 1="blue", 2="yellow"), and thus its last index number is: 2 (which is 1 less than its quantity of items)

------

so, since you can add/remove items from a list, its quantity of items and thus its last item's index number, can change (aka: is dynamic), so using a static (non-changing) value, within the 'GetRandomInt (MIN_VALUE, MAX_VALUE)' randomization Function/Script will cause errors, as you add/remove items, see below examples

------

random_integer_variable = GetRandomInt (0, 2)

string_variable = StringListItem (example_object.example_stringlist_attribute, random_integer_variable)
msg (string_variable)
// display output: (randomly selects one of these: red, blue, or yellow)
// NO error

-----

list add (example_object.example_stringlist_attribute, "green")

random_integer_variable = GetRandomInt (0, 2)

string_variable = StringListItem (example_object.example_stringlist_attribute, random_integer_variable)
msg (string_variable)
// (ERROR) the 4th item (3="green") will NEVER be selected, as the range is only: index numbers: 0 to 2 (items: 1 to 3)

-----

random_integer_variable = GetRandomInt (0, 3)

string_variable = StringListItem (example_object.example_stringlist_attribute, random_integer_variable)
msg (string_variable)
// display output: (randomly selects one of these: red, blue, yellow, or green)
// NO error

------

list remove (example_object.example_stringlist_attribute, "green")

random_integer_variable = GetRandomInt (0, 3)

string_variable = StringListItem (example_object.example_stringlist_attribute, random_integer_variable)
msg (string_variable)
// if the 'GetRandomInt' selects '3', then: ERROR, as there no longer is the 4th item (3="green"), as it was removed

------

so... you need to find the quantity of items, every time, which you can do like this (see the many segments/examples below)

-----

example_object.example_stringlist_attribute = NewStringList ()
list add (example_object.example_stringlist_attribute, "red")
list add (example_object.example_stringlist_attribute, "blue")
list add (example_object.example_stringlist_attribute, "yellow")

---

list_count_integer_attribute = ListCount (example_object.example_stringlist_attribute)

viable_last_index_number_integer_variable = list_count_integer_attribute - 1

viable_random_integer_variable = GetRandomInt (0, viable_last_index_number_integer_variable)

// if you rather, you can combine these code lines into a single code line (but its easy to mess up the syntax and its harder to understand: how it works / what it is doing):
// StringListItem (example_object.example_stringlist_attribute, GetRandomInt (0, ListCount (example_object.example_stringlist_attribute) - 1))

string_variable = StringListItem (example_object.example_stringlist_attribute, viable_random_integer_variable)
msg (string_variable)
// display output (selects one of the items)
// NO error

-----

list add (example_object.example_stringlist_attribute, "green")

list_count_integer_attribute = ListCount (example_object.example_stringlist_attribute)

viable_last_index_number_integer_variable = list_count_integer_attribute - 1

viable_random_integer_variable = GetRandomInt (0, viable_last_index_number_integer_variable)

string_variable = StringListItem (example_object.example_stringlist_attribute, viable_random_integer_variable)
msg (string_variable)
// display output (selects one of the items)
// NO error

-------

list add (example_object.example_stringlist_attribute, "orange")
list add (example_object.example_stringlist_attribute, "purple")

list_count_integer_attribute = ListCount (example_object.example_stringlist_attribute)

viable_last_index_number_integer_variable = list_count_integer_attribute - 1

viable_random_integer_variable = GetRandomInt (0, viable_last_index_number_integer_variable)

string_variable = StringListItem (example_object.example_stringlist_attribute, viable_random_integer_variable)
msg (string_variable)
// display output (selects one of the items)
// NO error

---------

list remove (example_object.example_stringlist_attribute, "purple")
list remove (example_object.example_stringlist_attribute, "orange")
list remove (example_object.example_stringlist_attribute, "green")
list remove (example_object.example_stringlist_attribute, "yellow")
list remove (example_object.example_stringlist_attribute, "blue")

list_count_integer_attribute = ListCount (example_object.example_stringlist_attribute)

viable_last_index_number_integer_variable = list_count_integer_attribute - 1

viable_random_integer_variable = GetRandomInt (0, viable_last_index_number_integer_variable)

string_variable = StringListItem (example_object.example_stringlist_attribute, viable_random_integer_variable)
msg (string_variable)
// display output: red // as this is the only item left to select, lol
// NO error

--------------

the last issue to handle:

when removing items (or if you just create an empty list), you can have the list with no items (an empty/emptied list), and thus you'll get an ERROR, as it's trying to randomly select an item from an empty list (or if you're trying to remove an item from an empty list too as well), lol

so, you need some code to handle/check if the list is empty, before/if you remove an item, and/or: do the 'GetRandomInt' or not scripting:

if (ListCount (example_object.example_stringlist_attribute) = 0) {
  msg ("ERROR: the list is empty: can't perform the action on an empty list")
} else {
  // list remove (BLAH) BLAH scripting
  // and/or
  // GetRandomInt (0, ListCount (BLAH) - 1) BLAH scripting
}

Could the problem be that 'StringListItem' counts from zero. Not sure how the 'Split' function counts.
I = GetRandomInt(1,4) is generating a random number between 1 and 4. Because 'StringListItem' counts 0, 1, 2, 3, if I =4, then there's nothing to match against.


@hegemonkhan
It's to complex I can't follow what you are trying to convey, I need a simpler answer


These lines:

I = GetRandomInt(1,4) // I thing there is a list count command that will tell you how many are in the list.

should be:

I = GetRandomInt(1,ListCount (player.N1)) - 1

But I think it would be simpler just to replace these lines:

I = GetRandomInt(1,4) // I thing there is a list count command that will tell you how many are in the list.
N = stringListItem (player.N1, I)

With:

N = PickOneString (player.N1)

Quest already has a function to pick a random string from a list.

Also, did you try the code I posted earlier? I pasted it into a command in my test game, and it worked fine for me.


@mrangel
Yours was the first I tried but I guess I change something in it for a reason I can't remember, but after working with all the different code people offered me I now was able to read yours and see exactly how to implement it because the scenario I was using it in changed from the example I changed, so thanks as well as everyone else who helped


That's the problem with programming...
10 programmers can each give you 3 ways to solve a problem...
But only YOUR code will work where you are having the problem...


Log in to post a reply.

Support

Forums