This Trac instance is not used for development anymore!

We migrated our development workflow to git and Gitea.
To test the future redirection, replace trac by ariadne in the page URL.

source: ps/trunk/source/simulation2/components/tests/test_TerritoryManager.h

Last change on this file was 27965, checked in by Vladislav Belov, 13 months ago

Revert non-ASCII characters from source and configuration files introduced in rP27786.

Fixes #6846

Differential Revision: https://code.wildfiregames.com/D5185

  • Property svn:eol-style set to native
File size: 19.5 KB
Line 
1/* Copyright (C) 2023 Wildfire Games.
2 * This file is part of 0 A.D.
3 *
4 * 0 A.D. is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * 0 A.D. is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include "simulation2/system/ComponentTest.h"
19
20#include "maths/Matrix3D.h"
21#include "ps/CStr.h"
22#include "graphics/Terrain.h"
23#include "graphics/TerritoryBoundary.h"
24#include "simulation2/helpers/Grid.h"
25#include "simulation2/components/ICmpTerritoryManager.h"
26#include "simulation2/components/ICmpPlayerManager.h"
27#include "simulation2/components/ICmpTerritoryInfluence.h"
28#include "simulation2/components/ICmpOwnership.h"
29
30class MockPathfinderTerrMan : public ICmpPathfinder
31{
32public:
33 DEFAULT_MOCK_COMPONENT()
34
35 // Test data
36 Grid<NavcellData> m_PassabilityGrid;
37
38 virtual pass_class_t GetPassabilityClass(const std::string&) const override { return 0; }
39 virtual const Grid<NavcellData>& GetPassabilityGrid() override { return m_PassabilityGrid; }
40
41 // Irrelevant part of the mock.
42 virtual void GetPassabilityClasses(std::map<std::string, pass_class_t>&) const override {}
43 virtual void GetPassabilityClasses(std::map<std::string, pass_class_t>&, std::map<std::string, pass_class_t>&) const override {}
44 virtual entity_pos_t GetClearance(pass_class_t) const override { return entity_pos_t::FromInt(1); }
45 virtual entity_pos_t GetMaximumClearance() const override { return entity_pos_t::FromInt(1); }
46 virtual const GridUpdateInformation& GetAIPathfinderDirtinessInformation() const override { static GridUpdateInformation gridInfo; return gridInfo; }
47 virtual void FlushAIPathfinderDirtinessInformation() override {}
48 virtual Grid<u16> ComputeShoreGrid(bool = false) override { return Grid<u16> {}; }
49 virtual u32 ComputePathAsync(entity_pos_t, entity_pos_t, const PathGoal&, pass_class_t, entity_id_t) override { return 1; }
50 virtual void ComputePathImmediate(entity_pos_t, entity_pos_t, const PathGoal&, pass_class_t, WaypointPath&) const override {}
51 virtual u32 ComputeShortPathAsync(entity_pos_t, entity_pos_t, entity_pos_t, entity_pos_t, const PathGoal&, pass_class_t, bool, entity_id_t, entity_id_t) override { return 1; }
52 virtual WaypointPath ComputeShortPathImmediate(const ShortPathRequest&) const override { return WaypointPath(); }
53 virtual void SetDebugPath(entity_pos_t, entity_pos_t, const PathGoal&, pass_class_t) override {}
54 virtual bool IsGoalReachable(entity_pos_t, entity_pos_t, const PathGoal&, pass_class_t) override { return false; }
55 virtual bool CheckMovement(const IObstructionTestFilter&, entity_pos_t, entity_pos_t, entity_pos_t, entity_pos_t, entity_pos_t, pass_class_t) const override { return false; }
56 virtual ICmpObstruction::EFoundationCheck CheckUnitPlacement(const IObstructionTestFilter&, entity_pos_t, entity_pos_t, entity_pos_t, pass_class_t, bool = false) const override { return ICmpObstruction::FOUNDATION_CHECK_SUCCESS; }
57 virtual ICmpObstruction::EFoundationCheck CheckBuildingPlacement(const IObstructionTestFilter&, entity_pos_t, entity_pos_t, entity_pos_t, entity_pos_t, entity_pos_t, entity_id_t, pass_class_t) const override { return ICmpObstruction::FOUNDATION_CHECK_SUCCESS; }
58 virtual ICmpObstruction::EFoundationCheck CheckBuildingPlacement(const IObstructionTestFilter&, entity_pos_t, entity_pos_t, entity_pos_t, entity_pos_t, entity_pos_t, entity_id_t, pass_class_t, bool) const override { return ICmpObstruction::FOUNDATION_CHECK_SUCCESS; }
59 virtual void SetDebugOverlay(bool) override {}
60 virtual void SetHierDebugOverlay(bool) override {}
61 virtual void SendRequestedPaths() override {}
62 virtual void StartProcessingMoves(bool) override {}
63 virtual void UpdateGrid() override {}
64 virtual void GetDebugData(u32&, double&, Grid<u8>&) const override {}
65 virtual void SetAtlasOverlay(bool, pass_class_t = 0) override {}
66};
67
68class MockPlayerMgrTerrMan : public ICmpPlayerManager
69{
70public:
71 DEFAULT_MOCK_COMPONENT()
72
73 int32_t GetNumPlayers() override { return 2; }
74 entity_id_t GetPlayerByID(int32_t id) override { return id + 1; }
75};
76
77class MockTerrInfTerrMan : public ICmpTerritoryInfluence
78{
79public:
80 DEFAULT_MOCK_COMPONENT()
81
82 bool IsRoot() const override { return true; };
83 u16 GetWeight() const override { return 10; };
84 u32 GetRadius() const override { return m_Radius; };
85
86 u32 m_Radius = 0;
87};
88
89class MockOwnershipTerrMan : public ICmpOwnership
90{
91public:
92 DEFAULT_MOCK_COMPONENT()
93
94 player_id_t GetOwner() const override { return 1; };
95 void SetOwner(player_id_t) override {};
96 void SetOwnerQuiet(player_id_t) override {};
97};
98
99class MockPositionTerrMan : public ICmpPosition
100{
101public:
102 DEFAULT_MOCK_COMPONENT()
103
104 void SetTurretParent(entity_id_t, const CFixedVector3D&) override {}
105 entity_id_t GetTurretParent() const override { return INVALID_ENTITY; }
106 void UpdateTurretPosition() override {}
107 std::set<entity_id_t>* GetTurrets() override { return nullptr; }
108 bool IsInWorld() const override { return true; }
109 void MoveOutOfWorld() override {}
110 void MoveTo(entity_pos_t, entity_pos_t) override {}
111 void MoveAndTurnTo(entity_pos_t, entity_pos_t, entity_angle_t) override {}
112 void JumpTo(entity_pos_t, entity_pos_t) override {}
113 void SetHeightOffset(entity_pos_t) override {}
114 entity_pos_t GetHeightOffset() const override { return entity_pos_t::Zero(); }
115 void SetHeightFixed(entity_pos_t) override {}
116 entity_pos_t GetHeightFixed() const override { return entity_pos_t::Zero(); }
117 entity_pos_t GetHeightAtFixed(entity_pos_t, entity_pos_t) const override { return entity_pos_t::Zero(); }
118 bool IsHeightRelative() const override { return true; }
119 void SetHeightRelative(bool) override {}
120 bool CanFloat() const override { return false; }
121 void SetFloating(bool) override {}
122 void SetActorFloating(bool) override {}
123 void SetConstructionProgress(fixed) override {}
124 CFixedVector3D GetPosition() const override { return m_Pos; }
125 CFixedVector2D GetPosition2D() const override { return CFixedVector2D(m_Pos.X, m_Pos.Z); }
126 CFixedVector3D GetPreviousPosition() const override { return CFixedVector3D(); }
127 CFixedVector2D GetPreviousPosition2D() const override { return CFixedVector2D(); }
128 fixed GetTurnRate() const override { return fixed::Zero(); }
129 void TurnTo(entity_angle_t) override {}
130 void SetYRotation(entity_angle_t) override {}
131 void SetXZRotation(entity_angle_t, entity_angle_t) override {}
132 CFixedVector3D GetRotation() const override { return CFixedVector3D(); }
133 fixed GetDistanceTravelled() const override { return fixed::Zero(); }
134 void GetInterpolatedPosition2D(float, float&, float&, float&) const override {}
135 CMatrix3D GetInterpolatedTransform(float) const override { return CMatrix3D(); }
136
137 CFixedVector3D m_Pos;
138};
139
140
141class TestCmpTerritoryManager : public CxxTest::TestSuite
142{
143public:
144 void setUp()
145 {
146 CxxTest::setAbortTestOnFail(true);
147 g_VFS = CreateVfs();
148 TS_ASSERT_OK(g_VFS->Mount(L"", DataDir() / "mods" / "_test.sim" / "", VFS_MOUNT_MUST_EXIST));
149 TS_ASSERT_OK(g_VFS->Mount(L"cache", DataDir() / "_testcache" / "", 0, VFS_MAX_PRIORITY));
150 CXeromyces::Startup();
151 }
152
153 void tearDown()
154 {
155 CXeromyces::Terminate();
156 g_VFS.reset();
157 DeleteDirectory(DataDir()/"_testcache");
158 }
159
160 // Regression test for D5181 / fix for rP27673 issue
161 void test_calculate_territories_uninitialised()
162 {
163 ComponentTestHelper test(*g_ScriptContext);
164 ICmpTerritoryManager* cmp = test.Add<ICmpTerritoryManager>(CID_TerritoryManager, "", SYSTEM_ENTITY);
165
166 MockPathfinderTerrMan pathfinder;
167 test.AddMock(SYSTEM_ENTITY, IID_Pathfinder, pathfinder);
168
169 MockPlayerMgrTerrMan playerMan;
170 test.AddMock(SYSTEM_ENTITY, IID_PlayerManager, playerMan);
171
172 pathfinder.m_PassabilityGrid.resize(ICmpTerritoryManager::NAVCELLS_PER_TERRITORY_TILE * 5, ICmpTerritoryManager::NAVCELLS_PER_TERRITORY_TILE * 5);
173
174 MockTerrInfTerrMan terrInf;
175 test.AddMock(5, IID_TerritoryInfluence, terrInf);
176 MockOwnershipTerrMan ownership;
177 test.AddMock(5, IID_Ownership, ownership);
178 MockPositionTerrMan position;
179 test.AddMock(5, IID_Position, position);
180
181 position.m_Pos = CFixedVector3D(
182 entity_pos_t::FromInt(ICmpTerritoryManager::NAVCELLS_PER_TERRITORY_TILE * 5 + ICmpTerritoryManager::NAVCELLS_PER_TERRITORY_TILE / 2),
183 entity_pos_t::FromInt(1),
184 entity_pos_t::FromInt(ICmpTerritoryManager::NAVCELLS_PER_TERRITORY_TILE * 5 + ICmpTerritoryManager::NAVCELLS_PER_TERRITORY_TILE / 2)
185 );
186 terrInf.m_Radius = 1;
187
188 TS_ASSERT_EQUALS(cmp->GetTerritoryPercentage(0), 0);
189 TS_ASSERT_EQUALS(cmp->GetTerritoryPercentage(1), 4); // 5*5 = 25 -> 1 tile out of 25 is 4%
190 TS_ASSERT_EQUALS(cmp->GetTerritoryPercentage(2), 0);
191
192 terrInf.m_Radius = ICmpTerritoryManager::NAVCELLS_PER_TERRITORY_TILE * 10;
193
194 test.HandleMessage(cmp, CMessageTerrainChanged(0, 0, 0, 0), true);
195
196 TS_ASSERT_EQUALS(cmp->GetTerritoryPercentage(0), 0);
197 TS_ASSERT_EQUALS(cmp->GetTerritoryPercentage(1), 100);
198 TS_ASSERT_EQUALS(cmp->GetTerritoryPercentage(2), 0);
199 }
200
201 void test_boundaries()
202 {
203 Grid<u8> grid = GetGrid("--------"
204 "777777--"
205 "777777--"
206 "777777--"
207 "--------", 8, 5);
208
209 std::vector<STerritoryBoundary> boundaries = CTerritoryBoundaryCalculator::ComputeBoundaries(&grid);
210 TS_ASSERT_EQUALS(1U, boundaries.size());
211 TS_ASSERT_EQUALS(18U, boundaries[0].points.size()); // 2x6 + 2x3
212 TS_ASSERT_EQUALS((player_id_t)7, boundaries[0].owner);
213 TS_ASSERT_EQUALS(false, boundaries[0].blinking); // high bits aren't set by GetGrid
214
215 // assumes NAVCELLS_PER_TERRITORY_TILE is 8; dealt with in TestBoundaryPointsEqual
216 int expectedPoints[][2] = {{ 4, 8}, {12, 8}, {20, 8}, {28, 8}, {36, 8}, {44, 8},
217 {48,12}, {48,20}, {48,28},
218 {44,32}, {36,32}, {28,32}, {20,32}, {12,32}, { 4,32},
219 { 0,28}, { 0,20}, { 0,12}};
220
221 TestBoundaryPointsEqual(boundaries[0].points, expectedPoints);
222 }
223
224 void test_nested_boundaries1()
225 {
226 // test case from ticket #918; contains single-tile territories with double borders
227 Grid<u8> grid1 = GetGrid("--------"
228 "-111111-"
229 "-1-1213-"
230 "-111111-"
231 "--------", 8, 5);
232
233 std::vector<STerritoryBoundary> boundaries = CTerritoryBoundaryCalculator::ComputeBoundaries(&grid1);
234
235 size_t expectedNumBoundaries = 5;
236 TS_ASSERT_EQUALS(expectedNumBoundaries, boundaries.size());
237
238 STerritoryBoundary* onesOuter = NULL;
239 STerritoryBoundary* onesInner0 = NULL; // inner border around the neutral tile
240 STerritoryBoundary* onesInner2 = NULL; // inner border around the '2' tile
241 STerritoryBoundary* twosOuter = NULL;
242 STerritoryBoundary* threesOuter = NULL;
243
244 // expected number of points (!) in the inner boundaries for terrain 1 (there are two with the same size)
245 size_t onesInnerNumExpectedPoints = 4;
246
247 for (size_t i=0; i<expectedNumBoundaries; i++)
248 {
249 STerritoryBoundary& boundary = boundaries[i];
250 switch (boundary.owner)
251 {
252 case 1:
253 // to figure out which 1-boundary is which, we can use the number of points to distinguish between outer and inner,
254 // and within the inners we can split them by their X value (onesInner0 is the leftmost one, onesInner1 the
255 // rightmost one).
256 if (boundary.points.size() != onesInnerNumExpectedPoints)
257 {
258 TSM_ASSERT_EQUALS("Found multiple outer boundaries for territory owned by player 1", onesOuter, (STerritoryBoundary*) NULL);
259 onesOuter = &boundary;
260 }
261 else
262 {
263 TS_ASSERT_EQUALS(onesInnerNumExpectedPoints, boundary.points.size()); // all inner boundaries are of size 2
264 if (boundary.points[0].X < 24.f)
265 {
266 // leftmost inner boundary, i.e. onesInner0
267 TSM_ASSERT_EQUALS("Found multiple leftmost inner boundaries for territory owned by player 1", onesInner0, (STerritoryBoundary*) NULL);
268 onesInner0 = &boundary;
269 }
270 else
271 {
272 TSM_ASSERT_EQUALS("Found multiple rightmost inner boundaries for territory owned by player 1", onesInner2, (STerritoryBoundary*) NULL);
273 onesInner2 = &boundary;
274 }
275 }
276 break;
277 case 2:
278 TSM_ASSERT_EQUALS("Too many boundaries for territory owned by player 2", twosOuter, (STerritoryBoundary*) NULL);
279 twosOuter = &boundary;
280 break;
281
282 case 3:
283 TSM_ASSERT_EQUALS("Too many boundaries for territory owned by player 3", threesOuter, (STerritoryBoundary*) NULL);
284 threesOuter = &boundary;
285 break;
286
287 default:
288 TS_FAIL("Unexpected tile owner");
289 break;
290 }
291 }
292
293 TS_ASSERT_DIFFERS(onesOuter, (STerritoryBoundary*) NULL);
294 TS_ASSERT_DIFFERS(onesInner0, (STerritoryBoundary*) NULL);
295 TS_ASSERT_DIFFERS(onesInner2, (STerritoryBoundary*) NULL);
296 TS_ASSERT_DIFFERS(twosOuter, (STerritoryBoundary*) NULL);
297 TS_ASSERT_DIFFERS(threesOuter, (STerritoryBoundary*) NULL);
298
299 TS_ASSERT_EQUALS(onesOuter->points.size(), 20U);
300 TS_ASSERT_EQUALS(onesInner0->points.size(), 4U);
301 TS_ASSERT_EQUALS(onesInner2->points.size(), 4U);
302 TS_ASSERT_EQUALS(twosOuter->points.size(), 4U);
303 TS_ASSERT_EQUALS(threesOuter->points.size(), 4U);
304
305 int onesOuterExpectedPoints[][2] = {{12, 8}, {20, 8}, {28, 8}, {36, 8}, {44, 8}, {52, 8},
306 {56,12}, {52,16}, {48,20}, {52,24}, {56,28},
307 {52,32}, {44,32}, {36,32}, {28,32}, {20,32}, {12,32},
308 { 8,28}, { 8,20}, { 8,12}};
309 int onesInner0ExpectedPoints[][2] = {{20,24}, {24,20}, {20,16}, {16,20}};
310 int onesInner2ExpectedPoints[][2] = {{36,24}, {40,20}, {36,16}, {32,20}};
311 int twosOuterExpectedPoints[][2] = {{36,16}, {40,20}, {36,24}, {32,20}};
312 int threesOuterExpectedPoints[][2] = {{52,16}, {56,20}, {52,24}, {48,20}};
313
314 TestBoundaryPointsEqual(onesOuter->points, onesOuterExpectedPoints);
315 TestBoundaryPointsEqual(onesInner0->points, onesInner0ExpectedPoints);
316 TestBoundaryPointsEqual(onesInner2->points, onesInner2ExpectedPoints);
317 TestBoundaryPointsEqual(twosOuter->points, twosOuterExpectedPoints);
318 TestBoundaryPointsEqual(threesOuter->points, threesOuterExpectedPoints);
319 }
320
321 void test_nested_boundaries2()
322 {
323 Grid<u8> grid1 = GetGrid("-22222-"
324 "-2---2-"
325 "-2-1123"
326 "-2-1123"
327 "-2-2223"
328 "-222333", 7, 6);
329
330 std::vector<STerritoryBoundary> boundaries = CTerritoryBoundaryCalculator::ComputeBoundaries(&grid1);
331
332 // There should be two boundaries found for the territory of 2's (one outer and one inner edge), plus two regular
333 // outer edges of the territories of 1's and 3's. The order in which they're returned doesn't matter though, so
334 // we should first detect which one is which.
335 size_t expectedNumBoundaries = 4;
336 TS_ASSERT_EQUALS(expectedNumBoundaries, boundaries.size());
337
338 STerritoryBoundary* onesOuter = NULL;
339 STerritoryBoundary* twosOuter = NULL;
340 STerritoryBoundary* twosInner = NULL;
341 STerritoryBoundary* threesOuter = NULL;
342
343 for (size_t i=0; i < expectedNumBoundaries; i++)
344 {
345 STerritoryBoundary& boundary = boundaries[i];
346 switch (boundary.owner)
347 {
348 case 1:
349 TSM_ASSERT_EQUALS("Too many boundaries for territory owned by player 1", onesOuter, (STerritoryBoundary*) NULL);
350 onesOuter = &boundary;
351 break;
352
353 case 3:
354 TSM_ASSERT_EQUALS("Too many boundaries for territory owned by player 3", threesOuter, (STerritoryBoundary*) NULL);
355 threesOuter = &boundary;
356 break;
357
358 case 2:
359 // assign twosOuter first, then twosInner last; we'll swap them afterwards if needed
360 if (twosOuter == NULL)
361 twosOuter = &boundary;
362 else if (twosInner == NULL)
363 twosInner = &boundary;
364 else
365 TS_FAIL("Too many boundaries for territory owned by player 2");
366
367 break;
368
369 default:
370 TS_FAIL("Unexpected tile owner");
371 break;
372 }
373 }
374
375 TS_ASSERT_DIFFERS(onesOuter, (STerritoryBoundary*) NULL);
376 TS_ASSERT_DIFFERS(twosOuter, (STerritoryBoundary*) NULL);
377 TS_ASSERT_DIFFERS(twosInner, (STerritoryBoundary*) NULL);
378 TS_ASSERT_DIFFERS(threesOuter, (STerritoryBoundary*) NULL);
379
380 TS_ASSERT_EQUALS(onesOuter->points.size(), 8U);
381 TS_ASSERT_EQUALS(twosOuter->points.size(), 22U);
382 TS_ASSERT_EQUALS(twosInner->points.size(), 14U);
383 TS_ASSERT_EQUALS(threesOuter->points.size(), 14U);
384
385 // See if we need to swap the outer and inner edges of the twos territories (uses the extremely simplistic
386 // heuristic of comparing the amount of points to determine which one is the outer one and which one the inner
387 // one (which does happen to work in this case though).
388
389 if (twosOuter->points.size() < twosInner->points.size())
390 {
391 STerritoryBoundary* tmp = twosOuter;
392 twosOuter = twosInner;
393 twosInner = tmp;
394 }
395
396 int onesOuterExpectedPoints[][2] = {{28,16}, {36,16}, {40,20}, {40,28}, {36,32}, {28,32}, {24,28}, {24,20}};
397 int twosOuterExpectedPoints[][2] = {{12, 0}, {20, 0}, {28, 0}, {32, 4}, {36, 8}, {44, 8},
398 {48,12}, {48,20}, {48,28}, {48,36}, {48,44},
399 {44,48}, {36,48}, {28,48}, {20,48}, {12,48},
400 { 8,44}, { 8,36}, { 8,28}, { 8,20}, { 8,12}, { 8, 4}};
401 int twosInnerExpectedPoints[][2] = {{20,40}, {28,40}, {36,40}, {40,36}, {40,28}, {40,20}, {36,16},
402 {28,16}, {24,12}, {20, 8}, {16,12}, {16,20}, {16,28}, {16,36}};
403 int threesOuterExpectedPoints[][2] = {{36, 0}, {44, 0}, {52, 0}, {56, 4}, {56,12}, {56,20}, {56,28}, {52,32},
404 {48,28}, {48,20}, {48,12}, {44, 8}, {36, 8}, {32, 4}};
405
406 TestBoundaryPointsEqual(onesOuter->points, onesOuterExpectedPoints);
407 TestBoundaryPointsEqual(twosOuter->points, twosOuterExpectedPoints);
408 TestBoundaryPointsEqual(twosInner->points, twosInnerExpectedPoints);
409 TestBoundaryPointsEqual(threesOuter->points, threesOuterExpectedPoints);
410 }
411
412private:
413 /// Parses a string representation of a grid into an actual Grid structure, such that the (i,j) axes are located in the bottom
414 /// left hand side of the map. Note: leaves all custom bits in the grid values at zero (anything outside
415 /// ICmpTerritoryManager::TERRITORY_PLAYER_MASK).
416 Grid<u8> GetGrid(const std::string& def, u16 w, u16 h)
417 {
418 Grid<u8> grid(w, h);
419 const char* chars = def.c_str();
420
421 for (u16 y=0; y<h; y++)
422 {
423 for (u16 x=0; x<w; x++)
424 {
425 char gridDefChar = chars[x+y*w];
426 if (gridDefChar == '-')
427 continue;
428
429 ENSURE('0' <= gridDefChar && gridDefChar <= '9');
430 u8 playerId = gridDefChar - '0';
431 grid.set(x, h-1-y, playerId);
432 }
433 }
434
435 return grid;
436 }
437
438 void TestBoundaryPointsEqual(const std::vector<CVector2D>& points, int expectedPoints[][2])
439 {
440 // TODO: currently relies on an exact point match, i.e. expectedPoints must be specified going CCW or CW (depending on
441 // whether we're testing an inner or an outer edge) starting from the exact same point that the algorithm happened to
442 // decide to start the run from. This is an algorithmic detail and is not considered to be part of the specification
443 // of the return value. Hence, this method should also accept 'expectedPoints' to be a cyclically shifted
444 // version of 'points', so that the starting position doesn't need to match exactly.
445 for (size_t i = 0; i < points.size(); i++)
446 {
447 // the input numbers in expectedPoints are defined under the assumption that NAVCELLS_PER_TERRITORY_TILE is 8, so let's include
448 // a scaling factor to protect against that should NAVCELLS_PER_TERRITORY_TILE ever change
449 TS_ASSERT_DELTA(points[i].X, float(expectedPoints[i][0]) * 8.f / ICmpTerritoryManager::NAVCELLS_PER_TERRITORY_TILE, 1e-7);
450 TS_ASSERT_DELTA(points[i].Y, float(expectedPoints[i][1]) * 8.f / ICmpTerritoryManager::NAVCELLS_PER_TERRITORY_TILE, 1e-7);
451 }
452 }
453};
Note: See TracBrowser for help on using the repository browser.