worldgen 0.0.2

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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: de4a34b0248c80788bc6ce2f4a12403b49e8df05
4
+ data.tar.gz: d8210298cd91385beab0cb5366dcc19bfba9eefd
5
+ SHA512:
6
+ metadata.gz: 2829eab4c21503c6243774487c0121dd84fc41300103759116d97c2eeb378ed0a0b5cce0a2f16061d70e24b81bd8ec226375abda3e50827828e3d5316ab8b26f
7
+ data.tar.gz: 58b82dcbc654c466ced978d629881bcba395d4577becff34b40017b912bff9a51462668e426033c36ec7106618be51c2e7b1d066fc24054dd55270acf1822691
@@ -0,0 +1,19 @@
1
+ # Gem/Bundler stuff
2
+ /.bundle/
3
+ /.yardoc
4
+ /Gemfile.lock
5
+ /_yardoc/
6
+ /coverage/
7
+ /doc/
8
+ /pkg/
9
+ /spec/reports/
10
+ /tmp/
11
+ *.bundle
12
+ *.so
13
+ *.o
14
+ *.a
15
+ Makefile
16
+ mkmf.log
17
+
18
+ # Vim stuff
19
+ *.sw[op]
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in worldgen.gemspec
4
+ gemspec
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Rob Britton
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,59 @@
1
+ # Worldgen
2
+
3
+ Worldgen allows you to generate random worlds.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'worldgen'
11
+ ```
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install worldgen
20
+
21
+ ## Usage
22
+
23
+ So far there is not much. You can do square heightmaps:
24
+
25
+ ```ruby
26
+ # Create a 50x50 heightmap - this will be flat
27
+ heightmap = Worldgen::HeightMap.new 50
28
+ ```
29
+
30
+ Then you can do a diamond square fractal to it:
31
+
32
+ ```ruby
33
+ Worldgen::Algorithms.diamond_square! heightmap
34
+ ```
35
+
36
+ Then dump it to an image file:
37
+
38
+ ```ruby
39
+ Worldgen::Render.heightmap heightmap, "output.png"
40
+ ```
41
+
42
+ ## Contributing
43
+
44
+ 1. Fork it ( https://github.com/robbrit/worldgen/fork )
45
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
46
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
47
+ 4. Push to the branch (`git push origin my-new-feature`)
48
+ 5. Create a new Pull Request
49
+
50
+ ### Notes
51
+
52
+ Heightmaps are purely written in C for performance. If you're going to be
53
+ writing code that interacts with heightmaps, you're going to have a much
54
+ better time doing it in C since Ruby is a fair bit too slow once you get to
55
+ larger maps (512x512 or higher).
56
+
57
+ ### TODO
58
+
59
+ * Diamond Square output seems to be rougher than it should be
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ require "rake/extensiontask"
4
+
5
+ spec = Gem::Specification.load("worldgen.gemspec")
6
+ Rake::ExtensionTask.new("worldgen", spec)
@@ -0,0 +1,31 @@
1
+ #include "common.h"
2
+
3
+ /**
4
+ * Convert an array of doubles into normalized doubles between 0 and 1
5
+ **/
6
+ void normalize(double * values, int size) {
7
+ double min = values[0],
8
+ max = values[0];
9
+
10
+ int x;
11
+
12
+ for (x = 1; x < num_points(size); x++) {
13
+ if (values[x] > max) {
14
+ max = values[x];
15
+ }
16
+ if (values[x] < min) {
17
+ min = values[x];
18
+ }
19
+ }
20
+
21
+ for (x = 0; x < num_points(size); x++) {
22
+ values[x] = (values[x] - min) / (max - min);
23
+ }
24
+ }
25
+
26
+ /** Get the number of points for a heightmap of a given size. This will change
27
+ * later when we move from beyond just a simple square geometry.
28
+ */
29
+ int num_points(int size) {
30
+ return size * size;
31
+ }
@@ -0,0 +1,16 @@
1
+ #ifndef COMMON_H__
2
+ #define COMMON_H__
3
+
4
+ #define ARR(a, x, y) a[(x) * size + (y)]
5
+
6
+ typedef double * heightmap_points;
7
+
8
+ typedef struct {
9
+ int size;
10
+ heightmap_points heights;
11
+ } heightmap;
12
+
13
+ int num_points(int);
14
+ void normalize(double *, int);
15
+
16
+ #endif // COMMON_H__
@@ -0,0 +1,106 @@
1
+ #include <ruby.h>
2
+ #include <stdlib.h>
3
+
4
+ #include "common.h"
5
+
6
+ #define DEFAULT_ROUGHNESS 5
7
+
8
+ extern heightmap get_heights(VALUE);
9
+ extern void set_heights(VALUE, heightmap_points);
10
+ extern int get_size(VALUE);
11
+
12
+ double diamond_shift(double roughness) {
13
+ double r = (double)rand() / (double)RAND_MAX;
14
+
15
+ return (r * 2.0 - 1.0) * roughness;
16
+ }
17
+
18
+ /**
19
+ * Generate terrain using a diamond square algorithm.
20
+ * Arguments:
21
+ * `heightmap` - The heightmap to use for the algorithm
22
+ * `roughness` (optional) - How "rough" to make the surface
23
+ *
24
+ * Return value: nil
25
+ **/
26
+ VALUE diamond_square(int argc, VALUE *argv, VALUE self) {
27
+ int x, y;
28
+ double ratio = 500.0;
29
+ VALUE heightmap_obj, vroughness;
30
+ int size, side_size;
31
+ double roughness;
32
+ heightmap_points heights;
33
+
34
+ rb_scan_args(argc, argv, "11", &heightmap_obj, &vroughness);
35
+
36
+ size = get_size(heightmap_obj);
37
+ side_size = size - 1;
38
+
39
+ roughness = vroughness == Qnil ? DEFAULT_ROUGHNESS : NUM2DBL(vroughness);
40
+
41
+ // need to allocate on the heap since Ruby will throw stack size problems
42
+ // if we don't
43
+ heights = (double *)malloc(sizeof(double) * num_points(size));
44
+
45
+ memset(heights, 0.0, sizeof(double) * num_points(size));
46
+
47
+ ARR(heights, 0, 0) = ARR(heights, 0, size - 1) =
48
+ ARR(heights, size - 1, 0) = ARR(heights, size - 1, size - 1) =
49
+ diamond_shift(roughness);
50
+
51
+ while (side_size >= 2) {
52
+ int half_side = side_size / 2;
53
+
54
+ // Square step
55
+ for (x = 0; x < size - 1; x += side_size) {
56
+ for (y = 0; y < size - 1; y += side_size) {
57
+ double avg = (ARR(heights, x, y) +
58
+ ARR(heights, x + side_size, y) +
59
+ ARR(heights, x, y + side_size) +
60
+ ARR(heights, x + side_size, y + side_size)) / 4.0;
61
+
62
+ ARR(heights, x + half_side, y + half_side) = avg + diamond_shift(roughness);
63
+ }
64
+ }
65
+
66
+ for (x = 0; x < size - 1; x += half_side) {
67
+ for (y = (x + half_side) % side_size; y < size - 1; y += side_size) {
68
+ double avg = (ARR(heights, (x - half_side + size - 1) % (size - 1), y) +
69
+ ARR(heights, (x + half_side) % (size - 1), y) +
70
+ ARR(heights, x, (y + half_side) % (size - 1)) +
71
+ ARR(heights, x, (y - half_side + size - 1) % (size - 1))) / 4.0;
72
+
73
+ avg += diamond_shift(roughness);
74
+
75
+ ARR(heights, x, y) = avg;
76
+
77
+ if (x == 0) {
78
+ ARR(heights, size - 1, y) = avg;
79
+ }
80
+ if (y == 0) {
81
+ ARR(heights, x, size - 1) = avg;
82
+ }
83
+ }
84
+ }
85
+
86
+ side_size /= 2.0;
87
+ ratio /= 2.0;
88
+ }
89
+
90
+ // normalize
91
+ normalize(heights, size);
92
+
93
+ // copy into the array
94
+ set_heights(heightmap_obj, heights);
95
+
96
+ return Qnil;
97
+ }
98
+
99
+ void load_diamond_square() {
100
+ VALUE mod, algos;
101
+
102
+ mod = rb_define_module("Worldgen");
103
+ algos = rb_define_module_under(mod, "Algorithms");
104
+
105
+ rb_define_singleton_method(algos, "diamond_square!", diamond_square, -1);
106
+ }
@@ -0,0 +1,4 @@
1
+ require 'mkmf'
2
+
3
+ dir_config("worldgen")
4
+ create_makefile("worldgen")
@@ -0,0 +1,106 @@
1
+ #include <ruby.h>
2
+
3
+ #include "common.h"
4
+
5
+ #include <stdlib.h>
6
+ #include <stdio.h>
7
+ #include <time.h>
8
+
9
+ VALUE HeightmapData; // conversion between heightmap struct and Ruby
10
+
11
+ void delete_heightmap(void * ptr) {
12
+ heightmap *map = (heightmap *)ptr;
13
+ free(map->heights);
14
+ }
15
+
16
+ /**
17
+ * Get the heightmap for a HeightMap object
18
+ */
19
+ heightmap get_heights(VALUE heightmap_obj) {
20
+ VALUE heights_ptr = rb_iv_get(heightmap_obj, "@heights_ptr");
21
+ heightmap *map;
22
+
23
+ Data_Get_Struct(heights_ptr, heightmap, map);
24
+
25
+ return *map;
26
+ }
27
+
28
+ int get_size(VALUE heightmap_obj) {
29
+ return FIX2INT(rb_iv_get(heightmap_obj, "@size"));
30
+ }
31
+
32
+ void set_heights(VALUE heightmap_obj, heightmap_points map) {
33
+ // if we already have a height, kill it
34
+ VALUE heights_ptr;
35
+ heightmap * hmap;
36
+
37
+ hmap = ALLOC(heightmap);
38
+ hmap->heights = map;
39
+ hmap->size = get_size(heightmap_obj);
40
+
41
+ heights_ptr = Data_Wrap_Struct(HeightmapData, 0, delete_heightmap, hmap);
42
+
43
+ rb_iv_set(heightmap_obj, "@heights_ptr", heights_ptr);
44
+ }
45
+
46
+ /**
47
+ * Initialize the C side of things for a heightmap
48
+ */
49
+ VALUE initialize_native(VALUE self, VALUE vsize) {
50
+ int size = FIX2INT(vsize);
51
+ int memsize = num_points(size) * sizeof(double);
52
+
53
+ heightmap_points map = (heightmap_points)malloc(memsize);
54
+ memset(map, 0, memsize);
55
+ set_heights(self, map);
56
+
57
+ return Qnil;
58
+ }
59
+
60
+ /**
61
+ * Get the number of points within the heightmap. Right now this is a very
62
+ * simple calculation of size * size.
63
+ */
64
+ VALUE num_points_wrapped(VALUE self) {
65
+ return INT2FIX(num_points(FIX2INT(rb_iv_get(self, "@size"))));
66
+ }
67
+
68
+ /**
69
+ * Iterate over all the points in the heightmap.
70
+ * Example:
71
+ * ```
72
+ * heightmap.each_height do |x, y, height|
73
+ * puts "Height at (#{x}, #{y}) is #{height}"
74
+ * end
75
+ */
76
+ VALUE each_height(VALUE self) {
77
+ heightmap map = get_heights(self);
78
+ heightmap_points ptr = map.heights;
79
+ VALUE args = rb_ary_new2(3);
80
+ int size = get_size(self);
81
+ int x, y;
82
+
83
+ for (x = 0; x < size; x++) {
84
+ rb_ary_store(args, 0, INT2FIX(x));
85
+ for (y = 0; y < size; y++) {
86
+ rb_ary_store(args, 1, INT2FIX(y));
87
+ rb_ary_store(args, 2, DBL2NUM(*ptr++));
88
+ rb_yield(args);
89
+ }
90
+ }
91
+ return self;
92
+ }
93
+
94
+ void load_heightmap() {
95
+ VALUE mod, height_map;
96
+
97
+ mod = rb_define_module("Worldgen");
98
+
99
+ height_map = rb_define_class_under(mod, "HeightMap", rb_cObject);
100
+
101
+ rb_define_private_method(height_map, "initialize_native", initialize_native, 1);
102
+ rb_define_method(height_map, "num_points", num_points_wrapped, 0);
103
+ rb_define_method(height_map, "each_height", each_height, 0);
104
+
105
+ HeightmapData = rb_define_class_under(height_map, "HeightmapData", rb_cObject);
106
+ }
@@ -0,0 +1,13 @@
1
+ #include <ruby.h>
2
+ #include <stdlib.h>
3
+ #include <time.h>
4
+
5
+ extern void load_heightmap();
6
+ extern void load_diamond_square();
7
+
8
+ void Init_worldgen() {
9
+ srand((unsigned)time(NULL));
10
+
11
+ load_heightmap();
12
+ load_diamond_square();
13
+ }
@@ -0,0 +1,51 @@
1
+ require 'optparse'
2
+ require "worldgen"
3
+
4
+ options = {}
5
+
6
+ OptionParser.new do |opts|
7
+ opts.on("--heightmap [FILE]", String, "Output a heightmap to FILE") do |file|
8
+ options[:heightmap] = file
9
+ end
10
+
11
+ opts.on("--platemap [FILE]", String, "Output a platemap to FILE") do |file|
12
+ options[:platemap] = file
13
+ end
14
+
15
+ opts.on("--size N", Integer, "Generate a map of size 2^N + 1") do |n|
16
+ options[:size] = 2**n + 1
17
+ end
18
+
19
+ opts.on("--num-plates [N]", Integer, "Generate N plates") do |n|
20
+ options[:num_plates] = n
21
+ end
22
+ end.parse!
23
+
24
+ if not options[:size]
25
+ puts "No size specified."
26
+ exit
27
+ end
28
+
29
+ if options[:heightmap]
30
+ puts "Generating heightmap..."
31
+ heightmap = Worldgen::HeightMap.new(options[:size])
32
+ Worldgen::Algorithms.diamond_square!(heightmap)
33
+ Worldgen::Render.heightmap heightmap, options[:heightmap]
34
+ end
35
+
36
+ if options[:platemap]
37
+ puts "Generating plate map..."
38
+ if not options[:num_plates]
39
+ puts "num_plates not specified."
40
+ exit
41
+ end
42
+
43
+ platemap = Worldgen::PlateMap.new(options[:size])
44
+ platemap.generate_plates! options[:num_plates]
45
+ puts "Converting to height map..."
46
+ heightmap = platemap.to_height_map
47
+ render_heightmap heightmap, options[:platemap]
48
+ end
49
+
50
+ puts "Done."
51
+
@@ -0,0 +1,8 @@
1
+ require "worldgen/version"
2
+ require "worldgen/heightmap"
3
+ require "worldgen/render"
4
+ require_relative "worldgen.so"
5
+
6
+ module Worldgen
7
+ # Your code goes here...
8
+ end
@@ -0,0 +1,18 @@
1
+ module Worldgen
2
+ # A square heightmap
3
+ class HeightMap
4
+ # A class used internally to manage C-allocated memory
5
+ class HeightmapData
6
+ end
7
+
8
+ attr_reader :size
9
+
10
+ # Create a new square heightmap.
11
+ # Arguments:
12
+ # * size - the width/height of the map
13
+ def initialize size
14
+ @size = size
15
+ initialize_native(size)
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,44 @@
1
+ require 'RMagick'
2
+
3
+ module Worldgen::Render
4
+ # Render a heightmap to a grayscale file.
5
+ # Arguments:
6
+ # * map - The heightmap to render
7
+ # * filename - The filename to use. Image format will be inferred from the filename
8
+ def self.heightmap map, filename
9
+ # loading each one in is crazy slow, just throw it into a pixel map
10
+ image = Magick::Image.new(map.size, map.size) { self.background_color = "black" }
11
+
12
+ map.each_height do |x, y, pix_height|
13
+ grey = ("%2X" % (pix_height * 255).round) * 3
14
+ image.pixel_color x, y, "##{grey}"
15
+ end
16
+
17
+ #image.display
18
+ image.write filename
19
+ end
20
+
21
+ =begin
22
+ def self.platemap map, filename
23
+ image = Magick::Image.new(map.size, map.size) { self.background_color = "black" }
24
+
25
+ # draw plates
26
+ colours = [
27
+ "#FF0000", "#0000FF", "#FFFF00", "#00FF00",
28
+ "#FF6600", "#FF00FF", "#00FFFF", "#CCCCCC",
29
+ "#006600", "#000066", "#660066", "#666600"
30
+ ]
31
+ map.each_plate_point do |x, y, plate|
32
+ begin
33
+ image.pixel_color x, y, colours[plate]
34
+ rescue
35
+ puts "colour fail"
36
+ puts [x, y, plate, colour[plate]].inspect
37
+ end
38
+ end
39
+
40
+ #image.display
41
+ image.write filename
42
+ end
43
+ =end
44
+ end
@@ -0,0 +1,3 @@
1
+ module Worldgen
2
+ VERSION = "0.0.2"
3
+ end
@@ -0,0 +1,27 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'worldgen/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "worldgen"
8
+ spec.version = Worldgen::VERSION
9
+ spec.authors = ["Rob Britton"]
10
+ spec.email = ["rob@robbritton.com"]
11
+ spec.summary = %q{Gem to handle procedural content generation for worlds.}
12
+ #spec.description = %q{TODO: Write a longer description. Optional.}
13
+ spec.homepage = ""
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.extensions << "ext/worldgen/extconf.rb"
22
+
23
+ spec.add_dependency "rmagick", "~> 2.13.3"
24
+ spec.add_development_dependency "bundler", "~> 1.6"
25
+ spec.add_development_dependency "rake", "~> 10.0"
26
+ spec.add_development_dependency "rake-compiler", "~> 0.9.3"
27
+ end
metadata ADDED
@@ -0,0 +1,118 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: worldgen
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ platform: ruby
6
+ authors:
7
+ - Rob Britton
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-08-24 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rmagick
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 2.13.3
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 2.13.3
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.6'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.6'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '10.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '10.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake-compiler
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: 0.9.3
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 0.9.3
69
+ description:
70
+ email:
71
+ - rob@robbritton.com
72
+ executables: []
73
+ extensions:
74
+ - ext/worldgen/extconf.rb
75
+ extra_rdoc_files: []
76
+ files:
77
+ - ".gitignore"
78
+ - Gemfile
79
+ - LICENSE.txt
80
+ - README.md
81
+ - Rakefile
82
+ - ext/worldgen/common.c
83
+ - ext/worldgen/common.h
84
+ - ext/worldgen/diamondsquare.c
85
+ - ext/worldgen/extconf.rb
86
+ - ext/worldgen/heightmap.c
87
+ - ext/worldgen/worldgen.c
88
+ - generate.rb
89
+ - lib/worldgen.rb
90
+ - lib/worldgen/heightmap.rb
91
+ - lib/worldgen/render.rb
92
+ - lib/worldgen/version.rb
93
+ - worldgen.gemspec
94
+ homepage: ''
95
+ licenses:
96
+ - MIT
97
+ metadata: {}
98
+ post_install_message:
99
+ rdoc_options: []
100
+ require_paths:
101
+ - lib
102
+ required_ruby_version: !ruby/object:Gem::Requirement
103
+ requirements:
104
+ - - ">="
105
+ - !ruby/object:Gem::Version
106
+ version: '0'
107
+ required_rubygems_version: !ruby/object:Gem::Requirement
108
+ requirements:
109
+ - - ">="
110
+ - !ruby/object:Gem::Version
111
+ version: '0'
112
+ requirements: []
113
+ rubyforge_project:
114
+ rubygems_version: 2.1.11
115
+ signing_key:
116
+ specification_version: 4
117
+ summary: Gem to handle procedural content generation for worlds.
118
+ test_files: []