test(p0): find_cell_list golden conformance — unambiguous interior picks
P0 Task 4. FindCellList resolves a sphere deep inside room 0171 -> 0171, deep inside vestibule 0170 -> 0170, and re-picks 0170 from a stale 0171 seed (membership re-picks by containment, not the seed). Retail-faithful by construction (candidate cells loaded from the real dats). The subtle doorway-threshold pick is the trace-backed golden (Task 6). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
a90f34368f
commit
ec78beb843
1 changed files with 87 additions and 0 deletions
|
|
@ -0,0 +1,87 @@
|
|||
using System.Numerics;
|
||||
using AcDream.Core.Physics;
|
||||
using DatReaderWriter;
|
||||
using DatReaderWriter.Options;
|
||||
using Xunit;
|
||||
|
||||
namespace AcDream.Core.Tests.Conformance;
|
||||
|
||||
/// <summary>
|
||||
/// P0 Task 4 — golden conformance for the membership pick
|
||||
/// <see cref="CellTransit.FindCellList"/> (retail CObjCell::find_cell_list
|
||||
/// @ 0x52b4e0 pc:308742). The unambiguous cases are retail-faithful by
|
||||
/// construction: the candidate cells are loaded from the same dats retail
|
||||
/// loads, and a sphere clearly inside one room can only resolve to that
|
||||
/// room. The subtle doorway-threshold pick (the 0031↔0170↔0171 ping-pong)
|
||||
/// is the trace-backed golden in FindCellListConformanceTests (Task 6).
|
||||
/// </summary>
|
||||
public class FindCellListConformanceTests
|
||||
{
|
||||
private const float FootRadius = 0.4f; // player foot-sphere radius
|
||||
|
||||
/// <summary>Cache the whole threshold building (016F..0175) so portal expansion is faithful.</summary>
|
||||
private static PhysicsDataCache LoadThresholdBuilding(DatCollection dats)
|
||||
{
|
||||
var cache = new PhysicsDataCache();
|
||||
for (uint low = 0x016Fu; low <= 0x0175u; low++)
|
||||
ConformanceDats.LoadEnvCell(dats, cache, ConformanceDats.HoltburgLandblock | low);
|
||||
return cache;
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void FindCellList_DeepInsideRoom0171_Returns0171()
|
||||
{
|
||||
var datDir = ConformanceDats.ResolveDatDir();
|
||||
if (datDir is null) return;
|
||||
using var dats = new DatCollection(datDir, DatAccessType.Read);
|
||||
var cache = LoadThresholdBuilding(dats);
|
||||
|
||||
var world = Vector3.Transform(
|
||||
CottageDoorwayCharacterizationTests.Interior0171Local,
|
||||
cache.GetCellStruct(CottageDoorwayCharacterizationTests.Room0171)!.WorldTransform);
|
||||
|
||||
uint picked = CellTransit.FindCellList(cache, world, FootRadius,
|
||||
CottageDoorwayCharacterizationTests.Room0171);
|
||||
Assert.Equal(CottageDoorwayCharacterizationTests.Room0171, picked);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void FindCellList_DeepInsideVestibule0170_Returns0170()
|
||||
{
|
||||
var datDir = ConformanceDats.ResolveDatDir();
|
||||
if (datDir is null) return;
|
||||
using var dats = new DatCollection(datDir, DatAccessType.Read);
|
||||
var cache = LoadThresholdBuilding(dats);
|
||||
|
||||
var world = Vector3.Transform(
|
||||
CottageDoorwayCharacterizationTests.Interior0170Local,
|
||||
cache.GetCellStruct(CottageDoorwayCharacterizationTests.Vestibule0170)!.WorldTransform);
|
||||
|
||||
uint picked = CellTransit.FindCellList(cache, world, FootRadius,
|
||||
CottageDoorwayCharacterizationTests.Vestibule0170);
|
||||
Assert.Equal(CottageDoorwayCharacterizationTests.Vestibule0170, picked);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Seeding from the WRONG current cell (room 0171) while standing deep inside
|
||||
/// the vestibule (0170) must still resolve to 0170 — find_cell_list re-picks by
|
||||
/// containment, it does not trust the stale seed. This is the membership-stability
|
||||
/// property P1 must preserve.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void FindCellList_InVestibule_SeededFromRoom_Returns0170()
|
||||
{
|
||||
var datDir = ConformanceDats.ResolveDatDir();
|
||||
if (datDir is null) return;
|
||||
using var dats = new DatCollection(datDir, DatAccessType.Read);
|
||||
var cache = LoadThresholdBuilding(dats);
|
||||
|
||||
var world = Vector3.Transform(
|
||||
CottageDoorwayCharacterizationTests.Interior0170Local,
|
||||
cache.GetCellStruct(CottageDoorwayCharacterizationTests.Vestibule0170)!.WorldTransform);
|
||||
|
||||
uint picked = CellTransit.FindCellList(cache, world, FootRadius,
|
||||
CottageDoorwayCharacterizationTests.Room0171); // stale/wrong seed
|
||||
Assert.Equal(CottageDoorwayCharacterizationTests.Vestibule0170, picked);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue