146 lines
3.3 KiB
Ruby
146 lines
3.3 KiB
Ruby
# Nathan Hinton 19 Dec 2025
|
|
|
|
|
|
require 'securerandom'
|
|
|
|
require './planet'
|
|
|
|
# This class holds a game and should be the top level object.
|
|
class Game
|
|
attr_reader :players, :width, :height, :planets, :game_id
|
|
# Create the game
|
|
def initialize(width: 0, height: 0, planets: 0, game_id: nil, name: 'default name')
|
|
@game_id = game_id || SecureRandom.hex
|
|
@game_name = name
|
|
@players = []
|
|
@planets = []
|
|
planets.times do |idx|
|
|
planet = Planet.new()
|
|
# Move to a random position
|
|
position = [rand(width), rand(height), 0]
|
|
# Ensure that the planets position is random
|
|
while @planets.map{ |pl| pl.position}.include? position
|
|
position = [rand(width), rand(height), 0]
|
|
end
|
|
planet.move(position)
|
|
# Add to the list:
|
|
@planets.append(planet)
|
|
end
|
|
@width = width
|
|
@height = height
|
|
end
|
|
|
|
# Add a player to the game
|
|
#
|
|
# @param player [Player] The player to add to the game
|
|
def add_player(player)
|
|
# Check if there is a planet free for the player:
|
|
avail_planets = []
|
|
@planets.each do |planet|
|
|
avail_planets.append(planet) if planet.owner.nil?
|
|
end
|
|
if avail_planets == []
|
|
raise GameError, "No available planets to add player to"
|
|
end
|
|
planet = avail_planets.sample
|
|
|
|
# Add the player to the game
|
|
@players.append(player)
|
|
planet.capture(player)
|
|
player.home_planet = planet
|
|
end
|
|
|
|
# Remove a player from the game
|
|
#
|
|
# @param player [Player] The player to be removed
|
|
def remove_player(player)
|
|
idx = @players.index(player)
|
|
if idx.nil?
|
|
# Raise an error that the player could not be found
|
|
raise GameError, 'Player not found to remove!'
|
|
end
|
|
@players.delete_at(idx)
|
|
end
|
|
|
|
# Finds if a player is in this game
|
|
#
|
|
# @return [Boolean]
|
|
def find_player(player_name)
|
|
@players.each do |player|
|
|
if player.name == player_name
|
|
return true
|
|
end
|
|
end
|
|
return false
|
|
end
|
|
|
|
# Checks if the given id matches a player in the game. Returns the player if
|
|
# so. otherwise raises an error.
|
|
#
|
|
# @param id [String] The id of a player
|
|
# @return Player The player matching the id
|
|
def check_id(id)
|
|
@players.each do |player|
|
|
if player.id == id
|
|
return player
|
|
end
|
|
end
|
|
raise GameError, 'Invalid player id!'
|
|
end
|
|
|
|
# Gets the planets for a player
|
|
#
|
|
# @param id [String] Players id
|
|
# @return [Array<Planet>] List of planets captured by that player
|
|
def get_captured_planets(id)
|
|
player = check_id(id)
|
|
result = []
|
|
@planets.each do |planet|
|
|
result.append(planet) if planet.owner == player
|
|
end
|
|
return result
|
|
end
|
|
|
|
# Returns a string representation of the map
|
|
# Begin no coverage
|
|
# :nocov:
|
|
def to_s()
|
|
# Create char map:
|
|
game_map = []
|
|
@height.times do
|
|
tmp = []
|
|
@width.times do
|
|
tmp.append('')
|
|
end
|
|
game_map.append(tmp)
|
|
end
|
|
|
|
# Add planets to the map:
|
|
@planets.each do |planet|
|
|
pos_x, pos_y, pos_z = planet.position
|
|
puts("x: #{pos_x}, y: #{pos_y}")
|
|
game_map[pos_y][pos_x] += 'p'
|
|
end
|
|
|
|
require 'pp'
|
|
pp(game_map)
|
|
game_map.each do |row|
|
|
row.each do |col|
|
|
if col == ''
|
|
print(' ')
|
|
else
|
|
print(col)
|
|
end
|
|
end
|
|
print("\n")
|
|
end
|
|
end
|
|
# :nocov:
|
|
# End no coverage
|
|
|
|
end
|
|
|
|
# General game errors
|
|
class GameError<StandardError
|
|
end
|