shiroroku / DMCLoot

A Minecraft Mod that adds various RPG-like affixes to tools, weapons, and armor!
MIT License
2 stars 1 forks source link

[Game Balance] Rarity doesn't seem to match labels #4

Open AngleWyrm10 opened 3 years ago

AngleWyrm10 commented 3 years ago

After over 200 rolls of this particular form of dice, this is what I got: outcome

Whereas this is more what I thought would happen: Distributions

shiroroku commented 3 years ago

maybe my random code is wrong, can check it here: https://github.com/shiroroku/DMCLoot/blob/1db4b9a70a7a09b6416283f4be80b51c39c1ea16/src/main/java/com/dmcloot/Util/ModifierHelper.java#L24

im not real familiar with distributions and stuff, the current weight config is mostly a placeholder.

AngleWyrm10 commented 3 years ago

Ok, thank you for allowing me to assist in the development of this part of your mod. I've forked the code to study how and where the rarity generation system interacts with the rest of the code. I've got a preliminary sketch for you that I believe will have minimal changes and also be lag-free.

Proposal: A Spin the Wheel arrangement

Since each rarity has a chance weight, we can create a new static list in Utils/ModifierHelper, rarityLibrary, containing ModifierRarity objects. In that list is multiple copies of each rarity, according to their chance weight.

For example if RARE_WEIGHT happens to be 9, there will be 9 copies of ModifierRarity with name=RARE in the rarityLibrary. So the length of the list will also be the sum of all the different types of rarity chance weights.

It is then possible with a single roll of rand() to fetch a rarity with the probabilities specified by their chance weights.

This would depreciate the use of getRandomWeightedRarity and getRandomRarityWithWeights in favor of a new function, getRandomRarity which has a very simple internal of just grabbing a randomly indexed item from the library:

return rarityLibrary[ Random.nextInt(rarityLibarary.length()) ]

Additionally, I'd like to suggest that EMPTY_AFFIX_CHANCE be changed to a ModifierRarity object with a chance weight instead of a percent float. Then it can also be put in the rarityLibrary so all possible outcomes are the result of a single roll of the dice.

shiroroku commented 3 years ago

i agree with the empty affix chance thing, will look into that. though i dont understand how that is different than the weighted function i have. say if only epic and common have a weight of 2, then they both have 50% chance of being chosen. same as if you added 2 epic and 2 common to a list and chose at random.

AngleWyrm10 commented 3 years ago

[ Post edited because I just can't help myself XD ]

How is it different

It is faster because it does it's loops during construction instead of when called. It also handles some edge cases well, but none of that is critical, merely pretty.

I think it depends on personality: I'm the type that is never really content with my work, always fussing with it, improving it. It's something I like about software development, and game systems that include upgrade paths often appeal to me. But I recognize there are other psychological developmental pathways. Some take the a form akin to the strategy expressed as 'A good plan today is better than a great plan tomorrow,' and that's effective for production.


Here is what I've done today towards getting the mod to produce a curve of rarites that seems to match the labels closer than the current default weights:

I looked at the distribution in the first post that shows chance weights for the outcomes of rolling three six-sided dice. Since that is a naturally occurring chance curve, it seemed like a good place to start.

So I mapped those chance weights to the rarities in this mod's config file: 1 -> Mythic 3 -> Legendary 6 -> Epic 10 -> Rare 15 -> Uncommon 21 -> Common

To test if the system actually produced what was requested, I added the chance weights up (56) and figured that on average each time I draw 56 items they should be distributed according to those chance weights. The tests went well, with some expected and desirable variance due to randomness.

So if a 1 in 56 items chance seems like a reasonable setup for Mythic items in Minecraft, the above mapping works well for default values of the chance weights. If you want Mythic to occur more or less often than once in 56 items, there's a formula for that.

AngleWyrm10 commented 3 years ago

A formula to scale chance weights:

Given the example set of 56 chance weights, {1, 3, 6, 10, 15, 21} we wish to alter the probabilities of the most extreme case, which currently has 1/56 chance of being the randomly selected outcome. Let's say for the sake of example that testing shows it's occurrence to be too frequent, and instead we want it to appear with a frequency of 1/500.

Step 1: Scale the set of chance weights so there's 500 of them 500/56 × {1, 3, 6, 10, 15, 21} = {125/14, 375/14, 375/7, 625/7, 1875/14, 375/2}

But these aren't integer chance weights. So in order to convert the set to integers and still maintain their relative proportions to one another, we multiply by the greatest common divisor, which happens to be the denominator of the extreme value, 14.

Step 2: Scale up to an integer multiple 14 × {125/14, 375/14, 375/7, 625/7, 1875/14, 375/2} = {125, 375, 750, 1250, 1875, 2625}