Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 12 additions & 15 deletions Assets/Tests/EditMode/AI/SkirmishAiTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ public sealed class SkirmishAiTests

/// <summary>
/// End-to-end tick budget: this suite's deterministic match decides
/// at tick 2705, so 6.000 ticks is a ~2.2x margin — comfortably sane,
/// at tick 2726, so 6.000 ticks is a ~2.2x margin — comfortably sane,
/// and exact because the whole loop is deterministic.
/// </summary>
private const int EndToEndBudgetTicks = 6000;
Expand Down Expand Up @@ -189,10 +189,10 @@ private static void ApplyOpeningPosition(AiHost host)
for (byte slot = 0; slot < 2; slot++)
{
ushort fieldId = (ushort)(slot + 1);
int fieldCell = slot == HumanSlot ? 7 : 119;
int hqOrigin = slot == HumanSlot ? 4 : 120;
int builderX = slot == HumanSlot ? 13 : 113;
int builderY = slot == HumanSlot ? 7 : 119;
int fieldCell = slot == HumanSlot ? 7 : 117;
int hqOrigin = slot == HumanSlot ? 4 : 118;
int builderX = slot == HumanSlot ? 13 : 111;
int builderY = slot == HumanSlot ? 7 : 117;

Assert.That(host.Economy.TryAddField(fieldId, new GridPos2D(fieldCell, fieldCell), FieldReserveAE),
Is.True, $"field {fieldId} could not be registered");
Expand Down Expand Up @@ -286,15 +286,12 @@ public void SkirmishAi_PlacesRefineryPowerThenBarracks_ThroughTheSealedCommandPa
if (barracksTick == 0 && host.Construction.HasFinishedBuilding(AiSlot, UnitRole.Barracks)) barracksTick = tick;
}

Assert.Multiple(() =>
{
Assert.That(refineryTick, Is.GreaterThan(0u),
"the AI must place and complete its Refinery (D-077: no prerequisite) through PlaceBuilding intents");
Assert.That(powerTick, Is.GreaterThan(refineryTick),
"D-103 requires the AI to complete a Power plant after the Refinery and before its Barracks");
Assert.That(barracksTick, Is.GreaterThan(powerTick),
"the AI must complete the Barracks only after its required Power plant stands");
});
Assert.That(refineryTick, Is.GreaterThan(0u),
"the AI must place and complete its Refinery (D-077: no prerequisite) through PlaceBuilding intents");
Assert.That(powerTick, Is.GreaterThan(refineryTick),
"D-103 requires the AI to complete a Power plant after the Refinery and before its Barracks");
Assert.That(barracksTick, Is.GreaterThan(powerTick),
"the AI must complete the Barracks only after its required Power plant stands");
Assert.That(host.Construction.HasFinishedBuilding(HumanSlot, UnitRole.Refinery), Is.False,
"slot 0 is the passive fixture: nobody issues orders for it");

Expand Down Expand Up @@ -373,7 +370,7 @@ public void SkirmishAi_ProducesInfantry_AndMarchesPastMidMap()
Assert.That(CountUnits(host, AiSlot, UnitRole.BasicInfantry), Is.GreaterThanOrEqualTo(6),
"the Barracks keeps infantry queued — the attack threshold of the profile must be reachable");
Assert.That(MinCombatCellX(host, AiSlot), Is.LessThan(64),
"at the squad threshold the army marches toward the enemy start area (slot 1 starts at x ~ 113-122)");
"at the squad threshold the army marches toward the enemy start area (slot 1 starts at x ~ 111-120)");
}

// ----------------------------------------------------------------
Expand Down
55 changes: 53 additions & 2 deletions Assets/Tests/EditMode/Gameplay/CanonicalMatchSetupTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,8 @@ private struct FieldLayout
// slot 0 Alliance (role value), slot 1 Legion (role value + 17).
private const ushort DefHQAlliance = 3;
private const ushort DefHQLegion = 20;
private const ushort DefRefineryAlliance = 4;
private const ushort DefRefineryLegion = 21;

private sealed class ReferenceHost
{
Expand Down Expand Up @@ -196,7 +198,7 @@ private sealed class SlotLayout

private static readonly SlotLayout Slot1Layout = new SlotLayout
{
HqOriginX = 120, HqOriginY = 120,
HqOriginX = 118, HqOriginY = 118,
BuilderX = 111, BuilderY = 117,
};

Expand Down Expand Up @@ -401,7 +403,7 @@ public void MatchBootstrap_PlacesTheCanonicalOpeningGeometry()
new Vector2Int(62, 62),
}));
Assert.That(bootstrap.LocalHqOrigin, Is.EqualTo(new Vector2Int(4, 4)));
Assert.That(bootstrap.EnemyHqOrigin, Is.EqualTo(new Vector2Int(120, 120)));
Assert.That(bootstrap.EnemyHqOrigin, Is.EqualTo(new Vector2Int(118, 118)));
Assert.That(bootstrap.MapSize, Is.EqualTo(new Vector2Int(MapWidth, MapHeight)));

