3
\$\begingroup\$

I'm attempting to create a function that will give me a "fish" at random, though a bias random depending on the weight value for the "fish".

var FISH = {
 "level1": [
 //["name", xp, weight] 
 ["Shrimp", 10, 95],
 ["Sardine", 20, 85],
 ["Herring", 30, 75],
 ["Anchovies", 40, 65],
 ["Mackerel", 40, 55]
 ]
};
function randomRange(min, max) {
 return Math.random() * (max - min) + min;
}
function getRandomFish(level) {
 var fishForLevel = FISH[level],
 numberOfFish = fishForLevel.length,
 chance = randomRange(0, 100);
 if (numberOfFish > 1) {
 var fish = fishForLevel[Math.floor(randomRange(0, numberOfFish))];
 if (chance <= fish[2]) {
 return fish;
 } else {
 return getRandomFish(level);
 }
 } else {
 return fishForLevel[0];
 }
}

Example of outcome: http://jsfiddle.net/qAvAs/

If this could be made more efficient, how would one do so?

asked Aug 20, 2011 at 17:11
\$\endgroup\$

1 Answer 1

5
\$\begingroup\$

I'd suggest you select a random number that's from 0 to the total weight of your fish. Then, each fish can have a piece of that random range according to it's weight which gives it the weighting you want. This ends up giving each fish a number of buckets that corresponds to it's weighting value and then you pick a random number from 0 to the total number of buckets and find out who's bucket the random number landed in.

It's the same idea as turning each weighting number into a percentage change and then picking a random number from 0 to 99.

This code should do that:

var FISH = {
 "level1": [
 //["name", xp, weight] 
 ["Shrimp", 10, 95],
 ["Sardine", 20, 85],
 ["Herring", 30, 75],
 ["Anchovies", 40, 65],
 ["Mackerel", 40, 55]
 ]
};
function getRandomFish(level) {
 var fishForLevel = FISH[level];
 var fishTotalWeight = 0, fishCumWeight = 0, i;
 // sum up the weights
 for (i = 0; i < fishForLevel.length; i++) {
 fishTotalWeight += fishForLevel[i][2];
 }
 var random = Math.floor(Math.random() * fishTotalWeight);
 // now find which bucket out random value is in
 for (i = 0; i < fishForLevel.length; i++) {
 fishCumWeight += fishForLevel[i][2];
 if (random < fishCumWeight) {
 return(fishForLevel[i]);
 }
 }
}
answered Aug 20, 2011 at 17:22
\$\endgroup\$
1
  • \$\begingroup\$ I like this. Certainly seems more efficient then what I was using. :) \$\endgroup\$ Commented Aug 20, 2011 at 17:52

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.