using Luneraria.Core; using UnityEngine; namespace Luneraria.View { /// /// Hosts a match in the scene (U2C/U2D; human seat and tempo since U3). Update only hands frame /// time (times the speed) to the runner's fixed clock; it never decides anything in combat. /// Seed, start round and extra gold are the public fixtures of the golden scenarios. With /// HumanSlot >= 0 the HUD plans that seat and planning waits for its Ready; tempo steps /// (1×, 2×, 4×) and pause act only in combat, as in Godot (lune_game.gd). /// public sealed class LuneMatchDriver : MonoBehaviour { /// Tempo steps of the HUD's tempo button. public static readonly int[] SpeedSteps = { 1, 2, 4 }; public int Seed = 2; public int StartRound = 1; public int ExtraGold; public string Profile = ""; /// The seat a human plays through the HUD; -1 for a bot match (U2 tests, benchmark). public int HumanSlot = -1; /// Match speed: simulated seconds per real second (tests run faster than 1). public float Speed = 1f; /// Index into SpeedSteps (the player's tempo, on top of Speed). public int SpeedIndex; public bool Paused; public bool RecordTrace = true; public LuneMatchRunner Runner { get; private set; } /// Main-thread cost of the last frame's simulation (milliseconds). public double LastAdvanceMs { get; private set; } readonly System.Diagnostics.Stopwatch _clock = new System.Diagnostics.Stopwatch(); public int Tempo { get { return SpeedSteps[Mathf.Clamp(SpeedIndex, 0, SpeedSteps.Length - 1)]; } } public void Restart() { Runner = new LuneMatchRunner(new MatchOptions { Seed = Seed, HumanSlot = HumanSlot }, StartRound, ExtraGold, Profile); if (RecordTrace) Runner.Trace = new LuneTrace(); SpeedIndex = 0; Paused = false; } /// Next tempo step (1× → 2× → 4× → 1×). public void CycleSpeed() { SpeedIndex = (SpeedIndex + 1) % SpeedSteps.Length; } /// Pause exists only in combat; planning waits for the player anyway. public bool TogglePause() { if (Runner == null || Runner.Current != LuneMatchRunner.Stage.Combat) return false; Paused = !Paused; return true; } void Awake() { if (Runner == null) Restart(); } void Update() { _clock.Restart(); // Pause holds only the combat steps (Godot: a paused game still plans and settles). if (!(Paused && Runner.Current == LuneMatchRunner.Stage.Combat)) Runner.Advance(Time.deltaTime * Speed * Tempo); LastAdvanceMs = _clock.Elapsed.TotalMilliseconds; } } }