Open unorthodox-paradox opened 5 years ago
Some preliminary testing was conducted. At X10/Hertzallee any spawned AI buses would generate 100 random values concurrently at variable intervals. The values generated turned out to be distinct and not following a common pattern per vehicle (type) or frame, thus suggesting that OMSI is not the one to blame here.
Instead the fault lies with the following assumption of ours, which is anything but reasonable:
The distribution of random numbers generated through either facility is (expected to be) normal.
No, obviously it ought to be uniform (duh!).
This makes it crystal clear why, whenever we generate a random value without otherwise bounding its interval by probability -- which, unfortunately, in at least as many as half of all applicable instances we do not -- the probability of a value close to the interval's bounds being generated (typically implying an unusual trait being selected, or an exceptional exception occurring) is just as high as the one of a value close to the norm. This is of clearly not what we had in mind.
Background
OMSI offers two facilities for random number generation:
random
operator, wherem random
yields an integer, n, 0 ≤ n < m. Tworandom
invocations with the same argument m need – and typically should – not yield the same output.NrSpecRandom
callback, wherem (M.V.NrSpecRandom)
yields a float, n, where 0 ≤ n < 1. TwoNrSpecRandom
invocations with the same argument m must yield the same output when invoked by the same vehicle (more specifically vehicles with the samenumber
, which should normally be unique per AI-list, and hence loaded situation).It goes without saying that many scripts of this mod heavily depend on random number generation, particularly when, during initialization, several hundred per-vehicle traits, such as those contributing to the "personality" of each individual AI vehicle, are established. Such scripts were authored with certain (rather reasonable, in our opinion) assumptions in mind:
random
s are not cached, i.e., that callingn random
several times with the same argument n, will likely produce different output, provided n is high enough.random
s are not shared across vehicles, nor vehicle types (same .bus file); i.e., that callingn random
concurrently from different vehicle instances, with the same argument n, will likely produce different output, again provided n is high enough.NrSpecRandom
behaves similarly to a hash function, i.e., slight variation between vehicle numbers will cause significant output variation, regardless the provided seed, which may well be the same across vehicles requesting random number generation.Time
/Date
/GetTime
/ etc.Problem statement
Unfortunately, casual observation thus far, combined with the fact that the (atrociously vague) SDK documentation promises none of the above, have given rise to suspicion on the quality of random number generation:
number
s (e.g.1998
,1999
)n (M.V.NrSpecRandom)
invocations yield similar (or identical) output.Course of action
For now the above are merely speculation. Proper tests should be written and executed in a "vehicle-busy", ideally "strained" / low FPS setting, to test the aforementioned observations' validity. If OMSI's random number generation indeed turns out flawed, the only real workaround would be to write a plugin that consumes an OS-exposed PRNG's output and delivers it back to the scripts. To mitigate potential performance impact, the two approaches could also be combined, with the OS being used for obtaining crucial initial seeds and those being subsequently plugged into OMSI's facilities for further / subsequent generation.
Progress thus far
As a temp-fix, most initialization calls to random (in
ai_pre_cockpit.osc
,lights_ai.osc
, andlights.osc
) have been replaced by random→NrSpecRandom to at least mitigate cross-vehicle initialization similarities. The results are mixed. Post-initialization random number generation still relies on plain random.