Randomnize table ?

Started by MetalZelda, December 10, 2017, 02:31:53 PM

Previous topic - Next topic
December 10, 2017, 02:31:53 PM Last Edit: December 10, 2017, 02:34:51 PM by MetalZelda
Hello

Today I am mostly programming minigames, one of which is based on ALTTP.
But, I have taken another view of how the minigame would work.
Winnable items are shown before the game starts like so



Then a movement starts on winnable item's entity and the minigame starts.

This leads me to this question to make the minigame more dependant of an RNG (Random Number Generator) to make the minigame a bit more difficult
Winnable items are stored in a table

Code (lua) Select
local minigame_prices = {
  {"rupee", 0},
  {"amber_counter", 0},
  {"green_chuchu_counter", 0},
  {"heart_piece", 0},
  {"arrow", 0},
  {"rupee", 3},
  {"heart", 0},
  {"rupee", 5},
  {"rupee", 2},
}


Basically, it is

[chest 1] treasure = rupee, variant = 0

All I want is

[chest (random 1 - 9)] treasure = rupee, variant = 0

Any idea of how to make it happen ?

That depends on what you want to do.

1) If you want to show only the treasure of the chest you opened and not the others, then you only need a random number between 1 and #minigame_prizes (remember to rename your list "minigame_prices" to "minigame_priZes", because it's not the same thing). You can use:

local index = math.random(1, #minigame_prizes)
local prize = minigame_prizes[index]


2) If you want to show where all prizes are after you open the chest, then you need to code a random permutation. I would use the "Knuth shuffles" permutation algorithm (it is very simple and the code is short); you can adapt the code from here:
https://en.wikipedia.org/wiki/Random_permutation
You can either permute the prizes list directly, or permute a list with numbers from 1 to #minigame_prizes and then use the permuted indices list to associate the prizes to the corresponding chests.

We all enjoy games with chests. Does that mean we are all perverts?  :o
"If you make people think they're thinking, they'll love you. But if you really make them think, they'll hate you."

December 10, 2017, 05:33:28 PM #2 Last Edit: December 10, 2017, 05:39:52 PM by MetalZelda
Quote from: Diarandor on December 10, 2017, 05:13:24 PM
That depends on what you want to do.

1) If you want to show only the treasure of the chest you opened and not the others, then you only need a random number between 1 and #minigame_prizes (remember to rename your list "minigame_prices" to "minigame_priZes", because it's not the same thing). You can use:

local index = math.random(1, #minigame_prizes)
local prize = minigame_prizes[index]


2) If you want to show where all prizes are after you open the chest, then you need to code a random permutation. I would use the "Knuth shuffles" permutation algorithm (it is very simple and the code is short); you can adapt the code from here:
https://en.wikipedia.org/wiki/Random_permutation
You can either permute the prizes list directly, or permute a list with numbers from 1 to #minigame_prizes and then use the permuted indices list to associate the prizes to the corresponding chests.

We all enjoy games with chests. Does that mean we are all perverts?  :o

Yes, that's the way I wanna go
I did found some workaround by setting a random treasure at chest opening sequence

Code (lua) Select
-- Define what happen when the player tries to open a chest
-- Since chests are empty (no treasure), that makes things easier
for chests in map:get_entities_by_type("chest") do
  chests.on_opened = function()
    if minigame_state == "end" then
      sol.audio.play_sound("error")
      game:start_dialog("minigame.chest.need_pay", function()
        sol.audio.play_sound("objects/minecart/landing")
        chests:set_open(false)
        hero:unfreeze()
      end)
    else
      local rng = math.random(1, #minigame_prizes)
      rng = minigame_prizes[rng]

      local treasure, variant, savegame = rng[1], rng[2], rng[3]
      hero:start_treasure(treasure, variant + 1, savegame, function()
        game:start_dialog("minigame.chest.finished")
      end)
      minigame_state = "end"
     
    end
  end
end


I don't know if there's a better way to do so, since rng only applies when the choosen chest has been opened
Oh well, it does what I wanted

Y'all love chests chest is love chest is life :o

Remember to initialize a random seed once, and only once (the recommended way is to use the time as seed). This could be done in your main script.
"If you make people think they're thinking, they'll love you. But if you really make them think, they'll hate you."