using NUnit.Framework; using ProjectM.Simulation; using Unity.Mathematics; namespace ProjectM.Tests { /// /// Pure-function tests for (no ECS world), mirroring PlayerSpawnRingTests. /// Pins the locked M5 home-base grid coordinate space: planar 32x32, CellSize 1.0, corner-origin, /// center-returning, half-open cell bounds, floor-based world->cell. M6 placement builds on this. /// public class BaseGridMathTests { const float Eps = 1e-4f; // Locked config: center at (0,1,0); 32x32 cells of 1.0u => origin corner at (-16,1,-16). static BaseAnchor MakeAnchor() { var dims = new int2(32, 32); float cell = 1f; var anchorPos = new float3(0f, 1f, 0f); var gridOrigin = new float3( anchorPos.x - dims.x * cell * 0.5f, anchorPos.y, anchorPos.z - dims.y * cell * 0.5f); return new BaseAnchor { AnchorPos = anchorPos, GridOrigin = gridOrigin, CellSize = cell, GridDims = dims }; } [Test] public void CellToWorld_Returns_Cell_Centers() { var a = MakeAnchor(); AssertXz(BaseGridMath.CellToWorld(a, new int2(0, 0)), -15.5f, -15.5f); AssertXz(BaseGridMath.CellToWorld(a, new int2(31, 31)), 15.5f, 15.5f); AssertXz(BaseGridMath.CellToWorld(a, new int2(16, 16)), 0.5f, 0.5f); // Centers stay on the base plane. Assert.AreEqual(1f, BaseGridMath.CellToWorld(a, new int2(5, 9)).y, Eps); } [Test] public void RoundTrip_CellToWorld_Then_WorldToCell() { var a = MakeAnchor(); AssertCell(BaseGridMath.WorldToCell(a, BaseGridMath.CellToWorld(a, new int2(0, 0))), 0, 0); AssertCell(BaseGridMath.WorldToCell(a, BaseGridMath.CellToWorld(a, new int2(31, 31))), 31, 31); AssertCell(BaseGridMath.WorldToCell(a, BaseGridMath.CellToWorld(a, new int2(16, 16))), 16, 16); } [Test] public void WorldToCell_Uses_Floor_Not_Truncation() { var a = MakeAnchor(); // local x = worldX + 16, then floor. z = 0 -> cell.y = 16. Assert.AreEqual(0, BaseGridMath.WorldToCell(a, new float3(-15.6f, 1f, 0f)).x); Assert.AreEqual(-1, BaseGridMath.WorldToCell(a, new float3(-16.4f, 1f, 0f)).x); // A point exactly on a cell's lower edge belongs to the higher cell (half-open). Assert.AreEqual(1, BaseGridMath.WorldToCell(a, new float3(-15.0f, 1f, 0f)).x); Assert.AreEqual(16, BaseGridMath.WorldToCell(a, new float3(-15.6f, 1f, 0f)).y); } [Test] public void IsCellInPlot_Is_HalfOpen() { var a = MakeAnchor(); Assert.IsTrue(BaseGridMath.IsCellInPlot(a, new int2(0, 0))); Assert.IsTrue(BaseGridMath.IsCellInPlot(a, new int2(31, 31))); Assert.IsFalse(BaseGridMath.IsCellInPlot(a, new int2(-1, 0))); Assert.IsFalse(BaseGridMath.IsCellInPlot(a, new int2(0, 32))); Assert.IsFalse(BaseGridMath.IsCellInPlot(a, new int2(32, 32))); } [Test] public void IsPointInPlot_Bounds() { var a = MakeAnchor(); Assert.IsTrue(BaseGridMath.IsPointInPlot(a, a.AnchorPos)); // center Assert.IsTrue(BaseGridMath.IsPointInPlot(a, new float3(-16f, 1f, 0f))); // lower corner edge -> cell 0 Assert.IsTrue(BaseGridMath.IsPointInPlot(a, new float3(15.9f, 1f, 15.9f))); // cell (31,31) Assert.IsFalse(BaseGridMath.IsPointInPlot(a, new float3(-16.1f, 1f, 0f))); // cell (-1,*) out Assert.IsFalse(BaseGridMath.IsPointInPlot(a, new float3(16f, 1f, 0f))); // far edge -> cell 32 out } [Test] public void ClampCell_Bounds_To_Plot() { var a = MakeAnchor(); AssertCell(BaseGridMath.ClampCell(a, new int2(-5, 99)), 0, 31); AssertCell(BaseGridMath.ClampCell(a, new int2(10, 10)), 10, 10); } [Test] public void PlotCenter_Equals_AnchorPos() { var a = MakeAnchor(); var c = BaseGridMath.PlotCenter(a); Assert.AreEqual(a.AnchorPos.x, c.x, Eps); Assert.AreEqual(a.AnchorPos.y, c.y, Eps); Assert.AreEqual(a.AnchorPos.z, c.z, Eps); } static void AssertXz(float3 p, float x, float z) { Assert.AreEqual(x, p.x, Eps); Assert.AreEqual(z, p.z, Eps); } static void AssertCell(int2 c, int x, int y) { Assert.AreEqual(x, c.x); Assert.AreEqual(y, c.y); } } }