• New Horizons on Maelstrom
    Maelstrom New Horizons


    Visit our website www.piratehorizons.com to quickly find download links for the newest versions of our New Horizons mods Beyond New Horizons and Maelstrom New Horizons!

Solved Random or Quasi Random Numbers?

Pieter Boelen

Navigation Officer
Administrator
Storm Modder
Hearts of Oak Donator
Last week I learned about the concept of "quasi-random numbers" as opposed to truly or near-random ones.
Whereas with a truly random number, the result of a "dice roll" does not depend on the previous roll, that is NOT the case with quasy-random ones.

So with quasi-random, if a random number between 0 and 1 returned something HIGHER than 0.5 the first time it is called, the second time it is much more likely that a number LOWER than 0.5 is returned.
For REAL random numbers, the chance of higher/lower than 0.5 doesn't ever change; that is always 50%.
That is what I understand of it anyway.

I started wondering if this may be affecting our game in some ways way.
For example, there is the report of "the wind always coming from the wrong direction".
And I noticed that if I started the game as Jean Lafitte, it seems that I end up on Puerto Rico much more often than on Nevis, even though the chance should be 50%.

So is our game using quasi-random numbers that we are using as if they are truly random?
And is that making various systems that are intended to be independent actually be somewhat predictable?
Or are all these observations just a load on nonsense and this is just Murphy's Law at work?

And if we ARE dealing with quasi-random numbers that are messing us up, how can we use those to generate more truly random numbers?

Just a thing I was wondering about... :shrug
 
For example, there is the report of "the wind always coming from the wrong direction".
THIS! Wherever I sail, the wind always blows into front side of the ship on world map, it's sooo annoying. Seriously, you'd expect that wind is blowing in all directions, or in one constant direction depending on part of the year (or day, temperature or so), but nooo, it's always just coming from "wrong direction" just to slow you down.
I tried to sail with the wind, and while sailing with it, it changes faster than when sailing against it. I didn't actually measure time while doing it, so it might be subjective feeling, maybe we feel bad things more powerfully than good thing or something. Or we have quasi random numbers messing with us.
 
THIS! Wherever I sail, the wind always blows into front side of the ship on world map, it's sooo annoying. Seriously, you'd expect that wind is blowing in all directions, or in one constant direction depending on part of the year (or day, temperature or so), but nooo, it's always just coming from "wrong direction" just to slow you down.
I tried to sail with the wind, and while sailing with it, it changes faster than when sailing against it. I didn't actually measure time while doing it, so it might be subjective feeling, maybe we feel bad things more powerfully than good thing or something. Or we have quasi random numbers messing with us.
We do have an issue related to this: http://www.piratesahoy.net/threads/wind-direction-and-storm-occurance-in-3d-sailing-mode.24386/
But so far no progress on it as we don't know why it even seems to do that. o_O
 
This is one of the reasons i try to have random chance depend on large numbers do you wouldnt notice it that often. But we could do some tests. I will post some results soon.
 
The frand (returns random number between 0 and 1) is defined in the PROGRAM folder:
Code:
float FRAND(float _x) { return rand(32768) / 32768.0 * _x; }

The rand one itself is probably a native game function that we cannot see or edit.
We might be able to have a look in the CoAS source code to see what it actually does.

What if we make a new function named irand and replace all calls to rand with that one.
Then to get a random number, we could have it try a random number of times before returning a value.
Might not help performance, but should at least make things more random. Maybe?
 
you could for example do something like this:

Code:
irand(int num)
{
 return sqrt(rand(num)*rand(num))
}

But I have no idea if that would work.

But to me it seems like its doing quite fine.
I used this code
Code:
int randtest = 9;
    int max = 10000;
    string attr;
    for(int n=0; n<=randtest; n++) {
        attr = n;
        PChar.testrand.(attr) = 0;
    }
    for(n=0; n<max; n++) { 
        attr = makeint(rand(randtest));
        PChar.testrand.(attr) = sti(PChar.testrand.(attr)) + 1;
    }
    aref nums; makearef(nums, PChar.testrand);
    for(n=0; n<=randtest; n++) {
        int amount = sti(GetAttributeValue(GetAttributeN(nums, n)));
        trace("num: "+n+" occurs "+amount+" times");
    }

