ruby-perlin-2D-map-generator 0.0.4 → 0.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +104 -40
- data/lib/CLI/command.rb +101 -8
- data/lib/ansi_colours.rb +3 -0
- data/lib/biome.rb +20 -10
- data/lib/building.rb +20 -0
- data/lib/flora_generator.rb +28 -0
- data/lib/map.rb +33 -1
- data/lib/map_config.rb +53 -8
- data/lib/map_tile_generator.rb +1 -0
- data/lib/pathfinding/a_star_finder.rb +70 -0
- data/lib/pathfinding/grid.rb +78 -0
- data/lib/pathfinding/priority_queue.rb +73 -0
- data/lib/poisson_disk_sampling/sample_area.rb +43 -0
- data/lib/poisson_disk_sampling/sampler.rb +108 -0
- data/lib/road_generator.rb +70 -0
- data/lib/tile.rb +80 -16
- data/lib/town_generator.rb +154 -0
- metadata +37 -13
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8bef2e8554e39c0e315b940f4a98a8927348ae576a7f12168c86c74f969c241b
|
4
|
+
data.tar.gz: b3debfe8269979c1f1f0be2a8def6a86de9fcd2a8ad6f548295113068ec04566
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c91f9810eda61b360e26b31944820b2587ff9e6a10776cdc84347475470573b381853e63b629781fbc0f18eb9fc33299fad31e2a436ef7f7a66d67db8dbb2ea2
|
7
|
+
data.tar.gz: 8c12388e0e7965165557bc5680f030d6d2da9a42e35cc066fbff2390de0e6076c2318e7d62000d17026fa91206adb1ff631eff0ff6af5d670ef81e3d206e45a0
|
data/README.md
CHANGED
@@ -3,16 +3,18 @@
|
|
3
3
|
[](https://badge.fury.io/rb/ruby-perlin-2D-map-generator)
|
4
4
|

|
5
5
|

|
6
|
+
<a href="https://codeclimate.com/github/matthewstyler/ruby-perlin-2D-map-generator/test_coverage"><img src="https://api.codeclimate.com/v1/badges/b99aae29d02b7a8a4cc6/test_coverage" /></a>
|
7
|
+
<a href="https://codeclimate.com/github/matthewstyler/ruby-perlin-2D-map-generator/maintainability"><img src="https://api.codeclimate.com/v1/badges/b99aae29d02b7a8a4cc6/maintainability" /></a>
|
6
8
|
[](https://rubygems.org/gems/ruby-perlin-2D-map-generator)
|
7
9
|
|
8
|
-
A gem that procedurally generates seeded and customizable 2D map using perlin noise.
|
10
|
+
A gem that procedurally generates seeded and customizable 2D map with optional roads and towns using perlin noise.
|
9
11
|
|
10
12
|
Include the gem in your project, or use the executable from the command line.
|
11
13
|
|
12
14
|
Map can be rendered in console using ansi colors or returned as 2D array of hashes describing each tile and binome. Completely customizable, use the --help option for full usage details.
|
13
15
|
|
14
16
|
|
15
|
-

|
16
18
|
|
17
19
|
|
18
20
|
# Installation
|
@@ -34,6 +36,7 @@ gem install ruby-perlin-2D-map-generator
|
|
34
36
|
See Command line Usage for full customization, below are some examples. Alter the temperature, moisture or elevation seeds to alter these maps:
|
35
37
|
|
36
38
|
- Plains with random terrain evens: `ruby-perlin-2D-map-generator render`
|
39
|
+
- Plains with random terrain events and two roads: `ruby-perlin-2D-map-generator render --roads=2`
|
37
40
|
- Desert (increase temperature, decrease moisture): `ruby-perlin-2D-map-generator render --temp=100 --moisture=-100`
|
38
41
|
- Mountainous with lakes (increase elevation, increase moisture) `ruby-perlin-2D-map-generator render --elevation=25 --moisture=25`
|
39
42
|
- Islands (decreaes elevation, increase moisture): `ruby-perlin-2D-map-generator render --elevation=-40 --moisture=25`
|
@@ -44,21 +47,42 @@ See Command line Usage for full customization, below are some examples. Alter th
|
|
44
47
|
--width=int The width of the generated map (default 128)
|
45
48
|
--height=int The height of the generated map (default 128)
|
46
49
|
|
50
|
+
--roads=int Add this many roads through the map,
|
51
|
+
starting and ending at edges
|
52
|
+
(default 0)
|
53
|
+
--towns=int Add this randomly sized towns
|
54
|
+
(default 0)
|
47
55
|
--hs=int The seed for a terrains height perlin generation
|
48
56
|
(default 10)
|
49
57
|
--ms=int The seed for a terrains moist perlin generation
|
50
58
|
(default 300)
|
51
59
|
--ts=int The seed for a terrains temperature perlin generation
|
52
60
|
(default 3000)
|
61
|
+
--rs=int The seed for generating roads
|
62
|
+
(default 100)
|
53
63
|
|
54
|
-
--elevation=float Adjust each generated elevation by this percent (
|
64
|
+
--elevation=float Adjust each generated elevation by this percent (-100 -
|
55
65
|
100) (default 0.0)
|
56
|
-
--moisture=float Adjust each generated moisture by this percent (
|
66
|
+
--moisture=float Adjust each generated moisture by this percent (-100 -
|
57
67
|
100) (default 0.0)
|
58
|
-
--temp=float Adjust each generated temperature by this percent (
|
68
|
+
--temp=float Adjust each generated temperature by this percent (-100
|
59
69
|
- 100) (default 0.0)
|
60
70
|
```
|
61
71
|
|
72
|
+
## Roads and the heuristic
|
73
|
+
Roads can be generated by providing a positive integer to the `roads=` argument. Roads are randomly seeded to begin
|
74
|
+
and start at an axis (but not the same axis).
|
75
|
+
|
76
|
+
A* pathfinding with a priority queue is used to generate the roads. The heuristic uses manhattan distance, and favours existing roads and similar elevations in adjacent tiles.
|
77
|
+
|
78
|
+
Roads can be configured to include/exclude generating paths thorugh water, mountains and flora.
|
79
|
+
|
80
|
+
Tiles containing roads are of type `road`, those without are of type `terrain`.
|
81
|
+
|
82
|
+
The `--roads_to_make` option allows you to specify multiple pairs of coordinates to attempt to build paths, subject to the heuristic and other option constraints. Expects a a single list, but must be sets of 4, example of two roads: `--roads_to_make=0,0,50,50,0,0,75,75`
|
83
|
+
|
84
|
+
## Towns
|
85
|
+
With Poisson Disk Sampling, towns can be generated randomly or with a provided x,y coordinate used as a centroid with radius. The result will be tiles that contain `Building` `items`. Buildings in a town are connected by roads, and additionally towns are connected to other towns by roads.
|
62
86
|
# Generate without rendering
|
63
87
|
|
64
88
|
```irb
|
@@ -112,7 +136,7 @@ $ ruby-perlin-2D-map-generator --help
|
|
112
136
|
```bash
|
113
137
|
Usage: ruby-perlin-2D-map-generator [OPTIONS] (DESCRIBE | RENDER)
|
114
138
|
|
115
|
-
Generate a seeded customizable procedurally generated 2D map.
|
139
|
+
Generate a seeded customizable procedurally generated 2D map with optional roads.
|
116
140
|
Rendered in the console using ansi colours, or described as a 2D array of
|
117
141
|
hashes with each tiles information.
|
118
142
|
|
@@ -128,40 +152,74 @@ Keywords:
|
|
128
152
|
coordinate tile details
|
129
153
|
|
130
154
|
Options:
|
131
|
-
--elevation=float
|
132
|
-
|
133
|
-
--fhx=float
|
134
|
-
|
135
|
-
--fhy=float
|
136
|
-
|
137
|
-
--fmx=float
|
138
|
-
|
139
|
-
--fmy=float
|
140
|
-
|
141
|
-
--ftx=float
|
142
|
-
|
143
|
-
--fty=float
|
144
|
-
|
145
|
-
--gf=bool
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
--
|
151
|
-
|
152
|
-
--
|
153
|
-
|
154
|
-
--
|
155
|
-
|
156
|
-
--
|
157
|
-
|
158
|
-
--
|
159
|
-
|
160
|
-
--
|
161
|
-
|
162
|
-
--
|
163
|
-
|
164
|
-
--
|
155
|
+
--elevation=float Adjust each generated elevation by
|
156
|
+
this percent (-100 - 100) (default 0.0)
|
157
|
+
--fhx=float The frequency for height generation
|
158
|
+
across the x-axis (default 2.5)
|
159
|
+
--fhy=float The frequency for height generation
|
160
|
+
across the y-axis (default 2.5)
|
161
|
+
--fmx=float The frequency for moist generation
|
162
|
+
across the x-axis (default 2.5)
|
163
|
+
--fmy=float The frequency for moist generation
|
164
|
+
across the y-axis (default 2.5)
|
165
|
+
--ftx=float The frequency for temp generation
|
166
|
+
across the x-axis (default 2.5)
|
167
|
+
--fty=float The frequency for temp generation
|
168
|
+
across the y-axis (default 2.5)
|
169
|
+
--gf=bool Generate flora, significantly affects
|
170
|
+
performance
|
171
|
+
--height=int The height of the generated map
|
172
|
+
(default 128)
|
173
|
+
-h, --help Print usage
|
174
|
+
--hs=int The seed for a terrains height perlin
|
175
|
+
generation (default 10)
|
176
|
+
--moisture=float Adjust each generated moisture by
|
177
|
+
this percent (-100 - 100) (default 0.0)
|
178
|
+
--ms=int The seed for a terrains moist perlin
|
179
|
+
generation (default 300)
|
180
|
+
--oh=int Octaves for height generation
|
181
|
+
(default 3)
|
182
|
+
--om=int Octaves for moist generation (default
|
183
|
+
3)
|
184
|
+
--ot=int Octaves for temp generation (default
|
185
|
+
3)
|
186
|
+
--ph=float Persistance for height generation
|
187
|
+
(default 1.0)
|
188
|
+
--pm=float Persistance for moist generation
|
189
|
+
(default 1.0)
|
190
|
+
--pt=float Persistance for temp generation
|
191
|
+
(default 1.0)
|
192
|
+
--road_exclude_flora_path=bool Controls if roads will run tiles
|
193
|
+
containing flora
|
194
|
+
--road_exclude_mountain_path=bool Controls if roads will run through
|
195
|
+
high mountains
|
196
|
+
--road_exclude_water_path=bool Controls if roads will run through
|
197
|
+
water
|
198
|
+
--roads=int Add this many roads through the map,
|
199
|
+
starting and ending at edges (default
|
200
|
+
0)
|
201
|
+
--roads_to_make ints Attempt to create a road from a start
|
202
|
+
and end point (4 integers), can be
|
203
|
+
supplied multiple paths
|
204
|
+
(default [])
|
205
|
+
--rs=int The seed for generating roads
|
206
|
+
(default 100)
|
207
|
+
--temp=float Adjust each generated temperature by
|
208
|
+
this percent (-100 - 100) (default 0.0)
|
209
|
+
--town_seed=int The seed for generating towns
|
210
|
+
(default 500)
|
211
|
+
--towns=int Add this many randomly sized towns
|
212
|
+
throughout the map
|
213
|
+
(default 0)
|
214
|
+
--towns_to_make ints Attempt to create a town at given x,y
|
215
|
+
coordinate, with z points and v radius
|
216
|
+
(4 integers). Can be supplied multiple
|
217
|
+
towns.
|
218
|
+
(default [])
|
219
|
+
--ts=int The seed for a terrains temperature
|
220
|
+
perlin generation (default 3000)
|
221
|
+
--width=int The width of the generated map
|
222
|
+
(default 128)
|
165
223
|
|
166
224
|
Examples:
|
167
225
|
Render with defaults
|
@@ -169,6 +227,12 @@ Examples:
|
|
169
227
|
|
170
228
|
Render with options
|
171
229
|
$ ruby-perlin-2D-map-generator render --elevation=-40 --moisture=25 --hs=1
|
230
|
+
|
231
|
+
Render with roads
|
232
|
+
$ ruby-perlin-2D-map-generator render --roads=2
|
233
|
+
|
234
|
+
Render with 5 roads, 1 provided road, 10 random towns and 1 provided town
|
235
|
+
$ ruby-perlin-2D-map-generator render --roads=5 --roads_to_make=0,0,50,50 --towns=10 --towns_to_make=5,5,10,3
|
172
236
|
|
173
237
|
Describe tile [1, 1]
|
174
238
|
$ ruby-perlin-2D-map-generator describe coordinates=1,1
|
data/lib/CLI/command.rb
CHANGED
@@ -12,7 +12,7 @@ module CLI
|
|
12
12
|
|
13
13
|
no_command
|
14
14
|
|
15
|
-
desc 'Generate a seeded customizable procedurally generated 2D map. Rendered in the console ' \
|
15
|
+
desc 'Generate a seeded customizable procedurally generated 2D map with optional roads. Rendered in the console ' \
|
16
16
|
' using ansi colours, or described as a 2D array of hashes with each tiles information.'
|
17
17
|
|
18
18
|
example 'Render with defaults',
|
@@ -21,6 +21,9 @@ module CLI
|
|
21
21
|
example 'Render with options',
|
22
22
|
' $ ruby-perlin-2D-map-generator render --elevation=-40 --moisture=25 --hs=1'
|
23
23
|
|
24
|
+
example 'Render with roads',
|
25
|
+
' $ ruby-perlin-2D-map-generator render --roads=2'
|
26
|
+
|
24
27
|
example 'Describe tile [1, 1]',
|
25
28
|
' $ ruby-perlin-2D-map-generator describe coordinates=1,1'
|
26
29
|
end
|
@@ -41,6 +44,24 @@ module CLI
|
|
41
44
|
desc 'Used with the describe command, only returns the given coordinate tile details'
|
42
45
|
end
|
43
46
|
|
47
|
+
option :roads_to_make do
|
48
|
+
arity one
|
49
|
+
long '--roads_to_make ints'
|
50
|
+
convert :int_list
|
51
|
+
validate ->(v) { v >= 0 }
|
52
|
+
desc 'Attempt to create a road from a start and end point (4 integers), can be supplied multiple paths'
|
53
|
+
default MapConfig::DEFAULT_ROADS_TO_MAKE
|
54
|
+
end
|
55
|
+
|
56
|
+
option :towns_to_make do
|
57
|
+
arity one
|
58
|
+
long '--towns_to_make ints'
|
59
|
+
convert :int_list
|
60
|
+
validate ->(v) { v >= 0 }
|
61
|
+
desc 'Attempt to create a town at given x,y coordinate, with z points and v radius (4 integers). Can be supplied multiple towns.'
|
62
|
+
default MapConfig::DEFAULT_TOWNS_TO_MAKE
|
63
|
+
end
|
64
|
+
|
44
65
|
option :height_seed do
|
45
66
|
long '--hs int'
|
46
67
|
# or
|
@@ -210,7 +231,7 @@ module CLI
|
|
210
231
|
long '--temp float'
|
211
232
|
long '--temp=float'
|
212
233
|
|
213
|
-
desc 'Adjust each generated temperature by this percent (
|
234
|
+
desc 'Adjust each generated temperature by this percent (-100 - 100)'
|
214
235
|
convert ->(val) { val.to_f / 100.0 }
|
215
236
|
validate ->(val) { val >= -1.0 && val <= 1.0 }
|
216
237
|
default MapConfig::DEFAULT_TEMP_ADJUSTMENT
|
@@ -220,7 +241,7 @@ module CLI
|
|
220
241
|
long '--elevation float'
|
221
242
|
long '--elevation=float'
|
222
243
|
|
223
|
-
desc 'Adjust each generated elevation by this percent (
|
244
|
+
desc 'Adjust each generated elevation by this percent (-100 - 100)'
|
224
245
|
convert ->(val) { val.to_f / 100.0 }
|
225
246
|
validate ->(val) { val >= -1.0 && val <= 1.0 }
|
226
247
|
default MapConfig::DEFAULT_HEIGHT_ADJUSTMENT
|
@@ -230,12 +251,83 @@ module CLI
|
|
230
251
|
long '--moisture float'
|
231
252
|
long '--moisture=float'
|
232
253
|
|
233
|
-
desc 'Adjust each generated moisture by this percent (
|
254
|
+
desc 'Adjust each generated moisture by this percent (-100 - 100)'
|
234
255
|
convert ->(val) { val.to_f / 100.0 }
|
235
256
|
validate ->(val) { val >= -1.0 && val <= 1.0 }
|
236
257
|
default MapConfig::DEFAULT_MOIST_ADJUSTMENT
|
237
258
|
end
|
238
259
|
|
260
|
+
option :roads do
|
261
|
+
long '--roads int'
|
262
|
+
long '--roads=int'
|
263
|
+
|
264
|
+
desc 'Add this many roads through the map, starting and ending at edges'
|
265
|
+
convert Integer
|
266
|
+
validate ->(val) { val >= 0 }
|
267
|
+
default MapConfig::DEFAULT_NUM_OF_ROADS
|
268
|
+
end
|
269
|
+
|
270
|
+
option :road_seed do
|
271
|
+
long '--rs int'
|
272
|
+
long '--rs=int'
|
273
|
+
|
274
|
+
desc 'The seed for generating roads'
|
275
|
+
convert Integer
|
276
|
+
default MapConfig::DEFAULT_ROAD_SEED
|
277
|
+
end
|
278
|
+
|
279
|
+
option :road_exclude_water_path do
|
280
|
+
long '--road_exclude_water_path bool'
|
281
|
+
long '--road_exclude_water_path=bool'
|
282
|
+
|
283
|
+
desc 'Controls if roads will run through water'
|
284
|
+
convert :bool
|
285
|
+
default MapConfig::DEFAULT_ROAD_EXCLUDE_WATER_PATH
|
286
|
+
end
|
287
|
+
|
288
|
+
option :road_exclude_mountain_path do
|
289
|
+
long '--road_exclude_mountain_path bool'
|
290
|
+
long '--road_exclude_mountain_path=bool'
|
291
|
+
|
292
|
+
desc 'Controls if roads will run through high mountains'
|
293
|
+
convert :bool
|
294
|
+
default MapConfig::DEFAULT_ROAD_EXCLUDE_MOUNTAIN_PATH
|
295
|
+
end
|
296
|
+
|
297
|
+
option :road_exclude_flora_path do
|
298
|
+
long '--road_exclude_flora_path bool'
|
299
|
+
long '--road_exclude_flora_path=bool'
|
300
|
+
|
301
|
+
desc 'Controls if roads will run tiles containing flora'
|
302
|
+
convert :bool
|
303
|
+
default MapConfig::DEFAULT_ROAD_EXCLUDE_FLORA_PATH
|
304
|
+
end
|
305
|
+
|
306
|
+
option :town_seed do
|
307
|
+
long '--town_seed int'
|
308
|
+
long '--town_seed=int'
|
309
|
+
|
310
|
+
desc 'The seed for generating towns'
|
311
|
+
convert Integer
|
312
|
+
default MapConfig::DEFAULT_TOWN_SEED
|
313
|
+
end
|
314
|
+
|
315
|
+
option :towns do
|
316
|
+
long '--towns int'
|
317
|
+
long '--towns=int'
|
318
|
+
|
319
|
+
desc 'Add this many randomly sized towns throughout the map'
|
320
|
+
convert Integer
|
321
|
+
validate ->(val) { val >= 0 }
|
322
|
+
default MapConfig::DEFAULT_NUM_OF_TOWNS
|
323
|
+
end
|
324
|
+
|
325
|
+
option :verbose do
|
326
|
+
arity one
|
327
|
+
long '--verbose'
|
328
|
+
desc 'Used with the render command, outputs loading information'
|
329
|
+
end
|
330
|
+
|
239
331
|
flag :help do
|
240
332
|
short '-h'
|
241
333
|
long '--help'
|
@@ -259,10 +351,11 @@ module CLI
|
|
259
351
|
map = Map.new(map_config: MapConfig.new(
|
260
352
|
width: params[:width],
|
261
353
|
height: params[:height],
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
354
|
+
all_perlin_configs: MapConfig::AllPerlinConfigs.new(perlin_height_config, perlin_moist_config, perlin_temp_config),
|
355
|
+
generate_flora: params[:generate_flora],
|
356
|
+
road_config: MapConfig::RoadConfig.new(*params.to_h.slice(:road_seed, :roads, :road_exclude_water_path, :road_exclude_mountain_path, :road_exclude_flora_path, :roads_to_make).values),
|
357
|
+
town_config: MapConfig::TownConfig.new(*params.to_h.slice(:town_seed, :towns, :towns_to_make).values),
|
358
|
+
verbose: params[:verbose]
|
266
359
|
))
|
267
360
|
case params[:command]
|
268
361
|
when 'render' then map.render
|
data/lib/ansi_colours.rb
CHANGED
data/lib/biome.rb
CHANGED
@@ -32,6 +32,10 @@ class Biome
|
|
32
32
|
TAIGA_TERRAIN.include?(self)
|
33
33
|
end
|
34
34
|
|
35
|
+
def high_mountain?
|
36
|
+
HIGH_MOUNTAIN.include?(self)
|
37
|
+
end
|
38
|
+
|
35
39
|
def flora_available
|
36
40
|
!flora_range.nil?
|
37
41
|
end
|
@@ -132,6 +136,12 @@ class Biome
|
|
132
136
|
TAIGA_COAST
|
133
137
|
].freeze
|
134
138
|
|
139
|
+
HIGH_MOUNTAIN = [
|
140
|
+
SNOW,
|
141
|
+
ROCKS,
|
142
|
+
MOUNTAIN
|
143
|
+
].freeze
|
144
|
+
|
135
145
|
LAND_TERRAIN = (ALL_TERRAIN - WATER_TERRAIN).freeze
|
136
146
|
|
137
147
|
class << self
|
@@ -141,21 +151,21 @@ class Biome
|
|
141
151
|
case elevation
|
142
152
|
when 0.95..1
|
143
153
|
SNOW
|
144
|
-
when 0.9
|
154
|
+
when 0.9...0.95
|
145
155
|
ROCKS
|
146
|
-
when 0.8
|
156
|
+
when 0.8...0.9
|
147
157
|
if moist < 0.9
|
148
158
|
MOUNTAIN
|
149
159
|
else
|
150
160
|
SHOAL
|
151
161
|
end
|
152
|
-
when 0.7
|
162
|
+
when 0.7...0.8
|
153
163
|
if moist < 0.9
|
154
164
|
MOUNTAIN_FOOT
|
155
165
|
else
|
156
166
|
SHOAL
|
157
167
|
end
|
158
|
-
when 0.6
|
168
|
+
when 0.6...0.7
|
159
169
|
if moist < 0.8
|
160
170
|
if desert_condition?(moist, temp)
|
161
171
|
STEPPE_DESERT
|
@@ -169,7 +179,7 @@ class Biome
|
|
169
179
|
else
|
170
180
|
SHOAL
|
171
181
|
end
|
172
|
-
when 0.3
|
182
|
+
when 0.3...0.6
|
173
183
|
if desert_condition?(moist, temp)
|
174
184
|
DESERT
|
175
185
|
elsif taiga_condition?(moist, temp)
|
@@ -177,7 +187,7 @@ class Biome
|
|
177
187
|
else
|
178
188
|
VALLEY
|
179
189
|
end
|
180
|
-
when 0.2
|
190
|
+
when 0.2...0.3
|
181
191
|
if desert_condition?(moist, temp)
|
182
192
|
DEEP_DESERT
|
183
193
|
elsif taiga_condition?(moist, temp)
|
@@ -185,25 +195,25 @@ class Biome
|
|
185
195
|
else
|
186
196
|
DEEP_VALLEY
|
187
197
|
end
|
188
|
-
when 0.15
|
198
|
+
when 0.15...0.2
|
189
199
|
if taiga_condition?(moist, temp)
|
190
200
|
TAIGA_COAST
|
191
201
|
else
|
192
202
|
COASTLINE
|
193
203
|
end
|
194
|
-
when 0.05
|
204
|
+
when 0.05...0.15
|
195
205
|
if taiga_condition?(moist, temp)
|
196
206
|
ICE
|
197
207
|
else
|
198
208
|
SHOAL
|
199
209
|
end
|
200
|
-
when 0.025
|
210
|
+
when 0.025...0.05
|
201
211
|
if taiga_condition?(moist, temp)
|
202
212
|
ICE
|
203
213
|
else
|
204
214
|
OCEAN
|
205
215
|
end
|
206
|
-
when 0.0
|
216
|
+
when 0.0...0.025
|
207
217
|
if taiga_condition?(moist, temp)
|
208
218
|
ICE
|
209
219
|
else
|
data/lib/building.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'tile_item'
|
4
|
+
|
5
|
+
#
|
6
|
+
# Represents a building item on a tile
|
7
|
+
#
|
8
|
+
class Building < TileItem
|
9
|
+
TOWN_RENDER_PRIORITY = DEFAULT_RENDER_PRIORITY + 1
|
10
|
+
|
11
|
+
HOUSE = "\u{1F3E0}"
|
12
|
+
|
13
|
+
def initialize(render_symbol)
|
14
|
+
super self, render_symbol: render_symbol, render_priority: TOWN_RENDER_PRIORITY
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.random_town_building(_seed)
|
18
|
+
Building.new(HOUSE)
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
#
|
4
|
+
# Generates flora for the given tiles
|
5
|
+
#
|
6
|
+
class FloraGenerator
|
7
|
+
attr_reader :tiles
|
8
|
+
|
9
|
+
def initialize(tiles)
|
10
|
+
@tiles = tiles
|
11
|
+
end
|
12
|
+
|
13
|
+
def generate(config)
|
14
|
+
return unless config.generate_flora
|
15
|
+
|
16
|
+
puts 'generating flora...' if config.verbose
|
17
|
+
tiles.each do |row|
|
18
|
+
row.each do |tile|
|
19
|
+
next unless tile.biome.flora_available
|
20
|
+
|
21
|
+
range_max_value = tiles[(tile.y - tile.biome.flora_range)...(tile.y + tile.biome.flora_range)]&.map do |r|
|
22
|
+
r[(tile.x - tile.biome.flora_range)...(tile.x + tile.biome.flora_range)]
|
23
|
+
end&.flatten&.map(&:height)&.max
|
24
|
+
tile.add_flora if range_max_value == tile.height
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
data/lib/map.rb
CHANGED
@@ -2,6 +2,9 @@
|
|
2
2
|
|
3
3
|
require 'map_tile_generator'
|
4
4
|
require 'map_config'
|
5
|
+
require 'road_generator'
|
6
|
+
require 'town_generator'
|
7
|
+
require 'flora_generator'
|
5
8
|
|
6
9
|
class Map
|
7
10
|
attr_reader :config
|
@@ -30,6 +33,35 @@ class Map
|
|
30
33
|
# rubocop:enable Naming/MethodParameterName:
|
31
34
|
|
32
35
|
def tiles
|
33
|
-
@tiles
|
36
|
+
return @tiles if @tiles
|
37
|
+
|
38
|
+
generate_tiles
|
39
|
+
generate_flora
|
40
|
+
generate_roads
|
41
|
+
generate_towns
|
42
|
+
|
43
|
+
@tiles
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
def generate_tiles
|
49
|
+
@tiles = MapTileGenerator.new(map: self).generate
|
50
|
+
end
|
51
|
+
|
52
|
+
def generate_flora
|
53
|
+
FloraGenerator.new(@tiles).generate(config)
|
54
|
+
end
|
55
|
+
|
56
|
+
def generate_roads
|
57
|
+
road_generator = RoadGenerator.new(@tiles)
|
58
|
+
road_generator.generate_num_of_random_roads(config.road_config)
|
59
|
+
road_generator.generate_roads_from_coordinate_list(config.road_config.roads_to_make, config.verbose)
|
60
|
+
end
|
61
|
+
|
62
|
+
def generate_towns
|
63
|
+
town_generator = TownGenerator.new(@tiles, seed: config.town_config.town_seed)
|
64
|
+
town_generator.generate_random_towns(config.town_config)
|
65
|
+
town_generator.generate_towns_from_coordinate_list(config.town_config)
|
34
66
|
end
|
35
67
|
end
|
data/lib/map_config.rb
CHANGED
@@ -25,25 +25,57 @@ class MapConfig
|
|
25
25
|
DEFAULT_TEMP_X_FREQUENCY = 2.5
|
26
26
|
DEFAULT_TEMP_ADJUSTMENT = 0.0
|
27
27
|
|
28
|
+
DEFAULT_ROAD_SEED = 100
|
29
|
+
DEFAULT_NUM_OF_ROADS = 0
|
30
|
+
DEFAULT_ROAD_EXCLUDE_WATER_PATH = true
|
31
|
+
DEFAULT_ROAD_EXCLUDE_MOUNTAIN_PATH = true
|
32
|
+
DEFAULT_ROAD_EXCLUDE_FLORA_PATH = true
|
33
|
+
DEFAULT_ROADS_TO_MAKE = [].freeze
|
34
|
+
|
35
|
+
DEFAULT_TOWN_SEED = 500
|
36
|
+
DEFAULT_NUM_OF_TOWNS = 0
|
37
|
+
DEFAULT_TOWNS_TO_MAKE = [].freeze
|
38
|
+
|
39
|
+
DEFAULT_VERBOSE = false
|
40
|
+
|
28
41
|
PERLIN_CONFIG_OPTIONS = %i[width height noise_seed octaves x_frequency y_frequency persistance adjustment].freeze
|
29
|
-
|
42
|
+
ALL_PERLIN_CONFIGS = %i[perlin_height_config perlin_moist_config perlin_temp_config].freeze
|
43
|
+
ROAD_CONFIG_OPTIONS = %i[road_seed roads road_exclude_water_path road_exclude_mountain_path road_exclude_flora_path roads_to_make verbose].freeze
|
44
|
+
TOWN_CONFIG_OPTIONS = %i[town_seed towns towns_to_make verbose].freeze
|
30
45
|
|
31
|
-
|
46
|
+
PerlinConfig = Struct.new(*PERLIN_CONFIG_OPTIONS)
|
47
|
+
AllPerlinConfigs = Struct.new(*ALL_PERLIN_CONFIGS)
|
48
|
+
RoadConfig = Struct.new(*ROAD_CONFIG_OPTIONS)
|
49
|
+
TownConfig = Struct.new(*TOWN_CONFIG_OPTIONS)
|
32
50
|
|
33
|
-
|
34
|
-
height: DEFAULT_TILE_COUNT, generate_flora: DEFAULT_GENERATE_FLORA)
|
35
|
-
raise ArgumentError unless perlin_height_config.is_a?(PerlinConfig) && perlin_moist_config.is_a?(PerlinConfig)
|
51
|
+
attr_reader :generate_flora, :perlin_height_config, :perlin_moist_config, :perlin_temp_config, :width, :height, :road_config, :town_config, :verbose
|
36
52
|
|
53
|
+
# rubocop:disable Metrics/ParameterLists:
|
54
|
+
def initialize(all_perlin_configs: default_perlin_configs, width: DEFAULT_TILE_COUNT,
|
55
|
+
height: DEFAULT_TILE_COUNT, generate_flora: DEFAULT_GENERATE_FLORA, road_config: default_road_config, town_config: default_town_config, verbose: DEFAULT_VERBOSE)
|
56
|
+
validate(all_perlin_configs)
|
37
57
|
@generate_flora = generate_flora
|
38
|
-
@perlin_height_config = perlin_height_config
|
39
|
-
@perlin_moist_config = perlin_moist_config
|
40
|
-
@perlin_temp_config = perlin_temp_config
|
58
|
+
@perlin_height_config = all_perlin_configs.perlin_height_config
|
59
|
+
@perlin_moist_config = all_perlin_configs.perlin_moist_config
|
60
|
+
@perlin_temp_config = all_perlin_configs.perlin_temp_config
|
41
61
|
@width = width
|
42
62
|
@height = height
|
63
|
+
@road_config = road_config
|
64
|
+
@town_config = town_config
|
65
|
+
@verbose = verbose
|
66
|
+
town_config.verbose = verbose
|
67
|
+
road_config.verbose = verbose
|
43
68
|
end
|
69
|
+
# rubocop:enable Metrics/ParameterLists:
|
44
70
|
|
45
71
|
private
|
46
72
|
|
73
|
+
def validate(all_perlin_configs)
|
74
|
+
unless all_perlin_configs.perlin_height_config.is_a?(PerlinConfig) && all_perlin_configs.perlin_moist_config.is_a?(PerlinConfig) && all_perlin_configs.perlin_temp_config.is_a?(PerlinConfig)
|
75
|
+
raise ArgumentError
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
47
79
|
def default_perlin_height_config
|
48
80
|
PerlinConfig.new(DEFAULT_TILE_COUNT, DEFAULT_TILE_COUNT, DEFAULT_HEIGHT_SEED, DEFAULT_HEIGHT_OCTAVES,
|
49
81
|
DEFAULT_HEIGHT_X_FREQUENCY, DEFAULT_HEIGHT_Y_FREQUENCY, DEFAULT_HEIGHT_PERSISTANCE, DEFAULT_HEIGHT_ADJUSTMENT)
|
@@ -58,4 +90,17 @@ class MapConfig
|
|
58
90
|
PerlinConfig.new(DEFAULT_TILE_COUNT, DEFAULT_TILE_COUNT, DEFAULT_TEMP_SEED, DEFAULT_TEMP_OCTAVES,
|
59
91
|
DEFAULT_TEMP_X_FREQUENCY, DEFAULT_TEMP_Y_FREQUENCY, DEFAULT_TEMP_PERSISTANCE, DEFAULT_TEMP_ADJUSTMENT)
|
60
92
|
end
|
93
|
+
|
94
|
+
def default_road_config
|
95
|
+
RoadConfig.new(DEFAULT_ROAD_SEED, DEFAULT_NUM_OF_ROADS, DEFAULT_ROAD_EXCLUDE_WATER_PATH, DEFAULT_ROAD_EXCLUDE_MOUNTAIN_PATH, DEFAULT_ROAD_EXCLUDE_FLORA_PATH, DEFAULT_ROADS_TO_MAKE,
|
96
|
+
DEFAULT_VERBOSE)
|
97
|
+
end
|
98
|
+
|
99
|
+
def default_town_config
|
100
|
+
TownConfig.new(DEFAULT_TOWN_SEED, DEFAULT_NUM_OF_TOWNS, DEFAULT_TOWNS_TO_MAKE, DEFAULT_VERBOSE)
|
101
|
+
end
|
102
|
+
|
103
|
+
def default_perlin_configs
|
104
|
+
AllPerlinConfigs.new(default_perlin_height_config, default_perlin_moist_config, default_perlin_temp_config)
|
105
|
+
end
|
61
106
|
end
|