[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Re: [QUIZ] Space Merchant (#71

Jacob Fugal

3/17/2006 6:34:00 PM

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 = 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
4 Answers

horndude77

3/20/2006 2:43:00 AM

0

Ok here is my quick SpaceMerchant::Sector class. I wasn't able to
participate in last weeks quiz (and I suggested it!) so I want to be
sure and do something in this week. I need to go through and clean this
up now, but I wanted to get this out there quick because I haven't seen
any parts besided the Galaxy put up. At the very end is the code I've
been using to tests with. Ok thanks!

-----Jay Anderson

module SpaceMerchant
class Sector
attr_reader :name

def initialize(name, region)
@name, @region = name, region
@planets = []
@stations = []
@links = []
end

def link(other_sector)
@links << other_sector
end

def add_planet(planet)
@planets << planet
end

def add_station(station)
@stations << station
end

def handle_event(player)
menu = :main_menu
while menu != :done
menu = send menu, player
end
end

def main_menu player
puts "Sector #{name}"
puts "#{@region.name}"
puts
if(@stations.length > 0) then
puts "Station#{'s' if @stations.length>0}:
"+@stations.map{|s|s.name}.join(', ')
end
if(@planets.length > 0) then
puts "Planet#{'s' if @planets.length>0}:
"+@planets.map{|p|p.name}.join(', ')
end

puts
puts '(D)ock with station' if @stations.length > 0
puts '(L)and on planet' if @stations.length > 0
puts
if(@links.length > 0) then
puts 'Warp to nearby sector:
'+@links.map{|l|'['+l.name+']'}.join(', ')
end
puts
puts '(Q)uit game'
print '?'

response = gets.chomp
case response
when /^d/i
return :dock
when /^l/i
return :land
when /^q/i
puts "Are you sure you want to quit? (y/n)"
y_or_n = ''
while (y_or_n = gets) !~ /^(y|n)/i
puts "Are you sure you want to quit? (y/n)"
end
if y_or_n =~ /^y/i then puts 'goodbye!'; exit 0; end
return :main_menu
else
new_loc = @links.select{|l| l.name == response}
if new_loc.length > 0 then
puts "Travelling..."
player[:location] = new_loc.first
return :done
else
puts " *** INVALID CHOICE ***"
return :main_menu
end
end
end

def dock player
if @stations.length < 1 then
puts "There are no stations to dock with"
return :main_menu
end
puts "Choose station to dock with:"
puts
@stations.each_with_index do |s,index|
puts " #{index}: #{s.name}"
end
puts
puts "(M)ain menu"
print "?"

response = gets.chomp
choice = response.to_i
if response =~ /^m/i then
return :main_menu
elsif choice.to_s != response || choice >= @stations.length
then
puts " *** INVALID CHOICE ***"
return :dock
else
puts "Docking..."
player[:location] = @stations[choice]
return :done
end
end

def land player
if @planets.length < 1 then
puts "There are no planets to land on"
return :main_menu
end
puts "Choose planet to land on:"
puts
@planets.each_with_index do |p,index|
puts " #{index}: #{p.name}"
end
puts
puts "(M)ain menu"
print "?"

response = gets.chomp
choice = response.to_i
if response =~ /^m/i then
return :main_menu
elsif choice.to_s != response || choice >= @planets.length
then
puts " *** INVALID CHOICE ***"
return :dock
else
puts "Landing..."
player[:location] = @planets[choice]
return :done
end
end
end
end


if __FILE__ == $0
Named = Struct.new(:name)
region = Named.new('The Region')
s = SpaceMerchant::Sector.new('Test Sector', region)
5.times do |i|
s.add_planet(Named.new("planet #{i}"))
s.add_station(Named.new("station #{i}"))
s.link(SpaceMerchant::Sector.new("#{i}", region))
end

player = {}
s.handle_event(player)
p player
end

Timothy Bennett

3/20/2006 3:14:00 AM

0


Here's the Sector implementation I was working on. It can use a
bunch of cleaning up (choose_station and choose_planet need to be
merged together at least in part - much duplicate code there), but as
this is the second posted Sector implementation, and no one has
mentioned working on a Planet or Station implementation, I'm going to
go ahead and send in a Planet class tomorrow instead of cleaning this
up.

module SpaceMerchant
class Sector
attr_reader :links, :planets, :stations, :location

def initialize ( name, location = nil )
@name = name
@location = location
@links = []
@planets = []
@stations = []
end

def name
@name.to_s
end

def to_s
name
end

def add_planet ( planet )
@planets << planet
end

def add_station ( station )
@stations << station
end

def link ( to_sector )
@links << to_sector
end

def handle_event ( player )
player[:visited_sectors] ||= []
player[:visited_sectors] << self unless player
[:visited_sectors].find { |sector| sector == self }
print_menu
choice = gets.chomp
case choice
when /d/i: choose_station
when /l/i: choose_planet
when /p/i: plot_course
when /q/i: throw(:quit)
when /\d+/: warp player, choice
else invalid_choice
end
end

def == ( other )
if other.class == Sector
self.name == other.name
elsif other.class == String
self.name == other
else
false
end
end

private

def warp ( player, sector_name )
sector = Galaxy.instance.sectors.find { |sector| sector_name
== sector.name }
if sector && @links.find { |sec| sector_name == sec }
player[:location] = sector
puts "Warping to Sector #{sector_name}..."
elsif sector.nil?
puts "Sector #{sector_name} does not exist."
else
puts "Sector #{sector_name} cannot be reached from here."
end
puts
end

def print_menu
puts "Sector #{@name}"
puts @location if @location
puts

puts "Station" + (@stations.size == 1 ? '' : 's') +
": " + @stations.map{|stat| stat.name}.join(', ') unless
@stations.empty?

puts "Planet" + (@planets.size == 1 ? '' : 's') +
": " + @planets.map{|plan| plan.name}.join(', ')} unless
@planets.empty?
puts "Nothing here!" if @stations.empty? && @planets.empty?
puts

puts "(D)ock with station" unless @stations.empty?
puts "(L)and on planet" unless @planets.empty?
puts "(P)lot a course"
puts

puts "(Q)uit game"
puts

puts "Or warp to nearby sector: #{@links.join(', ')}"
puts
end

def invalid_choice
puts "Please enter a valid choice."
end

def choose_station
player = Player.instance
puts "There are no stations to dock with!" if @stations.empty?
if @stations.size == 1
dock @stations[0], player
else
@stations.each_with_index do |station, index|
puts "(#{index + 1}) #{station.name}"
end
puts "Enter the number of the station to dock with: "

station_index = gets.chomp.to_i - 1
if @stations[station_index]
dock @stations[station_index], player
else
puts "Invalid station."
end
end
end

def choose_planet
player = Player.instance
puts "There are no planets to land on!" if @planets.empty?
if @planets.size == 1
land @planets[0], player
else
@planets.each_with_index do |planet, index|
puts "(#{index + 1}) #{planet}"
end
puts "Enter the number of the planet to land on: "

planet_index = gets.chomp.to_i - 1
if @planets[planet_index]
dock @planets[planet_index], player
else
puts "Invalid planet."
end
end
end

def land (planet, player)
puts "Landing on #{planet.name}..."
player[:location] = planet
end

def dock (station, player)
puts "Docking at #{station.name}..."
player[:location] = station
end

def plot_course
player = Player.instance
galaxy = Galaxy.instance
unknown_sectors = galaxy.sectors - player[:visited_sectors]
reachable_sectors = galaxy.find_reachable(self, unknown_sectors)
reachable_sectors.each do |sector|
puts "#{sector}" + sector.location ? "(#
{sector.location})" : ''
end