These results are given:
Code:
num: 0 occurs 1006 times
num: 1 occurs 978 times
num: 2 occurs 1073 times
num: 3 occurs 1033 times
num: 4 occurs 1018 times
num: 5 occurs 981 times
num: 6 occurs 971 times
num: 7 occurs 981 times
num: 8 occurs 987 times
num: 9 occurs 972 times

Also with 100 numbers and doing it 100000 times you would expect them all to be 1000, the larges derivation I could find was 937 which is about a 6% derivation. That's not that bad for an rng....
Also for larger number it doesn't seem like there is some kind of distribution, the derivations are all over so I'd say the rng for potc is quite good.
 
Many years ago I wrote a golf game which used the rand function (which in the program language used was quasi-random). It had the ability to start from a seed number, as I believe C++ does too. I set the seed first but the had the programme overwrite it on the disk when called so that the next start would be a different sequence.
I would have thought in POTC with some many variables and events that calls to the random function would soon diverge from a recognisable pattern, but if you always play the same way especially at the start you will have a tendency to see repeat "random" chances.

In my golf game I made the mistake of writing the new seed just with a save so one bright spark just worked through his chosen shot(s) remembering them if they were good but crashing the game when it went not quite right until he could work through to the "perfect" round. It takes all sorts! In this case because the seed did not change his game repeated exactly because the "random" element followed the same pattern.

So does srand work to set a seed (as in C++) in POTC and if so what dynamic variable is available in game that would be different each start (usually a call to get real time) - perhaps something based on the many choices (ship,character,nation,flag etc intertwined ) - although for the same choices it would then be the same pattern until something changed
 
@Levis: I'm quite willing to believe that each number occurs an approximate equal number of times.
That happens for quasi-random numbers too.

But what I would want to know is what is the occurrences of, for example, a "1" being followed by another "1".
For truly random, this chance should the same as for any other number.
But for quasi-random, I think the chance of the same numbers following each other repeatedly would be really low.

Not sure of that one though....
 
So does srand work to set a seed (as in C++) in POTC and if so what dynamic variable is available in game that would be different each start (usually a call to get real time) - perhaps something based on the many choices (ship,character,nation,flag etc intertwined ) - although for the same choices it would then be the same pattern until something changed
Not sure if we can manually set the seed anywhere. That's probably one of those hidden engine things. :facepalm
 
Can't test this now, but say you do something like this:
Code:
int randtest = 9;
int max = 10000;
int old = 0;
int new = 0;
string attr;
for(int n=0; n<=randtest; n++) {
attr = n;
PChar.testrand.(attr) = 0;
}
for(n=0; n<max; n++) {
new = makeint(rand(randtest));
attr = new- old;
old = new;
PChar.testrand.(attr) = sti(PChar.testrand.(attr)) + 1;
}
aref nums; makearef(nums, PChar.testrand);
for(n=0; n<=randtest; n++) {
int amount = sti(GetAttributeValue(GetAttributeN(nums, n)));
trace("num: "+n+" occurs "+amount+" times");
}

This way you will measure the difference between the previous and current random nummer. If it's a true random number generator these differences should also be distributed equally right?

else there should be more info here:
http://c2.com/cgi/wiki?UnitTestingRandomness
 
