/* Purpose: a simple random number generator -BEN- */
+#if defined(WINDOWS)
+#include <Windows.h>
+#endif
+
#include "z-rand.h"
};
+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;
}
/*
- * 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;
*/
void Rand_state_set(u32b seed)
{
- Rand_Xorshift_seed(seed, Rand_state);
+ Rand_seed(seed, Rand_state);
}
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 */
past = scaling * m;
do {
- ret = Rand_Xorshift(state);
+ ret = Rand_Xoshiro128starstar(state);
} while (ret >= past);
return ret / scaling;
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);
/* Move left otherwise */
else
{
- high = mid;
+ high = (s16b)mid;
}
}
/*
* 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);
}
* "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)
{
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;
}