From 8808864e56f29b83c42ae2de192f766ee5333606 Mon Sep 17 00:00:00 2001
From: Allanis <allanis@saracraft.net>
Date: Thu, 28 Mar 2013 13:25:53 +0000
Subject: [PATCH] [Add] Now we can use mersenne twister instead of rand(), you
 are welcome. :)

---
 bin/Makefile |   6 ++-
 src/rng.c    | 106 ++++++++++++++++++++++++++++++++++++++++++++++++++-
 src/rng.h    |   8 ++--
 3 files changed, 114 insertions(+), 6 deletions(-)

diff --git a/bin/Makefile b/bin/Makefile
index 7787544..ee05d6f 100644
--- a/bin/Makefile
+++ b/bin/Makefile
@@ -1,6 +1,8 @@
 # OPTIONS.
 DEBUG = 1
-APPNAME = Lephisto
+
+OS := LINUX
+#OS := WIN32
 
 # VERSION.
 VMAJOR  = 0
@@ -22,7 +24,7 @@ CTTF = $(shell freetype-config --cflags)
 CAL  = -lopenal
 CVORBIS =
 CGL  =
-CFLAGS = $(CLUA) $(CSDL) $(CXML) $(CTTF) $(CGL) $(CAL) $(CVORBIS) $(VERSION)
+CFLAGS = $(CLUA) $(CSDL) $(CXML) $(CTTF) $(CGL) $(CAL) $(CVORBIS) $(VERSION) -D$(OS)
 ifdef DEBUG
 CFLAGS += -W -Wall -g3 -DDEBUG -DLUA_USE_APICHECK -std=c99
 else
diff --git a/src/rng.c b/src/rng.c
index 528ab0a..daf6b65 100644
--- a/src/rng.c
+++ b/src/rng.c
@@ -1,8 +1,112 @@
+#include <stdint.h>
+#include <math.h>
 #include <unistd.h>
+#include <time.h>
+#ifdef LINUX
+#include <sys/time.h>
+#include <fcntl.h>
+#endif
 #include <SDL.h>
+
 #include "rng.h"
+#include "log.h"
+
+// Mersenne twister state.
+static uint32_t MT[624];
+static uint32_t mt_y;
+static int mt_pos = 0;  // Current number.
+
+static uint32_t rng_timeEntropy(void);
+// Mersenne twister.
+static void mt_initArray(uint32_t seed);
+static void mt_genArray(void);
+static uint32_t mt_getInt(void);
 
 void rng_init(void) {
-  srand(getpid() + SDL_GetTicks());
+  uint32_t i;
+
+#ifdef LINUX
+  int fd; char buf[4];
+  fd = open("/dev/random", O_RDONLY);
+  if(fd != -1) {
+    if(read(fd, buf, 4) < 4)
+      memcpy(&i, buf, 4);
+    else
+      i = rng_timeEntropy();
+    close(fd);
+  } else
+    i = rng_timeEntropy();
+#else
+  i = rng_timeEntropy();
+#endif
+  mt_initArray(i);
+  for(i = 0; i < 10; i++)
+    // Generate numbers to get away from poor initial values.
+    mt_genArray();
+}
+
+// Use the time as source of entropy.
+static uint32_t rng_timeEntropy(void) {
+  int i;
+  
+#ifdef WIN32
+  struct _timeb tb;
+  _ftime(&tb);
+  i = tb.time * 1000 + tb.millitm;
+#else
+  struct timeval tv;
+  gettimeofday(&tv, NULL);
+  i = tv.tv_sec * 1000000 + tv.tv_usec;
+#endif
+  return i;
+}
+
+// Generates the initial mersenne twister based on seed.
+static void mt_initArray(uint32_t seed) {
+  int i;
+  MT[0] = seed;
+  for(i = 1; i < 624; i++)
+    MT[i] = 1812433253 * (MT[i-1] ^ (((MT[i-1])) + i) >> 30);
+  mt_pos = 0;
+}
+
+// Generate an array of numbers.
+static void mt_genArray(void) {
+  int i;
+  for(i = 0; i < 624; i++) {
+    mt_y = (MT[i] & 0x80000000) + ((MT[i] % 624) & 0x7FFFFFFF);
+    if(mt_y % 2)
+      // Odd.
+      MT[i] = (MT[(i+397) % 624] ^ (mt_y >> 1)) ^ 2567483615;
+    else
+      // Even.
+      MT[i] = MT[(i+397) % 624] ^ (mt_y >> 1);
+  }
+  mt_pos = 0;
+}
+
+// Get the next int.
+static uint32_t mt_getInt(void) {
+  if(mt_pos >= 624) mt_genArray();
+
+  mt_y = MT[mt_pos++];
+  mt_y ^= mt_y >> 11;
+  mt_y ^= (mt_y << 7)   & 2636928640;
+  mt_y ^= (mt_y << 15)  & 4022730752;
+  mt_y ^= (mt_y >> 18);
+
+  return mt_y;
+}
+
+// Return a random int.
+unsigned int randint(void) {
+  return mt_getInt();
+}
+
+// Return a random double.
+static double m_div = (double)(0xFFFFFFFF) + 1.;
+double randfp(void) {
+  double m = (double)mt_getInt();
+  return m / m_div;
 }
 
diff --git a/src/rng.h b/src/rng.h
index 1d2b053..e017a75 100644
--- a/src/rng.h
+++ b/src/rng.h
@@ -1,8 +1,10 @@
 #pragma once
-#include <stdlib.h>
+#include <limits.h>
 
-#define RNG(L,H)  ((int)L + (int)((double)(H-L+1) * (rand()/(RAND_MAX+1.))))
-#define RNGF()  (rand()/(RAND_MAX+1.))
+#define RNG(L,H)  ((int)L + (int)((double)(H-L+1) * (randfp()))
+#define RNGF()  (randfp())
 
 void rng_init(void);
+unsigned int randint(void);
+double randfp(void);