Code:
Value 0 occurs 107 times 
Value 1 occurs 107 times 
Value 2 occurs 99 times 
Value 3 occurs 93 times 
Value 4 occurs 107 times 
Value 5 occurs 109 times 
Value 6 occurs 104 times 
Value 7 occurs 91 times 
Value 8 occurs 93 times 
Value 9 occurs 93 times 
Value 10 occurs 101 times 
Value 11 occurs 104 times 
Value 12 occurs 101 times 
Value 13 occurs 86 times 
Value 14 occurs 103 times 
Value 15 occurs 85 times 
Value 16 occurs 90 times 
Value 17 occurs 104 times 
Value 18 occurs 76 times 
Value 19 occurs 117 times 
Value 20 occurs 90 times 
Value 21 occurs 97 times 
Value 22 occurs 103 times 
Value 23 occurs 104 times 
Value 24 occurs 98 times 
Value 25 occurs 98 times 
Value 26 occurs 88 times 
Value 27 occurs 94 times 
Value 28 occurs 90 times 
Value 29 occurs 94 times 
Value 30 occurs 104 times 
Value 31 occurs 110 times 
Value 32 occurs 88 times 
Value 33 occurs 92 times 
Value 34 occurs 110 times 
Value 35 occurs 107 times 
Value 36 occurs 107 times 
Value 37 occurs 111 times 
Value 38 occurs 94 times 
Value 39 occurs 85 times 
Value 40 occurs 107 times 
Value 41 occurs 86 times 
Value 42 occurs 107 times 
Value 43 occurs 105 times 
Value 44 occurs 111 times 
Value 45 occurs 109 times 
Value 46 occurs 96 times 
Value 47 occurs 103 times 
Value 48 occurs 88 times 
Value 49 occurs 87 times 
Value 50 occurs 86 times 
Value 51 occurs 103 times 
Value 52 occurs 103 times 
Value 53 occurs 106 times 
Value 54 occurs 89 times 
Value 55 occurs 107 times 
Value 56 occurs 115 times 
Value 57 occurs 90 times 
Value 58 occurs 102 times 
Value 59 occurs 103 times 
Value 60 occurs 95 times 
Value 61 occurs 114 times 
Value 62 occurs 107 times 
Value 63 occurs 117 times 
Value 64 occurs 103 times 
Value 65 occurs 99 times 
Value 66 occurs 91 times 
Value 67 occurs 81 times 
Value 68 occurs 106 times 
Value 69 occurs 101 times 
Value 70 occurs 98 times 
Value 71 occurs 91 times 
Value 72 occurs 104 times 
Value 73 occurs 102 times 
Value 74 occurs 103 times 
Value 75 occurs 106 times 
Value 76 occurs 126 times 
Value 77 occurs 85 times 
Value 78 occurs 106 times 
Value 79 occurs 96 times 
Value 80 occurs 86 times 
Value 81 occurs 98 times 
Value 82 occurs 100 times 
Value 83 occurs 121 times 
Value 84 occurs 82 times 
Value 85 occurs 100 times 
Value 86 occurs 91 times 
Value 87 occurs 110 times 
Value 88 occurs 106 times 
Value 89 occurs 116 times 
Value 90 occurs 107 times 
Value 91 occurs 100 times 
Value 92 occurs 96 times 
Value 93 occurs 111 times 
Value 94 occurs 111 times 
Value 95 occurs 98 times 
Value 96 occurs 92 times 
Value 97 occurs 93 times 
Value 98 occurs 124 times 
Value 99 occurs 90 times
Code:
Interval 0 occurs 108 times 
Interval 1 occurs 210 times 
Interval 2 occurs 178 times 
Interval 3 occurs 209 times 
Interval 4 occurs 189 times 
Interval 5 occurs 186 times 
Interval 6 occurs 181 times 
Interval 7 occurs 183 times 
Interval 8 occurs 170 times 
Interval 9 occurs 175 times 
Interval 10 occurs 176 times 
Interval 11 occurs 176 times 
Interval 12 occurs 177 times 
Interval 13 occurs 150 times 
Interval 14 occurs 173 times 
Interval 15 occurs 174 times 
Interval 16 occurs 188 times 
Interval 17 occurs 151 times 
Interval 18 occurs 152 times 
Interval 19 occurs 164 times 
Interval 20 occurs 147 times 
Interval 21 occurs 172 times 
Interval 22 occurs 137 times 
Interval 23 occurs 138 times 
Interval 24 occurs 169 times 
Interval 25 occurs 149 times 
Interval 26 occurs 168 times 
Interval 27 occurs 156 times 
Interval 28 occurs 165 times 
Interval 29 occurs 160 times 
Interval 30 occurs 150 times 
Interval 31 occurs 138 times 
Interval 32 occurs 128 times 
Interval 33 occurs 138 times 
Interval 34 occurs 124 times 
Interval 35 occurs 120 times 
Interval 36 occurs 125 times 
Interval 37 occurs 118 times 
Interval 38 occurs 116 times 
Interval 39 occurs 129 times 
Interval 40 occurs 125 times 
Interval 41 occurs 121 times 
Interval 42 occurs 105 times 
Interval 43 occurs 92 times 
Interval 44 occurs 107 times 
Interval 45 occurs 104 times 
Interval 46 occurs 121 times 
Interval 47 occurs 111 times 
Interval 48 occurs 120 times 
Interval 49 occurs 103 times 
Interval 50 occurs 114 times 
Interval 51 occurs 86 times 
Interval 52 occurs 62 times 
Interval 53 occurs 92 times 
Interval 54 occurs 98 times 
Interval 55 occurs 86 times 
Interval 56 occurs 86 times 
Interval 57 occurs 104 times 
Interval 58 occurs 103 times 
Interval 59 occurs 84 times 
Interval 60 occurs 77 times 
Interval 61 occurs 100 times 
Interval 62 occurs 92 times 
Interval 63 occurs 61 times 
Interval 64 occurs 74 times 
Interval 65 occurs 81 times 
Interval 66 occurs 69 times 
Interval 67 occurs 75 times 
Interval 68 occurs 56 times 
Interval 69 occurs 59 times 
Interval 70 occurs 69 times 
Interval 71 occurs 56 times 
Interval 72 occurs 46 times 
Interval 73 occurs 43 times 
Interval 74 occurs 52 times 
Interval 75 occurs 55 times 
Interval 76 occurs 42 times 
Interval 77 occurs 36 times 
Interval 78 occurs 40 times 
Interval 79 occurs 45 times 
Interval 80 occurs 36 times 
Interval 81 occurs 30 times 
Interval 82 occurs 33 times 
Interval 83 occurs 46 times 
Interval 84 occurs 39 times 
Interval 85 occurs 29 times 
Interval 86 occurs 28 times 
Interval 87 occurs 25 times 
Interval 88 occurs 22 times 
Interval 89 occurs 19 times 
Interval 90 occurs 16 times 
Interval 91 occurs 16 times 
Interval 92 occurs 20 times 
Interval 93 occurs 17 times 
Interval 94 occurs 19 times 
Interval 95 occurs 16 times 
Interval 96 occurs 10 times 
Interval 97 occurs 4 times 
Interval 98 occurs 5 times 
Interval 99 occurs 1 times