puts
puts "Enter the sector name to which you wish to travel: "
sector_name = gets.chomp
destination = galaxy.sectors.find { |sector| sector ==
sector.name }
path = galaxy.find_path( self, destination, unknown_sectors)
puts
unless @path.nil?
puts "Your course:"
path.each do |sector|
puts "#{sector}" + sector.location ? "(#
{sector.location})" : ''
end

puts "Confirm course (y/n)?"
confirm = gets.chomp =~ /y/i

if confirm
me[:location] = destination
puts "Traveling to Sector #{destination}..."
end
else
puts "That sector can not be reached."
end
end
end
end



Timothy Bennett

3/20/2006 3:23:00 AM

0

Correction to this solution: in plot_course, @path.nil? should be
path.nil?

I should note here that plot_course is almost completely untested,
since it depends heavily on Galaxy, which I haven't completely
stubbed out.

Tim

On Mar 19, 2006, at 7:14 PM, Timothy Bennett wrote:

>
> Here's the Sector implementation I was working on. It can use a
> bunch of cleaning up (choose_station and choose_planet need to be
> merged together at least in part - much duplicate code there), but
> as this is the second posted Sector implementation, and no one has
> mentioned working on a Planet or Station implementation, I'm going
> to go ahead and send in a Planet class tomorrow instead of cleaning
> this up.
>
> module SpaceMerchant
> class Sector
> attr_reader :links, :planets, :stations, :location
>
> def initialize ( name, location = nil )
> @name = name
> @location = location
> @links = []
> @planets = []
> @stations = []
> end
>
> def name
> @name.to_s
> end
>
> def to_s
> name
> end
>
> def add_planet ( planet )
> @planets << planet
> end
>
> def add_station ( station )
> @stations << station
> end
>
> def link ( to_sector )
> @links << to_sector
> end
>
> def handle_event ( player )
> player[:visited_sectors] ||= []
> player[:visited_sectors] << self unless player
> [:visited_sectors].find { |sector| sector == self }
> print_menu
> choice = gets.chomp
> case choice
> when /d/i: choose_station
> when /l/i: choose_planet
> when /p/i: plot_course
> when /q/i: throw(:quit)
> when /\d+/: warp player, choice
> else invalid_choice
> end
> end
>
> def == ( other )
> if other.class == Sector
> self.name == other.name
> elsif other.class == String
> self.name == other
> else
> false
> end
> end
>
> private
>
> def warp ( player, sector_name )
> sector = Galaxy.instance.sectors.find { |sector| sector_name
> == sector.name }
> if sector && @links.find { |sec| sector_name == sec }
> player[:location] = sector
> puts "Warping to Sector #{sector_name}..."
> elsif sector.nil?
> puts "Sector #{sector_name} does not exist."
> else
> puts "Sector #{sector_name} cannot be reached from here."
> end
> puts
> end
>
> def print_menu
> puts "Sector #{@name}"
> puts @location if @location
> puts
>
> puts "Station" + (@stations.size == 1 ? '' : 's') +
> ": " + @stations.map{|stat| stat.name}.join(', ') unless
> @stations.empty?
>
> puts "Planet" + (@planets.size == 1 ? '' : 's') +
> ": " + @planets.map{|plan| plan.name}.join(', ')} unless
> @planets.empty?
> puts "Nothing here!" if @stations.empty? && @planets.empty?
> puts
>
> puts "(D)ock with station" unless @stations.empty?
> puts "(L)and on planet" unless @planets.empty?
> puts "(P)lot a course"
> puts
>
> puts "(Q)uit game"
> puts
>
> puts "Or warp to nearby sector: #{@links.join(', ')}"
> puts
> end
>
> def invalid_choice
> puts "Please enter a valid choice."
> end
>
> def choose_station
> player = Player.instance
> puts "There are no stations to dock with!" if @stations.empty?
> if @stations.size == 1
> dock @stations[0], player
> else
> @stations.each_with_index do |station, index|
> puts "(#{index + 1}) #{station.name}"
> end
> puts "Enter the number of the station to dock with: "
>
> station_index = gets.chomp.to_i - 1
> if @stations[station_index]
> dock @stations[station_index], player
> else
> puts "Invalid station."
> end
> end
> end
>
> def choose_planet
> player = Player.instance
> puts "There are no planets to land on!" if @planets.empty?
> if @planets.size == 1
> land @planets[0], player
> else
> @planets.each_with_index do |planet, index|
> puts "(#{index + 1}) #{planet}"
> end
> puts "Enter the number of the planet to land on: "
>
> planet_index = gets.chomp.to_i - 1
> if @planets[planet_index]
> dock @planets[planet_index], player
> else
> puts "Invalid planet."
> end
> end
> end
>
> def land (planet, player)
> puts "Landing on #{planet.name}..."
> player[:location] = planet
> end
>
> def dock (station, player)
> puts "Docking at #{station.name}..."
> player[:location] = station
> end
>
> def plot_course
> player = Player.instance
> galaxy = Galaxy.instance
> unknown_sectors = galaxy.sectors - player[:visited_sectors]
> reachable_sectors = galaxy.find_reachable(self, unknown_sectors)
> reachable_sectors.each do |sector|
> puts "#{sector}" + sector.location ? "(#
> {sector.location})" : ''
> end
>
> puts
> puts "Enter the sector name to which you wish to travel: "
> sector_name = gets.chomp
> destination = galaxy.sectors.find { |sector| sector ==
> sector.name }
> path = galaxy.find_path( self, destination, unknown_sectors)
> puts
> unless @path.nil?
> puts "Your course:"
> path.each do |sector|
> puts "#{sector}" + sector.location ? "(#
> {sector.location})" : ''
> end
>
> puts "Confirm course (y/n)?"
> confirm = gets.chomp =~ /y/i
>
> if confirm
> me[:location] = destination
> puts "Traveling to Sector #{destination}..."
> end
> else
> puts "That sector can not be reached."
> end
> end
> end
> end
>
>



