mirror of
https://github.com/Ninjdai1/pokeemerald.git
synced 2024-11-16 11:37:40 +01:00
Shuffle implementation (#3097)
This commit is contained in:
parent
862602233d
commit
eab4e32e2a
@ -20,6 +20,22 @@ u16 Random2(void);
|
||||
void SeedRng(u16 seed);
|
||||
void SeedRng2(u16 seed);
|
||||
|
||||
void Shuffle8(void *data, size_t n);
|
||||
void Shuffle16(void *data, size_t n);
|
||||
void Shuffle32(void *data, size_t n);
|
||||
void ShuffleN(void *data, size_t n, size_t size);
|
||||
|
||||
static inline void Shuffle(void *data, size_t n, size_t size)
|
||||
{
|
||||
switch (size)
|
||||
{
|
||||
case 1: Shuffle8(data, n); break;
|
||||
case 2: Shuffle16(data, n); break;
|
||||
case 4: Shuffle32(data, n); break;
|
||||
default: ShuffleN(data, n, size); break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Structured random number generator.
|
||||
* Instead of the caller converting bits from Random() to a meaningful
|
||||
* value, the caller provides metadata that is used to return the
|
||||
|
42
src/random.c
42
src/random.c
@ -32,6 +32,48 @@ u16 Random2(void)
|
||||
return gRng2Value >> 16;
|
||||
}
|
||||
|
||||
#define SHUFFLE_IMPL \
|
||||
u32 tmp; \
|
||||
--n; \
|
||||
while (n > 1) \
|
||||
{ \
|
||||
int j = Random() % (n+1); \
|
||||
SWAP(data[n], data[j], tmp); \
|
||||
--n; \
|
||||
}
|
||||
|
||||
void Shuffle8(void *data_, size_t n)
|
||||
{
|
||||
u8 *data = data_;
|
||||
SHUFFLE_IMPL;
|
||||
}
|
||||
|
||||
void Shuffle16(void *data_, size_t n)
|
||||
{
|
||||
u16 *data = data_;
|
||||
SHUFFLE_IMPL;
|
||||
}
|
||||
|
||||
void Shuffle32(void *data_, size_t n)
|
||||
{
|
||||
u32 *data = data_;
|
||||
SHUFFLE_IMPL;
|
||||
}
|
||||
|
||||
void ShuffleN(void *data, size_t n, size_t size)
|
||||
{
|
||||
void *tmp = alloca(size);
|
||||
--n;
|
||||
while (n > 1)
|
||||
{
|
||||
int j = Random() % (n+1);
|
||||
memcpy(tmp, (u8 *)data + n*size, size); // tmp = data[n];
|
||||
memcpy((u8 *)data + n*size, (u8 *)data + j*size, size); // data[n] = data[j];
|
||||
memcpy((u8 *)data + j*size, tmp, size); // data[j] = tmp;
|
||||
--n;
|
||||
}
|
||||
}
|
||||
|
||||
__attribute__((weak, alias("RandomUniformDefault")))
|
||||
u32 RandomUniform(enum RandomTag tag, u32 lo, u32 hi);
|
||||
|
||||
|
@ -2,6 +2,47 @@
|
||||
#include "test.h"
|
||||
#include "random.h"
|
||||
|
||||
// We expect each element to have an indexSum of 3.5 * 1024.
|
||||
// Therefore the maximum error is 8*3584, or 28672.
|
||||
#define SHUFFLE_TEST_IMPL \
|
||||
u32 i, j, error; \
|
||||
u16 indexSum[7]; \
|
||||
memset(indexSum, 0, sizeof(indexSum)); \
|
||||
for (i = 0; i < 1024; i++) \
|
||||
{ \
|
||||
Shuffle(array, ARRAY_COUNT(array), sizeof(array[0])); \
|
||||
for (j = 0; j < ARRAY_COUNT(array); j++) \
|
||||
indexSum[array[j]] += j; \
|
||||
} \
|
||||
error = 0; \
|
||||
for (i = 0; i < ARRAY_COUNT(indexSum); i++) \
|
||||
error += abs(3584 - indexSum[i]); \
|
||||
EXPECT_LT(error, (int)(28672 * 0.025));
|
||||
|
||||
TEST("Shuffle randomizes the array [Shuffle8]")
|
||||
{
|
||||
u8 array[8] = { 0, 1, 2, 3, 4, 5, 6, 7 };
|
||||
SHUFFLE_TEST_IMPL;
|
||||
}
|
||||
|
||||
TEST("Shuffle randomizes the array [Shuffle16]")
|
||||
{
|
||||
u16 array[8] = { 0, 1, 2, 3, 4, 5, 6, 7 };
|
||||
SHUFFLE_TEST_IMPL;
|
||||
}
|
||||
|
||||
TEST("Shuffle randomizes the array [Shuffle32]")
|
||||
{
|
||||
u32 array[8] = { 0, 1, 2, 3, 4, 5, 6, 7 };
|
||||
SHUFFLE_TEST_IMPL;
|
||||
}
|
||||
|
||||
TEST("Shuffle randomizes the array [Shuffle64]")
|
||||
{
|
||||
u64 array[8] = { 0, 1, 2, 3, 4, 5, 6, 7 };
|
||||
SHUFFLE_TEST_IMPL;
|
||||
}
|
||||
|
||||
TEST("RandomUniform generates lo..hi")
|
||||
{
|
||||
u32 lo, hi, i;
|
||||
|
Loading…
Reference in New Issue
Block a user