using System; using System.Collections.Generic; using Luneraria.Core; using NUnit.Framework; using UnityEngine; namespace Luneraria.View.Tests { /// /// U2C: the host loop gives the same match at every frame rate. The runner is fed frame /// times of 30, 60 and 120 FPS, of an unlimited frame rate (tiny, jittering frames), and of a /// stuttering machine (long stalls between short frames); every run must end with the state /// fingerprint of the plain core run (LuneTrace.RunCore), step for step and round for round. /// public sealed class FrameRateIndependenceTests { static readonly Dictionary> Rates = new Dictionary> { { "30 fps", frame => 1.0 / 30.0 }, { "60 fps", frame => 1.0 / 60.0 }, { "120 fps", frame => 1.0 / 120.0 }, { "unlimited (0.4-3.9 ms jitter)", frame => 0.0004 + ((frame * 7919) % 97) / 97.0 * 0.0035 }, { "stutter (stalls up to 0.4 s)", frame => frame % 23 == 0 ? 0.4 : 1.0 / 144.0 }, }; static void Compare(int seed, int startRound, int extraGold, double speed) { var options = new MatchOptions { Seed = seed, HumanSlot = -1 }; LuneTrace core = LuneTrace.RunCore(options, startRound, extraGold, ""); foreach (KeyValuePair> rate in Rates) { var runner = new LuneMatchRunner(options, startRound, extraGold) { Trace = new LuneTrace(), PlanningSeconds = .5, SettledSeconds = .5 }; int frames = 0; while (runner.Current != LuneMatchRunner.Stage.Over && frames < 20000000) runner.Advance(rate.Value(frames++) * speed); Debug.Log(string.Format("LUNE_FPS seed {0} {1}: {2} frames, {3} steps, hash {4:X16} (core {5:X16})", seed, rate.Key, frames, runner.Trace.Steps, runner.Trace.Hash, core.Hash)); Assert.AreEqual(core.Steps, runner.Trace.Steps, rate.Key + ": steps"); CollectionAssert.AreEqual(core.RoundHashes, runner.Trace.RoundHashes, rate.Key + ": round fingerprints"); Assert.AreEqual(core.Hash, runner.Trace.Hash, rate.Key + ": match fingerprint"); Assert.AreEqual(core.Rounds, runner.Trace.Rounds, rate.Key + ": rounds"); } } [Test] public void FullBotMatchSeed2IsTheSameAtEveryFrameRate() { Compare(2, 1, 0, 1.0); } [Test] public void HighWaveMatchFromRound21IsTheSameAtEveryFrameRate() { Compare(9, 21, 4000, 1.0); } [Test] public void MatchSpeedDoesNotChangeTheMatch() { Compare(2, 1, 0, 8.0); } [Test] public void ClockRunsWholeStepsOnly() { var clock = new LuneClock(0.05); int steps = 0; steps += clock.Advance(0.049, () => true); Assert.AreEqual(0, steps); Assert.That(clock.Alpha, Is.InRange(0.97, 0.99)); steps += clock.Advance(0.052, () => true); Assert.AreEqual(2, steps); Assert.That(clock.Alpha, Is.InRange(0.01, 0.03)); } } }