Assert.That(bootstrap.Runner.Session.LocalSlot, Is.EqualTo((byte)MatchBootstrap.LocalSlot),
Expand Down Expand Up @@ -438,6 +440,55 @@ public void ReferenceOpeningPosition_RegistersFiveFiniteFields()
}
}

[Test]
public void CanonicalOpeningGeometry_UsesD107PointAndFootprintMirrors()
{
Assert.That(Slot0Layout.HqOriginX + Slot1Layout.HqOriginX, Is.EqualTo(122),
"3x3 footprint origins mirror as o -> 122-o");
Assert.That(Slot0Layout.HqOriginY + Slot1Layout.HqOriginY, Is.EqualTo(122));
Assert.That(Slot0Layout.BuilderX + Slot1Layout.BuilderX, Is.EqualTo(124),
"point coordinates mirror as p -> 124-p");
Assert.That(Slot0Layout.BuilderY + Slot1Layout.BuilderY, Is.EqualTo(124));
Assert.That(FieldLayouts[0].X + FieldLayouts[1].X, Is.EqualTo(124));
Assert.That(FieldLayouts[0].Y + FieldLayouts[1].Y, Is.EqualTo(124));
Assert.That(FieldLayouts[2].X + FieldLayouts[3].X, Is.EqualTo(124));
Assert.That(FieldLayouts[2].Y + FieldLayouts[3].Y, Is.EqualTo(124));
Assert.That(FieldLayouts[4].X, Is.EqualTo(62));
Assert.That(FieldLayouts[4].Y, Is.EqualTo(62));
}

[Test]
public void CanonicalOpeningGeometry_OffersEqualMirroredRefineryPlacements()
{
ReferenceHost host = BuildReferenceHost(CanonicalSeed);
ApplyOpeningPosition(host);
host.Kernel.StepTick(); // commit the two completed HQ power balances
int mismatches = 0;
int allianceApplied = 0;
int legionApplied = 0;

for (int y = 0; y <= 122; y++)
{
for (int x = 0; x <= 122; x++)
{
CommandResultCode alliance = host.Construction.ValidatePlacement(
0, DefRefineryAlliance, x, y);
CommandResultCode legion = host.Construction.ValidatePlacement(
1, DefRefineryLegion, 122 - x, 122 - y);
if (alliance != legion) mismatches++;
if (alliance == CommandResultCode.Applied) allianceApplied++;
if (legion == CommandResultCode.Applied) legionApplied++;
}
}

Assert.That(mismatches, Is.EqualTo(0),
"D-107 requires every legal or rejected refinery origin to mirror exactly");
Assert.That(allianceApplied, Is.EqualTo(45),
"the corrected Alliance opening has 45 legal follow-up refinery origins");
Assert.That(legionApplied, Is.EqualTo(45),
"the corrected Legion opening has the same 45 legal mirrored origins");
}

[Test]
public void ReferenceOpeningPosition_IsSeedSensitive()
{
Expand Down
5 changes: 4 additions & 1 deletion Assets/Tests/EditMode/Simulation/CombatSystemTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -116,10 +116,13 @@ private static EntityId PlaceActiveDefensePlatformSite(TestHost host, byte team,
FactionId faction = host.Economy.GetSlotFaction(team);
ushort powerDefId = SimDefinitions.ToDefinitionId(faction, UnitRole.Power);
ushort platformDefId = SimDefinitions.ToDefinitionId(faction, UnitRole.DefensePlatform);
Assert.That(host.Construction.PlaceCompletedBuilding(team, powerDefId, 50, 50).IsValid, Is.True,
EntityId power = host.Construction.PlaceCompletedBuilding(team, powerDefId, originX + 6, originY);
Assert.That(power.IsValid, Is.True,
"a completed Power plant unlocks the DefensePlatform site");
host.Economy.ExecuteTick(Tick.Zero);
Assert.That(host.Construction.TryPlaceBuilding(team, platformDefId, originX, originY), Is.True);
Assert.That(host.Entities.DespawnUnit(power), Is.True,
"remove the fixture anchor so combat can observe only the active site");

UnitState[] units = host.Entities.RawUnits;
for (int i = 0; i < host.Entities.Capacity; i++)
Expand Down
Loading
Loading