namespace PKHeX.Core;
///
/// Generation 3 & 4 RNG logic.
///
public static class ClassicEraRNG
{
///
/// Generate a chain shiny PID for the provided trainer ID.
///
/// Seed to use for the RNG.
/// Trainer ID to use for the PID generation.
/// Shiny PID.
/// Consumes 15 RNG calls
public static uint GetChainShinyPID(ref uint seed, in uint id32)
{
// 1 3-bit for lower
// 1 3-bit for upper
// 13 rand bits
uint lower = LCRNG.Next16(ref seed) & 7;
uint upper = LCRNG.Next16(ref seed) & 7;
for (int i = 3; i < 16; i++)
lower |= (LCRNG.Next16(ref seed) & 1) << i;
var tid16 = (ushort)(id32 & 0xFFFFu);
var sid16 = (ushort)(id32 >> 16);
upper = ((lower ^ tid16 ^ sid16) & 0xFFF8) | (upper & 0x7);
return (upper << 16) | lower;
}
///
/// Rolls the RNG forward twice to get the usual Method 1 call-ordered PID.
///
/// Seed right before the first PID call.
/// 32-bit value containing the PID (high | low).
public static uint GetSequentialPID(ref uint seed)
{
var rand1 = LCRNG.Next16(ref seed);
var rand2 = LCRNG.Next16(ref seed);
return (rand2 << 16) | rand1;
}
///
/// Rolls the RNG forward twice to get the usual Method 1 call-ordered PID.
///
/// Seed right before the first PID call.
/// 32-bit value containing the PID (high | low).
public static uint GetSequentialPID(uint seed)
{
var rand1 = LCRNG.Next16(ref seed);
var rand2 = LCRNG.Next16(ref seed);
return (rand2 << 16) | rand1;
}
///
/// Rolls the RNG forward twice to get the reverse Method 1 call-ordered PID.
///
/// Seed right before the first PID call.
/// Generation 3 Unown
/// 32-bit value containing the PID (high | low).
public static uint GetReversePID(ref uint seed)
{
var rand1 = LCRNG.Next16(ref seed);
var rand2 = LCRNG.Next16(ref seed);
return (rand2 << 16) | rand1;
}
///
/// Rolls the RNG forward twice to get the reverse Method 1 call-ordered PID.
///
/// Seed right before the first PID call.
/// Generation 3 Unown
/// 32-bit value containing the PID (high | low).
public static uint GetReversePID(uint seed)
{
var rand1 = LCRNG.Next16(ref seed);
var rand2 = LCRNG.Next16(ref seed);
return (rand1 << 16) | rand2;
}
///
/// Generates IVs for a given seed.
///
/// Seed to use for the RNG.
/// 32-bit value containing the IVs (HABSCD, low->high).
public static uint GetSequentialIVs(ref uint seed)
{
var rand1 = LCRNG.Next16(ref seed);
var rand2 = LCRNG.Next16(ref seed);
return (rand2 << 15) | rand1;
}
}