24 if (
x >= 0 &&
y >= 0 &&
x < grid.getWidth() &&
y < grid.getHeight()) grid.setCell(
x,
y,
semantic);
27std::vector<std::pair<int, int>>
cells(
const Grid2D& grid) {
28 std::vector<std::pair<int, int>> result;
29 for (
int y = 0;
y < grid.getHeight(); ++
y)
30 for (
int x = 0;
x < grid.getWidth(); ++
x)
35std::vector<std::vector<std::pair<int, int>>> islands(
const Grid2D& grid) {
36 std::vector<std::vector<std::pair<int, int>>> result;
37 std::vector<unsigned char> visited(std::size_t(grid.getWidth() * grid.getHeight()));
38 constexpr int dx[] = {-1, 1, 0, 0};
39 constexpr int dy[] = {0, 0, -1, 1};
40 for (
int y = 0;
y < grid.getHeight(); ++
y) {
41 for (
int x = 0;
x < grid.getWidth(); ++
x) {
42 const int start =
y * grid.getWidth() +
x;
44 result.emplace_back();
45 std::queue<std::pair<int, int>>
pending;
47 visited[std::size_t(
start)] = 1;
51 result.back().push_back(
current);
55 if (
nx < 0 || ny < 0 || nx >= grid.getWidth() ||
ny >= grid.getHeight())
continue;
56 const int index =
ny * grid.getWidth() +
nx;
58 visited[std::size_t(
index)] = 1;
71 std::uniform_real_distribution<float> probability(0.f, 1.f);
80 for (
int oy = -1;
oy <= 1; ++
oy)
81 for (
int ox = -1;
ox <= 1; ++
ox)
88 grid = std::move(next);
96 std::uniform_int_distribution<int> startX(0,
settings.width - 1);
97 std::uniform_int_distribution<int> startY(0,
settings.height - 1);
98 std::uniform_int_distribution<int>
direction(0, 3);
103 constexpr int dx[] = {-1, 1, 0, 0};
104 constexpr int dy[] = {0, 0, -1, 1};
105 for (
int iteration = 0; iteration <
iterations; ++iteration) {
124 std::vector<std::pair<int, int>> stack{{1, 1}};
125 setOccupied(grid, 1, 1,
settings.semantic);
126 constexpr int dx[] = {-2, 2, 0, 0};
127 constexpr int dy[] = {0, 0, -2, 2};
128 while (!stack.empty()) {
129 const auto current = stack.back();
130 std::vector<int> candidates;
131 for (
int d = 0;
d < 4; ++
d) {
135 candidates.push_back(
d);
137 if (candidates.empty()) {
141 std::shuffle(candidates.begin(), candidates.end(), rng);
142 const int d = candidates.front();
147 stack.emplace_back(
nx,
ny);
162 }
else if (
operation ==
"generate.random_noise") {
163 std::uniform_real_distribution<float> probability(0.f, 1.f);
167 }
else if (
operation ==
"generate.checkerboard" ||
operation ==
"generate.dot_grid") {
174 }
else if (
operation ==
"generate.shape") {
184 }
else if (
operation ==
"generate.cellular") {
186 }
else if (
operation ==
"generate.random_walk") {
188 }
else if (
operation ==
"generate.maze") {
190 }
else if (
operation ==
"generate.poisson") {
192 std::vector<std::pair<int, int>> accepted;
193 std::vector<std::pair<int, int>> candidates;
195 for (
int x = 0;
x <
settings.width; ++
x) candidates.emplace_back(
x,
y);
196 std::shuffle(candidates.begin(), candidates.end(), rng);
197 for (
const auto& candidate : candidates) {
198 const bool clear = std::none_of(accepted.begin(), accepted.end(), [&](
const auto&
point) {
199 const float dx = float(point.first - candidate.first);
200 const float dy = float(point.second - candidate.second);
201 return dx * dx + dy * dy < radius * radius;
204 accepted.push_back(candidate);
205 grid.setCell(candidate.first, candidate.second,
settings.semantic);
210 "unsupported generator: " + std::string(
operation), {}, {},
211 "procgen.gridGraph"));
217 std::uint64_t
seed, std::string_view rule) {
222 std::mt19937_64 rng(
seed);
225 : int(std::round(std::clamp(
weight, 0.f, 1.f) *
float(
active.size())));
226 active.resize(std::size_t(amount));
232 constexpr int dx[] = {-1, 1, 0, 0};
233 constexpr int dy[] = {0, 0, -1, 1};
238 }
else if (
operation ==
"select.neighbors") {
241 for (
int oy = -1;
oy <= 1; ++
oy)
242 for (
int ox = -1;
ox <= 1; ++
ox)
244 if ((mode == 0 && neighbors ==
count) || (mode == 1 && neighbors >=
count) ||
245 (mode == 2 && neighbors <=
count))
249 if (rule.size() != 9)
251 "rule must contain exactly nine characters (0/1/*)", {},
252 {},
"procgen.gridGraph"));
255 for (
int oy = -1;
oy <= 1 && match; ++
oy)
256 for (
int ox = -1;
ox <= 1; ++
ox) {
257 const char expected = rule[std::size_t((
oy + 1) * 3 +
ox + 1)];
258 if (expected !=
'*' &&
268 const bool keep = mode == 0 ? int(
island.size()) <
count
271 if (
operation ==
"select.island_centers") {
278 const int x = int(std::llround(
double(
sx) /
double(
island.size())));
279 const int y = int(std::llround(
double(
sy) /
double(
island.size())));
288 "unsupported selector: " + std::string(
operation), {}, {},
289 "procgen.gridGraph"));
298 "pathfinding grids must have equal dimensions", {}, {},
299 "procgen.gridGraph"));
300 const auto startCells =
cells(starts);
301 const auto targetCells =
cells(targets);
302 if (startCells.empty() || targetCells.empty())
304 "pathfinding requires start and target cells", {}, {},
305 "procgen.gridGraph"));
310 const int start = startCells.front().second *
width + startCells.front().first;
313 int destination = -1;
314 while (!
pending.empty() && destination < 0) {
323 constexpr int dx[] = {-1, 1, 0, 0};
324 constexpr int dy[] = {0, 0, -1, 1};
325 for (
int d = 0;
d < 4; ++
d) {
330 if (
previous[std::size_t(next)] < 0) {
ActionParameterOperation operation
std::vector< QuestEvent > pending
Stable, structured diagnostics shared by engine modules.
graphics::Canvas * previous
std::array< PixelCell, kPixelChunkSize *kPixelChunkSize > cells
RoadLaneDirection direction
TerrainThermalSettings settings
std::vector< char > inside
static Diagnostic error(DiagnosticCode code, std::string message, std::string path={}, DiagnosticDetails details={}, std::string source={})
Construct an error diagnostic with the standard error severity.
Move-only operation result carrying either a value or Status.
static Result success(T value)
Construct a successful result owning value.
static Result failure(Status status)
Construct a failed result from a structured status.
Intermediate 2D generation result. cells store semantic ids (see Semantic.h), not tile GIDs — convert...
int getWidth() const
Returns the width.
void resize(int width, int height)
Resize.
void setCell(int x, int y, int semantic)
Sets the cell.
int getHeight() const
Returns the height.
Result< Grid2D > findPath(const Grid2D &navigation, const Grid2D &starts, const Grid2D &targets, int semantic)
Finds path.
Result< Grid2D > generate(std::string_view operation, const GenerateSettings &settings)
Generate.
Result< Grid2D > select(const Grid2D &input, std::string_view operation, int mode, int count, float weight, std::uint64_t seed, std::string_view rule)
Select.
GenerateSettings public API.