mirror of
https://github.com/OatmealDome/Rotationator.git
synced 2026-04-24 23:26:55 -05:00
Program: Switch to sead::Random as the RNG
.NET's built-in algorithms don't let me save their internal state for debugging purposes.
This commit is contained in:
parent
7eebc76421
commit
8a34971659
|
|
@ -1,4 +1,4 @@
|
|||
using System.CommandLine;
|
||||
using System.CommandLine;
|
||||
using System.CommandLine.Invocation;
|
||||
using System.Text.Json;
|
||||
using OatmealDome.BinaryData;
|
||||
|
|
@ -54,8 +54,6 @@ List<VersusRule> defaultGachiRulePool = new List<VersusRule>()
|
|||
VersusRule.Lift
|
||||
};
|
||||
|
||||
Random random = new Random();
|
||||
|
||||
//
|
||||
// Command handling
|
||||
//
|
||||
|
|
@ -97,6 +95,11 @@ void Run(InvocationContext context)
|
|||
int phaseLength = context.ParseResult.GetValueForOption(phaseLengthOption);
|
||||
int scheduleLength = context.ParseResult.GetValueForOption(scheduleLengthOption);
|
||||
string? overridePhasesPath = context.ParseResult.GetValueForOption(overridePhasesOption);
|
||||
|
||||
uint seed = (uint)Environment.TickCount;
|
||||
SeadRandom random = new SeadRandom(seed);
|
||||
|
||||
Console.WriteLine("Random seed: " + seed);
|
||||
|
||||
dynamic lastByaml = ByamlFile.Load(lastByamlPath);
|
||||
|
||||
|
|
@ -256,7 +259,7 @@ void Run(InvocationContext context)
|
|||
for (int j = currentPhase.RegularInfo.Stages.Count; j < 2; j++)
|
||||
{
|
||||
currentPhase.RegularInfo.Stages.Add(PickStage(currentPhase, lastPhase, nextOverridePhase, VersusRule.Paint,
|
||||
stagePools[VersusRule.Paint]));
|
||||
stagePools[VersusRule.Paint], random));
|
||||
}
|
||||
|
||||
currentPhase.RegularInfo.Stages.Sort();
|
||||
|
|
@ -264,13 +267,13 @@ void Run(InvocationContext context)
|
|||
if (currentPhase.GachiInfo.Rule == VersusRule.None)
|
||||
{
|
||||
currentPhase.GachiInfo.Rule = PickGachiRule(currentPhase.GachiInfo, lastPhase.GachiInfo, nextOverridePhase,
|
||||
gachiRulePool);
|
||||
gachiRulePool, random);
|
||||
}
|
||||
|
||||
for (int j = currentPhase.GachiInfo.Stages.Count; j < 2; j++)
|
||||
{
|
||||
currentPhase.GachiInfo.Stages.Add(PickStage(currentPhase, lastPhase, nextOverridePhase,
|
||||
currentPhase.GachiInfo.Rule, stagePools[currentPhase.GachiInfo.Rule]));
|
||||
currentPhase.GachiInfo.Rule, stagePools[currentPhase.GachiInfo.Rule], random));
|
||||
}
|
||||
|
||||
currentPhase.GachiInfo.Stages.Sort();
|
||||
|
|
@ -320,14 +323,14 @@ void Run(InvocationContext context)
|
|||
// Utility function to pick a random element from a pool.
|
||||
//
|
||||
|
||||
T GetRandomElementFromPool<T>(List<T> pool, Func<T, bool> validityChecker)
|
||||
T GetRandomElementFromPool<T>(List<T> pool, Func<T, bool> validityChecker, SeadRandom random)
|
||||
{
|
||||
T element;
|
||||
int tries = 0;
|
||||
|
||||
do
|
||||
{
|
||||
element = pool[random.Next(0, pool.Count)];
|
||||
element = pool[random.GetInt32(pool.Count)];
|
||||
|
||||
tries++;
|
||||
|
||||
|
|
@ -347,7 +350,7 @@ T GetRandomElementFromPool<T>(List<T> pool, Func<T, bool> validityChecker)
|
|||
//
|
||||
|
||||
VersusRule PickGachiRule(GambitStageInfo stageInfo, GambitStageInfo lastStageInfo, OverridePhase? nextPhaseOverride,
|
||||
List<VersusRule> pool)
|
||||
List<VersusRule> pool, SeadRandom random)
|
||||
{
|
||||
if (pool.Count == 0)
|
||||
{
|
||||
|
|
@ -363,13 +366,13 @@ VersusRule PickGachiRule(GambitStageInfo stageInfo, GambitStageInfo lastStageInf
|
|||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return rule != lastStageInfo.Rule;
|
||||
});
|
||||
}, random);
|
||||
}
|
||||
|
||||
int PickStage(GambitVersusPhase phase, GambitVersusPhase lastPhase, OverridePhase? nextPhaseOverride, VersusRule rule,
|
||||
List<int> pool)
|
||||
List<int> pool, SeadRandom random)
|
||||
{
|
||||
List<int> bannedStagesForRule = bannedStages[rule];
|
||||
|
||||
|
|
@ -418,5 +421,5 @@ int PickStage(GambitVersusPhase phase, GambitVersusPhase lastPhase, OverridePhas
|
|||
pool = newPool.ToList();
|
||||
}
|
||||
|
||||
return GetRandomElementFromPool(pool, IsStageValid);
|
||||
return GetRandomElementFromPool(pool, IsStageValid, random);
|
||||
}
|
||||
|
|
|
|||
85
Rotationator/SeadRandom.cs
Normal file
85
Rotationator/SeadRandom.cs
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
namespace Rotationator;
|
||||
|
||||
// sead::Random
|
||||
public class SeadRandom
|
||||
{
|
||||
private readonly uint[] _state;
|
||||
|
||||
public SeadRandom() : this((uint)Environment.TickCount)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public SeadRandom(uint seed)
|
||||
{
|
||||
_state = new uint[4];
|
||||
_state[0] = 1812433253 * (seed ^ (seed >> 30)) + 1;
|
||||
_state[1] = 1812433253 * (_state[0] ^ (_state[0] >> 30)) + 2;
|
||||
_state[2] = 1812433253 * (_state[1] ^ (_state[1] >> 30)) + 3;
|
||||
_state[3] = 1812433253 * (_state[2] ^ (_state[2] >> 30)) + 4;
|
||||
}
|
||||
|
||||
public SeadRandom(uint seedOne, uint seedTwo, uint seedThree, uint seedFour)
|
||||
{
|
||||
_state = new uint[] { seedOne, seedTwo, seedThree, seedFour };
|
||||
}
|
||||
|
||||
public SeadRandom(uint[] context)
|
||||
{
|
||||
if (context.Length != 4)
|
||||
{
|
||||
throw new ArgumentException("Invalid context for SeadRandom");
|
||||
}
|
||||
|
||||
_state = context;
|
||||
}
|
||||
|
||||
public uint GetUInt32()
|
||||
{
|
||||
uint v1 = _state[0] ^ (_state[0] << 11);
|
||||
_state[0] = _state[1];
|
||||
uint v2 = _state[3];
|
||||
uint v3 = v1 ^ (v1 >> 8) ^ v2 ^ (v2 >> 19);
|
||||
_state[1] = _state[2];
|
||||
_state[2] = v2;
|
||||
_state[3] = v3;
|
||||
|
||||
return v3;
|
||||
}
|
||||
|
||||
// f32 al::getRandom()
|
||||
public float GetSingle()
|
||||
{
|
||||
uint random = (GetUInt32() >> 9) | 0x3F800000;
|
||||
return BitConverter.UInt32BitsToSingle(random) + -1.0f;
|
||||
}
|
||||
|
||||
// f32 al::getRandom(f32, f32)
|
||||
public float GetSingle(float min, float max)
|
||||
{
|
||||
return (GetSingle() * (max - min)) + min;
|
||||
}
|
||||
|
||||
// f32 al::getRandom(f32)
|
||||
public float GetSingle(float factor)
|
||||
{
|
||||
return GetSingle(0.0f, factor);
|
||||
}
|
||||
|
||||
// s32 al::getRandom(s32, s32)
|
||||
public int GetInt32(int min, int max)
|
||||
{
|
||||
return (int)GetSingle(min, max);
|
||||
}
|
||||
|
||||
// s32 al::getRandom(s32)
|
||||
public int GetInt32(int factor)
|
||||
{
|
||||
return GetInt32(0, factor);
|
||||
}
|
||||
|
||||
public uint[] GetContext()
|
||||
{
|
||||
return _state;
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user