Files
MVP1/Assets/Scripts/Modules/Tests/PlacementTests.cs
T

140 lines
7.8 KiB
C#

using System.Collections.Generic;
using Bogatyri.Settlement.Placement;
using NUnit.Framework;
// Тесты размещения зданий в 3D-поселении (ТЗ «Система строительства поселения» от 04.11.2026, раздел 11).
// Запуск: Window -> General -> Test Runner -> EditMode -> Run All.
public class PlacementTests
{
// Карта 20 x 20: всё открыто с Ратуши 1, кроме правой полосы (x >= 15 -- Ратуша 2);
// река по x = 10, скала в (2, 18), дерево "tree_1" в (5, 5), холм справа вверху
static SettlementMap Map()
{
var map = new SettlementMap(20, 20);
for (int y = 0; y < 20; y++)
for (int x = 0; x < 20; x++)
{
CellKind k = x == 10 ? CellKind.Water : x == 2 && y == 18 ? CellKind.Mountain : CellKind.Ground;
int height = x >= 16 && y >= 16 ? (x - 16) * 500 : 0; // склон: 0,5 м на клетку
map.SetCell(x, y, k, height, x >= 15 ? 2 : 1);
}
map.AddObstacle("tree_1", new[] { (5, 5) });
return map;
}
[Test]
public void Placement_FlatGround_Ok_AndForbiddenPlaces()
{
var map = Map();
Assert.AreEqual(PlaceError.None, map.Place("hall", "Ратуша", 1, 1, 3, 3, 0, 1), "01: ровная земля");
Assert.AreEqual(PlaceError.Water, map.Validate(9, 2, 2, 2, 0, 1, null, out _), "02: река");
Assert.AreEqual(PlaceError.Mountain, map.Validate(1, 17, 2, 2, 0, 1, null, out _), "02: скала");
Assert.AreEqual(PlaceError.Obstacle, map.Validate(4, 4, 2, 2, 0, 1, null, out _), "дерево мешает");
Assert.AreEqual(PlaceError.OutOfMap, map.Validate(19, 19, 2, 2, 0, 1, null, out _), "за краем");
Assert.AreEqual(PlaceError.ZoneLocked, map.Validate(15, 2, 2, 2, 0, 1, null, out _), "зона Ратуши 2");
Assert.AreEqual(PlaceError.None, map.Validate(15, 2, 2, 2, 0, 2, null, out _), "11: Ратуша 2 открыла зону");
}
[Test]
public void Placement_IfCleared_IgnoresOnlyTreesAndListsThem()
{
var map = Map();
Assert.AreEqual(PlaceError.Obstacle, map.Validate(4, 4, 2, 2, 0, 1, null, out _), "дерево мешает");
Assert.AreEqual(PlaceError.None, map.ValidateIfCleared(4, 4, 2, 2, 0, 1, null, out _), "если расчистить -- можно");
var under = map.ObstaclesUnder(4, 4, 2, 2, 0);
Assert.AreEqual(1, under.Count, "под зданием -- одно дерево");
Assert.AreEqual("tree_1", under[0]);
Assert.AreEqual(0, map.ObstaclesUnder(1, 1, 2, 2, 0).Count, "рядом деревьев нет");
Assert.AreEqual(PlaceError.Water, map.ValidateIfCleared(9, 2, 2, 2, 0, 1, null, out _), "река остаётся рекой");
Assert.AreEqual(PlaceError.ZoneLocked, map.ValidateIfCleared(15, 2, 2, 2, 0, 1, null, out _), "закрытая зона -- закрыта");
map.Place("a", "Дом", 1, 1, 2, 2, 0, 1);
Assert.AreEqual(PlaceError.Occupied, map.ValidateIfCleared(1, 1, 2, 2, 0, 1, null, out _), "чужое здание мешает");
Assert.IsTrue(map.ClearObstacle("tree_1"));
Assert.AreEqual(PlaceError.None, map.Place("b", "Дом", 4, 4, 2, 2, 0, 1), "после расчистки ставится");
}
[Test]
public void Placement_GapBetweenBuildings()
{
var map = Map();
map.Place("a", "Дом", 1, 1, 2, 2, 0, 1);
Assert.AreEqual(PlaceError.Occupied, map.Validate(2, 2, 2, 2, 0, 1, null, out _));
Assert.AreEqual(PlaceError.TooClose, map.Validate(3, 1, 2, 2, 0, 1, null, out _), "03: вплотную -- нарушен отступ");
Assert.AreEqual(PlaceError.None, map.Validate(4, 1, 2, 2, 0, 1, null, out _), "через клетку -- можно");
}
[Test]
public void Placement_Rotation_SwapsFootprint()
{
var map = Map();
// 4 x 1 у реки: повёрнутое на 90 -- 1 x 4 -- помещается вдоль реки, без поворота -- упирается в неё
Assert.AreEqual(PlaceError.Water, map.Validate(7, 12, 4, 1, 0, 1, null, out _));
foreach (int rot in new[] { 90, 270 })
Assert.AreEqual(PlaceError.None, map.Validate(9, 12, 4, 1, rot, 1, null, out _), "04: поворот " + rot);
Assert.AreEqual(PlaceError.Water, map.Validate(7, 12, 4, 1, 180, 1, null, out _), "04: 180 -- как 0");
map.Place("long", "Склад", 9, 12, 4, 1, 90, 1);
Assert.IsTrue(map.TryGetBuilding("long", out var b));
Assert.AreEqual(1, b.W);
Assert.AreEqual(4, b.H);
Assert.AreEqual("long", map.BuildingAt(9, 15));
Assert.IsNull(map.BuildingAt(10, 12));
}
[Test]
public void Placement_Slope_FoundationOrTooSteep()
{
var map = Map();
Assert.AreEqual(PlaceError.None, map.Validate(16, 16, 2, 2, 0, 2, null, out int f), "небольшой перепад");
Assert.AreEqual(500, f, "фундамент 0,5 м");
Assert.AreEqual(PlaceError.TooSteep, map.Validate(16, 16, 3, 2, 0, 2, null, out _), "1 м -- слишком круто");
}
[Test]
public void Placement_Move_IsAtomic_KeepsId()
{
var map = Map();
map.Place("farm", "Ферма", 1, 1, 3, 3, 0, 1);
map.Place("mine", "Шахта", 12, 1, 2, 2, 0, 1);
Assert.AreEqual(PlaceError.None, map.Move("farm", 2, 1, 0, 1), "свой прежний след не мешает");
Assert.IsTrue(map.TryGetBuilding("farm", out var moved));
Assert.AreEqual(2, moved.X);
Assert.AreEqual(PlaceError.Water, map.Move("farm", 8, 1, 0, 1), "09: ошибка -- здание на месте");
map.TryGetBuilding("farm", out var same);
Assert.AreEqual(2, same.X);
Assert.AreEqual(2, map.Buildings.Count, "без дублей");
Assert.AreEqual(PlaceError.None, map.Move("mine", 12, 6, 90, 1), "05: шахту можно переносить и поворачивать");
Assert.AreEqual(PlaceError.OutOfMap, map.Move("nope", 1, 1, 0, 1));
}
[Test]
public void Placement_ClearObstacle_OnceOnly_SurvivesReload()
{
var map = Map();
Assert.IsTrue(map.ClearObstacle("tree_1"), "10: расчищено -- одна награда");
Assert.IsFalse(map.ClearObstacle("tree_1"), "второй раз -- без награды");
Assert.IsNull(map.ObstacleAt(5, 5));
Assert.AreEqual(PlaceError.None, map.Validate(4, 4, 2, 2, 0, 1, null, out _));
// Загрузка: расчищенное не возвращается, даже если отмечено раньше, чем объект добавлен на карту
var copy = new SettlementMap(20, 20);
for (int y = 0; y < 20; y++) for (int x = 0; x < 20; x++) copy.SetCell(x, y, CellKind.Ground, 0, 1);
copy.RestoreCleared(new List<string>(map.Cleared));
copy.AddObstacle("tree_1", new[] { (5, 5) });
Assert.IsNull(copy.ObstacleAt(5, 5));
Assert.IsFalse(copy.ClearObstacle("tree_1"));
}
[Test]
public void Placement_Restore_NoOverlaps()
{
var map = Map();
Assert.IsTrue(map.Restore(new PlacedRect { Id = "a", Type = "Дом", X = 1, Y = 1, SizeW = 2, SizeH = 2, Rotation = 0 }));
Assert.IsFalse(map.Restore(new PlacedRect { Id = "b", Type = "Дом", X = 2, Y = 2, SizeW = 2, SizeH = 2, Rotation = 0 }), "12: наложение не восстанавливается");
Assert.IsFalse(map.Restore(new PlacedRect { Id = "a", Type = "Дом", X = 6, Y = 6, SizeW = 2, SizeH = 2, Rotation = 0 }), "тот же id -- не дубль");
Assert.AreEqual(270, SettlementMap.NormalizeRotation(-90));
}
}