From: Jacob Fugal Date: 2006-03-18T03:33:31+09:00 Subject: Re: [QUIZ] Space Merchant (#71) ------=_Part_2193_32568951.1142620392843 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable Content-Disposition: inline I've attached a library, GalaxyLoader, that parses a DSL for "world builders". There's a brief example of the DSL following, and an example world attached. The library also adds a class method Galaxy.load to your Galaxy class. With this library, loading a galaxy is as simple as: require 'galaxy_loader' galaxy =3D Galaxy.load('sample.glx') # do stuff with the galaxy... The DSL is fairly simple. A galaxy can have many sectors, possibly within regions: galaxy { region("Federation Space") { sector(1) { ... } sector(2) { ... } } region("Klingon Space") { sector(3) { ... } sector(4) { ... } } sector(5) { ... } sector(6) { ... } } A sector can have planets, stations and neighbors: galaxy { sector(1) { planet "Earth" station "Alpha" neighbors 2, 3 } sector(2) { station "Beta" neighbors 1, 3 } sector(3) { neighbors 1, 2 } } And that's all there is to it! I tried to make the GalaxyLoader class as consistent as possible, so it should be fairly easy to add further attributes to planets and stations by following the pattern of the existing methods. Enjoy! Jacob Fugal ------=_Part_2193_32568951.1142620392843 Content-Type: application/octet-stream; name=galaxy_loader.rb Content-Transfer-Encoding: 7bit X-Attachment-Id: f_ekwtx01d Content-Disposition: attachment; filename="galaxy_loader.rb" require 'galaxy' require 'sector' require 'planet' require 'station' class GalaxyLoader class InvalidContext < Exception; end def initialize @context_stack = [] @sectors = [] @neighbors = {} end def execute(definition) instance_eval(definition) end private def galaxy(&block) raise InvalidContext, "galaxy allowed only in root context" unless context == nil with(:galaxy => Galaxy.instance) do instance_eval(&block) if block resolve_neighbors end end def region(name, &block) raise InvalidContext, "region allowed only in galaxy context" unless context == :galaxy with(:region => name) do instance_eval(&block) if block end end def sector(name, &block) raise InvalidContext, "sector allowed only in galaxy or region context" unless context == :galaxy or context == :region with(:sector => Sector.new(name, @region)) do instance_eval(&block) if block @sectors[name] = @sector @galaxy.add_sector(@sector) end end def planet(name, &block) raise InvalidContext, "planet allowed only in sector context" unless context == :sector with(:planet => Planet.new(@sector, name)) do instance_eval(&block) if block @sector.add_planet(@planet) end end def station(name, &block) raise InvalidContext, "station allowed only in sector context" unless context == :sector with(:station => Station.new(@sector, name)) do instance_eval(&block) if block @sector.add_station(@station) end end def neighbors(*sectors) raise InvalidContext, "neighbors allowed only in sector context" unless context == :sector @neighbors[@sector] = sectors end def with(context) name = context.keys.first value = context[name] instance_eval("@#{name} = value") @context_stack << name yield @context_stack.pop instance_eval("@#{name} = nil") end def context @context_stack.last end def resolve_neighbors @neighbors.each do |sector,neighbors| neighbors.each do |name| neighbor = @sectors[name] sector.link(neighbor) end end end end def Galaxy.load(filename) GalaxyLoader.new.execute(File.read(filename)) Galaxy.instance end ------=_Part_2193_32568951.1142620392843 Content-Type: application/octet-stream; name=sample.glx Content-Transfer-Encoding: 7bit X-Attachment-Id: f_ekwuoos3 Content-Disposition: attachment; filename="sample.glx" galaxy { region("Federation Space") { sector(1) { planet "Earth" station "Alpha" neighbors 2, 3, 4 } sector(2) { neighbors 1, 3, 4, 8 } sector(3) { neighbors 1, 2, 5, 12 } sector(4) { neighbors 1, 2, 3, 16 } } region("Klingon Space") { sector(5) { planet "Kronos" station "Beta" neighbors 6, 7, 8 } sector(6) { neighbors 5, 7, 8, 15 } sector(7) { station "Gamma" neighbors 5, 6, 8, 10 } sector(8) { neighbors 2, 5, 6, 7 } } region("Romulan Space") { sector(9) { planet "Romulus" planet "Remus" neighbors 10, 11, 12 } sector(10) { neighbors 7, 9, 11, 12 } sector(11) { station "Delta" neighbors 9, 10, 12, 14 } sector(12) { neighbors 3, 9, 10, 11 } } region("Ferengi Space") { sector(13) { planet "Ferenginar" station "Epsilon" neighbors 14, 15, 16 } sector(14) { neighbors 11, 13, 15, 16 } sector(15) { station "Zeta" neighbors 6, 13, 14, 16 } sector(16) { neighbors 4, 13, 14, 15 } } } ------=_Part_2193_32568951.1142620392843--