Cleaning up and writing tests

This commit is contained in:
2025-10-02 21:45:52 -06:00
parent ed3cd08130
commit 279658f3e5
17 changed files with 584 additions and 56 deletions
+1
View File
@@ -3,3 +3,4 @@
**/.yard* **/.yard*
**/logs **/logs
**/*tmp* **/*tmp*
**/coverage
+1
View File
@@ -0,0 +1 @@
--require spec_helper
+11 -3
View File
@@ -21,7 +21,15 @@ task :serve do
end end
desc 'Create the YARD documentation for the project' namespace :doc do
task :doc do desc 'Create the YARD documentation for the project'
res = sh 'yard doc *.rb' task :yard do
res = sh 'yard doc *.rb'
end
desc 'Create code coverage'
task :coverage do
ENV['COVERAGE'] = 'true'
Rake::Task[:test].invoke
end
end end
+9 -3
View File
@@ -1,8 +1,14 @@
# Nathan Hinton 1 Oct 2025 # Nathan Hinton 1 Oct 2025
# This file basiacally creates a universe and runs a simulated game in it.
# Mostly for testing right now:
require './universe' require './universe'
require './player'
universe = Universe.new('test universe') universe = Universe.new('test universe', universe_size: 3)
universe.print_universe(simple: true) universe.create_universe
universe.print_universe()
planets = universe.planets
player = Player.new('test player')
puts player.name
+17
View File
@@ -5,11 +5,28 @@ PLANET_PRODUCTION_RESOURCES = [:ships]
# This class holds information about a planet. # This class holds information about a planet.
class Planet class Planet
attr_reader :owner attr_reader :owner
# Create a planet # Create a planet
#
# @param random [Random] The random generator for the game (ensures seeds can be duplicated)
def initialize(random) def initialize(random)
@random = random @random = random
@prod_rate = @random.rand @prod_rate = @random.rand
@resource = PLANET_PRODUCTION_RESOURCES[(@random.rand * PLANET_PRODUCTION_RESOURCES.length).floor] @resource = PLANET_PRODUCTION_RESOURCES[(@random.rand * PLANET_PRODUCTION_RESOURCES.length).floor]
@owner = nil @owner = nil
end end
# Change the ownership of a planet. Should check for things like the planet
# has no defenders left and other fun stuff (later)
#
# @param owner [Player] The owner of the planet
# @return [Boolean] If the operation was successful or not
def change_owner(owner)
# For now only unclaimed planets can be owned
if @owner.nil?
@owner = owner
return true
end
return false
end
end end
+14
View File
@@ -0,0 +1,14 @@
# Nathan Hinton 2 Oct 2025
# Class for the player. For now does not do much.
class Player
attr_reader :name
# initializes with just the player name.
#
# @param name [String] The name of the player
def initialize(name)
@name = name
end
end
+7 -1
View File
@@ -16,7 +16,6 @@ class Position
# initialize with a, b, c position # initialize with a, b, c position
raise NotImplementedError.new('(a, b, c) positioning not implimented!') raise NotImplementedError.new('(a, b, c) positioning not implimented!')
else else
require 'byebug';debugger
raise ArgumentError.new('Creation of a position requires two or three integer args for a position.') raise ArgumentError.new('Creation of a position requires two or three integer args for a position.')
end end
end end
@@ -35,7 +34,14 @@ class Position
return [x_pos, y_pos] return [x_pos, y_pos]
end end
# Returns the string formatted version
#
# @return [String] Returns a string representing the point.
def to_s def to_s
return "(#{@x_pos}, #{y_pos})" return "(#{@x_pos}, #{y_pos})"
end end
def ==(other)
return other.x_pos == @x_pos && other.y_pos == @y_pos
end
end end
+2
View File
@@ -0,0 +1,2 @@
# frozen_string_literal: true
# Nathan Hinton 2 Oct 2025
+44
View File
@@ -0,0 +1,44 @@
# Nathan Hinton 2 Oct 2025
require './planet'
require './player'
RSpec.describe Planet do
let(:seed) { 12345 }
let(:random) { Random.new(seed) }
let(:planet) { Planet.new(random) }
let(:player_1) {Player.new('tester 01') }
let(:player_2) {Player.new('tester 02') }
describe '#initialize' do
it 'stores the random off' do
expect(planet.instance_variable_get(:@random)).to eq(random)
end
it 'creates a production rate' do
expect(planet.instance_variable_get(:@prod_rate)).to eq(Random.new(seed).rand)
end
it 'sets a resource' do
expect(planet.instance_variable_get(:@resource)).to eq(PLANET_PRODUCTION_RESOURCES[(Random.new(seed).rand * PLANET_PRODUCTION_RESOURCES.length).floor])
end
it 'has a nil owner' do
expect(planet.instance_variable_get(:@owner)).to eq nil
end
end # describe #initialize
describe '#change_owner' do
it 'allows an ownership change when the current owner is nil' do
expect(planet.change_owner(player_1)).to eq(true)
expect(planet.instance_variable_get(:@owner)).to eq player_1
end
it 'does not change when already owned' do
planet.change_owner(player_2)
expect(planet.change_owner(player_1)).to eq(false)
expect(planet.instance_variable_get(:@owner)).to eq player_2
end
end
end
+72
View File
@@ -0,0 +1,72 @@
# frozen_string_literal: true
require './position'
RSpec.describe Position do
let(:even_pair) { [4, 6] } # 4+6 = 10 → even
let(:odd_pair) { [3, 4] } # 3+4 = 7 → odd
describe 'initialisation' do
context 'with two arguments' do
it 'stores the coordinates when the sum is even' do
pos = Position.new(*even_pair)
expect(pos.x_pos).to eq(even_pair[0])
expect(pos.y_pos).to eq(even_pair[1])
end
it 'raises ArgumentError when the sum is odd' do
expect { Position.new(*odd_pair) }
.to raise_error(ArgumentError, /must sum to an even number/)
end
end
context 'with three arguments' do
it 'raises NotImplementedError' do
expect { Position.new(1, 2, 3) }
.to raise_error(NotImplementedError, /positioning not implimented/)
end
end
context 'with an unsupported number of arguments' do
it 'raises ArgumentError when no arguments are supplied' do
expect { Position.new }
.to raise_error(ArgumentError, /requires two or three integer args/)
end
it 'raises ArgumentError when too many arguments are supplied' do
expect { Position.new(1, 2, 3, 4) }
.to raise_error(ArgumentError, /requires two or three integer args/)
end
end
end
describe '#two_d_cartesian' do
it 'returns the original (x, y) pair' do
pos = Position.new(*even_pair)
expect(pos.two_d_cartesian).to eq(even_pair)
end
end
describe '#two_d_hexagonal' do
it 'returns an array of nil values for a, b, c' do
pos = Position.new(*even_pair)
expect(pos.two_d_hexagonal).to eq([nil, nil, nil])
end
end
describe '#to_s' do
it 'puts out the coordinates' do
expect(Position.new(*even_pair).to_s).to eq('(4, 6)')
end
end
describe '#==' do
it 'returns false when the positions differ' do
expect(Position.new(*even_pair) == Position.new(6, 8)).to eq(false)
end
it 'returns true when the positions are the same' do
expect(Position.new(*even_pair) == Position.new(4, 6)).to eq(true)
end
end
end
+24 -31
View File
@@ -1,17 +1,13 @@
# Nathan Hinton 2 Oct 2025 # frozen_string_literal: true
# Test file for the ship object require_relative '../ship' # <-- adjust to the actual path of ship.rb
require './ship'
RSpec.describe Ship do RSpec.describe Ship do
let(:initial_x) { 0 } let(:ship) { Ship.new(0, 0) }
let(:initial_y) { 0 }
subject(:ship) { Ship.new(initial_x, initial_y) }
describe '#initialize' do describe '#initialize' do
it 'stores the given position' do it 'stores the given position' do
expect(ship.instance_variable_get(:@position)).to eq([initial_x, initial_y]) expect(ship.instance_variable_get(:@position)).to eq([0, 0])
end end
it 'sets the speed to 0.1' do it 'sets the speed to 0.1' do
@@ -24,23 +20,22 @@ RSpec.describe Ship do
end end
describe '#tick' do describe '#tick' do
it 'does nothing (but does not raise an exception)' do it 'does nothing (no exception) when called' do
expect { ship.tick }.not_to raise_error expect { ship.tick }.not_to raise_error
end end
end end
describe '#move' do describe '#move' do
context 'when coordinates are valid' do context 'when coordinates are valid (even sum, adjacent)' do
it 'accepts adjacent moves whose sum is even' do it 'accepts positions that satisfy the rules' do
# adjacent positions that satisfy the rules expect { ship.move(1, 1) }.not_to raise_error # sum 2
expect { ship.move(1, 1) }.not_to raise_error # sum = 2 expect { ship.move(2, 0) }.not_to raise_error # sum 2
expect { ship.move(2, 0) }.not_to raise_error # sum = 2 expect { ship.move(0, 2) }.not_to raise_error # sum 2
expect { ship.move(0, 2) }.not_to raise_error # sum = 2 expect { ship.move(-1, -1) }.not_to raise_error # sum -2
expect { ship.move(-1, -1) }.not_to raise_error # sum = -2
end end
end end
context 'when the x + y sum is odd' do context 'when the sum is odd' do
it 'raises an ArgumentError' do it 'raises an ArgumentError' do
expect { ship.move(0, 1) }.to raise_error( expect { ship.move(0, 1) }.to raise_error(
ArgumentError, ArgumentError,
@@ -51,7 +46,6 @@ RSpec.describe Ship do
context 'when the target is not adjacent' do context 'when the target is not adjacent' do
it 'raises an ArgumentError' do it 'raises an ArgumentError' do
# distance > 1: difference of sums != 2
expect { ship.move(3, 3) }.to raise_error( expect { ship.move(3, 3) }.to raise_error(
ArgumentError, ArgumentError,
/must be to an adjcent space/ /must be to an adjcent space/
@@ -65,23 +59,22 @@ RSpec.describe Ship do
end end
describe '#move_direction' do describe '#move_direction' do
it 'accepts direction values between 0 and 5' do it 'accepts direction values 0..5 and sets @moving correctly' do
(0..5).each do |direction| mapping = {
expect { ship.move_direction(direction) }.not_to raise_error 0 => [2, 0],
# verify the @moving vector matches the spec 1 => [1, 1],
expected = case direction 2 => [-1, 1],
when 0 then [2, 0] 3 => [-2, 0],
when 1 then [1, 1] 4 => [-1, -1],
when 2 then [-1, 1] 5 => [1, -1]
when 3 then [-2, 0] }
when 4 then [-1, -1] mapping.each do |dir, expected|
when 5 then [1, -1] expect { ship.move_direction(dir) }.not_to raise_error
end
expect(ship.instance_variable_get(:@moving)).to eq(expected) expect(ship.instance_variable_get(:@moving)).to eq(expected)
end end
end end
it 'raises an ArgumentError for invalid directions' do it 'raises ArgumentError for invalid directions' do
expect { ship.move_direction(-1) }.to raise_error( expect { ship.move_direction(-1) }.to raise_error(
ArgumentError, ArgumentError,
/must be between \(0..5\)/ /must be between \(0..5\)/
+104
View File
@@ -0,0 +1,104 @@
# This file was generated by the `rspec --init` command. Conventionally, all
# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
# The generated `.rspec` file contains `--require spec_helper` which will cause
# this file to always be loaded, without a need to explicitly require it in any
# files.
#
# Given that it is always loaded, you are encouraged to keep this file as
# light-weight as possible. Requiring heavyweight dependencies from this file
# will add to the boot time of your test suite on EVERY test run, even for an
# individual file that may not need all of that loaded. Instead, consider making
# a separate helper file that requires the additional dependencies and performs
# the additional setup, and require it from the spec files that actually need
# it.
#
# See https://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
if ENV['COVERAGE'] == 'true'
require 'simplecov'
SimpleCov.start
end
RSpec.configure do |config|
# rspec-expectations config goes here. You can use an alternate
# assertion/expectation library such as wrong or the stdlib/minitest
# assertions if you prefer.
config.expect_with :rspec do |expectations|
# This option will default to `true` in RSpec 4. It makes the `description`
# and `failure_message` of custom matchers include text for helper methods
# defined using `chain`, e.g.:
# be_bigger_than(2).and_smaller_than(4).description
# # => "be bigger than 2 and smaller than 4"
# ...rather than:
# # => "be bigger than 2"
expectations.include_chain_clauses_in_custom_matcher_descriptions = true
end
# rspec-mocks config goes here. You can use an alternate test double
# library (such as bogus or mocha) by changing the `mock_with` option here.
config.mock_with :rspec do |mocks|
# Prevents you from mocking or stubbing a method that does not exist on
# a real object. This is generally recommended, and will default to
# `true` in RSpec 4.
mocks.verify_partial_doubles = true
end
# This option will default to `:apply_to_host_groups` in RSpec 4 (and will
# have no way to turn it off -- the option exists only for backwards
# compatibility in RSpec 3). It causes shared context metadata to be
# inherited by the metadata hash of host groups and examples, rather than
# triggering implicit auto-inclusion in groups with matching metadata.
config.shared_context_metadata_behavior = :apply_to_host_groups
# The settings below are suggested to provide a good initial experience
# with RSpec, but feel free to customize to your heart's content.
=begin
# This allows you to limit a spec run to individual examples or groups
# you care about by tagging them with `:focus` metadata. When nothing
# is tagged with `:focus`, all examples get run. RSpec also provides
# aliases for `it`, `describe`, and `context` that include `:focus`
# metadata: `fit`, `fdescribe` and `fcontext`, respectively.
config.filter_run_when_matching :focus
# Allows RSpec to persist some state between runs in order to support
# the `--only-failures` and `--next-failure` CLI options. We recommend
# you configure your source control system to ignore this file.
config.example_status_persistence_file_path = "spec/examples.txt"
# Limits the available syntax to the non-monkey patched syntax that is
# recommended. For more details, see:
# https://rspec.info/features/3-12/rspec-core/configuration/zero-monkey-patching-mode/
config.disable_monkey_patching!
# This setting enables warnings. It's recommended, but in some cases may
# be too noisy due to issues in dependencies.
config.warnings = true
# Many RSpec users commonly either run the entire suite or an individual
# file, and it's useful to allow more verbose output when running an
# individual spec file.
if config.files_to_run.one?
# Use the documentation formatter for detailed output,
# unless a formatter has already been configured
# (e.g. via a command-line flag).
config.default_formatter = "doc"
end
# Print the 10 slowest examples and example groups at the
# end of the spec run, to help surface which specs are running
# particularly slow.
config.profile_examples = 10
# Run specs in random order to surface order dependencies. If you find an
# order dependency and want to debug it, you can fix the order by providing
# the seed, which is printed after each run.
# --seed 1234
config.order = :random
# Seed global randomization in this process using the `--seed` CLI option.
# Setting this allows you to use `--seed` to deterministically reproduce
# test failures related to randomization by passing the same `--seed` value
# as the one that triggered the failure.
Kernel.srand config.seed
=end
end
+12
View File
@@ -0,0 +1,12 @@
# If you are getting an error `uninitialized constant StringIO` make sure that
# your code is in an `it` block.
# Helper that captures STDOUT.
def capture_stdout
output = StringIO.new
$stdout = output
yield
output.string
ensure
$stdout = STDOUT
end
+38
View File
@@ -0,0 +1,38 @@
# Nathan Hinton 2 Oct 2025
require './universe_array'
RSpec.describe UniverseArray do
describe '#[]' do
it 'works with indexes' do
uni_arr = UniverseArray.new()
uni_arr[0] = []
uni_arr[0][0] = 'hi'
expect(uni_arr[0][0]).to eq 'hi'
end
it 'works with positions' do
uni_arr = UniverseArray.new()
uni_arr[0] = []
uni_arr[0][0] = 'hi'
expect(uni_arr[Position.new(0, 0)]).to eq 'hi'
end
end
describe '#[]=' do
it 'works with indexes' do
uni_arr = UniverseArray.new()
uni_arr[0] = []
uni_arr[0][0] = 'hi'
expect(uni_arr[0][0]).to eq 'hi'
end
it 'works with positions' do
uni_arr = UniverseArray.new()
uni_arr[0] = []
uni_arr[Position.new(0, 0)] = 'hi'
expect(uni_arr[Position.new(0, 0)]).to eq 'hi'
end
end
end
+146
View File
@@ -0,0 +1,146 @@
# frozen_string_literal: true
require './universe'
require './planet'
require './position'
require './universe_array'
require './spec/stdout_helper'
RSpec.describe Universe do
let(:name) { 'Test Universe' }
let(:universe_size) { 3 }
let(:seed) { 12345 }
subject(:universe) do
Universe.new(
name,
universe_size: universe_size,
seed: seed,
create_chances: { planet: 1 } # force a planet at every valid spot
)
end
describe '#initialize' do
it 'stores all expected instance variables' do
expect(universe.name).to eq(name)
expect(universe.instance_variable_get(:@universe_size)).to eq(universe_size)
expect(universe.instance_variable_get(:@seed)).to eq(seed)
end
it 'creates a deterministic Random object when a seed is given' do
rng = universe.instance_variable_get(:@random)
expect(rng).to be_a(Random)
expect(rng.rand(100)).to eq(Random.new(seed).rand(100))
end
it 'initializes the random if no seed is passed in' do
uni = Universe.new(name)
rng = uni.instance_variable_get(:@random)
expect(rng).to be_a(Random)
end
end
describe '#create_universe' do
end
describe '#distance' do
it 'is symmetric' do
a = Position.new(0, 0)
b = Position.new(4, 2)
expect(universe.distance(a, b)).to eq(universe.distance(b, a))
end
it 'returns 0 when both points are identical' do
p = Position.new(1, 1)
expect(universe.distance(p, p)).to eq(0)
end
it 'correctly computes known hex distances' do
p0 = Position.new(0, 0)
p1 = Position.new(2, 0)
p2 = Position.new(4, 2)
p3 = Position.new(2, 2)
# (0,0) to (2,0) → 1
expect(universe.distance(p0, p1)).to eq(1)
# (0,0) to (4,2) → 3
expect(universe.distance(p0, p2)).to eq(3)
# (0,0) to (2,2) → 2
expect(universe.distance(p0, p3)).to eq(2)
end
end
describe '#map generation' do
it 'creates the expected dimensions' do
universe.create_universe
map = universe.instance_variable_get(:@universe_map)
# Each valid (x,y) pair inside the radius contains a Planet
# (our stub) and every other entry is nil.
expect(map).to be_a(UniverseArray)
# Check how may nodes were created:
expect(map.flatten.compact.length).to eq(19) # 1 + 1*6 + 2*6
end
it 'contains a planet at every valid point when create_chances is 1' do
universe.create_universe
map = universe.instance_variable_get(:@universe_map)
map.each do |row|
row.each do |idx|
# The indexes are allowed to be nil
if !idx.nil?
expect(idx).to be_a(Planet)
end
end
end
end
it 'is deterministic when the same seed is used' do
first_universe = Universe.new(
name,
universe_size: universe_size,
seed: seed,
create_chances: { planet: 0.1 }
)
first_map = first_universe.instance_variable_get(:@universe_map)
second_universe = Universe.new(
name,
universe_size: universe_size,
seed: seed,
create_chances: { planet: 0.1 }
)
second_map = second_universe.instance_variable_get(:@universe_map)
expect(first_map).to eq(second_map)
end
end
describe '#print_universe' do
it 'prints the center point as “O”' do
out = capture_stdout do
universe.create_universe
universe.print_universe
end
expect(out).to include('O')
end
it 'can print blank spaces for nothing' do
out = capture_stdout do
uni = Universe.new(name, create_chances: {planet: 0.0})
uni.create_universe
uni.print_universe
end
expect(out).to include('O')
expect(out).to include('- -')
end
end
describe '#planets' do
it 'lists all of the generated planets' do
universe.create_universe
expect(universe.planets.length).to eq(19)
end
end
end
+73 -16
View File
@@ -48,9 +48,10 @@ require './universe_array'
# @param universe_size [Integer] Controlls the size of the generated universe. This is a radius from the center point. # @param universe_size [Integer] Controlls the size of the generated universe. This is a radius from the center point.
class Universe class Universe
# Setup logger for this class: # Setup logger for this class:
sh 'mkdir -p logs'
@@logger = Logger.new('logs/universe.log') @@logger = Logger.new('logs/universe.log')
attr_reader :name
def initialize(name, universe_size: 4, create_chances: {planet: 1}, seed: nil) def initialize(name, universe_size: 4, create_chances: {planet: 1}, seed: nil)
@name = name @name = name
@@ -69,12 +70,15 @@ class Universe
@seed = seed @seed = seed
@random = Random.new(@seed) @random = Random.new(@seed)
end end
end # Initialize
def create_universe()
# Set center of universe # Set center of universe
@center = Position.new(@universe_size + 2, @universe_size) @center = Position.new(@universe_size + 2, @universe_size)
@@logger.info "Generating Universe '#{@name}' with seed #{@seed}" @@logger.info "Generating Universe '#{@name}' with seed #{@seed}"
puts "Center is #{@center}" @@logger.info "Center is #{@center}"
@universe_map = UniverseArray.new() @universe_map = UniverseArray.new()
# Generate the universe. First generate the x values: # Generate the universe. First generate the x values:
(0 .. (@universe_size * 2)).each do |y_pos| (0 .. (@universe_size * 2)).each do |y_pos|
@@ -90,16 +94,21 @@ class Universe
next next
end end
# Skip if it is the center
if position == @center
end
# Get what the planet should be: # Get what the planet should be:
spot = nil spot = nil
if @random.rand < @create_chances[:planet] if @random.rand < @create_chances[:planet]
spot = Planet.new(@random) spot = Planet.new(@random)
end end
@@logger.debug "Creating something at (#{position.x_pos} #{position.y_pos})" @@logger.debug "Creating something at (#{position})"
@universe_map[position.y_pos][position.x_pos] = spot @universe_map[position] = spot
end # Create y points end # Create y points
end # Create x points end # Create x points
end # Function initialize # Remove any empty nodes:
end # Function create_universe
# Returns the distance between points. This is returned as a number which # Returns the distance between points. This is returned as a number which
# indicates how far you have to go to get to a point. This is actually # indicates how far you have to go to get to a point. This is actually
@@ -110,14 +119,10 @@ class Universe
# @return [Integer] The distance between points in the universe. # @return [Integer] The distance between points in the universe.
def distance(position_a, position_b) def distance(position_a, position_b)
result = 0 # We can just add the abs diff of each direction. result = 0 # We can just add the abs diff of each direction.
require 'byebug';debugger if position_a.nil?
dist_x = (position_b.x_pos - position_a.x_pos).abs dist_x = (position_b.x_pos - position_a.x_pos).abs
dist_y = (position_b.y_pos - position_a.y_pos).abs dist_y = (position_b.y_pos - position_a.y_pos).abs
# Sanity check, our coordinates should add to be even:
if (dist_x + dist_y).odd?
raise RangeError.new('When calculating the distance we calculated a non even number. This is not allowed!')
end
res = (dist_x / 2) + dist_y res = (dist_x / 2) + dist_y
if dist_x >= dist_y if dist_x >= dist_y
res = (dist_x + dist_y) / 2 res = (dist_x + dist_y) / 2
@@ -128,18 +133,31 @@ class Universe
# Prints the universe to the screen. # Prints the universe to the screen.
def print_universe(simple: false) def print_universe(simple: false)
(0 .. (@universe_size * 2)).each do |y_pos| (0 .. (@universe_map.length)).each do |y_pos|
# Print empty space before chart (for angles) # Print empty space before chart (for angles)
nextline = '' if @universe_map[y_pos].nil?
next
end
if @universe_map[y_pos] == []
puts '_' * (4 * @universe_size * 2)
next
end
nextline = '|'
if y_pos < @universe_size if y_pos < @universe_size
nextline += ' ' * ((@universe_size - y_pos).abs - 1) nextline += ' ' * ((@universe_size - y_pos).abs - 1)
else else
nextline += ' ' * ((@universe_size - y_pos).abs) nextline += ' ' * ((@universe_size - y_pos).abs)
end end
if @universe_size.odd?
nextline += ' '
end
# Print more empty space for the odd places (provides offset) # Print more empty space for the odd places (provides offset)
if y_pos.odd? if y_pos.odd?
print ' ' print '| '
else
print '|'
end end
#Actually loop through everything #Actually loop through everything
@@ -156,9 +174,9 @@ class Universe
end end
# Print what we are: # Print what we are:
value = @universe_map[position.y_pos][position.x_pos] value = @universe_map[position]
nextline += ' ' nextline += ' '
if [x_pos, y_pos] == @center if position == @center
print 'O' print 'O'
elsif value.class == Planet elsif value.class == Planet
print 'P' print 'P'
@@ -184,6 +202,32 @@ class Universe
end # For each row end # For each row
end # Function print_universe end # Function print_universe
# Returns all of the planets contained in the universe:
#
# @return [Array<Planet>]
def planets
result = []
@universe_map.flatten.each do |item|
result.push(item) if item.is_a? Planet
end
return result
end
################################################################################
################################################################################
################################################################################
################################################################################
################################################################################
################################################################################
################################################## ##################################################
################### UNIVERSE ##################### ################### UNIVERSE #####################
################################################## ##################################################
@@ -195,8 +239,9 @@ class Universe
# #
# @param player [Player] The player who is asking for the position # @param player [Player] The player who is asking for the position
# @param position [Position] The position that is being requested # @param position [Position] The position that is being requested
# @return [Planet, nil] Returns the thing at that point.
def get_position(player, position) def get_position(player, position)
return @universe_map[position]
end end
# Sets a position as explored for a player. This should be called as ships # Sets a position as explored for a player. This should be called as ships
@@ -242,6 +287,12 @@ class Universe
def remove_planet(planet, position) def remove_planet(planet, position)
end end
# Change the ownership of a planet
#
# @param planet [Planet] The planet to be modified
# @param player [Player] The player who should now own the planet
# @param position [Position] The position of the planet
################################################## ##################################################
##################### PLAYER ##################### ##################### PLAYER #####################
################################################## ##################################################
@@ -251,6 +302,12 @@ class Universe
# @param player [Player] The player who should be added to the universe # @param player [Player] The player who should be added to the universe
def add_player(player) def add_player(player)
@player_list.push(player) @player_list.push(player)
# Give the player a planet
free_planets = []
planets.each do |planet|
free_planets.push(planet) if planet.owner.nil?
end
return 'Added player to universe' return 'Added player to universe'
end end
+9 -2
View File
@@ -7,12 +7,19 @@ require './position'
# indexing as well as point type indexing # indexing as well as point type indexing
class UniverseArray < Array class UniverseArray < Array
def initialize def initialize
super
end end
def [](index, *rest) def [](index, *rest)
if index.is_a?(Position) if index.is_a?(Position)
return self[position.y_pos][position.x_pos] return self[index.y_pos][index.x_pos]
else
super
end
end
def []=(index, *rest)
if index.is_a?(Position)
return self[index.y_pos][index.x_pos] = rest[0]
else else
super super
end end