Random objects/encounters in different areas of the game
hegemonkhan
22 Apr 2018, 16:23this involves using the 'list/dictionary' Attribute (+ GetRandomInt/GetRandomDouble/RandomChance/DiceRoll for the randomness), if you need help with using lists/dictionaries, let me know.
the 'GetRandomInt' and 'RandomChance' work especially well together too:
for example (an item) drop system:
the 'GetRandomInt' selects the (type of) item
and the 'RandomChance' determines whether that selected item, is actually dropped (successful) or not (failed)
create ("example_object")
create ("sword")
create ("candy")
create ("axe")
create ("chocolate")
example_object.example_objectlist_attribute = NewObjectList ()
list add (example_object.example_objectlist_attribute, sword)
list add (example_object.example_objectlist_attribute, candy)
list add (example_object.example_objectlist_attribute, axe)
list add (example_object.example_objectlist_attribute, chocolate)
list_count_integer_variable = ListCount (example_object.example_objectlist_attribute)
last_index_number_integer_variable = list_count_integer_variable - 1
viable_randomly_selected_index_number_integer_variable = GetRandomInt (0, last_index_number_integer_variable)
viable_randomly_selected_list_item_object_variable = ObjectListItem (example_object.example_objectlist_attribute, viable_randomly_selected_index_number_integer_variable)
// you can use 'if' too, instead of the 'switch' below, as 'if' and 'switch' are functionally the same, though the syntax for them is a bit different, of course
// though, if you got a lot of items in your list, then it'd be better to use a Script Dictionary, or to have each item Object have the 'drop' script on it, and call/do/use that 'drop' script, but this is a bit more advanced design... so not showing it here... showing the 'switch' instead as seen below
switch (viable_randomly_selected_list_item_object_variable) {
case (sword) {
if (RandomChance (10)) {
CloneObjectAndMove (sword, player)
}
}
case (candy) {
if (RandomChance (90)) { // 90% (a high) chance of dropping (getting) it // common item drop
CloneObjectAndMove (candy, player)
}
}
case (axe) {
if (RandomChance (10)) { // 10% (a low) chance of dropping (getting) it // rare item drop
CloneObjectAndMove (axe, player)
}
}
case (chocolate) {
if (RandomChance (50)) { // 50% (1/2) chance of dropping (getting) it // a 1/2 (which is still quite good odds, lol) item drop
CloneObjectAndMove (chocolate, player)
}
}
}
as for controlled randomness (lol), as far as I know, the only way to enforce a probability is to directly control it:
for example, if you want a '1/6' odd/chance/probability, then you got to literally have it happen on the 6th time, which means a 'counter' to track it:
create ("example_object")
example_object.counter_integer_attribute = 0
example_object.flag_boolean_attribute = false
// ---------
// if the 'example_object.counter_integer_attribute = 0' causes the 'changed' script to fire, then you need this code:
example_object.changedcounter_integer_attribute => {
if (example_object.counter_integer_attribute = 6) {
example_object.flag_boolean_attribute = true // this is needed to happen before this 'changed' script fires again by the 'example_object.counter_integer_attribute = 0' line below, lol
msg ("BLAH ACTION/EVENT") // and this too, as well, lol
example_object.counter_integer_attribute = 0
} else if (example_object.flag_boolean_attribute) {
example_object.flag_boolean_attribute = false
} else {
example_object.counter_integer_attribute = example_object.counter_integer_attribute + 1
}
}
// otherwise / if-not, you can just use this code:
example_object.changedcounter_integer_attribute => {
if (example_object.counter_integer_attribute = 6) {
example_object.counter_integer_attribute = 0
msg ("BLAH ACTION/EVENT")
} else {
example_object.counter_integer_attribute = example_object.counter_integer_attribute + 1
}
}
hegemonkhan
22 Apr 2018, 17:13if you want all items to be tried (if the first item fails, try for the next item, and so forth)... the best design (if you got a lot of items) would be recursion usage (see diablo 2's recursion, item drop / treasure class, system)

DarkLizerd
22 Apr 2018, 17:35HK: "as for controlled randomness (lol), as far as I know, the only way to enforce a probability is to directly control it:
for example, if you want a '1/6' odd/chance/probability, then you got to literally have it happen on the 6th time, which means a 'counter' to track it:"
Nope... just go with a GetRandomInt (0, 6) to make it random...
For you randomness...
Do you want a selected random items in the room? Or scattered throughout your maze of rooms?
For the first:
You could add a bit of code in the "on first enter":
Room_01
// no creature
// no items
Room_02
Switch(GetRandomInt (0, 6))
Case 1,2,3: no creature
case 4: Bat
case 5: lost explorer
case 6: Giant spider
switch (0,3)
case 1: Bag of coins
case 2: rusty sword
case 3: Heal potion
Room_03
anything else
...
mrangel
22 Apr 2018, 21:03I'd previously considered making a collection of containers for the various events/encounters. This system would allow moving monsters or items to the player's location, or running a script.
These are basically unreachable rooms, each representing a random encounter. Any objects inside the 'encounter' are moved to the player's location when it is triggered. It also can have attributes encounter_script
(a script that is run when the encounter triggers), encounter_probability
(an int; higher numbers are more likely), encounter_enabled
(boolean), encounter_repeats
(boolean), encounter_locations
(objectlist of rooms where where the encounter can happen), and encounter_test
(script that can modify the values above, in case it's more likely in some places than others for example).
A script something like:
possible_encounters = NewObjectList()
total_probability = 0
foreach (enc, GetDirectChildren(ENCOUNTERS)) {
if (HasScript(enc, "encounter_test")) {
do (enc, "encounter_test")
}
if (GetBoolean(enc, "encounter_enabled")) {
found_room = true
if (HasAtribute (enc, "encounter_locations")) {
found_room = false
foreach (room, enc.encounter_locations) {
if (Contains (room, game.pov)) {
found_room = true
}
}
}
if (found_room) {
if (not HasInt (enc, "encounter_probability")) {
enc.encounter_probability = 10
}
list add (possible_encounters, enc)
total_probability = total_probability + enc.encounter_probability
}
}
}
if (total_probability < 100) {
total_probability = 100
}
chosen = GetRandomInt (1, total_probability)
while (ListCount(possible_encounters) > 0) {
encounter = ListItem (possible_encounters, 0)
list remove (possible_encounters, encounter)
chosen = chosen - encounter.encounter_probability
if (chosen < 0) {
possible_encounters = NewObjectList()
encounter_children = NewObjectList()
foreach (o, GetDirectChildren (encounter)) {
if (GetBoolean (encounter, "encounter_repeats")) {
list add (encounter_children, CloneObjectAndMove (o, game.pov.parent))
}
else {
list add (encounter_children, o)
o.parent = game.pov.parent
}
}
if (HasScript (encounter, "encounter_script")) {
// the "room" and "children" variables give the encounter script an easy way to find the
// room it's happening in, and the objects moved/cloned there (for example monsters)
params = NewDictionary()
dictionary add (params, "room", game.pov.parent)
dictionary add (params, "children", encounter_children)
do (encounter, "encounter_script", params)
}
if (not GetBoolean (encounter, "encounter_repeats")) {
RemoveObject (encounter)
}
}
}
You could run that from the enterroom script, or when visiting a new room for the first time, or something like that. Depending if you want random encounters to only occur in new rooms.