Fester Simulationstakt und Ansichten, die nur lesen; Nachweis, dass die Partie bei jeder Bildrate dieselbe ist. - LuneClock: Akkumulator, ganze Schritte zu 0,05 s, Alpha zum Interpolieren. - LuneMatchRunner: Host-Ablauf einer Bot-Partie (Planung über die Befehlsschnittstelle, Kampf im festen Takt, Abrechnung, nächste Runde); LuneMatchDriver reicht in Update nur Bildzeit weiter. - LuneTrace: Fingerabdruck der Partie (jeder Schritt, jede Abrechnung) und der reine Kernlauf zum Vergleich. - Ansichten: LuneMatchView, LuneUnitView (interpolierte Position, Blickrichtung, Clips aus Kampfereignissen, Teamring, Lebensbalken), LuneBuildingView mit Einsturz und Ruine aus den autoritativen HP, Turmblitze, LuneCameraRig wie lune_camera.gd, vorläufige Debug-Anzeige (kein HUD; U3 portiert das G3-HUD). - Einheitenbibliothek: Kohlenbeißer aus 131 Teilen zu einem Mesh, Animator- Controller mit den Blender-Clips, Ring- und Balkenmeshes, Markermaterialien. - Tests: EditMode (30/60/120 fps, unbegrenzt, Ruckler, 8x Tempo; Seed 2 und Seed 9 ab Runde 21) und PlayMode in der Szene bei echten Bildraten 30, 60, 120 und unbegrenzt: überall derselbe Fingerabdruck wie der Kern. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
86 lines
3.3 KiB
C#
86 lines
3.3 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using Luneraria.Core;
|
|
|
|
namespace Luneraria.View
|
|
{
|
|
/// <summary>
|
|
/// Fingerprint of a match (U2C): FNV-1a over every combat step (step, time, and per unit id,
|
|
/// alive, hit points, position, target) and every settlement (gains, lost buildings, winner).
|
|
/// Two runs are the same match exactly when their fingerprints are equal; the Unity match and
|
|
/// the plain core run are compared this way at any frame rate.
|
|
/// </summary>
|
|
public sealed class LuneTrace
|
|
{
|
|
const ulong Offset = 14695981039346656037UL;
|
|
const ulong Prime = 1099511628211UL;
|
|
ulong _hash = Offset;
|
|
public int Steps;
|
|
public readonly List<ulong> RoundHashes = new List<ulong>();
|
|
public readonly List<string> Rounds = new List<string>();
|
|
|
|
public ulong Hash { get { return _hash; } }
|
|
|
|
void Mix(ulong value)
|
|
{
|
|
for (int i = 0; i < 8; i++)
|
|
{
|
|
_hash ^= (value >> (i * 8)) & 0xFF;
|
|
_hash *= Prime;
|
|
}
|
|
}
|
|
|
|
void Mix(double value) { Mix((ulong)BitConverter.DoubleToInt64Bits(value)); }
|
|
void Mix(float value) { Mix((ulong)(uint)BitConverter.ToInt32(BitConverter.GetBytes(value), 0)); }
|
|
|
|
public void RecordStep(LuneCombat combat)
|
|
{
|
|
Steps++;
|
|
Mix((ulong)combat.Steps);
|
|
Mix(combat.Elapsed);
|
|
foreach (LuneUnit unit in combat.Units)
|
|
{
|
|
Mix((ulong)unit.Id);
|
|
Mix(unit.Alive ? 1UL : 0UL);
|
|
Mix(unit.Hp);
|
|
Mix(unit.Position.X);
|
|
Mix(unit.Position.Y);
|
|
Mix((ulong)(unit.Target != null ? unit.Target.Id : 0));
|
|
}
|
|
}
|
|
|
|
public void RecordSettlement(LuneMatch match)
|
|
{
|
|
Settlement settlement = match.LastSettlement;
|
|
foreach (int gain in settlement.Gains)
|
|
Mix((ulong)(uint)gain);
|
|
foreach (string building in settlement.BuildingsLost)
|
|
foreach (char c in building)
|
|
Mix((ulong)c);
|
|
Mix((ulong)(uint)match.Winner);
|
|
RoundHashes.Add(_hash);
|
|
Rounds.Add(string.Format("round {0}: {1} steps, lost [{2}], winner {3}", settlement.Round, match.Combat != null ? match.Combat.Steps : 0,
|
|
string.Join(",", settlement.BuildingsLost), match.Winner));
|
|
}
|
|
|
|
/// <summary>The same match without Unity: plan, begin, step to the end, round after round.</summary>
|
|
public static LuneTrace RunCore(MatchOptions options, int startRound, int extraGold, string profile, int maxRound = 60)
|
|
{
|
|
var match = LuneMatchRunner.NewMatch(options, startRound, extraGold);
|
|
var trace = new LuneTrace();
|
|
while (match.Phase != Phase.Over && match.RoundNumber <= maxRound)
|
|
{
|
|
for (int slot = 0; slot < 6; slot++)
|
|
LuneBot.Plan(match, slot, profile);
|
|
match.BeginCombat();
|
|
while (match.Phase == Phase.Combat)
|
|
{
|
|
match.StepCombat();
|
|
trace.RecordStep(match.Combat);
|
|
}
|
|
trace.RecordSettlement(match);
|
|
}
|
|
return trace;
|
|
}
|
|
}
|
|
}
|