CodingForums.com

CodingForums.com (http://www.codingforums.com/index.php)
-   JavaScript programming (http://www.codingforums.com/forumdisplay.php?f=2)
-   -   item generator with percentage variable (http://www.codingforums.com/showthread.php?t=286251)

komichi 01-22-2013 08:59 PM

item generator with percentage variable
 
I want learn how to make a javascript for an RPG where it generates and display a specific item, but the generation process is controlled by the percentage variable for items in certain category.

also, aside from the quality, and item type, it'd be nice if you could input a number in and it will also generate the item level from 3- to +3 (controlled by percentage) and display the number at the end modified by the aforementioned modifiers

For example, it might look something like

Enter 53, hit generate

Common: .30
Rare: .10

Armor Category (gloves, shoes, chest): .50
Weapon Category (sword, shield): .49

-3: .60
0: .40
+3: .30

Generated item: Common Glove ilvl. 50 (53-3)

Edit: Could anyone point me to where I might be able to learn how to make this?

WolfShade 01-22-2013 09:00 PM

These forums are generally for helping to troubleshoot problematic code, not for freebies.

komichi 01-22-2013 09:11 PM

Quote:

Originally Posted by WolfShade (Post 1308019)
These forums are generally for helping to troubleshoot problematic code, not for freebies.

Could I ask where I might find tutorials on how to do this then?

Old Pedant 01-22-2013 10:02 PM

You tell us the mathematical formulas you will use and we can tell you how to convert them into JavaScript code.

But without the math, there is no possible way for us to guess what you are trying to do.

komichi 01-22-2013 11:46 PM

Code:

<script type = "text/javascript">

var rarity =
[ "common ", "uncommon ", "rare "];

var weapons =
[ "sword ", "bow ", "staff "];

document.write (rarity[Math.floor( Math.random() * 3 )]);

document.write (weapons[Math.floor( Math.random() * 3 )]);

</script>

Here's a basic generator, but right now it's fully random, I want to control the rate of generation via probability.

like the probability of generating common is 60% or the probability of generating sword is 50%

I want to add the probability to both rarity and weapon var

also, is it possible to assign a universal probability of being generated to a group of items?

Old Pedant 01-23-2013 01:35 AM

Quote:

Originally Posted by komichi (Post 1308043)
I want to control the rate of generation via probability.
...
is it possible to assign a universal probability of being generated to a group of items?

And I say again: SHOW us some *ACTUAL* examples.

I will show you *one* example:
Code:

var rarityNum = Math.floor( 1 + Math.random() * 100 );
var rarity;
if ( rarityNum > 95 ) { rarity = "rare"; }
else if ( rarityNum > 65 ) { rarity = "uncommon"; }
else { rarity = "common"; }

Of you could do it thus:
Code:

var rarityNum = Math.floor( 1 + Math.random() * 100 );
var rarity = ( rarityNum > 95 ) ? "rare"
          : ( rarityNum > 65 ) "uncommon"
          : "common";

Naturally you can control the numbers (here 95 and 65) as you want.

rarityNum, as I coded it, will be a number form 1 to 100.

So also as coded, there is a 5% chance you will get "rare", 30% chance for "uncommon", and 65% chance for "common".

jmrker 01-24-2013 12:52 AM

Quote:

Originally Posted by Old Pedant (Post 1308058)
Of you could do it thus:
Code:

var rarityNum = Math.floor( 1 + Math.random() * 100 );
var rarity = ( rarityNum > 95 ) ? "rare"
          : ( rarityNum > 65 ) "uncommon"
          : "common";

Naturally you can control the numbers (here 95 and 65) as you want.

rarityNum, as I coded it, will be a number form 1 to 100.

So also as coded, there is a 5% chance you will get "rare", 30% chance for "uncommon", and 65% chance for "common".

I think you missed one little '?' in your last example. ;)
Code:

<script type="text/javascript">
var rarityNum = Math.floor( 1 + Math.random() * 100 );
var rarity = ( rarityNum > 95 ) ? "rare"
          : ( rarityNum > 65 ) ? "uncommon"
          : "common";
alert(rarity)
</script>

Looks like it's not only my lighting fast phalanges that can get away from me. :D

Old Pedant 01-24-2013 01:10 AM

I will blame it on my eyes. Better than blaming it on my old brain. (Never mind that the eyes are roughly the same age as the brain.)

rnd me 01-24-2013 02:40 AM

Quote:

Originally Posted by komichi (Post 1308043)
Here's a basic generator, but right now it's fully random, I want to control the rate of generation via probability.
like the probability of generating common is 60% or the probability of generating sword is 50%

one simple way is to simply build an array of the options, and repeat the items you want to be more common than others:

Code:

// helper function: random slot from array grabber:


// our dice-roll outcomes (some happen more often)
var rarity =[ "common",  "common",  "common",  "uncommon", "rare"];
var weapons =[ "sword",  "sword",  "bow",  "staff "];

// show a random pull using all the list's overlaped probabilities:
alert(  rarity.random() );

now, all things being equal, a sword will hit 50% of the time, bow 25%, and staff 25%, common 60%, uncommon 20%, and rare 20%...

EDIT:
we can indeed calculate many-item probabilities using existing data and a little math. buckle your seatbelt:

Code:

Array.prototype.random=function random(){
  function Rnd(w){return parseInt(Math.random()*(w+1));}
 return this[Rnd(this.length-1)];
};

Array.prototype.counts=function(name){
  var ob={};
  this.forEach(function(a){ ob[a]=ob[a]?(ob[a]+1):(ob[a]=1); });
 return name ? ob[name] : ob;
};



function combinedProb(rareness, weapon){
  return (rarity.counts(rareness) / rarity.length) *
      (weapons.counts(weapon) / weapons.length);
}


var rarity =[ "common",  "common",  "common",  "uncommon", "rare"];
var weapons =[ "sword",  "sword",  "bow",  "staff "];

combinedProb("common", "sword");//0.3
combinedProb("common", "bow");//0.15
combinedProb("rare", "bow");//0.05

in this fashion, we don't have to hand-code numbers or maintain tables of figures, we can just paste item names and let JS to the rest of the work.


edit2:

if you are using it a lot (hundreds of times or more) it might be worth it to pre-calc all the combined probabilities for instant lookup instead of on-demand calculation:
Code:

Array.prototype.counts=function(name){
  var ob={};
  this.forEach(function(a){ ob[a]=ob[a]?(ob[a]+1):(ob[a]=1); });
 return name ? ob[name] : ob;
};

function combinedProb(rareness, weapon){
  return (rarity.counts(rareness) / rarity.length) *
      (weapons.counts(weapon) / weapons.length);
}

var rarity =[ "common",  "common",  "common",  "uncommon", "rare"];
var weapons =[ "sword",  "sword",  "bow",  "staff "];


var combined={}; //the table of combined probs

//populat prob table using all possible combos of rarity and weapons:
rarity.forEach(function(r){
  var x=combined[r]={};
  weapons.forEach(function(w){
    x[w]=combinedProb(r,w);
  });
});

//now, we can use the combined object to instantly lookup combos:

combined.common.sword //0.3
combined.common.bow //0.15
combined.rare.bow //0.05

this not only performs faster, it allows the developer to skip the extra quotes around the names, and avoids the parens, making it more letters than syntax, all in all: a lot less typing on a complex application.

Old Pedant 01-24-2013 07:02 AM

But a big problem with this approach is the *granularity*.

Just to pick the example you used, if we wanted "rare" to be 1%, and still assuming the same 3 weapons (4 occurrences), we would need 20 values in the rarity array.

And *still* combined.rare.sword would be 2% instead of 1%.

And so on.

I think I would opt for a much simpler yet more flexible system:
Code:

var weapons = {
    "sword" : [ 70, 28, 2 ],
    "bow" : [ 60, 30, 10 ],
    "staff" : [ 80, 19, 1 ]
};

where the 3 numbers are the percentage chances that a given weapon will be common, uncommon, or rare.

Completely flexible: You can decide what "rare" means on a per-weapon basis *and* you can easily see the distribution *and* you can easily change it.

Changing the distribution with RndMe's dual array system might turn into a real challenge to get the numbers you actually want.

rnd me 01-24-2013 10:29 AM

Quote:

Originally Posted by Old Pedant (Post 1308370)
But a big problem with this approach is the *granularity*.

Just to pick the example you used, if we wanted "rare" to be 1%, and still assuming the same 3 weapons (4 occurrences), we would need 20 values in the rarity array.

it doesn't matter how many values are in the array, so long as we don't have to code them like we would with some sort of table of numbers.

you can easily get to the single-percent level.

if you want 1% rare and the rest to be the same, the only piece you need to touch is the rarity array.

i'd imagine you want 75 common, 24 uncommon, and 1 rare:
Code:

rarity= String([
  Array(75).join("common,"),
  Array(24).join("uncommon,"),
  "rare"
]).split(/,+/);


Old Pedant 01-24-2013 07:44 PM

And you really thing that is simpler and easier to understand than my table-based scheme?

Hmmm...maybe now I understand some of your coding better.

No, that was a joke. Your coding is top notch. But I do think that, in this case, your solution is too esoteric. Ehhh...one man's meat is another man's poisson distribution.

rnd me 01-25-2013 02:35 PM

Quote:

Originally Posted by Old Pedant (Post 1308525)
And you really thing that is simpler and easier to understand than my table-based scheme?
.

it's not easier to understand, it's easier to maintain. in a table, adding a new class or changing a value almost guarantees that you'll need to edit several cells to "reCalc" the table.

with an iterative counter, you let the JS do the work.

i admit the tokens are a little simplistic for precise or complex calculations, but for many simple problems, it's a workable design pattern.


you can use an object instead of an array, you would have to sum all the values in the object, and then you have the same info as my item counter:


Code:


// util pure functions:
function sum(a,b){return a+b;}
function lut(key){return this[key];}


//object-based calculator:
function combinedProb(rareness, weapon){
  return (rarity[rareness] / rarity.sum) *
      (weapons[weapon] / weapons.sum);
}

//new data structure:
var rarity ={ common: 6,  uncommon:2, rare:2 };
var weapons ={ sword:4, bow:2,  staff:2 };

//pre-calc the whole to assist calcing the part each time:
rarity.sum=Object.keys(rarity).map(lut,rarity).reduce(sum);
weapons.sum=Object.keys(weapons).map(lut,weapons).reduce(sum);


//test it:
combinedProb("common", "staff"); //0.15
combinedProb("uncommon", "staff"); //0.05
combinedProb("common", "sword"); //0.3


Old Pedant 01-25-2013 08:19 PM

I like this better.
Code:

//new data structure:
var rarity ={ common: 6,  uncommon:2, rare:2 };
var weapons ={ sword:4, bow:2,  staff:2 };

It "reads" clearer (to me, at least!) and feels easier to make changes to. Actually, amazing how such a relatively minor rewrite helps the clarity so much.

But it still requires the user to understand the combinatorial math. Not at all difficult, but probably too much for a lot of the newbies we get here.

007julien 01-26-2013 11:31 AM

A simple remark for @rnd me : Array(75).join("common,") build a string with 74 (and not 75 !) common, in the intervals of the 75 leer array's elements !


All times are GMT +1. The time now is 03:15 AM.

Powered by vBulletin®
Copyright ©2000 - 2013, Jelsoft Enterprises Ltd.