Files
space_game_server/core/game.rb
T

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