Snippet GetChance

kingkingyyk3

Visitor (Welcome to the Jungle, Baby!)
Reaction score
216
JASS:
library GetChance
/*
      Get Chance v1.0.4
        by kingking

  GetRandomInt/Real in warcraft 3 are commonly used to get the chance to trigger something, like effects.
  However, they are not precise.
  They will return close values sometimes.
  This has caused the chance is not so precise.
  This library is aimed to solve that.
  
  Usage :
  Chance.define(real probabilityToProc, integer weightage) -> Chance
  vars.getChance() -> boolean
  vars.reset() = Reset the allocated chance.
  set vars.probability = <probability>
  set vars.weightage = <weightage>
  
  It is a good idea for attaching this to units because allocated chances to return true are different.
  For best precision, probabilityToProc * weightage should be whole number.
  Weightage is the number for checking each loop.
  If you put 10 for it, then each 10 times of .getChance will reset the chance.

*/

    struct Chance
        private integer countdown
        private integer weight
        private integer procCount
        private real probably
        private integer left
        
        static method define takes real probabilityToProc, integer weightage returns thistype
            local thistype this = thistype.allocate()
            
            debug if weightage <= 0 then
                debug call BJDebugMsg("GetChance error! Invalid Weight found!")
                debug return 0
            debug endif
            
            set .probably = probabilityToProc
            set .procCount = R2I(probabilityToProc * weightage)
            set .weight = weightage
            
            return this
        endmethod
        
        method reset takes nothing returns nothing
            set .countdown = .weight
            set .left = .procCount
        endmethod
        
        method operator probability= takes real r returns nothing
            debug if r < 0. and r > 1. then
                debug call BJDebugMsg("GetChance error! Invalid Probability found!")
                debug return
            debug endif
            set .probably = r
            set .procCount = R2I(r * .weight)
        endmethod
        
        method operator weightage= takes integer i returns nothing
            debug if i <= 0 then
                debug call BJDebugMsg("GetChance error! Invalid Weight found!")
                debug return
            debug endif
            set .procCount = R2I(.probably * i)
            set .weight = i
        endmethod
        
        method getChance takes nothing returns boolean
            if .countdown == 0 then
                call .reset()
            endif
            if .probably == 1. then
                return true
            elseif .probably == 0. then
                return false
            endif
            set .countdown = .countdown - 1
            if .left > .countdown then
                return true
            endif
            if .left > 0 and GetRandomReal(0.,1.) <= .probably then
                set .left = .left - 1
                return true
            endif
            return false
        endmethod
    endstruct
    
    
endlibrary

UPDATES :
v1.0.0 : Initial Release.
v1.0.1 : Allow users to change probability and weightage freely.
v1.0.2 : Switched algorithm to array stack.
v1.0.3 : Switched algorithm to linked list.
v1.0.4 : Switched algorithm. Does not require preloading chance now and lot's faster(271% faster than v1.0.0).
v1.0.5 : Polished current algorithm by a small chance detecting, thus the distribution is better.
 

saw792

Is known to say things. That is all.
Reaction score
280
Wait, let me get this straight. You're solving the issue of 'randomness' by making everything pseudorandom?
 

Accname

2D-Graphics enthusiast
Reaction score
1,463
i dont see a point in this, for me random means random. if you use random and you get three times the same value that is the only prove that it really is random because you havent gotten what you were expecting.

if people dont like it they should not use it. if you want your random factors to be less random do some pseudo random if you like but please tell the users so instead of calling it random still because it aint anymore.
(yes i know there is no "random" in a computer, i dont want to start a discussion)
 

kingkingyyk3

Visitor (Welcome to the Jungle, Baby!)
Reaction score
216
Both of these solve the issue better than you do.
Why did you bother?

They are working on difference algorithm and interface.
Mine too.
Anyway, how did they solve the issue in better way?
 

Deaod

Member
Reaction score
6
For one, they dont use an algorithm with the possibility of infinite complexity.
Secondly, they can be more random or less random than your implementation.
Thirdly, your allocation algorithm for indices is off (starts at 2).

