Home > Blockchain >  Chance of something to happen using integers as percentages
Chance of something to happen using integers as percentages

Time:12-07

I'm working on a job system where you can mine different types of ores in a discord bot. Depending on your skill, the chances (stored in a database) to receive certain ores change. Some will have a 0% chance at certain skill levels. At Skill 1 the chances will be the following:

let coal_chance = 80
let copper_chance = 15
let iron_chance = 5
let gold_chance = 0
let diamond_chance = 0
let emerald_chance = 0

And at Skill 2 the following:

let coal_chance = 50
let copper_chance = 35
let iron_chance = 10
let gold_chance = 5
let diamond_chance = 0
let emerald_chance = 0

And so on. My question is, how can I make a chance system based on these percentages?

I tried making a system using Math.Random() and an if statement, but since I have to check for a different amount of values each time I would have to make one for every skill level, and if I ever wanted to set the chance of a certain ore to 0% inside the database, I would also have to change the code.

CodePudding user response:

The crude solution I came up with based on the comment of @sudheeshix:

const cumulativeChances = [ 
  {c: 100, i: "coal"},
  {c: 50, i: "copper"},
  {c: 15, i: "iron"},
  {c: 5, i: "gold"},
  {c: 0, i: "emerald"},
  {c: 0, i: "diamond"}
]
const mineOre = () => {
  let rng = Math.random() * 100
  let won = 'coal'
  for (item of cumulativeChances) {
    if (item.c < rng) break
    won = item.i
  }
  return won
}

// Testing if it works as intended
const calculatedChances = {
  coal: 0,
  copper: 0,
  iron: 0,
  gold: 0,
  emerald: 0,
  diamond: 0
}
let tries = i = 10000;
while(i--) {
  let won = mineOre()
  calculatedChances[won]  = (1 / tries * 100)
}
console.log(calculatedChances)

There is probably room for improvement, but it provides an idea. Happy coding :)

CodePudding user response:

Here's one way:

Convert your resource values to an array:

resources = ["coal", "copper", "iron", "gold", "diamond", "emerald"];
chances = [80, 15, 5, 0, 0, 0];

Then, generate cumulative sums of the percentages, based on this answer.

const cumulativeSum = (sum => value => sum  = value/100)(0);
cum_chances = chances.map(cumulativeSum);

The values are divided by 100 to get the float values as that's what Math.random() generates: values between 0 and 1. With the values in chances mentioned above, this will make cum_chances with values [0.8, 0.95, 1, 1, 1, 1].

Now, generate the random probability.

random_prob = Math.random();

And find the index of the first array item that where random_prob falls in, based on this answer.

idx = cum_chances.findIndex(function (el) {
    return el >= random_prob;
});
resource_found = resources[idx];

For example, if random_prob is 0.93, this will give you an index of 1 and so, resources[idx] will give you "copper".

  • Related