Looks pretty random to me. Interval means the previous number substracted from the current random number (absolute values).
it's not completly random, because then the interval should be evenly distributed also.

but using a function like this;
Code:
int truerand(int range)
{
    int randnumber[10];
    for(int n=0; n<10; n++) {
        randnumber[n] = makeint(round(rand(range*100)/100));
    }
    return randnumber[rand(9)]
}

didn't help in getting better intervals. so the problem does no lie in consecutive radom numbers.
But do try to at least always have a bigger number. I've seen some cases where rand(1) is used. I don't know how good this is.
 
I FINALLY noticed that this code here is NOT the regular 'frnd':
Code:
float FRAND(float _x) { return rand(32768) / 32768.0 * _x; }

Could it be that using 'frand' is better than using 'frnd'? I think they serve exactly the same purpose, no?
 
I FINALLY noticed that this code here is NOT the regular 'frnd':
Code:
float FRAND(float _x) { return rand(32768) / 32768.0 * _x; }

Could it be that using 'frand' is better than using 'frnd'? I think they serve exactly the same purpose, no?
I think so yes....
 
I haven't followed the discussion from the beginning, but after a quick glance I'm a bit skeptical about the entire thing. I see a possible performance impact there, but I'm not convinced there is any benefit do be had.
The entire "wind blowing from the wrong direction" thing might easily be the result of selective perception (and cognitive biases are strong, ask any serious poker player about that). At least I can easily remember many occasions of wind blowing for days from exactly the direction I wanted it to. But when that happens, people are somehow less annoyed and less inclined to complain.
So unless it have been proved statistically that the current RNG has a serious bias, I wouldn't bother changing anything.
 
Right.... Well, as long as we're not sure if we should do anything, I'm going to not do anything. ;)
 
I haven't followed the discussion from the beginning, but after a quick glance I'm a bit skeptical about the entire thing. I see a possible performance impact there, but I'm not convinced there is any benefit do be had.
The entire "wind blowing from the wrong direction" thing might easily be the result of selective perception (and cognitive biases are strong, ask any serious poker player about that). At least I can easily remember many occasions of wind blowing for days from exactly the direction I wanted it to. But when that happens, people are somehow less annoyed and less inclined to complain.
So unless it have been proved statistically that the current RNG has a serious bias, I wouldn't bother changing anything.

This is true. From what i've seen the wind's in my favor at about a 50/50 split, as would be expected. I think it's more likely to be down to bias and bad luck.
 
Back
Top