summaryrefslogtreecommitdiffstats
path: root/crawl-ref/source/dgn-proclayouts.h
blob: d40ee0462eec7e199befb07d0c2fb5b5fde57756 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
/**
 * @file
 * @brief Procedurally generated dungeon layouts.
 **/

#ifndef PROC_LAYOUTS_H
#define PROC_LAYOUTS_H

#include "fixedvector.h"

#include "dungeon.h"
#include "enum.h"
#include "externs.h"
#include "worley.h"

dungeon_feature_type sanitize_feature(dungeon_feature_type feature,
        bool strict = false);

class ProceduralSample
{
    public:
        ProceduralSample(const coord_def _c, const dungeon_feature_type _ft,
                         const uint32_t _cp, map_mask_type _m = MMT_NONE)
            : c(_c), ft(_ft), cp(_cp), m(_m)
        {
            ASSERT_RANGE(ft, DNGN_UNSEEN + 1, NUM_FEATURES);
        }
        coord_def coord() const { return c; }
        dungeon_feature_type feat() const { return ft; }
        uint32_t changepoint() const { return cp; }
        map_mask_type mask() const { return m; }
    private:
        coord_def c;
        dungeon_feature_type ft;
        // A lower bound estimate of when this feat can change in terms of
        // absolute abyss depth. If you say that a feature might change by
        // depth 1000, it will get checked at depth 1000. Then it will get
        // pushed back into the terrain queue with the new depth estimate.
        // If you overestimate the time between shifts, this will introduce
        // bad behavior when a game is loaded. [bh]
        uint32_t cp;
        map_mask_type m;
};

class ProceduralSamplePQCompare
{
    public:
        bool operator() (const ProceduralSample &lhs,
            const ProceduralSample &rhs)
        {
            return lhs.changepoint() > rhs.changepoint();
        }
};

class ProceduralLayout
{
    public:
        virtual ProceduralSample operator()(const coord_def &p,
            const uint32_t offset = 0) const = 0;
        virtual ~ProceduralLayout() { }
};

// Geometric layout that generates columns with width cw, col spacing cs, row width rw, and row spacing rs.
// cw is the only required parameter and will generate uniform columns.
class ColumnLayout : public ProceduralLayout
{
    public:
        ColumnLayout(int cw, int cs = -1, int rw = -1, int rs = -1)
        {
            cs = (cs < 0 ? cw : cs);
            _col_width = cw;
            _col_space = cs;
            _row_width = (rw < 0 ? cw : rw);
            _row_space = (rs < 0 ? cs : rs);
        }

        ProceduralSample operator()(const coord_def &p,
            const uint32_t offset = 0) const;
    private:
        int _col_width, _col_space, _row_width, _row_space;
};

class DiamondLayout : public ProceduralLayout
{
    public:
        DiamondLayout(int _w, int _s) : w(_w) , s(_s) { }
        ProceduralSample operator()(const coord_def &p,
            const uint32_t offset = 0) const;
    private:
        uint32_t w, s;
};

// A worley noise layout that selects between other layouts.
class WorleyLayout : public ProceduralLayout
{
    public:
        WorleyLayout(uint32_t _seed,
            vector<const ProceduralLayout*> _layouts,
            const float _scale = 2.0) :
            seed(_seed), layouts(_layouts), scale(_scale) {}
        ProceduralSample operator()(const coord_def &p,
            const uint32_t offset = 0) const;
    private:
        const uint32_t seed;
        const vector<const ProceduralLayout*> layouts;
        const float scale;
};

// A pseudo-random layout with variable density.
// By default, 45% of the area is wall. Densities in excess of 50% (500)
// are very likely to create isolated bubbles.
// See http://en.wikipedia.org/wiki/Percolation_theory for additional
// information.
// This layout is depth invariant.
class ChaosLayout : public ProceduralLayout
{
    public:
        ChaosLayout(uint32_t _seed, uint32_t _density = 450) :
            seed(_seed), baseDensity(_density) {}
        ProceduralSample operator()(const coord_def &p,
            const uint32_t offset = 0) const;
    private:
        const uint32_t seed;
        const uint32_t baseDensity;
};

// Similar to ChaosLayout, but changes relatively quickly with depth.
class RoilingChaosLayout : public ProceduralLayout
{
    public:
        RoilingChaosLayout(uint32_t _seed, uint32_t _density = 450) :
            seed(_seed), density(_density) {}
        ProceduralSample operator()(const coord_def &p,
            const uint32_t offset = 0) const;
    private:
        const uint32_t seed;
        const uint32_t density;
};

// A mostly empty layout.
class WastesLayout : public ProceduralLayout
{
    public:
        WastesLayout() { };
        ProceduralSample operator()(const coord_def &p,
            const uint32_t offset = 0) const;
};

class RiverLayout : public ProceduralLayout
{
    public:
        RiverLayout(uint32_t _seed, const ProceduralLayout &_layout) :
            seed(_seed), layout(_layout) {}
        ProceduralSample operator()(const coord_def &p,
            const uint32_t offset = 0) const;
    private:
        const uint32_t seed;
        const ProceduralLayout &layout;
};

