OSDN Git Service

[Refactor] #39076 "/* Paranoia */" を削除.
[hengband/hengband.git] / src / z-rand.c
index fbdd462..f160e54 100644 (file)
 
 /* Purpose: a simple random number generator -BEN- */
 
+#if defined(WINDOWS)
+#include <Windows.h>
+#endif
+
 #include "z-rand.h"
 
 
@@ -66,14 +70,18 @@ u32b Rand_state[RAND_DEG] = {
 };
 
 
+static u32b u32b_rotl(const u32b x, int k)
+{
+       return (x << k) | (x >> (32 - k));
+}
+
 /*
- * Initialize Xorshift Algorithm state
+ * Initialize RNG state
  */
-static void Rand_Xorshift_seed(u32b seed, u32b* state)
+static void Rand_seed(u32b seed, u32b* state)
 {
        int i;
 
-       /* Initialize Xorshift Algorithm RNG */
        for (i = 1; i <= 4; ++ i) {
                seed = 1812433253UL * (seed ^ (seed >> 30)) + i;
                state[i-1] = seed;
@@ -81,19 +89,24 @@ static void Rand_Xorshift_seed(u32b seed, u32b* state)
 }
 
 /*
- * Xorshift Algorithm
+ * Xoshiro128** Algorithm
  */
-static u32b Rand_Xorshift(u32b* state)
+static u32b Rand_Xoshiro128starstar(u32b *state)
 {
-       u32b t = state[0] ^ (state[0] << 11);
+       const u32b result = u32b_rotl(state[0] * 5, 7) * 9;
+
+       const u32b t = state[1] << 9;
+
+       state[2] ^= state[0];
+       state[3] ^= state[1];
+       state[1] ^= state[2];
+       state[0] ^= state[3];
 
-       state[0] = state[1];
-       state[1] = state[2];
-       state[2] = state[3];
+       state[2] ^= t;
 
-       state[3] = (state[3] ^ (state[3] >> 19)) ^ (t ^ (t >> 8));
+       state[3] = u32b_rotl(state[3], 11);
 
-       return state[3];
+       return result;
 }
 
 static const u32b Rand_Xorshift_max = 0xFFFFFFFF;
@@ -103,7 +116,7 @@ static const u32b Rand_Xorshift_max = 0xFFFFFFFF;
  */
 void Rand_state_set(u32b seed)
 {
-       Rand_Xorshift_seed(seed, Rand_state);
+       Rand_seed(seed, Rand_state);
 }
 
 void Rand_state_init(void)
@@ -111,13 +124,26 @@ void Rand_state_init(void)
 #ifdef RNG_DEVICE
 
        FILE *fp = fopen(RNG_DEVICE, "r");
-       u32b buf[4];
+       int n;
+       
        do {
-               fread(buf, sizeof(buf[0]), 4, fp);
-       } while ((buf[0] | buf[1] | buf[2] | buf[3]) == 0);
-       memcpy(Rand_state, buf, sizeof(buf));
+               n = fread(Rand_state, sizeof(Rand_state[0]), 4, fp);
+       } while (n != 4 || (Rand_state[0] | Rand_state[1] | Rand_state[2] | Rand_state[3]) == 0);
+       
        fclose(fp);
 
+#elif defined(WINDOWS)
+
+       HCRYPTPROV hProvider;
+
+       CryptAcquireContext(&hProvider, NULL, NULL, PROV_RSA_FULL, 0);
+
+       do {
+               CryptGenRandom(hProvider, sizeof(Rand_state[0]) * 4, (BYTE*)Rand_state);
+       } while ((Rand_state[0] | Rand_state[1] | Rand_state[2] | Rand_state[3]) == 0);
+
+       CryptReleaseContext(hProvider, 0);      
+
 #else
 
        /* Basic seed */
@@ -173,7 +199,7 @@ static s32b Rand_div_impl(s32b m, u32b* state)
        past = scaling * m;
 
        do {
-               ret = Rand_Xorshift(state);
+               ret = Rand_Xoshiro128starstar(state);
        } while (ret >= past);
 
        return ret / scaling;
@@ -267,9 +293,7 @@ s16b randnor(int mean, int stand)
 
        s16b low = 0;
        s16b high = RANDNOR_NUM;
-
-       /* Paranoia */
-       if (stand < 1) return (mean);
+       if (stand < 1) return (s16b)(mean);
 
        /* Roll for probability */
        tmp = (s16b)randint0(32768);
@@ -288,7 +312,7 @@ s16b randnor(int mean, int stand)
                /* Move left otherwise */
                else
                {
-                       high = mid;
+                       high = (s16b)mid;
                }
        }
 
@@ -307,18 +331,18 @@ s16b randnor(int mean, int stand)
 /*
  * Generates damage for "2d6" style dice rolls
  */
-s16b damroll(int num, int sides)
+s16b damroll(DICE_NUMBER num, DICE_SID sides)
 {
        int i, sum = 0;
        for (i = 0; i < num; i++) sum += randint1(sides);
-       return (sum);
+       return (s16b)(sum);
 }
 
 
 /*
  * Same as above, but always maximal
  */
-s16b maxroll(int num, int sides)
+s16b maxroll(DICE_NUMBER num, DICE_SID sides)
 {
        return (num * sides);
 }
@@ -360,7 +384,7 @@ s32b div_round(s32b n, s32b d)
  * "external" program parts like the main-*.c files.  It preserves
  * the current RNG state to prevent influences on game-play.
  *
- * Could also use rand() from <stdlib.h> directly. XXX XXX XXX
+ * Could also use rand() from <stdlib.h> directly. 
  */
 s32b Rand_external(s32b m)
 {
@@ -370,8 +394,8 @@ s32b Rand_external(s32b m)
        if (!initialized)
        {
                /* Initialize with new seed */
-               u32b seed = time(NULL);
-               Rand_Xorshift_seed(seed, Rand_state_external);
+               u32b seed = (u32b)time(NULL);
+               Rand_seed(seed, Rand_state_external);
                initialized = TRUE;
        }