Yes, GetProc works with a different interface.
ChanceToProc, however, does not (besides the names).

Also, both offer retrieving the current probability, which yours does not (and can not, for technical reasons).

Did you try using a "weight" of 1 and a chance <1?

Edit: I forgot to mention that your library doesnt solve the issue of long streaks.
 

kingkingyyk3

Visitor (Welcome to the Jungle, Baby!)
Reaction score
216
For one, they dont use an algorithm with the possibility of infinite complexity.
Does not fail for me. :)
I have another algorithm, that's using linked list, which does not have this possibility.
But this solution is working well so far.
I shall switch to linked list until someone faced the problem.

Secondly, they can be more random or less random than your implementation.
Because of different algorithm. No randomie at here, because this library is not for random chances, but for the exact numbers to proc.

Did you try using a "weight" of 1 and a chance <1?
It will return 0.0. Why would you put this value? LOL. I mentioned it in demo spell's script, the probability * weightage should be whole number, for best precision.
 

Deaod

Member
Reaction score
6
Does not fail for me.
Try using 0.99 probability, and 100 "weight". If you want more, use 0.99 and 1000 weight. Enjoy your thread crash.

No randomie at here, because this library is not for random chances, [...]
This library is nothing more than caching random numbers. Its still random, only that (EDIT: removed "before") you know the result before you actually need it.

Why would you put this value? LOL.
Because im a dumbass who wants to break your library. If i can break it intentionally, chances are that others will break it unintentionally and wonder why things dont work. You should make sure users cant break your libraries, even intentionally.
I mentioned it in demo spell's script, the probability * weightage should be whole number, for best precision.
Well how about you mention it where it actually matters? Like in the description of your library?
 

Deaod

Member
Reaction score
6
Okay, heres a benchmark.

Just a few conclusions: GetProc and GetChance beat the shit out of each other trying to place last in benchmarks. Using GetProc, you get one random bit of information at the cost of 0.045ms.
Using GetChance, you get one random bit of information at the cost of anything between 0.020ms and 0.050ms. Interestingly, using what the demo suggests (chance 1./3 and weight 3) yields the 0.050ms result. What to do against that? Simple, increase the weight. But then whats the fucking point of this library? GetProc ensures the distribution of streaks is not as random as it could be (look at the first post of its thread on wc3c, theres some test data there). GetChance does....nothing? Seriously, if its going to be slower than GetProc, then you could use GetProc, but if you increase the weight, it essentially becomes a slower wrapper around GetRandomInt().
Interestingly, ChanceToProc beats the crap out of both of them with 0.016ms per bit of information. If only it had a better interface.

Also, using a negative probability or a probability greater than 1 makes this library crash the thread its running on. Oh, and rounding errors are going to kill your libraries purpose.

You also failed to properly respond to the infinite (computational) complexity point i brought up (which btw, accounts for most of your speed loss at very high probabilities and weights). Its like throwing all pieces of a puzzle into the air, hoping they will assemble in mid air and drop to the ground as the finished puzzle. Its simply bogus.

Seriously, drop this and use other peoples resources.
 

Attachments

  • GetChanceTest.w3m
    24.3 KB · Views: 295

kingkingyyk3

Visitor (Welcome to the Jungle, Baby!)
Reaction score
216
Updated, changed algorithm to array stack.

Just a few conclusions: GetProc and GetChance beat the shit out of each other trying to place last in benchmarks. Using GetProc, you get one random bit of information at the cost of 0.045ms.
Using GetChance, you get one random bit of information at the cost of anything between 0.020ms and 0.050ms. Interestingly, using what the demo suggests (chance 1./3 and weight 3) yields the 0.050ms result.

Have you tried to benchmark the inlined code? Frankly speaking, speed isn't anything. Functionality takes over speed.
 

Deaod

Member
Reaction score
6
New Tests. As the new algorithm included no collision detection, i added it myself (without touching the original code, when not testing for collisions). This also means that whenever you now get a collision, the Data set would have been corrupted (not enough "true"). For example: probability 0.8, data set size 100 yields an average of 6 collisions. That means, the algorithm would insert only 79 to 74 true values instead of the desired 80 (on average).

