astromapper 1.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,18 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ Puzzle
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in astromapper.gemspec
4
+ gemspec
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Merovex
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,124 @@
1
+ Traveller Astromapper
2
+ ==========================
3
+
4
+ The **Traveller Astromapper** creates random Traveller star maps intended for YOTS.
5
+
6
+ The maps are generated using an inspired amalgam of [Mongoose](http://www.mongoosepublishing.com/rpgs/traveller/core-rulebooks-accessories.html) and [Classic Traveller](http://www.farfuture.net/) rules, with some [Gurps Space](http://www.sjgames.com/gurps/books/space/) 4e and 3e.
7
+
8
+ Mongoose rules are used when generating the World characteristics. Classic Traveller is used when fleshing out star system details such as stars, non-world orbits, presence of companion stars. Gurps is used to flesh out star characteristics and the impact of a companion star on the primary's orbits.
9
+
10
+ * Sector: 40x32 hex grid
11
+ * Tract: 8x10 hex grid (Traveller Subsector)
12
+ * Volume: 1-hex
13
+ * World: primary inhabited planet.
14
+ * Orbit: A slot around primary star, may include companion stars, planets, belts or nothing.
15
+
16
+ Installation
17
+ ============
18
+
19
+ This software relies upon Ruby 1.9.2+.
20
+
21
+ To convert from SVG to JPG, PNG, GIF you will need to install Imagemagick with -rsvg flag (later feature).
22
+
23
+ How to Use Traveller Astromapper
24
+ ======================
25
+
26
+ To create a new Traveller Astromapper project, execute the following on the command line:
27
+
28
+ ```
29
+ astromapper new yots_sector
30
+ ```
31
+
32
+ The command creates the following directory structure:
33
+
34
+ ```
35
+ yots_sector
36
+ ├── _astromapper.yml
37
+ ├── output
38
+ └── templates
39
+ └── names.yml
40
+ ```
41
+
42
+ ASCII Output
43
+ ------------
44
+
45
+ The block below shows Traveller Astromapper's ASCII output. The top row is the key system aspects: Volume ID, World UWP, Temperature, Presence of Bases & Gas Giants, Trade Codes, Stars, Primary Star's Orbits, Name. The rows that follow elaborate the primary star's orbits. Rows with two dashes are the Primary's orbits, orbit type, UWP, and orbit distance (usable for travel and year length). Other rows with the '/' are that orbit's satellites. When the UWP is dots, that orbit is empty.
46
+
47
+ ```
48
+ 1201 E949556-5 T ..G.. .. Lt,NI F0IV/DB R..WGG..S Secundus
49
+ -- 1. R // X600000-0 // 0.4 au
50
+ / 7 rad. X420000
51
+ / 9 rad. X620000
52
+ -- 2. . // .......-. // 0.7 au
53
+ -- 3. . // .......-. // 1.4 au
54
+ -- 4. * W // E949556-5 // 2.8 au
55
+ -- 5. G // Large GG // 5.6 au
56
+ -- 6. G // Large GG // 11.2 au
57
+ / 1 rad. XR00000
58
+ / 6 rad. X402000
59
+ / 7 rad. X405000
60
+ / 9 rad. X100000
61
+ / 10 rad. X302000
62
+ -- 7. . // .......-. // 22.4 au
63
+ -- 8. . // .......-. // 44.8 au
64
+ -- 9. - S // DB // 89.6 au
65
+ ```
66
+
67
+ To generate a (mostly) random Traveller sector in the ASCII format, execute the following on the command line:
68
+
69
+ ```
70
+ astromapper generate
71
+ ```
72
+
73
+ SVG Output
74
+ ----------
75
+
76
+ Traveller Astromapper converts the ASCII output as described above to create an SVG file describing the key aspects of a volume. This includes the Star type, Starport, Name and the presence of bases (Navy, Scout, etc.) and Gas Giants.
77
+
78
+ To convert that ASCII into an SVG image, execut the following:
79
+
80
+ ```
81
+ astrographer svg
82
+ ```
83
+
84
+ Copyright
85
+ =========
86
+
87
+ Copyright 2012--13, Benjamin C. Wilson. All Rights Reserved.
88
+
89
+ You may not use this work for commercial purposes. You may not alter, transform or build upon this work. Any of the above conditions can be waived if you get permission from the copyright holder. Where the work or any of its elements is in the public domain under applicable law, that status is in no way affected by the license. For any reuse or distribution, you must make clear to others the license terms of this work. In no way are any of the following rights affected by the license:
90
+
91
+ * Your fair dealing or fair use rights, or other applicable copyright exceptions and limitations;
92
+ * The author's moral rights;
93
+ * Rights other persons may have either in the work itself or in how the work is used, such as publicity or privacy rights.
94
+
95
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
96
+
97
+ Product names, logos, brands, and other trademarks featured or referred to in software are the property of their respective trademark holders. Usage of those marks does not convey sponsorship or endorsement of this generator.
98
+
99
+ Credits
100
+ =======
101
+
102
+ SVG Output uses some algorithms from [phreeow.net Perl mapping software](http://www.phreeow.net/wiki/tiki-index.php?page=Subsector+mapping+and+generating+software) with drawing hexes in the Classic Traveller way.
103
+
104
+ Known bugs
105
+ ===========
106
+ * If the dice pool is too small, the generated output will repeat.
107
+
108
+ Troubleshooting
109
+ ===============
110
+
111
+ Changelog
112
+ =========
113
+
114
+ Version 0.1 (1 March 2012)
115
+ --------------------------
116
+ * Initially written
117
+ * Generate Sector Map
118
+ * Convert to SVG
119
+
120
+ Version 1.0 (7 April 2013)
121
+ --------------------------
122
+ * Re-implemented as Ruby Gem
123
+
124
+ * A News sections might also be include to lists project updates for users.
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,29 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+
5
+ require 'astromapper/version'
6
+
7
+ Gem::Specification.new do |s|
8
+ s.name = "astromapper"
9
+ s.version = Astromapper::VERSION
10
+ s.authors = ["Merovex"]
11
+ s.email = ["dausha@gmail.com"]
12
+ s.description = %q{Astromapper generates Traveller RPG Star Charts (from Sector to Domain).}
13
+ s.summary = %q{Generating Traveller RPG Star Charts for YOTS}
14
+ s.homepage = ""
15
+ s.license = "MIT"
16
+
17
+ s.files = `git ls-files`.split("\n")
18
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
20
+ s.require_paths = ["lib"]
21
+
22
+ s.add_development_dependency "bundler", "~> 1.3"
23
+ s.add_development_dependency "rake"
24
+ s.add_development_dependency "rspec", "~> 2.6"
25
+ s.add_development_dependency "cucumber"
26
+ s.add_development_dependency "aruba"
27
+ s.add_dependency "activesupport"
28
+ s.add_dependency "thor"
29
+ end
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- mode: ruby -*-
3
+
4
+ require "astromapper"
5
+ Astromapper::Cli.start
@@ -0,0 +1,54 @@
1
+
2
+ # require "awesome_print"
3
+ require "active_support/all"
4
+ # require "notifier"
5
+ require "pathname"
6
+ require "thor"
7
+ require "thor/group"
8
+ require "yaml"
9
+
10
+ module Astromapper
11
+ require 'astromapper/extensions/float'
12
+ require 'astromapper/extensions/integer'
13
+ require 'astromapper/extensions/string'
14
+
15
+ autoload :Builder, "astromapper/builder"
16
+ autoload :Cli, "astromapper/cli"
17
+ # autoload :Dependency, "astromapper/dependency"
18
+ autoload :Exporter, "astromapper/exporter"
19
+ autoload :Generator, "astromapper/generator"
20
+ # autoload :Stats, "astromapper/stats"
21
+ # autoload :Stream, "astromapper/stream"
22
+ # autoload :TOC, "astromapper/toc"
23
+ autoload :Svg, "astromapper/svg"
24
+ autoload :Version, "astromapper/version"
25
+
26
+ Encoding.default_internal = "utf-8"
27
+ Encoding.default_external = "utf-8"
28
+ def self.config(root_dir = nil)
29
+ root_dir ||= Pathname.new(Dir.pwd)
30
+ path = root_dir.join("_astromapper.yml")
31
+
32
+ raise "Invalid Bookmaker directory; couldn't found #{path} file." unless File.file?(path)
33
+ content = File.read(path)
34
+ erb = ERB.new(content).result
35
+
36
+ YAML.load(erb)#.with_indifferent_access
37
+ end
38
+ def self.output_file(ext="txt")
39
+ "output/#{config['name'].to_permalink}.#{ext}"
40
+ end
41
+ def self.names(root_dir = nil)
42
+ root_dir ||= Pathname.new(Dir.pwd)
43
+ path = root_dir.join("templates/names.yml")
44
+
45
+ raise "Invalid Bookmaker directory; couldn't found #{path} file." unless File.file?(path)
46
+ content = File.read(path)
47
+ erb = ERB.new(content).result
48
+
49
+ @names = YAML.load(erb)#.with_indifferent_access
50
+ end
51
+ def self.logger
52
+ @logger ||= Logger.new(File.open("/tmp/astromapper.log", "a"))
53
+ end
54
+ end
@@ -0,0 +1,43 @@
1
+ require 'open3'
2
+
3
+ module Astromapper
4
+ module Builder
5
+ autoload :Orbit, "astromapper/builder/orbit"
6
+ autoload :Sector, "astromapper/builder/sector"
7
+ autoload :Star, "astromapper/builder/star"
8
+ autoload :Volume, "astromapper/builder/volume"
9
+
10
+ class Base
11
+ attr_accessor :root_dir
12
+
13
+ def self.constitute(root_dir)
14
+ new(root_dir).constitute
15
+ end
16
+ def initialize(root_dir)
17
+ @root_dir = Pathname.new(root_dir)
18
+ end
19
+
20
+ def config
21
+ Astromapper.config(root_dir)
22
+ end
23
+ def toss(a=2,b=2)
24
+ (a.d6 - b).whole
25
+ # (@@dice.roll(a) - b).whole
26
+ end
27
+ def names
28
+ Astromapper.names
29
+ end
30
+
31
+ def spawn_command(cmd)
32
+ begin
33
+ stdout_and_stderr, status = Open3.capture2e(*cmd)
34
+ rescue Errno::ENOENT => e
35
+ puts e.message
36
+ else
37
+ puts stdout_and_stderr unless status.success?
38
+ status.success?
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,370 @@
1
+ module Astromapper
2
+ module Builder
3
+
4
+ # Class Orbit
5
+ class Orbit < Astromapper::Builder::Base
6
+ attr_accessor :id, :kid, :au, :port, :orbit_number, :xsize
7
+ def initialize(star,orbit_number,companion=nil)
8
+ @orbit_number = orbit_number.round
9
+ @au = star.orbit_to_au(orbit_number)
10
+ @kid = '.'
11
+ @star = star
12
+ @atmo = 0
13
+ @moons = 0
14
+ @h20 = 0
15
+ @popx = 0
16
+ @tek = 0
17
+ @port = 'X'
18
+ @govm = 0
19
+ @law = 0
20
+ @xsize = '.'
21
+ begin
22
+ @zone = case
23
+ when @au < @star.biozone[0] then -1 # Inside
24
+ when @au > @star.biozone[1] then 1 # Outside
25
+ else 0
26
+ end
27
+ @distant = (@au > @star.biozone[1] * 10)
28
+ rescue
29
+ # There is no biozone, so all is "inside"
30
+ @zone = -1
31
+ @distant = 1000
32
+ end
33
+ end
34
+ def uwp
35
+ '.......-.' # "%s%s%s%s%s%s%s-%s" % [port, @size.hexd, @atmo.hexd, @h20.hexd, @popx.hexd, @govm.hexd, @law.hexd, @tek.hexd]
36
+ end
37
+ def port
38
+ @port || 'X'
39
+ end
40
+ def populate
41
+ case
42
+ when @au > @star.outer_limit then return self
43
+ when limit? then return self
44
+ when inner? then populate_inner
45
+ when outer? then populate_outer
46
+ else populate_biozone
47
+ end
48
+ end
49
+ def populate_biozone
50
+ return World.new(@star, @orbit_number)
51
+ roll = toss(2,0)
52
+ return (roll < 12) ? World.new(@star, @orbit_number) : GasGiant.new(@star, @orbit_number)
53
+ end
54
+ def populate_inner
55
+ roll = toss(2,0)
56
+ return case
57
+ when roll < 5 then self
58
+ when (5..6) === roll then Hostile.new(@star, @orbit_number)
59
+ when (7..9) === roll then Rockball.new(@star, @orbit_number)
60
+ when (10..11) === roll then Belt.new(@star, @orbit_number)
61
+ else GasGiant.new(@star, @orbit_number)
62
+ end
63
+ end
64
+ def populate_outer
65
+ roll = toss(1,0)
66
+ roll += 1 if distant?
67
+ return case
68
+ when roll == 1 then Rockball.new(@star, @orbit_number)
69
+ when roll == 2 then Belt.new(@star, @orbit_number)
70
+ when roll == 3 then self
71
+ when (4..7) === roll then GasGiant.new(@star, @orbit_number)
72
+ else Rockball.new(@star, @orbit_number)
73
+ end
74
+ end
75
+ def to_s
76
+ @kid
77
+ end
78
+ def to_ascii
79
+ bio = (@zone == 0 ) ? '*' : ' '
80
+ bio = '-' if @au > @star.outer_limit
81
+ output = " -- %2s. %s %s // %s // %4.1f au" % [@orbit_number + 1, bio, @kid, self.uwp, @au]
82
+ @moons.each {|m| output += m.to_ascii} unless @moons.nil? or @moons == 0
83
+ output
84
+
85
+ end
86
+ def period; (@au * 365.25).round(2); end
87
+ def km; return (150000000 * @au).to_i; end
88
+ def radii; (@au * 200).to_i; end
89
+ def limit?; return @au < @star.limit ; end
90
+ def inner?; return @zone < 0; end
91
+ def outer?; return @zone > 0; end
92
+ def biozone?; return @zone == 0; end
93
+ def distant?; @distant; end
94
+ end # End Orbit
95
+
96
+ class Companion<Orbit
97
+ def initialize(star,orbit_number,companion)
98
+ @star = star
99
+ @comp = companion
100
+ super
101
+ @kid = 'S'
102
+ end
103
+ def uwp
104
+ "%-9s" % [@comp.classification]
105
+ end
106
+ end
107
+ class Belt<Orbit
108
+ def initialize(star,orbit_number)
109
+ super
110
+ @kid = 'B'
111
+ end
112
+ def uwp
113
+ 'XR00000-0'
114
+ end
115
+ end
116
+
117
+
118
+ class Planet<Orbit
119
+ def initialize(star,orbit_number)
120
+ super
121
+ @moons = make_moons(toss(1,3))
122
+ @size = toss if @size.nil? or @size == 0
123
+ end
124
+ def make_moons(c)
125
+ moons = {}
126
+ c.times { |i|
127
+ m = Moon.new(self,i)
128
+ moons["#{m.orbit}"] = m
129
+ }
130
+ moons.values.sort{ |a,b| a.orbit <=> b.orbit } unless @moons.size < 2
131
+ end
132
+ def uwp
133
+ "%s%s%s%s%s%s%s-%s" % [port, @size.hexd, @atmo.hexd, @h20.hexd, @popx.hexd, @govm.hexd, @law.hexd, @tek.hexd]
134
+ end
135
+ end
136
+
137
+ class Rockball<Planet
138
+ def initialize(star,orbit_number)
139
+ super
140
+ @kid = 'R'
141
+ end
142
+ end
143
+
144
+ class Hostile<Planet
145
+ def initialize(star,orbit_number)
146
+ super
147
+ @atmo = [10,11,12,13,14].sample
148
+ @hydro = toss(2,4)
149
+ @kid = 'H'
150
+ end
151
+ end
152
+
153
+ class GasGiant<Planet
154
+ def initialize(star,orbit_number)
155
+ super
156
+ @xsize = (toss(1,0) < 4) ? 'L' : 'S'
157
+ moons = toss(2,0)
158
+ moons = (moons - 4).whole if @xsize == 'S'
159
+ @moons = make_moons(moons)
160
+ @kid = 'G'
161
+ end
162
+ def uwp
163
+ (@xsize == 'S') ? 'Small GG ' : 'Large GG '
164
+ end
165
+ end
166
+
167
+ class Terrestrial<Planet
168
+ def initialize(star,orbit_number)
169
+ super
170
+ @kid = 'R'
171
+
172
+ # Size, Climate & Biosphere. MgT 170--71.
173
+ @size = toss(2,1)
174
+ @atmo = toss()
175
+ # 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F
176
+ temp_dice = toss(2,0) + [0, 0,-2,-2,-1,-1, 0, 0, 1, 1, 2, 6, 6, 2,-1, 2][@atmo]
177
+
178
+ @temp = %w{F F F C C T T T T T H H R R R R R }[temp_dice]
179
+
180
+ # Hydrographics. MgT p. 172
181
+ @h20 = case
182
+ when (@size < 2 or !biozone?) then 0
183
+ when ([0,1,10,11,12].include?(@atmo)) then (toss(2,11) + @size).max(10)
184
+ else @h20 = (toss(2,7) + @size).max(10)
185
+ end
186
+ @h20 -= 2 if @temp == 'H'
187
+ @h20 -= 6 if @temp == 'R'
188
+ @h20 = @h20.whole
189
+
190
+ # Adjust Atmosphere and Hydrographics when not Normal. MgT p. 180.
191
+ if (%{opera firm}.include?(config['genre'].downcase))
192
+ @atmo = case
193
+ when (@size < 3 or (@size < 4 and @atmo < 3)) then 0
194
+ when ([3,4].include?(@size) and (3..5).include?(@atmo)) then 1
195
+ when ([3,4].include?(@size) and @atmo > 5) then 10
196
+ else @atmo
197
+ end
198
+ @h20 -= 6 if (((3..4).include?(@size) and @atmo == 'A' ) or @atmo < 2)
199
+ @h20 -= 4 if ([2,3,11,12].include?(@atmo))
200
+ end
201
+ end
202
+ end # End Terrestrial
203
+
204
+ #===============
205
+ # Big Dea
206
+ #
207
+ #
208
+ #
209
+ #
210
+ #
211
+ #
212
+ #
213
+ #
214
+
215
+ class World<Terrestrial
216
+ attr_accessor :factions, :temp, :gas_giant
217
+ def initialize(star,orbit_number)
218
+ super
219
+
220
+ @port_roll = toss(2,0)
221
+
222
+ @kid = 'W'
223
+ @popx = toss()
224
+ if ('firm' == config['genre'].downcase)
225
+ @popx -= 1 if (@size < 3 or @size > 9)
226
+ @popx += [-1, -1, -1, -1, -1, 1, 1, -1, 1, -1, -1, -1, -1, -1, -1, -1][@atmo]
227
+ @port_roll = (@port_roll - 7 + @popx.whole).whole
228
+ end
229
+ @popx = @popx.whole
230
+
231
+ # Government & Law. MgT p. 173
232
+ @govm = (toss(2,7) + @popx).whole
233
+ @law = (toss(2,7) + @govm).whole
234
+
235
+ # Identify Factions. MgT p. 173
236
+ fax_r = 1.d3.max(3)
237
+ fax_r += 1 if [0,7].include?(@law)
238
+ fax_r -= 1 if @law > 9
239
+ rolls = [toss(2,0),toss(2,0),toss(2,0),toss(2,0),toss(2,0)]
240
+ @factions = (@popx == 0) ? [] : fax_r.times.map { |r| %w{O O O O F F M M N N S S P}[rolls.shift] }
241
+
242
+ # Set Technology die modifier based on World attributes. MgT p. 170
243
+ tek_dm = { 'A' => 6, 'B' => 4, 'C' => 2, 'D' => 0, 'E' => 0, 'X' => -4}[port]
244
+ tek_dm += [2,2,1,1,1,0,0,0,0,0,0,0,0,0,0,0][@size]
245
+ tek_dm += [1,1,1,1,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1][@atmo]
246
+ tek_dm += [1,0,0,0,0,0,0,0,0,1,2][@h20]
247
+ tek_dm += [0,1,1,1,1,1,0,0,0,1,2,3,4][@popx]
248
+ tek_dm += [1,0,0,0,0,1,0,2,0,0,0,0,0,-2,-2,0][@govm]
249
+ tek_limit = environmental_tek_limits[@atmo]
250
+ @tek = (toss(1,0) + tek_dm).min( tek_limit ) # MgT p. 179 Environmental Limits
251
+
252
+ # For those who want to limit technology
253
+ @tek = @tek.max(config['tech_cap']) unless config['tech_cap'].nil?
254
+ @tek = @tek.min(tek_limit)
255
+ @tek = @tek.min(@popx)
256
+ @law = @govm = @tek = 0 if @popx == 0
257
+
258
+ # Fix temperature (Me)
259
+ @temp = 'F' if (trade_codes.include?('IC') or trade_codes.include?('Va'))
260
+ @temp = 'T' if ((trade_codes.include?('Ag') or trade_codes.include?('Ga') or trade_codes.include?('Ri') or trade_codes.include?('Wa')) and @temp != 'T')
261
+
262
+ base = {
263
+ "Navy" => { 'A' => 8, 'B' => 8, 'C' => 20, 'D' => 20, 'E' => 20, 'X' => 20 }[port],
264
+ "Scout" => { 'A' => 10, 'B' => 8, 'C' => 8, 'D' => 7, 'E' => 20, 'X' => 20 }[port],
265
+ "Consolate" => { 'A' => 6, 'B' => 8, 'C' => 10, 'D' => 20, 'E' => 20, 'X' => 20 }[port],
266
+ "Pirate" => { 'A' => 20, 'B' => 12, 'C' => 10, 'D' => 12, 'E' => 20, 'X' => 20 }[port]
267
+ }
268
+
269
+ @base = {}
270
+ base.keys.each {|key| @base[key] = (2.d6 > base[key] - 1) ? key[0] : '.'}
271
+ end
272
+ def travel_code
273
+ @code = (@atmo > 9 or [0,7,10].include?(@govm) or [0,9,10,11,12,13].include?(@law)) ? 'AZ' : '..'
274
+ end
275
+ def gravity
276
+ @gravity = [0,0.05,0.15,0.25,0.35,0.45,0.7,0.9,1.0,1.25,1.4][@size] if @gravity.nil?
277
+ @gravity
278
+ end
279
+ def bases
280
+ return [@base['Navy'],@base['Scout'],@gas_giant,@base['Consolate'],@base['Pirate']].join('')
281
+ end
282
+ def port
283
+ %w{X X X E E D D C C B B A A A A A A A A A}[@port_roll.whole]
284
+ end
285
+ def environmental_tek_limits
286
+ [8,8,5,5,3,0,0,3,0,8,9,10,5,8]
287
+ end
288
+ def empty?
289
+ (uwp.include?('X000000'))
290
+ end
291
+ def trade_codes
292
+ code = []
293
+ code << 'Ag' if ((4..9) === @atmo and (4..8) === @h20 and (5..7) === @popx)
294
+ code << 'As' if (@size == 0 and @atmo == 0 and @h20 ==0)
295
+ code << 'Ba' if (@popx == 0 and @govm == 0 and @law == 0)
296
+ code << 'De' if (@atmo > 1 and @h20 == 0)
297
+ code << 'Fl' if (@atmo > 9 and @h20 > 0)
298
+ code << 'Ga' if (@size > 4 and (4..9) === @atmo and (4..8) === @hydro)
299
+ code << 'Hi' if (@popx > 8)
300
+ code << 'Ht' if (@tek > 12)
301
+ code << 'IC' if (@atmo < 2 and @h20 > 0)
302
+ code << 'In' if ([0,1,2,4,7,9].include?(@atmo) and @popx > 8)
303
+ code << 'Lo' if ((1..3) === @popx)
304
+ code << 'Lt' if (@tek < 6)
305
+ code << 'Na' if ((0..3) === @atmo and (0..3) === @h20 and @popx > 5)
306
+ code << 'NI' if ((4..6) === @popx)
307
+ code << 'Po' if ((2..5) === @atmo and (0..3) === @h20)
308
+ code << 'Ri' if ([6,8].include?(@atmo) and (6..8) === @popx)
309
+ code << 'Va' if (@atmo == 0)
310
+ code << 'Wa' if (@hydro == 10)
311
+ code
312
+ end
313
+ end # End World (Mainworld)
314
+
315
+ class Moon < Astromapper::Builder::Base
316
+ attr_accessor :orbit, :size, :h20
317
+ @@orbits = { 'C' => (1..14).to_a, 'R' => [1,1,1,2,2,3] }
318
+ @@orbits['F'] = @@orbits['C'].map{|c| c * 5}
319
+ @@orbits['E'] = @@orbits['C'].map{|c| c * 25}
320
+
321
+ def initialize(planet,i=0)
322
+ @planet = planet
323
+ @popx = 0
324
+ @law = 0
325
+ @tek = 0
326
+ @govm = 0
327
+ @size = case
328
+ when @planet.xsize = 'L' then toss(2,4)
329
+ when @planet.xsize = 'S' then toss(2,6)
330
+ else @planet.size - toss(1,0)
331
+ end
332
+ orbit = toss(2,i)
333
+ @orbit = (case
334
+ when (@size < 1) then @@orbits['R'][toss(1,1)]
335
+ when (orbit == 12 and @planet.xsize == 'L') then @@orbits['E'][toss(2,0)]
336
+ when (orbit < 8) then @@orbits['C'][toss(2,0)]
337
+ when (orbit > 7) then @@orbits['C'][toss(2,0)]
338
+ else 0
339
+ end).whole
340
+ @h20 = (case
341
+ when (@planet.inner?) then 0
342
+ when (@size == 0) then 0
343
+ when (@planet.outer?) then toss(2,4)
344
+ when (@planet.biozone?) then toss(2,7)
345
+ else 0
346
+ end).whole
347
+ @atmo = toss(2,7) + @size
348
+ @atmo = (case
349
+ when (@size == 0) then 0
350
+ when (@planet.inner?) then @atmo - 4
351
+ when (@planet.outer?) then @atmo - 4
352
+ else 0
353
+ end).whole
354
+ end
355
+ def to_ascii
356
+ "\n%28s/ %3d rad. %s" % ['', @orbit, uwp]
357
+ end
358
+ def uwp
359
+ size = case
360
+ when @size < 0 then 'S'
361
+ when @size == 0 then 'R'
362
+ else @size.hexd
363
+ end
364
+ # size = (@size == 0) ? 'R' : @size.hexd
365
+ "%s%s%s%s%s%s%s" % ['X', size,@atmo.hexd,@h20.hexd,@popx.hexd,@govm.hexd,@law.hexd]
366
+ end
367
+ end # End Moon
368
+
369
+ end # End Builder
370
+ end # End Astromapper