Finished testing and docs for now. Time for new features!
This commit is contained in:
@@ -4,3 +4,4 @@
|
||||
**/logs
|
||||
**/*tmp*
|
||||
**/coverage
|
||||
game/spec/examples.txt
|
||||
|
||||
+2
-1
@@ -24,7 +24,8 @@ end
|
||||
namespace :doc do
|
||||
desc 'Create the YARD documentation for the project'
|
||||
task :yard do
|
||||
res = sh 'yard doc *.rb'
|
||||
res = sh 'yard doc *.rb --list-undoc'
|
||||
sh 'yard stats *.rb --list-undoc'
|
||||
end
|
||||
|
||||
desc 'Create code coverage'
|
||||
|
||||
+17
-17
@@ -1,17 +1,17 @@
|
||||
# Nathan Hinton 2 Oct 2025
|
||||
# Does not work sadly...
|
||||
|
||||
require 'logger'
|
||||
|
||||
module Log
|
||||
@log = Logger.new('game.log')
|
||||
@log.level = Logger::INFO
|
||||
|
||||
def self.logger
|
||||
@logger
|
||||
end
|
||||
|
||||
def logger
|
||||
Log.logger
|
||||
end
|
||||
end
|
||||
# BROKEN :( # Nathan Hinton 2 Oct 2025
|
||||
# BROKEN :( # Does not work sadly...
|
||||
# BROKEN :(
|
||||
# BROKEN :( require 'logger'
|
||||
# BROKEN :(
|
||||
# BROKEN :( module Log
|
||||
# BROKEN :( @log = Logger.new('game.log')
|
||||
# BROKEN :( @log.level = Logger::INFO
|
||||
# BROKEN :(
|
||||
# BROKEN :( def self.logger
|
||||
# BROKEN :( @logger
|
||||
# BROKEN :( end
|
||||
# BROKEN :(
|
||||
# BROKEN :( def logger
|
||||
# BROKEN :( Log.logger
|
||||
# BROKEN :( end
|
||||
# BROKEN :( end
|
||||
|
||||
+1
-1
@@ -12,7 +12,7 @@ class Planet
|
||||
def initialize(random)
|
||||
@random = random
|
||||
@prod_rate = @random.rand
|
||||
@resource = PLANET_PRODUCTION_RESOURCES[(@random.rand * PLANET_PRODUCTION_RESOURCES.length).floor]
|
||||
@resource = PLANET_PRODUCTION_RESOURCES.sample(random: @random)
|
||||
@owner = nil
|
||||
end
|
||||
|
||||
|
||||
@@ -41,6 +41,11 @@ class Position
|
||||
return "(#{@x_pos}, #{y_pos})"
|
||||
end
|
||||
|
||||
# Custom comparison. We need to check the the point is the same, not the
|
||||
# identity.
|
||||
#
|
||||
# @param other [Positon] The position to compare with
|
||||
# @return [Boolean] If they are in the same position as each other.
|
||||
def ==(other)
|
||||
return other.x_pos == @x_pos && other.y_pos == @y_pos
|
||||
end
|
||||
|
||||
+4
-1
@@ -3,9 +3,12 @@
|
||||
|
||||
# This class will be the container for ships. For now they are all the same
|
||||
class Ship
|
||||
def initialize(x_pos, y_pos)
|
||||
attr_reader :owner
|
||||
|
||||
def initialize(x_pos, y_pos, owner)
|
||||
@position = [x_pos, y_pos]
|
||||
@speed = 0.1
|
||||
@owner = owner
|
||||
end
|
||||
|
||||
# Called every game tick
|
||||
|
||||
@@ -1,2 +1,159 @@
|
||||
# frozen_string_literal: true
|
||||
# Nathan Hinton 2 Oct 2025
|
||||
|
||||
# This is for testing the API that the clients can use.
|
||||
|
||||
|
||||
# Most of the api is here as it relates to interacting with the universe
|
||||
require './universe'
|
||||
require './player'
|
||||
require './position'
|
||||
require './ship'
|
||||
|
||||
RSpec.describe 'API' do
|
||||
|
||||
# Universe setup
|
||||
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
|
||||
|
||||
before(:each) do
|
||||
universe.create_universe
|
||||
end
|
||||
|
||||
|
||||
# Player setup
|
||||
let(:player_1) { Player.new('test player 01') }
|
||||
let(:player_2) { Player.new('test player 02') }
|
||||
|
||||
# Positions setup
|
||||
let(:center_position) { Position.new(5, 3) }
|
||||
describe 'UNIVERSE API' do
|
||||
describe '#get_position' do
|
||||
it 'returns a position in the universe' do
|
||||
expect(universe.get_position(player_1, Position.new(0, 0))).to be nil
|
||||
expect(universe.get_position(player_1, Position.new(3, 5))).to be_a(Planet)
|
||||
expect(universe.get_position(player_1, center_position)).to be_a(Star)
|
||||
end
|
||||
end # describe Universe#get_position
|
||||
end # describe 'UNIVERSE API'
|
||||
|
||||
|
||||
describe 'SHIPS API' do
|
||||
describe '@create_ship' do
|
||||
it 'returns false when the player is invalid' do
|
||||
expect(universe.create_ship(player_1, Position.new(3, 5))).to eq false
|
||||
end
|
||||
end # describe '@create_ship'
|
||||
|
||||
describe '@move_ship' do
|
||||
it 'returns false when the player is invalid' do
|
||||
expect(universe.move_ship(player_1, Ship.new(2, 4, player_1), Position.new(3, 5))).to eq false
|
||||
end
|
||||
end # describe '@move_ship'
|
||||
|
||||
describe '@remove_ship' do
|
||||
it 'returns false when the player is invalid' do
|
||||
expect(universe.remove_ship(player_1, Position.new(3, 5))).to eq false
|
||||
end
|
||||
end # describe '@remove_ship'
|
||||
end # describe 'SHIPS API'
|
||||
|
||||
|
||||
|
||||
describe 'PLANETS API' do
|
||||
describe '@remove_planet' do
|
||||
end # describe '@remove_planet'
|
||||
end # describe 'PLANETS API'
|
||||
|
||||
|
||||
describe 'PLAYER API' do
|
||||
describe '#add_player' do
|
||||
it 'adds with free planets' do
|
||||
expect(universe.add_player(player_1)).to be(true)
|
||||
expect(universe.instance_variable_get(:@player_list)).to eq [player_1]
|
||||
end
|
||||
|
||||
it 'fails to add when all planets are occopuied' do
|
||||
# Make all the planets owned by player_2
|
||||
universe.planets.each do |planet|
|
||||
planet.change_owner(player_2)
|
||||
end
|
||||
expect(universe.add_player(player_1)).to be(false)
|
||||
expect(universe.instance_variable_get(:@player_list)).to eq []
|
||||
end
|
||||
|
||||
it 'raises an error if a planet can not be taken' do
|
||||
# This is an exceptional case. This is actually proper behavior when
|
||||
# not trying to deal out planets.
|
||||
end
|
||||
end # describe 'add_player'
|
||||
|
||||
describe '#remove_player' do
|
||||
it 'can remove an existing player' do
|
||||
universe.add_player(player_1)
|
||||
expect(universe.remove_player(player_1)).to eq true
|
||||
expect(universe.remove_player(player_2)).to eq true
|
||||
expect(universe.instance_variable_get(:@player_list)).to eq []
|
||||
end
|
||||
|
||||
it 'can remove a non existing player' do
|
||||
expect(universe.remove_player(player_2)).to eq true
|
||||
end
|
||||
end # describe 'remove_player'
|
||||
|
||||
describe '#validate_player' do
|
||||
it 'returns true when a player is valid' do
|
||||
universe.add_player(player_1)
|
||||
expect(universe.validate_player(player_1)).to eq true
|
||||
end
|
||||
|
||||
it 'returns false when the player is not in the player list' do
|
||||
expect(universe.validate_player(player_2)).to eq false
|
||||
end
|
||||
end # describe 'validate_player'
|
||||
|
||||
|
||||
describe '#get_player_ships' do
|
||||
it 'lists all ships owned by a player' do
|
||||
universe.add_player(player_1)
|
||||
universe.add_player(player_2)
|
||||
expect(universe.get_player_ships(player_1)).to eq []
|
||||
ship_1 = Ship.new(2, 4, player_1)
|
||||
ship_2 = Ship.new(2, 4, player_2)
|
||||
ship_3 = Ship.new(3, 5, player_1)
|
||||
universe.instance_variable_set(:@ship_list, [ship_1, ship_2, ship_3])
|
||||
expect(universe.get_player_ships(player_1)).to eq [ship_1, ship_3]
|
||||
expect(universe.get_player_ships(player_2)).to eq [ship_2]
|
||||
end
|
||||
|
||||
it 'returns an empty list when a player that is not registered gets ships' do
|
||||
ship_2 = Ship.new(2, 4, player_2)
|
||||
universe.instance_variable_set(:@ship_list, [ship_2])
|
||||
expect(universe.get_player_ships(player_2)).to eq []
|
||||
end
|
||||
end # describe 'get_player_ships'
|
||||
|
||||
describe '#get_player_planets' do
|
||||
it 'returns the planets owned by a player' do
|
||||
universe.add_player(player_1)
|
||||
expect(universe.get_player_planets(player_2)).to eq []
|
||||
expect(universe.get_player_planets(player_1).length).to eq 1
|
||||
end
|
||||
|
||||
it 'returns an empty list for a unregistered player' do
|
||||
expect(universe.get_player_planets(player_2)).to eq []
|
||||
end
|
||||
|
||||
end # describe 'get_player_planets'
|
||||
end # describe 'PLAYER API'
|
||||
end
|
||||
|
||||
@@ -13,15 +13,15 @@ RSpec.describe Planet do
|
||||
|
||||
describe '#initialize' do
|
||||
it 'stores the random off' do
|
||||
expect(planet.instance_variable_get(:@random)).to eq(random)
|
||||
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)
|
||||
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])
|
||||
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
|
||||
@@ -31,13 +31,13 @@ RSpec.describe Planet do
|
||||
|
||||
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.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.change_owner(player_1)).to eq false
|
||||
expect(planet.instance_variable_get(:@owner)).to eq player_2
|
||||
end
|
||||
end
|
||||
|
||||
@@ -10,8 +10,8 @@ RSpec.describe Position 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])
|
||||
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
|
||||
@@ -43,30 +43,30 @@ RSpec.describe Position do
|
||||
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)
|
||||
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])
|
||||
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)')
|
||||
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)
|
||||
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)
|
||||
expect(Position.new(*even_pair) == Position.new(4, 6)).to eq true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,17 +1,19 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require_relative '../ship' # <-- adjust to the actual path of ship.rb
|
||||
require './ship'
|
||||
|
||||
require './player'
|
||||
|
||||
RSpec.describe Ship do
|
||||
let(:ship) { Ship.new(0, 0) }
|
||||
let(:ship) { Ship.new(0, 0, Player.new('test player 01')) }
|
||||
|
||||
describe '#initialize' do
|
||||
it 'stores the given position' do
|
||||
expect(ship.instance_variable_get(:@position)).to eq([0, 0])
|
||||
expect(ship.instance_variable_get(:@position)).to eq [0, 0]
|
||||
end
|
||||
|
||||
it 'sets the speed to 0.1' do
|
||||
expect(ship.instance_variable_get(:@speed)).to eq(0.1)
|
||||
expect(ship.instance_variable_get(:@speed)).to eq 0.1
|
||||
end
|
||||
|
||||
it 'does not set @moving until a direction is chosen' do
|
||||
@@ -70,7 +72,7 @@ RSpec.describe Ship do
|
||||
}
|
||||
mapping.each do |dir, expected|
|
||||
expect { ship.move_direction(dir) }.not_to raise_error
|
||||
expect(ship.instance_variable_get(:@moving)).to eq(expected)
|
||||
expect(ship.instance_variable_get(:@moving)).to eq expected
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -52,7 +52,6 @@ RSpec.configure do |config|
|
||||
|
||||
# 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
|
||||
@@ -87,7 +86,7 @@ RSpec.configure do |config|
|
||||
# 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
|
||||
# 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
|
||||
@@ -100,5 +99,4 @@ RSpec.configure do |config|
|
||||
# test failures related to randomization by passing the same `--seed` value
|
||||
# as the one that triggered the failure.
|
||||
Kernel.srand config.seed
|
||||
=end
|
||||
end
|
||||
|
||||
@@ -18,6 +18,13 @@ RSpec.describe UniverseArray do
|
||||
uni_arr[0][0] = 'hi'
|
||||
expect(uni_arr[Position.new(0, 0)]).to eq 'hi'
|
||||
end
|
||||
|
||||
it 'returns nil when access outside universe' do
|
||||
uni_arr = UniverseArray.new()
|
||||
uni_arr[3] = []
|
||||
expect(uni_arr[Position.new(3, 51)]).to eq nil
|
||||
expect(uni_arr[Position.new(0, 0)]).to eq nil
|
||||
end
|
||||
end
|
||||
|
||||
describe '#[]=' do
|
||||
|
||||
+20
-16
@@ -24,15 +24,15 @@ RSpec.describe Universe do
|
||||
|
||||
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)
|
||||
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))
|
||||
expect(rng.rand(100)).to eq Random.new(seed).rand(100)
|
||||
end
|
||||
|
||||
it 'initializes the random if no seed is passed in' do
|
||||
@@ -50,12 +50,12 @@ RSpec.describe Universe 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))
|
||||
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)
|
||||
expect(universe.distance(p, p)).to eq 0
|
||||
end
|
||||
|
||||
it 'correctly computes known hex distances' do
|
||||
@@ -64,13 +64,13 @@ RSpec.describe Universe do
|
||||
p2 = Position.new(4, 2)
|
||||
p3 = Position.new(2, 2)
|
||||
# (0,0) to (2,0) → 1
|
||||
expect(universe.distance(p0, p1)).to eq(1)
|
||||
expect(universe.distance(p0, p1)).to eq 1
|
||||
# (0,0) to (4,2) → 3
|
||||
expect(universe.distance(p0, p2)).to eq(3)
|
||||
expect(universe.distance(p0, p2)).to eq 3
|
||||
# (0,0) to (2,2) → 2
|
||||
expect(universe.distance(p0, p3)).to eq(2)
|
||||
expect(universe.distance(p0, p3)).to eq 2
|
||||
end
|
||||
end
|
||||
end # describe '#distance'
|
||||
|
||||
describe '#map generation' do
|
||||
it 'creates the expected dimensions' do
|
||||
@@ -80,7 +80,7 @@ RSpec.describe Universe do
|
||||
# (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
|
||||
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
|
||||
@@ -89,12 +89,16 @@ RSpec.describe Universe do
|
||||
map.each do |row|
|
||||
row.each do |idx|
|
||||
# The indexes are allowed to be nil
|
||||
if !idx.nil?
|
||||
expect(idx).to be_a(Planet)
|
||||
if idx.nil?
|
||||
next # Is allowed to be nil
|
||||
end
|
||||
if idx.is_a? Star
|
||||
next # Is allowed to be star
|
||||
end
|
||||
expect(idx).to be_a(Planet)
|
||||
end
|
||||
end
|
||||
end
|
||||
end # describe '#map generation'
|
||||
|
||||
it 'is deterministic when the same seed is used' do
|
||||
first_universe = Universe.new(
|
||||
@@ -113,7 +117,7 @@ RSpec.describe Universe do
|
||||
)
|
||||
second_map = second_universe.instance_variable_get(:@universe_map)
|
||||
|
||||
expect(first_map).to eq(second_map)
|
||||
expect(first_map).to eq second_map
|
||||
end
|
||||
end
|
||||
|
||||
@@ -140,7 +144,7 @@ RSpec.describe Universe do
|
||||
describe '#planets' do
|
||||
it 'lists all of the generated planets' do
|
||||
universe.create_universe
|
||||
expect(universe.planets.length).to eq(19)
|
||||
expect(universe.planets.length).to eq 18
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
# Nathan Hinton Oct 2 2025
|
||||
|
||||
# Literally just a class to have something else in space...
|
||||
|
||||
class Star
|
||||
def initialize
|
||||
end
|
||||
end
|
||||
+52
-8
@@ -4,6 +4,7 @@
|
||||
require 'logger'
|
||||
|
||||
require './planet'
|
||||
require './star'
|
||||
require './position'
|
||||
require './universe_array'
|
||||
|
||||
@@ -60,6 +61,7 @@ class Universe
|
||||
|
||||
# Setup internal lists:
|
||||
@player_list = []
|
||||
@planet_list = []
|
||||
@ship_list = []
|
||||
|
||||
# initizlize RNG
|
||||
@@ -73,6 +75,8 @@ class Universe
|
||||
end # Initialize
|
||||
|
||||
|
||||
# Create the universe. This will setup all of the planets and a blank slate
|
||||
# for the universe.
|
||||
def create_universe()
|
||||
# Set center of universe
|
||||
@center = Position.new(@universe_size + 2, @universe_size)
|
||||
@@ -96,12 +100,17 @@ class Universe
|
||||
|
||||
# Skip if it is the center
|
||||
if position == @center
|
||||
@universe_map[position] = Star.new()
|
||||
next
|
||||
end
|
||||
|
||||
# Get what the planet should be:
|
||||
spot = nil
|
||||
if @random.rand < @create_chances[:planet]
|
||||
spot = Planet.new(@random)
|
||||
@planet_list.push(spot)
|
||||
#else
|
||||
# spot = ''
|
||||
end
|
||||
@@logger.debug "Creating something at (#{position})"
|
||||
@universe_map[position] = spot
|
||||
@@ -119,7 +128,6 @@ class Universe
|
||||
# @return [Integer] The distance between points in the universe.
|
||||
def distance(position_a, position_b)
|
||||
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_y = (position_b.y_pos - position_a.y_pos).abs
|
||||
|
||||
@@ -176,9 +184,9 @@ class Universe
|
||||
# Print what we are:
|
||||
value = @universe_map[position]
|
||||
nextline += ' '
|
||||
if position == @center
|
||||
if value.is_a?(Star)
|
||||
print 'O'
|
||||
elsif value.class == Planet
|
||||
elsif value.is_a?(Planet)
|
||||
print 'P'
|
||||
else
|
||||
print ' '
|
||||
@@ -262,6 +270,7 @@ class Universe
|
||||
# @param player [Player] The player who owns the ship
|
||||
# @param position [Position] The position that the ship should be created at
|
||||
def create_ship(player, position)
|
||||
return false unless validate_player(player)
|
||||
end
|
||||
|
||||
# Move a player's ship to a given position
|
||||
@@ -270,6 +279,15 @@ class Universe
|
||||
# @param ship [Ship] The ship that should be moved
|
||||
# @param position [Position] The position the ship should be moved to.
|
||||
def move_ship(player, ship, position)
|
||||
return false unless validate_player(player)
|
||||
# Ensure the ship exists before moving it.
|
||||
end
|
||||
|
||||
# Remove a ship from the game
|
||||
# @param player [Player] The player who owns the ship to be removed
|
||||
# @param ship [Ship] The ship to be removed
|
||||
def remove_ship(player, ship)
|
||||
return false unless validate_player(player)
|
||||
end
|
||||
|
||||
|
||||
@@ -301,14 +319,24 @@ class Universe
|
||||
#
|
||||
# @param player [Player] The player who should be added to the universe
|
||||
def add_player(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'
|
||||
if free_planets == []
|
||||
@@logger.debug 'Failed to find an unoccopuied planet for new player!'
|
||||
return false
|
||||
end
|
||||
home_planet = free_planets.sample(random: @random)
|
||||
# Can;t figure out how to test this...
|
||||
# if !home_planet.change_owner(player)
|
||||
# raise Exception.new('Failed to allocate a new player a home planet!')
|
||||
# end
|
||||
home_planet.change_owner(player)
|
||||
@player_list.push(player)
|
||||
@@logger.debug "Added player '#{player.name}' with home planet #{home_planet}"
|
||||
return true
|
||||
end
|
||||
|
||||
# Remove a player from the list in this universe
|
||||
@@ -316,15 +344,30 @@ class Universe
|
||||
# @param player [Player] The player that should be removed from the player list.
|
||||
def remove_player(player)
|
||||
if @player_list.delete(player).nil?
|
||||
return 'Failed to remove player! Does not exist in this universe!'
|
||||
@@logger.debug 'Failed to remove player! Does not exist in this universe! Returning true anyway though!'
|
||||
end
|
||||
return 'Removed player from universe'
|
||||
@@logger.debug "Removed player '#{player.name}' from universe"
|
||||
return true
|
||||
end
|
||||
|
||||
# Validates if a player exists and is in a good state in the server
|
||||
#
|
||||
# @param player [Player] The player to validate
|
||||
def validate_player(player)
|
||||
# check if in player list:
|
||||
unless @player_list.include?(player)
|
||||
@@logger.warn "Player '#{player}' Tried to perform an action but is an invalid player!"
|
||||
return false
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
# Returns a list of ships owned by the player
|
||||
#
|
||||
# @param player [Player] The player who wants to get their ships.
|
||||
# @return [Array<Ship>]
|
||||
def get_player_ships(player)
|
||||
return [] unless validate_player(player)
|
||||
result = []
|
||||
@ship_list.each do |ship|
|
||||
if ship.owner == player
|
||||
@@ -338,6 +381,7 @@ class Universe
|
||||
#
|
||||
# @param player [Player] The player who wants to get their planets.
|
||||
def get_player_planets(player)
|
||||
return [] unless validate_player(player)
|
||||
result = []
|
||||
@planet_list.each do |planet|
|
||||
if planet.owner == player
|
||||
|
||||
+22
-2
@@ -1,22 +1,42 @@
|
||||
# Nathan Hinton 1 Oct 2025
|
||||
# Create a custom hash class for the universe.
|
||||
|
||||
require 'logger'
|
||||
|
||||
require './position'
|
||||
|
||||
# This will contain the universe hash inside it. It will allow for array type
|
||||
# indexing as well as point type indexing
|
||||
class UniverseArray < Array
|
||||
def initialize
|
||||
end
|
||||
|
||||
@@logger = Logger.new('logs/universe.log')
|
||||
|
||||
# Custom accessor. This allows us to access either with a position object
|
||||
# (preferred as it does validation) or direct access.
|
||||
#
|
||||
# @param index [Integer, Position] If it is an integer nothing special. If a
|
||||
# Position it will be intepreted for us into the regular indexint.
|
||||
# @param rest [Object] Actually, I have no idea why this is here. (copy paste)
|
||||
# @return Whatever is at that position. Can be anything.
|
||||
def [](index, *rest)
|
||||
#require 'byebug';debugger
|
||||
if index.is_a?(Position)
|
||||
if self[index.y_pos].nil?
|
||||
@@logger.debug "attempted access outside of known universe!"
|
||||
return nil
|
||||
end
|
||||
return self[index.y_pos][index.x_pos]
|
||||
else
|
||||
super
|
||||
end
|
||||
end
|
||||
|
||||
# Custom writer. This allows us to access either with a position object
|
||||
# (preferred as it does validation) or direct access.
|
||||
#
|
||||
# @param index [Integer, Position] If it is an integer nothing special. If a
|
||||
# Position it will be intepreted for us into the regular indexint.
|
||||
# @param rest [Object] This (if intercepted) has the value we should assign
|
||||
def []=(index, *rest)
|
||||
if index.is_a?(Position)
|
||||
return self[index.y_pos][index.x_pos] = rest[0]
|
||||
|
||||
Reference in New Issue
Block a user