Intended to work on AI today, but the universe had different plans for me
Something that's bothered me for a while is that the Mac version of LT looks...very different from the Windows / Linux versions. When I say very different, I mean....you spawn in a totally different universe, the icons look different, the ships look different, etc. Now that's not too surprising, because all of those things are procedural. So I just suspected some platform-specific code in the random generators was causing it.
Today I finally decided to tackle this issue, which I knew had to be dealt with sooner or later. Come release time, I want everyone to be experiencing the same universe when they enter the same seed! Don't want one set of universes for Mac, etc.. After some thorough investigation, I was a bit shocked to realize the source of this problem. It actually had very little to do with the way the random computations were performed, and everything to do with the way in which they were used.
Turns out, there's an absolutely evil piece in the c++ standard that says "the order of evaluation of function parameters is unspecified." Now, I always knew that. But I guess I never really understood the consequences until today. I guess it never really sank in. But here's what it means...suppose you have the following piece of code:
This kind of thing happens all over the codebase, because we're creating things using random generators all the time in a procedural game. The thing is, when you pull a number out of a random generator, it changes the state of the generator (because next time you pull a number out, you want it to be a different number). So, thanks to the c++ standard, this very reasonable and seemingly-well-formed line of code is actually unspecified behavior. Depending on the compiler, the first or second parameter may be evaluated first, and since it changes the state of the random generator, it will cause the parameters to be swapped depending on the order of evaluation. Wow
Code: Select all
myFunction(randomGenerator->GetFloat(0, 1), randomGenerator->GetFloat(0, 1));
Well, guess what. You guessed it, it just so happens that Clang and gcc implement this differently, hence the major differences in the versions of LT. I never realized just how much of my code was actually not platform-independent.
Honestly, this is not my fault, this is the fault of the standards committee To have such a perfectly-sensible statement as above causing different behavior on different platforms is totally and completely unacceptable. There are very few places in which I feel c++ really messed up, but I'm going to have to add this one to the list. It's really a great pain and causes a great deal of superfluous code to have to pull those parameters out and manually evaluate them in order before passing to a function call.
In the end, after re-writing a lot of the random-related code, I was able to get the universes to mostly sync up (there must be a handful of bad spots remaining, but I'll find them). But man, this irks me
[ You can visit devtime.ltheory.com for more detailed information on today's work. ]