Javascript choose biggest more often than smaller - javascript

I'm busy with nodejs a bit for modding a game, but I'd like to know how to do something like this:
var zombieDirector =
{
zombieBison = 1
zombieChicken = 2
zombie = 3
skeleton = 3
}
and those names have another var like
var zombieBison = 'Entities/Zombies/zombieBison.cfg'
and now make the Bison spawned rare and skeleton and zombie more often.
you get this, where randomZombie equals to 'Entities/Zombies/aZombie.cfg'
ks.map.spawnEntity('zombie', randomZombie, 0, 0, 3);
I can't get any further than
var randomZombie = zombieDirector[Math.floor(Math.random() * zombieDirector.length)];
On another note: No JQuery please
Thanks in advance

In essence, you're talking about weighted random number generation. A little tricky, if you want to use math, but you can do it with an array, like this:
var choices = [];
for(prop in zombieDirector) {
for(var i = 0; i<zombieDirector[prop]; i++) {
choices.push(prop);
}
}
var choice = choices[Math.floor(Math.random() * choices.length + .5)];
The variable choice will now have a random monster name, weighted based on the number you provide in zombieDirector.

Related

How to choose between multiple options with different chances whithout making ugly code

I am asking this question for my JS code, but it's actually a problem that I'm having in every programming language.
Let's say I have 5 names for dogs in my simulation, I can hold them in an array and choose a random name for every dog like this
var NAMES = ["Scafy","Shimshon","WoofWoof","Mitzy","AnotherDogName"]//possible names for the dogs
dog.name = NAMES[Math.floor(Math.random()*NAMES.length)] // chooses a random name from for the dog
So this is simple. but my problem is when I want some of the sames to have higher or lower chance, with 5 names is not that difficult to do this:
give WoofWoof much higher chance of getting chosen than the other names by doing this ugly mess:
var NAMES = ["Scafy","Shimshon","WoofWoof","Mitzy","AnotherDogName"]//possible names for the dogs
function choose(){
var random = Math.random()*100
var name = NAMES[0]
if (random>20)
name = NAMES[1]
if (random>30)
name = NAMES[2]
if (random>80)
name = NAMES[3]
if (random>90)
name = NAMES[4]
return name
}
This method works, but it's ugly, and becomes unbelievably complicated when there are a lot of options to choose from and many different chances.
I am sure than I am not the only one who had encounter this problem, and I feel like I'm missing a very elegant solution that hides just below my nose (I hope this sentence makes sense in english too)
This is a general question, I asked it in JS, but I have the same problem in any programming language.
My question is what's the most elegant way of doing it
Thank you
You wish to make your code look better and be more scalable? If so, this answer will help you.
//dog names and chances
var NAMES = [
{
name: "Scafy",
chance: 0.2
},
{
name: "Shimshon",
chance: 0.1
},
{
name: "WoofWoof",
chance: 0.5
},
{
name: "Mitzy",
chance: 0.1
},
{
name: "AnotherDogName",
chance: 0.1
}
]
//In chances dont add up to 1
var maxChance = 0;
for (let i = 0; i < NAMES.length; i++) {
maxChance += NAMES[i].chance;
}
function choose() {
//to make chance range fair.
var random = Math.random() * maxChance
var name;
//keeps track of were one is in the chancing
let randomTrack = 0;
//chancing
for (let i = 0; i < NAMES.length; i++) {
randomTrack += NAMES[i].chance;
if (random <= randomTrack) {
name = NAMES[i].name;
//stop when you dog got lucky
break;
}
}
return name;
}

Switching id names in javascript

Working on chess board using html and javascript. I am trying to add a function so that the user can flip the perspective of the board and running into a glitch that I understand, but can't figure out how to solve. Code as below....
function flipBoard(){
document.getElementById("a8").id = "h1";
document.getElementById("a7").id = "h2";
document.getElementById("a6").id = "h3";
document.getElementById("a5").id = "h4";
document.getElementById("a4").id = "h5";
document.getElementById("a3").id = "h6";
document.getElementById("a2").id = "h7";
document.getElementById("a1").id = "h8";
document.getElementById("h8").id = "a1";
document.getElementById("h7").id = "a2";
document.getElementById("h6").id = "a3";
document.getElementById("h5").id = "a4";
document.getElementById("h4").id = "a5";
document.getElementById("h3").id = "a6";
document.getElementById("h2").id = "a7";
document.getElementById("h1").id = "a8";
}
So.... I thought this would work just fine, but discovered that this wreaks havoc on my board by position half white, half black pieces on both sides of the board. The problem of course is that after the original "a1" square is renamed to "h8", there are now TWO "h8" squares, and at the end of the code it switches both back to "a1".
I have no idea how to get the id names to switch at the same time, otherwise I'd have to add a whole lot of code switching the id names to some third name as a place holder before switching them over to the desired name. Possible, but tedious and I feel there has to be a simpler way to do this.
Any ideas?
You can reduce the repetition of your current code by generating the id values programmatically in a loop:
function flipBoard(){
var a, h, aVal, hVal, aEl, hEl;
for(a = 8, h = 1; a > 0; --a, ++h) {
aVal = 'a' + a;
hVal = 'h' + h;
// Store off the current values
aEl = document.getElementById(aVal);
hEl = document.getElementById(hVal);
// swap them
aEl.id = hVal;
hEl.id = aVal;
}
}
demo fiddle
Save the reference to the element in variable. For example:
function flip(){
var aEight = document.getElementById("a8"),
hOne = document.getElementById("h1");
aEight.id = "h1";
hOne.id = "a8";
}
By separating out the steps of finding your elements and changing their ids, you'll easily be able to keep track of the flipped elements.

