Support deep cloning for BattleRandom

This commit is contained in:
2024-12-29 15:00:15 +01:00
parent 40803f0269
commit 9bdd584b54
3 changed files with 64 additions and 15 deletions

View File

@@ -1,5 +1,6 @@
using System.Diagnostics.CodeAnalysis;
using System.Reflection;
using Pcg;
using PkmnLib.Dynamic.Models;
using PkmnLib.Static;
using PkmnLib.Static.Species;
@@ -123,7 +124,7 @@ public class DeepCloneTests
await Assert.That(clone).IsNotEqualTo(battle);
await Assert.That(clone.Sides[0].Pokemon[0]).IsNotEqualTo(battle.Sides[0].Pokemon[0]);
await Assert.That(clone.Sides[1].Pokemon[0]).IsNotEqualTo(battle.Sides[1].Pokemon[0]);
await Assert.That(clone.Sides[0].Pokemon[0]!.Species).IsEqualTo(battle.Sides[0].Pokemon[0]!.Species);
await Assert.That(clone.Sides[1].Pokemon[0]!.Species).IsEqualTo(battle.Sides[1].Pokemon[0]!.Species);
@@ -137,4 +138,40 @@ public class DeepCloneTests
await Assert.That(pokemon.BattleData!.SeenOpponents).DoesNotContain(battle.Sides[1].Pokemon[0]!);
await Assert.That(pokemon.StatBoost.Defense).IsEqualTo((sbyte)2);
}
/// <summary>
/// We have custom handling for the random number generator within the deep cloning handling. We need to ensure that
/// the random number generator is cloned correctly, so that the state of the random number generator is the same
/// in the clone as it is in the original, while still being a different instance.
/// </summary>
[Test]
public async Task DeepCloneIntegrationTestsBattleRandom()
{
var battleRandom = new BattleRandomImpl(0);
battleRandom.GetInt();
var clone = battleRandom.DeepClone();
await Assert.That(clone).IsNotEqualTo(battleRandom);
// We hack out way into the private fields of the random number generator to ensure that the state is the same
// in the clone as it is in the original. None of this is part of the public API, so we use reflection to
// access the private fields.
var pcgRandomField = typeof(RandomImpl).GetField("_random", BindingFlags.NonPublic | BindingFlags.Instance)!;
var pcgRandom = (PcgRandom)pcgRandomField.GetValue(battleRandom)!;
var clonePcgRandom = (PcgRandom)pcgRandomField.GetValue(clone)!;
await Assert.That(clonePcgRandom).IsNotEqualTo(pcgRandom);
var pcgRngField = typeof(PcgRandom).GetField("_rng", BindingFlags.NonPublic | BindingFlags.Instance)!;
var pcgRng = pcgRngField.GetValue(pcgRandom)!;
var clonePcgRng = pcgRngField.GetValue(clonePcgRandom)!;
var pcgStateField = pcgRng.GetType().GetField("_state", BindingFlags.NonPublic | BindingFlags.Instance)!;
var pcgState = pcgStateField.GetValue(pcgRng);
var clonePcgState = pcgStateField.GetValue(clonePcgRng);
await Assert.That(clonePcgState).IsEqualTo(pcgState);
var randomNumber = battleRandom.GetInt();
var cloneRandomNumber = clone.GetInt();
await Assert.That(cloneRandomNumber).IsEqualTo(randomNumber);
}
}