11-09-2003, 04:54 PM
vor_lord,Nov 9 2003, 10:26 AM Wrote:There have been a lot of indications that positioning affects random number rolls (at least back in the classic days), so I don't think they are using a standard call anyway. I'd guess their implementation avoids floats altogether. Were you perhaps referring to a 'standard/classic' algorithm? They may in fact be using something like that. Which one exhibits 2-point correlation in particular?They do not use a standard call as that could yield different results on different hardware platforms (Intel, AMD, Macs, etc.) depending on how they each implemented such a thing at the processor level. The PRNGs that are used in multiplayer games must stay in synch or it will start giving each of the players different results in the same game, and then who is right?
Are there any knowledgeable modders that can help here? Maybe some true CS guys?
EDIT: By true CS guys I mean as contrasted with myself as an electrical engineer who codes for a living. I don't mean to say that Ferengi is not a 'true' CS guy.
The system in Diablo2 is mostly integer calculations except in a few small sections of code. For the PRNGs in the game they are using 2 DWORDs for handling this. Here is a better listing that I save from some time ago.
Quote:Jarulf made a post on the Amazon basin outlining the random number generator. Relevant portion:
In reply to:
>If the number generator was written by Blizzard, this contradicts your first assertion and is indeed a critical
>point in this discussion. If it is not written by Blizzard and not a component of the C runtime library, how can
>you assert that it is not flawed?
As far as I know, the one used in D2 should not be "invented" or written by Blizzard themselves. BY the way, it works like this (the exact explanation may depend on how one view the data, 2 32 bit values can be seen as a 64 bit value for example. I like to view it as two separate 32 bit values though.
Each seed is made up of 2 32 bit values (or one may see them as 1 64 bit value). I will call it seed_lo and seed_hi.
Next, an intermediate value (64 BIT!!!) is calculated as:
seed_lo * 0x6ac690c5 + seed_hi
Note, it will "roll over" if above max value for an unsigned 64 bit value.
The upper 32 bits are stored away as the new seed_hi while the lower 32 bits are stored away as seed_lo. In addition the lower 32 bits (the new seed_lo) is used to generate the random number through a mod division:
random number = seed_lo mod X
Thus generating an integer value in the range from 0 to X-1
The game will always when needing a random value, thus do a Rnd[X] which will return a value in the range 0 to X-1. If one need a value in the range Y to Z, one have to do Y + Rnd[Z-Y+1]. Here we have the reason for the off by 1 bug found in pre 1.08 version of Diablo 2. Where affixes and properties of an item like AC could never have its maximum value, the programmer forgot the +1 and used Y + Rnd[Z-Y]. This has been fixed for most cases but last I checked not for AC and possibly for things like number of arrows in a quiver and such, have not checked each case, I have informed Blizzard about it though. The same bug actually existed in several other places, like damage calcs. Since they used higher precision through fixed point arithmetic, the errors was only 1/256 of a damage point, which for practical purposes is neglectable but still exist in the game, that is, if your weapon do a maximum of 50 damage, the most you can do is 49 + 255/256 of a point. Since selecting items from a list and such only uses random values from 0 up to X, this should not happen.
Feel free to do whatever tests there can be done on this random number generator. By the way, when the seed is initialized, it is always made so that seed_hi has the value of 0x0000029a, while seed_lo can get whatever "random" number one want, initially for example based on some time stamp. The algorithm will never, if seeded correctly with 0x29a and a non 0 seed_lo, reach a state where seed_lo and seed_hi are 0 (since then from then on it would definitely not randomize any more ).
From my looking at the process I have not seen any indication that the "successive numbers strongly tend to be the same" as Ferengi puts it. In fact comparing this to several of the PRNG algorithms that I have found on the net (that are considered to be about as could as you can get without resorting more than 64 bits), this one is very similar in form and function. Considering the number of times that it is called at some points in the game, it is probably an adaptation that has been optimized for the speed at the reduction of some of the factors in the other PRND that would not be getting exploited. (Keeping in mind that a server will be running up to 128 games simultaneously.)