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"
.