Browse Source

Merge pull request #386 from greenfire27/GetRandomBell

GetRandomBell
Peter Robinson 8 years ago
parent
commit
618106ee10

+ 1 - 0
engine/compilers/VisualStudio 2013/Torque 2D.vcxproj

@@ -961,6 +961,7 @@
     <ClInclude Include="..\..\source\io\zip\zipTempStream.h" />
     <ClInclude Include="..\..\source\math\box_ScriptBinding.h" />
     <ClInclude Include="..\..\source\math\matrix_ScriptBinding.h" />
+    <ClInclude Include="..\..\source\math\mNormalDistribution.h" />
     <ClInclude Include="..\..\source\math\random_ScriptBinding.h" />
     <ClInclude Include="..\..\source\math\rectClipper.h" />
     <ClInclude Include="..\..\source\math\vector_ScriptBinding.h" />

+ 3 - 0
engine/compilers/VisualStudio 2013/Torque 2D.vcxproj.filters

@@ -3198,6 +3198,9 @@
     <ClInclude Include="..\..\source\audio\audioDescriptions.h">
       <Filter>audio</Filter>
     </ClInclude>
+    <ClInclude Include="..\..\source\math\mNormalDistribution.h">
+      <Filter>math</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <CustomBuild Include="..\..\source\math\mMath_ASM.asm">

+ 1 - 0
engine/compilers/VisualStudio 2015/Torque 2D.vcxproj

@@ -961,6 +961,7 @@
     <ClInclude Include="..\..\source\io\zip\zipTempStream.h" />
     <ClInclude Include="..\..\source\math\box_ScriptBinding.h" />
     <ClInclude Include="..\..\source\math\matrix_ScriptBinding.h" />
+    <ClInclude Include="..\..\source\math\mNormalDistribution.h" />
     <ClInclude Include="..\..\source\math\random_ScriptBinding.h" />
     <ClInclude Include="..\..\source\math\rectClipper.h" />
     <ClInclude Include="..\..\source\math\vector_ScriptBinding.h" />

+ 3 - 0
engine/compilers/VisualStudio 2015/Torque 2D.vcxproj.filters

@@ -3198,6 +3198,9 @@
     <ClInclude Include="..\..\source\audio\audioDescriptions.h">
       <Filter>audio</Filter>
     </ClInclude>
+    <ClCompile Include="..\..\source\math\mNormalDistribution.h">
+      <Filter>math</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <CustomBuild Include="..\..\source\math\mMath_ASM.asm">

+ 66 - 0
engine/source/math/mNormalDistribution.h

@@ -0,0 +1,66 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2013 GarageGames, LLC
+//
+// 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.
+//-----------------------------------------------------------------------------
+
+#ifndef _MNORMALDISTRIBUTION_H_
+#define _MNORMALDISTRIBUTION_H_
+
+#include <random>
+
+//-----------------------------------------------------------------------------
+// Modified from this Stack Overflow answer: http://stackoverflow.com/a/28619226/289956
+//-----------------------------------------------------------------------------
+
+class NormalDistributionGenerator
+{
+   std::mt19937 generator;
+   std::normal_distribution<F64> distribution;
+   S32 min;
+   S32 max;
+public:
+   NormalDistributionGenerator(S32 min, S32 max) :
+      distribution(std::round((min + max) / 2), std::round((max - min) / 6)), min(min), max(max)
+   {
+      generator.seed(Platform::getRealMilliseconds());
+   }
+
+   NormalDistributionGenerator(S32 min, S32 max, S32 mean) :
+      distribution(mean, std::round((max - min) / 6)), min(min), max(max)
+   {
+      generator.seed(Platform::getRealMilliseconds());
+   }
+
+   NormalDistributionGenerator(S32 min, S32 max, S32 mean, S32 stddev) :
+      distribution(mean, stddev), min(min), max(max)
+   {
+      generator.seed(Platform::getRealMilliseconds());
+   }
+
+   S32 operator ()() {
+      while (true) {
+         S32 number = (S32)std::round(this->distribution(generator));
+         if (number >= this->min && number <= this->max)
+            return number;
+      }
+   }
+};
+
+#endif //_MNORMALDISTRIBUTION_H_

+ 57 - 0
engine/source/math/random_ScriptBinding.h

@@ -20,6 +20,8 @@
 // IN THE SOFTWARE.
 //-----------------------------------------------------------------------------
 
+#include "math/mNormalDistribution.h"
+
 ConsoleFunctionGroupBegin(RandomNumbers, "Functions relating to the generation of random numbers.");
 
 
@@ -111,6 +113,61 @@ ConsoleFunctionWithDocs(getRandomF, ConsoleFloat, 3, 3, (min, max))
     
 }
 
+/*! Gets a random integer number with normal distribution (a bell curve) from min to max with optional mean and standard deviation.
+@param min The minimum range of the random integer number.
+@param max The maximum range of the random integer number.
+@param mean The Most commonly occuring value or the center of the "bell". Must be between the min and max. Defaults to the center value between min and max.
+@param stdDev The standard deviation affects how far values tend to be from the mean. Defaults to 1/6th of the difference between min and max.
+@return A random floating-point number from min to max.
+*/
+ConsoleFunctionWithDocs(getRandomBell, ConsoleInt, 3, 5, (min, max, [ mean ]?, [ stdDev ]?))
+{
+   S32 min = dAtoi(argv[1]);
+   S32 max = dAtoi(argv[2]);
+
+   if (min > max)
+   {
+      const S32 temp = min;
+      min = max;
+      max = temp;
+   }
+
+   if (argc == 3)
+   {
+      NormalDistributionGenerator g(min, max);
+      return g();
+   }
+   else if (argc > 3 && argc <= 5)
+   {
+      S32 mean = dAtoi(argv[3]);
+      if (mean > max)
+      {
+         mean = max;
+      }
+
+      if (mean < min)
+      {
+         mean = min;
+      }
+
+      if (argc == 4)
+      {
+         NormalDistributionGenerator g(min, max, mean);
+         return g();
+      }
+      else
+      {
+         NormalDistributionGenerator g(min, max, mean, dAtoi(argv[4]));
+         return g();
+      }
+   }
+   else
+   {
+      Con::warnf("getRandomBell() - Invalid number of parameters!");
+      return 0;
+   }
+}
+
 //------------------------------------------------------------------------------
 
 ConsoleFunctionGroupEnd(RandomNumbers)