// A reimagining of the beloved newabyss layout.
class NewAbyssLayout : public ProceduralLayout
{
    public:
        NewAbyssLayout(uint32_t _seed) : seed(_seed) {}
        ProceduralSample operator()(const coord_def &p,
            const uint32_t offset = 0) const;
    private:
        const uint32_t seed;
};

// This layout takes chunks of a single level the player has seen, corrupts them
// and uses them to build the level.
class LevelLayout : public ProceduralLayout
{
    public:
        LevelLayout(level_id id, uint32_t _seed,
            const ProceduralLayout &_layout);
        ProceduralSample operator()(const coord_def &p,
            const uint32_t offset = 0) const;
    private:
        feature_grid grid;
        uint32_t seed;
        const ProceduralLayout &layout;
};

// Clamps another layout so that it changes no more frequently than specified
// by the clamp parameter. This is useful if you can't find a good analytic
// bound on how rapidly your layout changes. If you provide a high valued clamp
// to a fast changing layout, aliasing will occur.
// If bursty is true, changes will be not be distributed uniformly over the
// clamp period.
class ClampLayout : public ProceduralLayout
{
    public:
        ClampLayout(const ProceduralLayout &_layout, int _clamp, bool _bursty) :
            layout(_layout), clamp(_clamp), bursty(_bursty) {}
        ProceduralSample operator()(const coord_def &p,
            const uint32_t offset = 0) const;
    private:
        const ProceduralLayout &layout;
        const int clamp;
        const bool bursty;
};

class CityLayout : public ProceduralLayout
{
    public:
        CityLayout() {}
        ProceduralSample operator()(const coord_def &p,
            const uint32_t offset = 0) const;
    private:
};

// Base class is only needed for a couple of support functions
// TODO: Refactor those functions into ProceduralFunctions

class NoiseLayout : public ProceduralLayout
{
    public:
        NoiseLayout() { };
        ProceduralSample operator()(const coord_def &p, const uint32_t offset = 0) const;

    protected:
        double _optimum_range(const double val, const double rstart, const double rend) const;
        double _optimum_range_mid(const double val, const double rstart, const double rmax1, const double rmax2, const double rend) const;
};

class ForestLayout : public NoiseLayout
{
    public:
        ForestLayout() { };
        ProceduralSample operator()(const coord_def &p, const uint32_t offset = 0) const;
};

class UnderworldLayout : public NoiseLayout
{
    public:
        UnderworldLayout() { };
        ProceduralSample operator()(const coord_def &p, const uint32_t offset = 0) const;
};

// ProceduralFunctions abstract a noise calculation for x,y,z coordinates (which could
// include distortion by domain transformation)

class ProceduralFunction
{
    public:
        double operator()(const coord_def &p, const uint32_t offset) const;
        double operator()(double x, double y, double z) const;
};

class SimplexFunction : public ProceduralFunction
{
    public:
        SimplexFunction(double _scale_x, double _scale_y, double _scale_z,
                        double _seed_x, double _seed_y, double _seed_z = 0,
                        int _octaves = 1)
            : scale_x(_scale_x), scale_y(_scale_y), scale_z(_scale_z),
              seed_x(_seed_x), seed_y(_seed_y), seed_z(_seed_z),
              octaves(_octaves) { };

        double operator()(const coord_def &p, const uint32_t offset) const;
        double operator()(double x, double y, double z) const;

    private:
        const double scale_x;
        const double scale_y;
        const double scale_z;
        const double seed_x;
        const double seed_y;
        const double seed_z;
        const int octaves;
};

class WorleyFunction : public ProceduralFunction
{
    public:
        WorleyFunction(double _scale_x, double _scale_y, double _scale_z,
                        double _seed_x, double _seed_y, double _seed_z = 0)
            : scale_x(_scale_x), scale_y(_scale_y), scale_z(_scale_z),
              seed_x(_seed_x), seed_y(_seed_y), seed_z(_seed_z) { };
        double operator()(const coord_def &p, const uint32_t offset) const;
        double operator()(double x, double y, double z) const;
        worley::noise_datum datum(double x, double y, double z) const;

    private:
        const double scale_x;
        const double scale_y;
        const double scale_z;
        const double seed_x;
        const double seed_y;
        const double seed_z;
};

class DistortFunction : public ProceduralFunction
{
    public:
        DistortFunction(const ProceduralFunction &_base,
                        const ProceduralFunction &_offx, double _scalex,
                        const ProceduralFunction &_offy, double _scaley)
            : base(_base), off_x(_offx), scale_x(_scalex),
                          off_y(_offy), scale_y(_scaley) { };
        double operator()(double x, double y, double z) const;

    protected:
        const ProceduralFunction &base;
        const ProceduralFunction &off_x;
        const double scale_x;
        const ProceduralFunction &off_y;
        const double scale_y;
};

class WorleyDistortFunction : public DistortFunction
{
    public:
        WorleyDistortFunction(const WorleyFunction &_base,
                              const ProceduralFunction &_offx, double _scalex,
                              const ProceduralFunction &_offy, double _scaley)
            : DistortFunction(_base,_offx,_scalex,_offy,_scaley), wbase(_base) { };
        worley::noise_datum datum(double x, double y, double z) const;

    private:
        const WorleyFunction &wbase;
};

#endif /* PROC_LAYOUTS_H */