Obtain a random item from an array containing elements with assigned weights

In my game development project, I have an array of objects representing creatures. Each creature object includes a unique identifier and a corresponding weight or probability for spawning.

I am struggling to create an algorithm that will randomly spawn creatures based on their weights. I need help figuring out how to implement this feature effectively.

Could anyone provide some guidance?

Here is an example of the creatures array:

var creatures = [
    {id: 1, weight: 25},
    {id: 2, weight: 15},
    {id: 3, weight: 5},
    {id: 4, weight: 45},
    {id: 5, weight: 10}
]

Answer №1

After coming across a helpful algorithm written in PHP on this blog, I decided to adapt it for use in JavaScript. The algorithm seems like it could be a good fit for your requirements.

Here is the adapted code:

var creatures = [{
    id: 1,
    weight: 25
  }, {
    id: 2,
    weight: 15
  }, {
    id: 3,
    weight: 5
  }, {
    id: 4,
    weight: 45
  }, {
    id: 5,
    weight: 10
  }],
  sumOfWeights = creatures.reduce(function(memo, creature) {
    return memo + creature.weight;
  }, 0),
  selectedWeigths = {};

function getRandom(sumOfWeights) {
  var random = Math.floor(Math.random() * (sumOfWeights + 1));

  return function(creature) {
    random -= creature.weight;
    return random <= 0;
  };
}

for (var i = 0; i < 1000; i++) {
  var creature = creatures.find(getRandom(sumOfWeights));
  selectedWeigths[creature.weight] = (selectedWeigths[creature.weight] || 0) + 1;
}

console.log(selectedWeigths);

I hope this solution proves to be useful for you.

Answer №2

To create a new array, iterate through each creature and add its ID to the array based on its weight. Then generate a random number within the range of the array's size to return the corresponding ID.

var creatureIds = [];
for(var i=0;i<creatures.length;i++){
    for(var x=0;x<creatures[i].weight;x++){
        creatureIds.push(creatures[i].id);
    }
}

// Obtain a random index between 0 and the length of IDs.
var min = 0;
var max = creatureIds.length;
var index = Math.floor(Math.random() * (max - min + 1)) + min;

var randomWeightedCreatureId = creatureIds[index];

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

When attempting to display an updated value in a dialog window using an ajax response for the second time, the change

Upon submission of my form, a PHP script is triggered via AJAX to perform validation. Currently, the script simply echoes the post value. For example, if a user inputs "Dog" into "formEntry," the AJAX response will display Dog. However, if the user cancels ...

Upcoming verification with JSON Web Token

I am looking to incorporate JWT auth into my Next app. Currently, I have mapped out the flow as such: User enters email and password to log in Server responds with status 200 and a jwt access token in httpOnly cookies My main dilemma lies in deciding on ...

Tips for detecting and handling errors in user input from the console

Is there a way to catch errors in Chrome's developer tools console when an input throws an error? I attempted using window.addEventListener("error") but it seems that the onerror event listener on window does not capture the console errors. ...

Trouble with displaying my three.js 3D model

I've tried multiple solutions I found, but none have fixed the issue of not being able to display 3D models. Many have suggested that it could be a problem with the camera, but so far I haven't been able to resolve it. Any assistance would be gre ...

Submitting dataURL via Ajax using multipart/form-data

I'm currently working on a program that is responsible for extracting a dataURL from a canvas element and then transmitting it to the server side for conversion back into a JPG file. Now, my next step involves retrieving this image from the server pro ...

Having trouble converting the JQuery result from the REST request into the correct format

Currently, I am working on making a REST request for an array of objects using JQuery. During the execution of the code within the "success" section, everything works perfectly fine - the objects in the array are converted to the correct type. However, I ...

There seems to be an issue with connecting to the local server at https://localhost:3000/socket.io/ while using a

I am currently working on a Node.js project where I have a client.js for client-side code, and a server.js on a remote server using sockets to communicate over port 3000 In addition, Apache is running on port 80, with a ProxyPass configuration in place to ...

The Problem of Restoring Column Height in Tabulator 4.6.3 Filters

The Issue After activating and deactivating header filters, the column height does not return to its original state. Is this the expected behavior? Is there a way to reset the column height? Check out this JS Fiddle example: https://jsfiddle.net/birukt ...

Rendering images in Next.js version 10

Just recently, Next.js version 10 was launched featuring the latest Image element, making it a great asset for websites that heavily rely on images! When I receive an HTML response from the server, it looks something like this: HTML = "<div> &l ...

Tooltip positioned within a custom container using Material UI

Currently, as part of my Chrome extension development utilizing React and Material UI, I am implementing an inject page strategy. I have managed to set up a tooltip for the Fab button, but unfortunately, it appears outside the DOM of my extension. Upon ins ...

Why isn't the background-image displaying with the use of the url() function?

I've been attempting to set an image as the background using background-img:url(imageLing), but it's not working properly. When I inspect the element, it shows me background-image: url(assets/backgrounds/5.jpg);. What could be causing this issue? ...

Link several jQuery elements to a function simultaneously

Having 3 jQuery objects is my current situation: var first = $('.el1'); var second = $('.el2'); var third = $('.el3'); I am trying to attach a "change" event to all of them simultaneously, but facing some challenges :( $(fi ...

"Modifying Code Aesthetics in WebStorm/IDEA: A Step-by-

Here is the code style I am currently using in my JavaScript project: var obj = { a: 1 , b: 2 , c: 3 } var arr = [ 'a1' , 'a2' , 'a3' ] const w = 1 , w2 = 2 , w3 = 3 The team claims they are following npm's co ...

Create an Interactive Data Visualization with JSON using CanvasJS Charts

Having some trouble creating a chart using CanvasJS. After fetching data from the API and checking the JSON array, I encounter two errors when attempting to generate dataPoints for the graph: "data invalid" on the data field and "NaN" on the value field. ...

Receive live feedback from shell_exec command as it runs

I have been working on a PHP-scripted web page that takes the filename of a previously uploaded JFFS2 image on the server. The goal is to flash a partition with this image and display the results. Previously, I had used the following code: $tmp = shell_ex ...

transferring function from server to the client module named Next 13

After referencing the documentation for the app directory in Next.js, it is recommended to fetch data inside Server Components whenever feasible. Server Components always carry out data fetching on the server. This advice is particularly helpful for me as ...

Vue event manager, accessible for all components

I have created a new Vue instance and assigned it to the window object, thinking that it would be accessible throughout all components. I expected this setup to allow me access to events emitted anywhere within my application. However, it seems like this ...

The art of sketching precise lines encircling a circular shape through the

What is the best way to use a for loop in JavaScript to draw lines around a circle, similar to those on a clock face? ...

Ignoring TypeScript overloads after the initial overload declaration

Issue An error occurs when attempting to call an overload method for a specific function. The call only works for the first defined overload, causing an error if the call is made to the second overload with mismatched typing compared to the first overload ...

You cannot convert a function to a string while utilizing axios get in nuxtServerInit

While attempting to connect my app to the backend using Udemy's Nuxt.js course, I encountered a GET http://localhost:3000/ 500 (Internal Server Error) on the client side with the following code: import Vuex from 'vuex'; import axios from &a ...