This can also be replicated using probability 0.8 and data set size 10. Less collisions occur when using 5, but there still are collisions.

If you use a chance of 1 and data set size of 10, the collision detection will cause a crash (that means the data is corrupted beyond repair) about 60% of the time. A data set size of 100 results in 100% crashs (as far as i could tell).

I still think this library is superfluous. We already have two other libraries to make random less random and redistribute chance so that long streaks occur less frequently.

EDIT:
1.0.3 still has collisions (mostly due to chainRemove not working as it should). I can upload a testmap once i get access to my own PC again.
 

Attachments

  • GetChanceTest.w3m
    25.4 KB · Views: 321

kingkingyyk3

Visitor (Welcome to the Jungle, Baby!)
Reaction score
216
Ok, updated to v1.0.4. It is super fast(Faster than GetProc) and returns precise value now.
 

Deaod

Member
Reaction score
6
Again, this library shouldnt exist, as there are already two other libraries doing what i assume this library tries to do, but in a better way.

Besides that, the algorithm this version uses is bullcrap. Think about what will happen if you use a probability thats either very high or very low.
 

kingkingyyk3

Visitor (Welcome to the Jungle, Baby!)
Reaction score
216
Your documentation doesn't explain weight.
"GetRandomInt/Real in warcraft 3" being "not precise" is not explained.

Okay.
 

Deaod

Member
Reaction score
6
Thats IT? Thats all you could find wrong with this library? Are you kidding me?

Alright, since noone else can do the math, heres how this works:
JASS:
        method getChance takes nothing returns boolean
            if .countdown == 0 then
                call .reset()
            endif
            if .probably == 1. then
                return true
            elseif .probably == 0. then
                return false
            endif
            set .countdown = .countdown - 1
            if .left &gt; .countdown then
                return true
            endif
            if .left &gt; 0 and GetRandomInt(0,1) == 0 then
                set .left = .left - 1
                return true
            endif
            return false
        endmethod

countdown is the data set size (he calls it weight). Its decremented by one every time getChance is called. When it reaches 0 its set to "weight" again.
.left is the number of "true"s getChance has yet to return before .countdown reaches 0.
[ljass]if .left > 0 and GetRandomInt(0,1) == 0 then[/ljass]
This is where the algorithm fails so much. A 50% probability regardless of probability you passed to the Chance instance. That means when you have a 99% probability and a data set size of 100, you are most likely to have the one "false" as one of the first 6 generated values. 50%^7 is already less than the 1% probability youd have, had you simply used GetRandomReal.
Thats a bit of an extreme example, but how about a 25% chance. Again, let data set size be 100. The first 50 values are going to be 50% true and 50% false. But you only have 25 "true"s to distribute. So youre very unlikely to have any "true" in the last 50 values you generate.
Now, lets take a prime, like 29, 23, 19 or 13. If you want to have accurate results (to the extent possible for this library), youre going to have to use a data set size of 100. Same thing happens. Youre going to have most "true"s in the first half of all generated values and almost zero in the second half.
That, in my book, is worse than the default GetRandomReal. Take a chance of 19%, youre going to have a streak of more than 50(!!) "false", before you get another "true" again (while better implementations allow streaks of 10 or so at most, depending on weight).

It can work rather well for all probabilities p=1/n;n is element of {1,2,3,4,...}, but thats about it.
Edit: But its not like its the only library of its kind that can work well with such probabilities. GetProc and ChanceToProc do work well too, PLUS they can handle all probabilities correctly.
Edit, the 2nd: This library can also work well with probabilities p=n-1/n;n is element of {1,2,3,4,...}.
 

Jesus4Lyf

Good Idea™
Reaction score
397
Thats IT? Thats all you could find wrong with this library? Are you kidding me?

Alright, since noone else can do the math, heres how this works:
Thank you for your helpful explanation. Actually, my issue was not with understanding the math, it was with wondering why you'd implement something like this in the first place. :)
The other two points were regarding the code being broken.

