载入中...
搜索中...
未找到
BuiltinAlgorithms.cpp
浏览该文件的文档.
2#include "procgen/Semantic.h"
5
6#include <algorithm>
7#include <cmath>
8#include <cstdint>
9#include <random>
10#include <string>
11#include <vector>
12
13namespace eve::procgen {
14namespace {
15
16bool genDungeonBsp(const Params &params, Grid2D &out, std::string &error) {
17 const int w = params.getWidth();
18 const int h = params.getHeight();
19 if (w < 8 || h < 8) {
20 error = "dungeon.bsp: size must be at least 8x8";
21 return false;
22 }
23
24 const int divisionMin = params.getInt("divisionMin", 3);
25 const int divisionRandMax = params.getInt("divisionRandMax", 4);
26 const int roomMinX = params.getInt("roomMinX", params.getInt("roomMin", 5));
27 const int roomRandMaxX = params.getInt("roomRandMaxX", params.getInt("roomRand", 2));
28 const int roomMinY = params.getInt("roomMinY", params.getInt("roomMin", 5));
29 const int roomRandMaxY = params.getInt("roomRandMaxY", params.getInt("roomRand", 2));
30
31 auto matrix = dtlutil::makeMatrix(w, h, 0);
32 // room=1, road=2; wall remains 0
33 dtl::shape::SimpleRogueLike<std::uint_fast8_t> shape(
34 1, 2, size_t(std::max(1, divisionMin)), size_t(std::max(0, divisionRandMax)),
35 size_t(std::max(1, roomMinX)), size_t(std::max(0, roomRandMaxX)),
36 size_t(std::max(1, roomMinY)), size_t(std::max(0, roomRandMaxY)));
37
38 if (!shape.drawSEED(matrix, params.getSeed())) {
39 error = "dungeon.bsp: DTL SimpleRogueLike draw failed";
40 return false;
41 }
42
43 dtlutil::copyMatrixToGrid(matrix, out, [](std::uint_fast8_t v) -> uint32_t {
44 if (v == 1) return Semantic::Floor;
45 if (v == 2) return Semantic::Corridor;
46 return Semantic::Wall;
47 });
48 out.setMeta("algorithm", "dungeon.bsp");
50 return true;
51}
52
53bool genCaveCellular(const Params &params, Grid2D &out, std::string &error) {
54 const int w = params.getWidth();
55 const int h = params.getHeight();
56 if (w < 4 || h < 4) {
57 error = "cave.cellular: size must be at least 4x4";
58 return false;
59 }
60 const int loops = params.getInt("loops", 5);
61 const double fill = double(params.getFloat("fill", 0.45f));
62
63 auto matrix = dtlutil::makeMatrix(w, h, 0);
64 // land=1, border/wall=0
65 dtl::shape::CellularAutomatonIsland<std::uint_fast8_t> shape(1, 0, size_t(std::max(1, loops)),
66 fill);
68 if (!shape.draw(matrix)) {
69 error = "cave.cellular: DTL CellularAutomatonIsland draw failed";
70 return false;
71 }
72
73 dtlutil::copyMatrixToGrid(matrix, out, [](std::uint_fast8_t v) -> uint32_t {
74 return v == 1 ? Semantic::Floor : Semantic::Wall;
75 });
76 out.setMeta("algorithm", "cave.cellular");
78 return true;
79}
80
81bool genMazeBacktrack(const Params &params, Grid2D &out, std::string &error) {
82 const int w = params.getWidth();
83 const int h = params.getHeight();
84 // MazeDig works best on odd dimensions.
85 const int mw = w < 5 ? 5 : (w % 2 == 0 ? w - 1 : w);
86 const int mh = h < 5 ? 5 : (h % 2 == 0 ? h - 1 : h);
87
88 auto matrix = dtlutil::makeMatrix(mw, mh, 0);
89 // empty(floor)=1, wall=0
90 dtl::shape::MazeDig<std::uint_fast8_t> shape(1, 0);
91 if (!shape.drawSEED(matrix, params.getSeed())) {
92 error = "maze.backtrack: DTL MazeDig draw failed";
93 return false;
94 }
95
96 out.resize(w, h);
98 for (int y = 0; y < mh && y < h; ++y) {
99 for (int x = 0; x < mw && x < w; ++x) {
100 out.setCell(x, y, matrix[size_t(y)][size_t(x)] == 1 ? Semantic::Floor : Semantic::Wall);
101 }
102 }
103 out.setMeta("algorithm", "maze.backtrack");
105 return true;
106}
107
108bool genNoiseTerrain(const Params &params, Grid2D &out, std::string &error) {
109 const int w = params.getWidth();
110 const int h = params.getHeight();
111 if (w < 2 || h < 2) {
112 error = "noise.terrain: size must be at least 2x2";
113 return false;
114 }
115 const float frequency = params.getFloat("frequency", 6.f);
116 const int octaves = params.getInt("octaves", 4);
117 // Height bands in [0, maxHeight]
118 const int maxHeight = params.getInt("maxHeight", 9);
119
120 auto matrix = dtlutil::makeMatrix(w, h, 0);
121 dtl::shape::PerlinIsland<std::uint_fast8_t> shape(double(std::max(0.1f, frequency)),
122 size_t(std::max(1, octaves)),
123 std::uint_fast8_t(std::max(1, maxHeight)), 0);
124 if (!shape.drawSEED(matrix, params.getSeed())) {
125 error = "noise.terrain: DTL PerlinIsland draw failed";
126 return false;
127 }
128
129 const float waterMax = params.getFloat("waterMax", 0.25f);
130 const float sandMax = params.getFloat("sandMax", 0.35f);
131 const float grassMax = params.getFloat("grassMax", 0.65f);
132 const float dirtMax = params.getFloat("dirtMax", 0.80f);
133 const float stoneMax = params.getFloat("stoneMax", 0.92f);
134
135 dtlutil::copyMatrixToGrid(matrix, out, [&](std::uint_fast8_t v) -> uint32_t {
136 const float t = maxHeight <= 0 ? 0.f : float(v) / float(maxHeight);
137 if (t < waterMax) return Semantic::Water;
138 if (t < sandMax) return Semantic::Sand;
139 if (t < grassMax) return Semantic::Grass;
140 if (t < dirtMax) return Semantic::Dirt;
141 if (t < stoneMax) return Semantic::Stone;
142 return Semantic::Snow;
143 });
144 out.setMeta("algorithm", "noise.terrain");
146 return true;
147}
148
150bool genCaveDrunkard(const Params &params, Grid2D &out, std::string &error) {
151 const int w = params.getWidth();
152 const int h = params.getHeight();
153 if (w < 4 || h < 4) {
154 error = "cave.drunkard: size must be at least 4x4";
155 return false;
156 }
157 const float floorPct = std::clamp(params.getFloat("floorPct", 0.45f), 0.05f, 0.95f);
158 const int target = int(float(w * h) * floorPct);
159
160 out.resize(w, h);
161 out.fill(Semantic::Wall);
162
163 std::mt19937 rng(params.getSeed());
164 std::uniform_int_distribution<int> dirDist(0, 3);
165 int x = w / 2;
166 int y = h / 2;
167 int carved = 0;
168 int guard = w * h * 20;
169 while (carved < target && guard-- > 0) {
170 if (out.getCell(x, y) != Semantic::Floor) {
171 out.setCell(x, y, Semantic::Floor);
172 ++carved;
173 }
174 switch (dirDist(rng)) {
175 case 0: if (x > 1) --x; break;
176 case 1: if (x < w - 2) ++x; break;
177 case 2: if (y > 1) --y; break;
178 default: if (y < h - 2) ++y; break;
179 }
180 }
181 // Outer wall frame
182 for (int i = 0; i < w; ++i) {
183 out.setCell(i, 0, Semantic::Wall);
184 out.setCell(i, h - 1, Semantic::Wall);
185 }
186 for (int j = 0; j < h; ++j) {
187 out.setCell(0, j, Semantic::Wall);
188 out.setCell(w - 1, j, Semantic::Wall);
189 }
190 out.setMeta("algorithm", "cave.drunkard");
192 return true;
193}
194
195} // namespace
196
197// Defined in WfcSimple.cpp
199// Defined in heightmap/BuiltinHeightmap.cpp
201
203 if (builtinsRegistered_) return;
204 registerAlgorithm("dungeon.bsp", genDungeonBsp);
205 registerAlgorithm("cave.cellular", genCaveCellular);
206 registerAlgorithm("cave.drunkard", genCaveDrunkard);
207 registerAlgorithm("maze.backtrack", genMazeBacktrack);
208 registerAlgorithm("noise.terrain", genNoiseTerrain);
209 registerWfcSimple(*this);
212 builtinsRegistered_ = true;
213}
214
215} // namespace eve::procgen
int y
Definition Grass.cpp:135
int x
Definition Grass.cpp:135
int h
int w
std::string error
int v
void registerAlgorithm(const std::string &id, GeneratorFn fn)
void registerBuiltins()
Register built-in DTL / custom map algorithms (idempotent).
Intermediate 2D generation result. cells store semantic ids (see Semantic.h), not tile GIDs — convert...
Definition Grid2D.h:16
void resize(int width, int height)
Definition Grid2D.cpp:13
void fill(int semantic)
Definition Grid2D.cpp:33
void setCell(int x, int y, int semantic)
Definition Grid2D.cpp:23
int getCell(int x, int y) const
Definition Grid2D.cpp:28
void setMeta(const std::string &key, const std::string &value)
Definition Grid2D.cpp:47
Generation parameters. Algorithm-specific keys live in values as strings (no overloads; typed setters...
Definition Params.h:13
uint32_t getSeed() const
Definition Params.cpp:8
int getHeight() const
Definition Params.cpp:15
int getWidth() const
Definition Params.cpp:14
float getFloat(const std::string &key, float defaultValue) const
Definition Params.cpp:32
int getInt(const std::string &key, int defaultValue) const
Definition Params.cpp:23
constexpr uint32_t Floor
Definition Semantic.h:12
constexpr uint32_t Grass
Definition Semantic.h:16
constexpr uint32_t Stone
Definition Semantic.h:18
constexpr uint32_t Wall
Definition Semantic.h:11
constexpr uint32_t Sand
Definition Semantic.h:15
constexpr uint32_t Dirt
Definition Semantic.h:17
constexpr uint32_t Corridor
Definition Semantic.h:13
constexpr uint32_t Water
Definition Semantic.h:14
constexpr uint32_t Snow
Definition Semantic.h:19
void copyMatrixToGrid(const std::vector< std::vector< std::uint_fast8_t > > &matrix, Grid2D &grid, const std::function< uint32_t(std::uint_fast8_t)> &mapValue)
Definition DtlHelpers.h:35
void placeSpawnAndStairs(Grid2D &grid, uint32_t seed)
Place spawn + stairs on walkable cells (floor/corridor/grass/dirt/sand).
Definition DtlHelpers.h:49
void seedEngine(uint32_t seed)
Definition DtlHelpers.h:24
std::vector< std::vector< std::uint_fast8_t > > makeMatrix(int width, int height, std::uint_fast8_t fill=0)
Definition DtlHelpers.h:29
void registerWfcSimple(GeneratorRegistry &registry)
void registerTerrainHeightmapAlgorithm(GeneratorRegistry &registry)
void registerRoguelikeGenerator(GeneratorRegistry &registry)
Register the "level.roguelike" algorithm (idempotent).