horndude77

3/20/2006 4:27:00 AM

0

Ok, here's my somewhat cleaned up version. I added a rudamentary
ability to save the game, but it would require changing the main code
to actually be able to load it.

module SpaceMerchant
class Sector
attr_reader :name, :region, :planets, :stations, :links

def initialize(name, region)
@name, @region = name, region
@planets = []
@stations = []
@links = []
end

def link(other_sector)
@links << other_sector
end

def add_planet(planet)
@planets << planet
end

def add_station(station)
@stations << station
end

def handle_event(player)
@player = player
@menu = :main_menu
while @menu != :done
puts '-'*60
send @menu
end
end

def main_menu
puts "Sector #{name}"
puts "#{@region.name}"
puts
if(@stations.length > 0) then
puts "Station#{'s' if @stations.length>0}:
"+@stations.map{|s|s.name}.join(', ')
end
if(@planets.length > 0) then
puts "Planet#{'s' if @planets.length>0}:
"+@planets.map{|p|p.name}.join(', ')
end
if(@links.length > 0) then
puts "Nearby Sector#{'s' if @links.length>0}:
"+@links.map{|s|s.name}.join(', ')
end

puts
puts '(D)ock with station' if @stations.length > 0
puts '(L)and on planet' if @stations.length > 0
puts '(W)arp to nearby sector' if @links.length > 0
puts
puts '(S)ave game'
puts '(Q)uit game'
print '?'