I need him to fix those things before I can review the resource at all. It allows me to see whether or not a resource is justified in the first place, and what the interface to it should be if it is. Then we can look at how he implements it... :thup:

(At the moment, this is an incoherent mess to me.)
 
General chit-chat
Help Users
  • No one is chatting at the moment.
  • Ghan Ghan:
    Howdy
  • Ghan Ghan:
    Still lurking
    +3
  • The Helper The Helper:
    I am great and it is fantastic to see you my friend!
    +1
  • The Helper The Helper:
    If you are new to the site please check out the Recipe and Food Forum https://www.thehelper.net/forums/recipes-and-food.220/
  • Monovertex Monovertex:
    How come you're so into recipes lately? Never saw this much interest in this topic in the old days of TH.net
  • Monovertex Monovertex:
    Hmm, how do I change my signature?
  • tom_mai78101 tom_mai78101:
    Signatures can be edit in your account profile. As for the old stuffs, I'm thinking it's because Blizzard is now under Microsoft, and because of Microsoft Xbox going the way it is, it's dreadful.
  • The Helper The Helper:
    I am not big on the recipes I am just promoting them - I use the site as a practice place promoting stuff
    +2
  • Monovertex Monovertex:
    @tom_mai78101 I must be blind. If I go on my profile I don't see any area to edit the signature; If I go to account details (settings) I don't see any signature area either.
  • The Helper The Helper:
    You can get there if you click the bell icon (alerts) and choose preferences from the bottom, signature will be in the menu on the left there https://www.thehelper.net/account/preferences
  • The Helper The Helper:
    I think I need to split the Sci/Tech news forum into 2 one for Science and one for Tech but I am hating all the moving of posts I would have to do
  • The Helper The Helper:
    What is up Old Mountain Shadow?
  • The Helper The Helper:
    Happy Thursday!
    +1
  • Varine Varine:
    Crazy how much 3d printing has come in the last few years. Sad that it's not as easily modifiable though
  • Varine Varine:
    I bought an Ender 3 during the pandemic and tinkered with it all the time. Just bought a Sovol, not as easy. I'm trying to make it use a different nozzle because I have a fuck ton of Volcanos, and they use what is basically a modified volcano that is just a smidge longer, and almost every part on this thing needs to be redone to make it work
  • Varine Varine:
    Luckily I have a 3d printer for that, I guess. But it's ridiculous. The regular volcanos are 21mm, these Sovol versions are about 23.5mm
  • Varine Varine:
    So, 2.5mm longer. But the thing that measures the bed is about 1.5mm above the nozzle, so if I swap it with a volcano then I'm 1mm behind it. So cool, new bracket to swap that, but THEN the fan shroud to direct air at the part is ALSO going to be .5mm to low, and so I need to redo that, but by doing that it is a little bit off where it should be blowing and it's throwing it at the heating block instead of the part, and fuck man
  • Varine Varine:
    I didn't realize they designed this entire thing to NOT be modded. I would have just got a fucking Bambu if I knew that, the whole point was I could fuck with this. And no one else makes shit for Sovol so I have to go through them, and they have... interesting pricing models. So I have a new extruder altogether that I'm taking apart and going to just design a whole new one to use my nozzles. Dumb design.
  • Varine Varine:
    Can't just buy a new heatblock, you need to get a whole hotend - so block, heater cartridge, thermistor, heatbreak, and nozzle. And they put this fucking paste in there so I can't take the thermistor or cartridge out with any ease, that's 30 dollars. Or you can get the whole extrudor with the direct driver AND that heatblock for like 50, but you still can't get any of it to come apart
  • Varine Varine:
    Partsbuilt has individual parts I found but they're expensive. I think I can get bits swapped around and make this work with generic shit though
  • Ghan Ghan:
    Heard Houston got hit pretty bad by storms last night. Hope all is well with TH.
  • The Helper The Helper:
    Power back on finally - all is good here no damage
    +2
  • V-SNES V-SNES:
    Happy Friday!
    +1

      The Helper Discord

      Members online

      No members online now.

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top