2017-12-05 19:27:33 +01:00
|
|
|
#ifndef GUARD_RANDOM_H
|
|
|
|
#define GUARD_RANDOM_H
|
2017-02-03 01:30:08 +01:00
|
|
|
|
|
|
|
extern u32 gRngValue;
|
|
|
|
extern u32 gRng2Value;
|
|
|
|
|
|
|
|
//Returns a 16-bit pseudorandom number
|
|
|
|
u16 Random(void);
|
|
|
|
u16 Random2(void);
|
|
|
|
|
|
|
|
//Returns a 32-bit pseudorandom number
|
|
|
|
#define Random32() (Random() | (Random() << 16))
|
2020-02-14 22:12:35 +01:00
|
|
|
|
|
|
|
// The number 1103515245 comes from the example implementation of rand and srand
|
|
|
|
// in the ISO C standard.
|
2020-02-14 22:05:43 +01:00
|
|
|
#define ISO_RANDOMIZE1(val)(1103515245 * (val) + 24691)
|
|
|
|
#define ISO_RANDOMIZE2(val)(1103515245 * (val) + 12345)
|
2017-02-03 01:30:08 +01:00
|
|
|
|
|
|
|
//Sets the initial seed value of the pseudorandom number generator
|
|
|
|
void SeedRng(u16 seed);
|
|
|
|
void SeedRng2(u16 seed);
|
|
|
|
|
2023-02-20 21:06:01 +01:00
|
|
|
/* 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
|
|
|
|
* meaningful value directly. This allows code to interpret the random
|
|
|
|
* call, for example, battle tests know what the domain of a random call
|
|
|
|
* is, and can exhaustively test it.
|
|
|
|
*
|
|
|
|
* RandomTag identifies the purpose of the value.
|
|
|
|
*
|
2023-03-27 18:32:16 +02:00
|
|
|
* RandomUniform(tag, lo, hi) returns a number from lo to hi inclusive
|
|
|
|
* with uniform probability.
|
|
|
|
*
|
2023-07-19 17:44:21 +02:00
|
|
|
* RandomUniformExcept(tag, lo, hi, reject) returns a number from lo to
|
|
|
|
* hi inclusive with uniform probability, excluding those for which
|
|
|
|
* reject returns TRUE.
|
|
|
|
*
|
2023-03-27 18:32:16 +02:00
|
|
|
* RandomElement(tag, array) returns an element in array with uniform
|
|
|
|
* probability. The array must be known at compile-time (e.g. a global
|
|
|
|
* const array).
|
2023-02-20 21:06:01 +01:00
|
|
|
*
|
|
|
|
* RandomPercentage(tag, t) returns FALSE with probability (1-t)/100,
|
|
|
|
* and TRUE with probability t/100.
|
|
|
|
*
|
|
|
|
* RandomWeighted(tag, w0, w1, ... wN) returns a number from 0 to N
|
|
|
|
* inclusive. The return value is proportional to the weights, e.g.
|
|
|
|
* RandomWeighted(..., 1, 1) returns 50% 0s and 50% 1s.
|
|
|
|
* RandomWeighted(..., 2, 1) returns 2/3 0s and 1/3 1s. */
|
|
|
|
|
|
|
|
enum RandomTag
|
|
|
|
{
|
|
|
|
RNG_NONE,
|
|
|
|
RNG_ACCURACY,
|
|
|
|
RNG_CONFUSION,
|
|
|
|
RNG_CRITICAL_HIT,
|
|
|
|
RNG_CUTE_CHARM,
|
|
|
|
RNG_DAMAGE_MODIFIER,
|
2023-03-27 18:32:16 +02:00
|
|
|
RNG_DIRE_CLAW,
|
2023-02-20 21:06:01 +01:00
|
|
|
RNG_FLAME_BODY,
|
|
|
|
RNG_FORCE_RANDOM_SWITCH,
|
|
|
|
RNG_FROZEN,
|
2023-07-20 11:14:12 +02:00
|
|
|
RNG_HITS,
|
2023-02-20 21:06:01 +01:00
|
|
|
RNG_HOLD_EFFECT_FLINCH,
|
|
|
|
RNG_INFATUATION,
|
2023-07-20 11:14:12 +02:00
|
|
|
RNG_LOADED_DICE,
|
2023-07-19 17:44:21 +02:00
|
|
|
RNG_METRONOME,
|
2023-02-20 21:06:01 +01:00
|
|
|
RNG_PARALYSIS,
|
|
|
|
RNG_POISON_POINT,
|
|
|
|
RNG_RAMPAGE_TURNS,
|
|
|
|
RNG_SECONDARY_EFFECT,
|
|
|
|
RNG_SLEEP_TURNS,
|
|
|
|
RNG_SPEED_TIE,
|
|
|
|
RNG_STATIC,
|
|
|
|
RNG_STENCH,
|
2023-03-27 18:32:16 +02:00
|
|
|
RNG_TRI_ATTACK,
|
2023-02-20 21:06:01 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
#define RandomWeighted(tag, ...) \
|
|
|
|
({ \
|
|
|
|
const u8 weights[] = { __VA_ARGS__ }; \
|
|
|
|
u32 sum, i; \
|
|
|
|
for (i = 0, sum = 0; i < ARRAY_COUNT(weights); i++) \
|
|
|
|
sum += weights[i]; \
|
|
|
|
RandomWeightedArray(tag, sum, ARRAY_COUNT(weights), weights); \
|
|
|
|
})
|
|
|
|
|
|
|
|
#define RandomPercentage(tag, t) \
|
|
|
|
({ \
|
2023-04-05 14:07:02 +02:00
|
|
|
u32 r; \
|
|
|
|
if (t <= 0) \
|
|
|
|
{ \
|
|
|
|
r = FALSE; \
|
|
|
|
} \
|
|
|
|
else if (t >= 100) \
|
|
|
|
{ \
|
|
|
|
r = TRUE; \
|
|
|
|
} \
|
|
|
|
else \
|
|
|
|
{ \
|
|
|
|
const u8 weights[] = { 100 - t, t }; \
|
|
|
|
r = RandomWeightedArray(tag, 100, ARRAY_COUNT(weights), weights); \
|
|
|
|
} \
|
|
|
|
r; \
|
2023-02-20 21:06:01 +01:00
|
|
|
})
|
|
|
|
|
2023-03-27 18:32:16 +02:00
|
|
|
#define RandomElement(tag, array) \
|
|
|
|
({ \
|
|
|
|
*(typeof((array)[0]) *)RandomElementArray(tag, array, sizeof((array)[0]), ARRAY_COUNT(array)); \
|
|
|
|
})
|
|
|
|
|
2023-02-20 21:06:01 +01:00
|
|
|
u32 RandomUniform(enum RandomTag, u32 lo, u32 hi);
|
2023-07-19 17:44:21 +02:00
|
|
|
u32 RandomUniformExcept(enum RandomTag, u32 lo, u32 hi, bool32 (*reject)(u32));
|
2023-02-20 21:06:01 +01:00
|
|
|
u32 RandomWeightedArray(enum RandomTag, u32 sum, u32 n, const u8 *weights);
|
2023-03-27 18:32:16 +02:00
|
|
|
const void *RandomElementArray(enum RandomTag, const void *array, size_t size, size_t count);
|
2023-02-20 21:06:01 +01:00
|
|
|
|
|
|
|
u32 RandomUniformDefault(enum RandomTag, u32 lo, u32 hi);
|
2023-07-19 17:44:21 +02:00
|
|
|
u32 RandomUniformExceptDefault(enum RandomTag, u32 lo, u32 hi, bool32 (*reject)(u32));
|
2023-02-20 21:06:01 +01:00
|
|
|
u32 RandomWeightedArrayDefault(enum RandomTag, u32 sum, u32 n, const u8 *weights);
|
2023-03-27 18:32:16 +02:00
|
|
|
const void *RandomElementArrayDefault(enum RandomTag, const void *array, size_t size, size_t count);
|
2023-02-20 21:06:01 +01:00
|
|
|
|
2017-12-05 19:27:33 +01:00
|
|
|
#endif // GUARD_RANDOM_H
|