response = gets.chomp
case response
when /^d/i
@menu = :dock
when /^l/i
@menu = :land
when /^w/i
@menu = :warp
when /^s/i
@menu = :save
when /^q/i
@menu = :quit
else
puts " *** INVALID CHOICE ***"
@menu = :main_menu
end
end

def warp
result = nil
begin
result = choose_move(@links, 'sector to warp to')
end until result != :bad
puts "Warping..." if result != :main_menu
end

def dock
result = nil
begin
result = choose_move(@stations, 'station to dock with')
end until result != :bad
puts "Docking..." if result != :main_menu
end

def land
result = nil
begin
result = choose_move(@planets, 'planet to land on')
end until result != :bad
puts "Landing..." if result != :main_menu
end

def choose_move choices, string
if choices.length < 1 then
puts "There is no #{string}"
return @menu = :main_menu
end
puts "Choose #{string}:"
puts
choices.each_with_index do |c,index|
puts " #{index}: #{c.name}"
end
puts
puts "(M)ain menu"
print "?"

response = gets.chomp
choice = response.to_i
if response =~ /^m/i then
return @menu = :main_menu
elsif choice.to_s != response || choice >= choices.length
then
puts " *** INVALID CHOICE ***"
return :bad
else
@player[:location] = choices[choice]
return @menu = :done
end
end

def save
@menu = :main_menu
filename = @player[:name]+".save"
if(File.exists? filename) then
puts "Do you want to overwrite previous saved game?"
if gets.chomp !~ /^y/i
puts "Game not saved"
return
end
end
File.open(filename, 'wb') do |f|
Marshal.dump(@player, f)
end
puts "Game Saved."
end

def quit
puts "Are you sure you want to quit? (y/n)"
y_or_n = gets.chomp
case y_or_n
when /^y/i
puts 'goodbye!'
exit 0
when /^n/i
@menu = :main_menu
else
puts "Hmm... I'll assume you don't want to quit from
that."
@menu = :main_menu
end
end
end
end


if __FILE__ == $0
Named = Struct.new(:name)
region = Named.new('The Region')
s = SpaceMerchant::Sector.new('Test Sector', region)
5.times do |i|
s.add_planet(Named.new("planet #{i}"))
s.add_station(Named.new("station #{i}"))
s.link(SpaceMerchant::Sector.new("#{i}", region))
end

player = {:name => "test"}
s.handle_event(player)
p player
end