Attempt to filter array items that were recently used

Array.prototype.spil = function (x,max) {
if (this.length===max) {
this.shift();
this.push(x);
} else {
this.push(x);
}
return this;
}
var heard = [0],
freash = [];
$('#speak').bind('touchstart', function() {
var sounds = [
1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,
21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40
];
var temp = sounds;
for (var i=0; i<heard.length; i++) {
temp.splice(temp.indexOf(heard[i]), 1);
}
freash = temp;
var say = Math.floor(Math.random() * freash.length+1) + 1;
heard.spil(say,10);
say = document.getElementById('c'+say); // audio element
// use the sound...
});
My attempt to make the sound that plays 'an un-recent one' is not working! I want to make the last sound that played not play again for 10 button clicks.
heard is the array of sounds that you have already heard, this has a Array.spil function which will fill the array via push until it reaches its max length of ten when it will shift then push instead.
freash is the array of sounds with no members of the heard array present.
You can see that heard and freash are declared outside of the click (touchstart) scope.
If I click/tap over-and-over sometimes I am hearing sounds that have been played already much sooner than I am suppose to, often following each other.
This has been bothering me for days but, I can't see the problem in my logic. Can you?
I think this line
var say = Math.floor(Math.random() * freash.length+1) + 1;
should be
var say = freash[Math.floor(Math.random() * freash.length)];
Also consider the shortcut
var say = freash[Math.random() * freash.length | 0];

How to add multiples of a number and overwrite previous entry using js timing?

I am trying to create a function that continuously adds the same number to itself. Or simply displays multiples of one number every so many seconds with the setInterval method.
For now, let's just say I want to display multiples of ten.
I know how to get a regular while loop to simply display multiples of ten in a row, but what I want to do here is continually replace the previous text every time the function is called. I am trying to create a game and this is going to be the experience calculator. So it needs to display the total experience earned over the given time.
I was trying something along the lines of this:
window.setInterval(
function writeExp ()
{
var j;
while (rounded > 0)
{
var i = w*10;
var j = j + i;
}
document.getElementByID("exp").innerHTML=j;
}, experience)
This seems logical enough to me, but obviously something is wrong, as it does not work. I have tried googling various things like how to sum numbers in javascript or continuously sum, among others, but it is somewhat difficult to word to get it more centered to my needs. So this is the best way to get my questions answered.
There are lot of undefineds in your code, but general example would be
var interval = 1000,
result = 0,
elem = document.getElementByID("exp");
window.setInterval(function () {
result *= 10;
elem.innerHTML = result;
}, interval);
or without global variables
var interval = 1000,
multiply = function (elem) {
var result = 0;
return function () {
result *= 10;
elem.innerHTML = result;
}
};
window.setInterval(multiply(document.getElementByID("exp")), interval);

Simple javascript game, hide / show random square

I'm working on a simple game and I need some help to improve my code
So here's the game:
Some square show and hide randomely for a few seconds and you have to clic on them.
I use RaphaelJS to draw the square and a few of JQuery ($.each() function)
I work in a div, that's how I draw my squares (6 squares), x y are random numbers.
var rec1 = paper.rect(x, y, 50, 50).attr({
fill: "blue",});
Can I use for() to build my squares with a different var name for each one ?
I try with var = varName+i but it didn't work.
To hide and show the square I use two functions call with two setTimeout:
function box1() {rec1.show();}
function hidebox1() {rec1.hide();}
var time1 = setTimeout(box1, 1000);
var time1 = setTimeout(hidebox1, 2000);
I know it looks crappy...
I'm sure there is a way to use a toggle, or something more fancy to do that if you could help me finding it :) Because right now I have to do that for every square...
Thanks a lot for your help.
Your instinct to try to use varName plus some i to identify which varName you want is spot on, and JavaScript (like most languages) has that idea built in through what's called an array.
A simple one looks something like this:
var foo = [1, 5, 198, 309];
With that array, you can access foo[0] which is 1, or foo[3] which is 309.
Note two things: First, we identify which element of the array we want using square brackets. Second, we start counting at 0, not 1.
You can create an empty array like var varName = []; and then add new elements to it using varName.push( newValueToPutIn );
With those tools, you can now get at what you wanted. Now you can do something like:
var recs = [];
for(var i = 0; i < 100; i++) {
var rec = paper.rect(x, y, 50, 50).attr({fill: 'blue'});
recs.push(rec);
}
And recs[0] and recs[1] and so forth will refer to your various boxes.
For the first question, an array is the way to go.
For the second part, you could encapsulate the square and its show/hide stuff into a new anonymous object, like this:
var recs = [];
var numberOfRecs = 6;
for (var i = 0; i < numberOfRecs; i++) {
//determine x and y?
recs.push({
box: paper.rect(x, y, 50, 50).attr({ fill: "blue" }),
showBriefly: function(timeFromNow, duration) {
window.setTimeout(this.box.show, timeFromNow);
window.setTimeout(this.box.hide, timeFromNow + duration);
}
});
}
//show the 3rd box 1000 ms from now, for a duration of 1000 ms
recs[2].showBriefly(1000, 1000);

Categories

Resources