Browse Source

Reimplemented the MSVC random number generator to produce same random number output on all platforms.

Lasse Öörni 14 years ago
parent
commit
4ca9035ba5
5 changed files with 93 additions and 16 deletions
  1. 5 5
      Docs/ScriptAPI.dox
  2. 6 5
      Engine/Engine/MathAPI.cpp
  3. 9 6
      Engine/Math/MathDefs.h
  4. 42 0
      Engine/Math/Random.cpp
  5. 31 0
      Engine/Math/Random.h

+ 5 - 5
Docs/ScriptAPI.dox

@@ -13,11 +13,6 @@
 - float Abs(float)
 - float Abs(float)
 - float Sqrt(float)
 - float Sqrt(float)
 - float Pow(float)
 - float Pow(float)
-- float Random()
-- float Random(float)
-- int RandomInt()
-- int RandomInt(int)
-- void SetRandomSeed(int)
 - float Min(float, float)
 - float Min(float, float)
 - float Max(float, float)
 - float Max(float, float)
 - float Clamp(float, float, float)
 - float Clamp(float, float, float)
@@ -25,6 +20,10 @@
 - float Mod(float, float)
 - float Mod(float, float)
 - float Floor(float)
 - float Floor(float)
 - float Ceil(float)
 - float Ceil(float)
+- float Random()
+- float Random(float)
+- int RandomInt()
+- int RandomInt(int)
 - String ToStringHex(int)
 - String ToStringHex(int)
 - void ErrorDialog(const String&, const String&)
 - void ErrorDialog(const String&, const String&)
 - void OpenConsoleWindow()
 - void OpenConsoleWindow()
@@ -58,6 +57,7 @@
 - void ClearDelayedExecute()
 - void ClearDelayedExecute()
 - void Remove()
 - void Remove()
 \section ScriptAPI_GlobalProperties Global properties
 \section ScriptAPI_GlobalProperties Global properties
+- uint randomSeed
 - String[]@ arguments
 - String[]@ arguments
 - uint numCpuCores
 - uint numCpuCores
 - Time@ time
 - Time@ time

+ 6 - 5
Engine/Engine/MathAPI.cpp

@@ -81,11 +81,6 @@ static void RegisterMathFunctions(asIScriptEngine* engine)
     engine->RegisterGlobalFunction("float Abs(float)", asFUNCTION(fabsf), asCALL_CDECL);
     engine->RegisterGlobalFunction("float Abs(float)", asFUNCTION(fabsf), asCALL_CDECL);
     engine->RegisterGlobalFunction("float Sqrt(float)", asFUNCTION(sqrtf), asCALL_CDECL);
     engine->RegisterGlobalFunction("float Sqrt(float)", asFUNCTION(sqrtf), asCALL_CDECL);
     engine->RegisterGlobalFunction("float Pow(float)", asFUNCTION(powf), asCALL_CDECL);
     engine->RegisterGlobalFunction("float Pow(float)", asFUNCTION(powf), asCALL_CDECL);
-    engine->RegisterGlobalFunction("float Random()", asFUNCTIONPR(Random, (), float), asCALL_CDECL);
-    engine->RegisterGlobalFunction("float Random(float)", asFUNCTIONPR(Random, (float), float), asCALL_CDECL);
-    engine->RegisterGlobalFunction("int RandomInt()", asFUNCTION(rand), asCALL_CDECL);
-    engine->RegisterGlobalFunction("int RandomInt(int)", asFUNCTIONPR(Random, (int), int), asCALL_CDECL);
-    engine->RegisterGlobalFunction("void SetRandomSeed(int)", asFUNCTION(srand), asCALL_CDECL);
     engine->RegisterGlobalFunction("float Min(float, float)", asFUNCTIONPR(Min, (float, float), float), asCALL_CDECL);
     engine->RegisterGlobalFunction("float Min(float, float)", asFUNCTIONPR(Min, (float, float), float), asCALL_CDECL);
     engine->RegisterGlobalFunction("float Max(float, float)", asFUNCTIONPR(Max, (float, float), float), asCALL_CDECL);
     engine->RegisterGlobalFunction("float Max(float, float)", asFUNCTIONPR(Max, (float, float), float), asCALL_CDECL);
     engine->RegisterGlobalFunction("float Clamp(float, float, float)", asFUNCTIONPR(Clamp, (float, float, float), float), asCALL_CDECL);
     engine->RegisterGlobalFunction("float Clamp(float, float, float)", asFUNCTIONPR(Clamp, (float, float, float), float), asCALL_CDECL);
