Skip to content
This repository was archived by the owner on Aug 20, 2024. It is now read-only.

Commit da6b247

Browse files
committed
filter starting positions such that all are mutually reachable by walking
1 parent 4e7fc29 commit da6b247

File tree

1 file changed

+66
-4
lines changed

1 file changed

+66
-4
lines changed

sources/startingPositions.cpp

+66-4
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,7 @@ namespace unnatural
2525
for (uint32 j = i + 1; j < n; j++)
2626
{
2727
const Real c = distance(tiles[positions[i]].position, tiles[positions[j]].position);
28-
//score = min(score, c); // this causes a crash when compiled with visual studio 2022 msvc with optimizations
29-
if (c < score)
30-
score = c;
28+
score = min(score, c);
3129
}
3230
}
3331
return score;
@@ -54,6 +52,69 @@ namespace unnatural
5452
});
5553
}
5654

55+
void filterPositionsByLargestConnectedWalkableComponent(std::vector<uint32> &positions)
56+
{
57+
const auto &walkable = [](uint32 i) -> bool
58+
{
59+
switch (tiles[i].type)
60+
{
61+
case TerrainTypeEnum::Road:
62+
case TerrainTypeEnum::Flat:
63+
case TerrainTypeEnum::Rough:
64+
return true;
65+
default:
66+
return false;
67+
}
68+
};
69+
70+
const uint32 cnt = tiles.size();
71+
std::vector<uint32> component;
72+
component.resize(cnt, m);
73+
74+
uint32 largestSize = 0;
75+
uint32 largestIndex = m;
76+
77+
const auto &floodfill = [&](const uint32 start)
78+
{
79+
const uint32 index = component[start];
80+
uint32 size = 1;
81+
std::vector<uint32> open;
82+
open.reserve(cnt / 10);
83+
open.push_back(start);
84+
while (!open.empty())
85+
{
86+
const uint32 i = open.back();
87+
open.pop_back();
88+
CAGE_ASSERT(component[i] == index);
89+
for (uint32 j : tiles[i].neighbors)
90+
{
91+
if (component[j] != m || !walkable(j))
92+
continue;
93+
component[j] = index;
94+
size++;
95+
open.push_back(j);
96+
}
97+
}
98+
if (size > largestSize)
99+
{
100+
largestSize = size;
101+
largestIndex = index;
102+
}
103+
};
104+
105+
uint32 next = 0;
106+
for (uint32 i = 0; i < cnt; i++)
107+
{
108+
if (component[i] != m || !walkable(i))
109+
continue;
110+
component[i] = next;
111+
floodfill(i);
112+
next++;
113+
}
114+
115+
std::erase_if(positions, [&](uint32 i) { return component[i] != largestIndex; });
116+
}
117+
57118
std::vector<uint32> generateCadidates()
58119
{
59120
std::vector<uint32> candidates;
@@ -62,7 +123,8 @@ namespace unnatural
62123
if (it->buildable)
63124
candidates.push_back(it.index);
64125
filterPositionsByBuildableRadius(candidates);
65-
CAGE_LOG(SeverityEnum::Info, "generator", Stringizer() + "starting position candidates: " + candidates.size() + " (after eliminating due to insufficient buildable neighbors)");
126+
filterPositionsByLargestConnectedWalkableComponent(candidates);
127+
CAGE_LOG(SeverityEnum::Info, "generator", Stringizer() + "starting position candidates: " + candidates.size());
66128
return candidates;
67129
}
68130

0 commit comments

Comments
 (0)