@@ -93,6 +88,12 @@ static void RegisterMathFunctions(asIScriptEngine* engine)
     engine->RegisterGlobalFunction("float Mod(float, float)", asFUNCTION(fmodf), asCALL_CDECL);
     engine->RegisterGlobalFunction("float Mod(float, float)", asFUNCTION(fmodf), asCALL_CDECL);
     engine->RegisterGlobalFunction("float Floor(float)", asFUNCTION(floorf), asCALL_CDECL);
     engine->RegisterGlobalFunction("float Floor(float)", asFUNCTION(floorf), asCALL_CDECL);
     engine->RegisterGlobalFunction("float Ceil(float)", asFUNCTION(ceilf), asCALL_CDECL);
     engine->RegisterGlobalFunction("float Ceil(float)", asFUNCTION(ceilf), asCALL_CDECL);
+    engine->RegisterGlobalFunction("float Random()", asFUNCTIONPR(Random, (), float), asCALL_CDECL);
+    engine->RegisterGlobalFunction("float Random(float)", asFUNCTIONPR(Random, (float), float), asCALL_CDECL);
+    engine->RegisterGlobalFunction("int RandomInt()", asFUNCTION(Rand), asCALL_CDECL);
+    engine->RegisterGlobalFunction("int RandomInt(int)", asFUNCTIONPR(Random, (int), int), asCALL_CDECL);
+    engine->RegisterGlobalFunction("void set_randomSeed(uint)", asFUNCTION(SetRandomSeed), asCALL_CDECL);
+    engine->RegisterGlobalFunction("uint get_randomSeed()", asFUNCTION(GetRandomSeed), asCALL_CDECL);
 }
 }
 
 
 static void ConstructIntRect(IntRect* ptr)
 static void ConstructIntRect(IntRect* ptr)

+ 9 - 6
Engine/Math/MathDefs.h

@@ -23,6 +23,8 @@
 
 
 #pragma once
 #pragma once
 
 
+#include "Random.h"
+
 #include <cstdlib>
 #include <cstdlib>
 #include <cmath>
 #include <cmath>
 
 
@@ -54,12 +56,6 @@ enum Intersection
 
 
 /// Linear interpolation between two float values.
 /// Linear interpolation between two float values.
 inline float Lerp(float lhs, float rhs, float t) { return lhs * (1.0f - t) + rhs * t; }
 inline float Lerp(float lhs, float rhs, float t) { return lhs * (1.0f - t) + rhs * t; }
-/// Return a random float between 0.0 (inclusive) and 1.0 (exclusive.)
-inline float Random() { return (rand() & 32767) / 32768.0f; }
-/// Return a random float between 0.0 and range, inclusive.
-inline float Random(float range) { return (rand() & 32767) * range / 32767.0f; }
-/// Return a random integer between 0 and range, inclusive.
-inline int Random(int range) { return ((rand() & 32767) * range + 16384) / 32767; }
 /// Return the smaller of two floats.
 /// Return the smaller of two floats.
 inline float Min(float lhs, float rhs) { return lhs < rhs ? lhs : rhs; }
 inline float Min(float lhs, float rhs) { return lhs < rhs ? lhs : rhs; }
 /// Return the larger of two floats.
 /// Return the larger of two floats.
@@ -147,3 +143,10 @@ inline float FastInvSqrt(float x)
 
 
 /// Update a hash with the given 8-bit value using the SDBM algorithm.
 /// Update a hash with the given 8-bit value using the SDBM algorithm.
 inline unsigned SDBMHash(unsigned hash, unsigned char c) { return c + (hash << 6) + (hash << 16) - hash; }
 inline unsigned SDBMHash(unsigned hash, unsigned char c) { return c + (hash << 6) + (hash << 16) - hash; }
+
+/// Return a random float between 0.0 (inclusive) and 1.0 (exclusive.)
+inline float Random() { return (Rand() & 32767) / 32768.0f; }
+/// Return a random float between 0.0 and range, inclusive.
+inline float Random(float range) { return (Rand() & 32767) * range / 32767.0f; }
+/// Return a random integer between 0 and range, inclusive.
+inline int Random(int range) { return ((Rand() & 32767) * range + 16384) / 32767; }

+ 42 - 0
Engine/Math/Random.cpp

@@ -0,0 +1,42 @@
+//
+// Urho3D Engine
+// Copyright (c) 2008-2011 Lasse Öörni
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+
+#include "Random.h"
+
+static unsigned randomSeed = 1;
+
+void SetRandomSeed(unsigned seed)
+{
+    randomSeed = seed;
+}
+
+unsigned GetRandomSeed()
+{
+    return randomSeed;
+}
+
+int Rand()
+{
+    randomSeed = randomSeed * 214013 + 2531011;
+    return (randomSeed >> 16) & 32767;
+}

+ 31 - 0
Engine/Math/Random.h

@@ -0,0 +1,31 @@
+//
+// Urho3D Engine
+// Copyright (c) 2008-2011 Lasse Öörni
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+
+#pragma once
+
+/// Set the random seed. The default seed is 1.
+void SetRandomSeed(unsigned seed);
+/// Return the current random seed.
+unsigned GetRandomSeed();
+/// Internal random generation function, which should operate similarly to MSVC rand().
+int Rand();