💾 Archived View for gemini.ctrl-c.club › ~nttp › games › text-based › orion.py captured on 2024-05-26 at 15:52:22.

View Raw

More Information

⬅️ Previous capture (2024-05-12)

-=-=-=-=-=-=-

#!/usr/bin/env python3
# coding=utf-8
# 
# Space Cruiser Orion: a text-based strategy game... in spaaace!
# 2019-05-02 Felix Pleșoianu <https://felix.plesoianu.ro/>
# 
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
# 
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
# 
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.

from __future__ import print_function
from __future__ import division

import math
import random

try:
	import readline
except ImportError as e:
	print("(Command line editing is unavailable.)\n")

import cmd

SPACE = 0
STAR = 1
PLANET = 2
ASTEROID = 3
OUTPOST = 4

MAXSHIPS = 20
SHIPOFFS = 10

game_banner = """
Urgent message from Space Patrol Dispatch:

Lost contact with our 5 outposts near Sirius Sector.
Hostile activity has been detected.
We can only spare one ship: the SPV Orion.
Your mission:
- re-establish communications in the area;
- hunt down any Mechanoid raiders.
Good luck, Captain.

(Type "help" or "?" to see a list of commands.)
"""

class Ship:
	def __init__(self):
		self.energy = random.randint(20, 30) * 100
		self.shields = self.energy / 10
		self.missiles = 0
		self.max_e = 3000
		self.max_s = 300
		
		self.damage = 0
		
		self.sector = None
		self.x = -1
		self.y = -1
		
		self.dock_count = 0
		self.kills = 0
	
	def jump_dest(self, course, distance):
		assert(1 <= course <= 9)
		course = (course - 1) / 8 * 2 * math.pi
		dx = int(math.cos(course) * distance)
		dy = int(-math.sin(course) * distance)
		return self.sector.x + dx, self.sector.y + dy
	
	def rocket_dest(self, course, distance):
		assert(1 <= course <= 9)
		course = (course - 1) / 8 * 2 * math.pi
		dx = int(math.cos(course) * distance)
		dy = int(-math.sin(course) * distance)
		return self.x + dx, self.y + dy
	
	def launch_path(self, course):
		assert(1 <= course <= 9)
		course = (course - 1) / 8 * 2 * math.pi
		dx = math.cos(course)
		dy = -math.sin(course)
		return dx, dy

	def distance_to(self, x, y):
		return math.hypot(abs(self.x - x), abs(self.y - y))

	def shoot_at(self, target, energy):
		if self.sector != target.sector:
			return -1
		else:
			energy /= self.distance_to(target.x, target.y)
			if target.shields >= energy:
				target.shields -= energy
				return 0
			else:
				energy -= target.shields
				target.shields = 0
				return energy

class Sector:
	def __init__(self, galaxy, x, y):
		self.squares = [bytearray(8) for i in range(8)]
		self.galaxy = galaxy
		self.x = x
		self.y = y
		
		self.major = False
		self.outpost = False
		self.scanned = False
	
		self.outpost_x = -1
		self.outpost_y = -1
	
		self.energy = 0
	
	def populate(self):
		for y in range(8):
			for x in range(8):
				self.squares[y][x] = SPACE
			if random.randint(1, 2) == 1:
				x = random.randint(1, 8) - 1
				if self.major:
					self.squares[y][x] = PLANET
				else:
					self.squares[y][x] = ASTEROID
		if self.major:
			x = random.randint(3, 6) - 1
			y = random.randint(3, 6) - 1
			self.squares[y][x] = STAR
		else:
			self.energy = 1000
	
	def random_free_square(self):
		x = random.randint(1, 8) - 1
		y = random.randint(1, 8) - 1
		while self.squares[y][x] != SPACE:
			x = random.randint(1, 8) - 1
			y = random.randint(1, 8) - 1
		return x, y

	def add_ship(self, slot):
		ship = self.galaxy.ships[slot]
		x, y = self.random_free_square()
		self.squares[y][x] = slot + SHIPOFFS
		ship.sector = self
		ship.x = x
		ship.y = y

	def remove_ship(self, slot):
		ship = self.galaxy.ships[slot]
		self.squares[ship.y][ship.x] = SPACE
		ship.sector = None
		ship.x = -1
		ship.y = -1

	def spawn_enemies(self, slot):
		if self.outpost:
			count = random.randint(1, 2)
		else:
			count = random.randint(2, 3)
		for i in range(count):
			self.galaxy.ships[slot] = Ship()
			self.add_ship(slot)
			slot += 1
		return slot

	def enemy_count(self):
		count = 0
		for y in range(8):
			for x in range(8):
				if self.squares[y][x] > SHIPOFFS:
					count += 1
		return count

	def __format__(self, fmt):
		star = "*" if self.major else "."

		if self.scanned:
			outpost = "!" if self.outpost else " "
		else:
			outpost = "?"

		if not self.scanned:
			return "-" + star + outpost
		elif self.galaxy.ships[0].sector == self:
			return "@" + star + outpost

		count = self.enemy_count()

		if count > 0:
			return str(count) + star + outpost
		else:
			return " " + star + outpost

class Galaxy:
	def __init__(self):
		self.ships = [None] * MAXSHIPS
		self.sectors = [[None] * 8 for i in range(8)]
		for y in range(8):
			for x in range(8):
				self.sectors[y][x] = Sector(self, x, y)
	
	def populate(self):
		major_sectors = [None] * 8
		for y in range(8):
			x = random.randint(1, 8) - 1
			self.sectors[y][x].major = True
			major_sectors[y] = self.sectors[y][x]
			for x in range(8):
				self.sectors[y][x].populate()
		random.shuffle(major_sectors)
		for i in range(5):
			major_sectors[i].outpost = True
			x, y = major_sectors[i].random_free_square()
			major_sectors[i].squares[y][x] = OUTPOST
			major_sectors[i].outpost_x = x
			major_sectors[i].outpost_y = y
		for i in range(1, MAXSHIPS):
			self.ships[i] = None
		slot = 1
		for i in range(8):
			slot = major_sectors[i].spawn_enemies(slot)
	
	def reset(self):
		for y in range(8):
			for x in range(8):
				self.sectors[y][x].major = False
				self.sectors[y][x].outpost = False
				self.sectors[y][x].scanned = False
		self.populate()
		self.ships[0] = Ship()
		self.ships[0].energy = 5000
		self.ships[0].shields = 500
		self.ships[0].missiles = 5
		self.ships[0].max_e = 10000
		self.ships[0].max_s = 1000
		x = random.randint(1, 8) - 1
		y = random.randint(1, 8) - 1
		sector = self.sectors[y][x]
		sector.add_ship(0)
		sector.scanned = True
	
	def enemies_active(self):
		count = 0
		for i in self.ships[1:]:
			if i != None and i.sector.outpost:
				count += 1
		return count
	
	def outposts_found(self):
		count = 0
		for y in range(8):
			for x in range(8):
				sector = self.sectors[y][x]
				if sector.outpost and sector.scanned:
					count += 1
		return count

def print_sector(sector):
	odds = sector.galaxy.ships[0].damage // 5
	print(" 000", end="")
	for i in range(8):
		print(" {:03d}".format(i + 1), end="")
	print("\n")
	for y in range(8):
		print(" {:03d}".format(y + 1), end="")
		for x in range(8):
			square = sector.squares[y][x]
			if random.randint(1, 10) <= odds:
				print(" ???", end="")
			elif square == STAR:
				print(" .*.", end="")
			elif square == PLANET:
				print(" .O.", end="")
			elif square == ASTEROID:
				print(" .o.", end="")
			elif square == OUTPOST:
				print(" -!-", end="")
			elif square == SPACE:
				print(" ...", end="")
			elif square == SHIPOFFS:
				print(" -@-", end="")
			else:
				print(" -M-", end="")
		print("\n")

def print_galaxy(galaxy):
	odds = galaxy.ships[0].damage // 5
	print(" 000", end="")
	for i in range(8):
		print(" {:03d}".format(i + 1), end="")
	print("\n")
	for y in range(8):
		print(" {:03d}".format(y + 1), end="")
		for x in range(8):
			if random.randint(1, 10) <= odds:
				print(" ???", end="")
			else:
				sector = galaxy.sectors[y][x]
				print(" {0}".format(sector), end="")
		print("\n")

def scan_area(sector):
	all_sec = sector.galaxy.sectors
	print("Scanning sectors:", end="")
	for y in range(sector.y - 1, sector.y + 2):
		for x in range(sector.x - 1, sector.x + 2):
			if x == sector.x and y == sector.y:
				pass
			elif 0 <= x <= 7 and 0 <= y <= 7:
				all_sec[y][x].scanned = True
				print(" ({}, {})".format(x + 1, y + 1), end="")
	print(" ...Done!")

def print_report(galaxy):
	player = galaxy.ships[0]
	x, y = player.sector.x, player.sector.y
	print("\nCurrent sector: {0}, {1}".format(x + 1, y + 1))
	print("Raiders active: {0}".format(galaxy.enemies_active()))
	print("Outposts found: {0}\n".format(galaxy.outposts_found()))
	print("Energy: {0:4.1f}".format(player.energy))
	print("Shields: {0:4.1f}".format(player.shields))
	print("Missiles: {0}".format(player.missiles))
	print("\nDamage: {0}\n".format(player.damage))

def jump_player(galaxy, course, distance):
	player = galaxy.ships[0]
	cost = distance * distance * 100
	x, y = player.jump_dest(course, distance)
	if x == player.sector.x and y == player.sector.y:
		print("That wouldn't take us very far at all, Captain!")
		return False
	elif distance > 8:
		print("We can't jump that far in one go, Captain!")
		return False
	elif cost > player.energy:
		print("We don't have enough energy, Captain!")
		return False
	elif 0 <= x <= 7 and 0 <= y <= 7:
		player.energy -= cost
		player.sector.remove_ship(0)
		galaxy.sectors[y][x].add_ship(0)
		galaxy.sectors[y][x].scanned = True
		print("Engaging Polaris drive...")
		print("Jumped to ({0}, {1})!".format(x + 1, y + 1))
		report_energy(player)
		return True
	else:
		print("That would strand us in deep space, Captain!")
		return False

def rocket_player(player, course, distance):
	cost = (distance + player.damage // 5) * 10
	squares = player.sector.squares
	x, y = player.rocket_dest(course, distance)
	if x == player.x and y == player.y:
		print("That wouldn't take us very far at all, Captain!")
		return False
	elif cost > player.energy:
		print("We don't have enough energy, Captain!")
		return False
	elif 0 <= x <= 7 and 0 <= y <= 7:
		if squares[y][x] != SPACE:
			report_collision(squares[y][x])
			return
		squares[player.y][player.x] = SPACE
		squares[y][x] = SHIPOFFS
		player.energy -= cost
		player.x = x
		player.y = y
		print("Engaging Polaris drive...")
		print("Rocketed to ({0}, {1})!".format(x + 1, y + 1))
		report_energy(player)
		return True
	else:
		print("That would strand us in deep space, Captain!")
		return False

def report_collision(square):
	print("But, Captain, that would send us hurtling into ", end="")
	if square == ASTEROID:
		print("an asteroid", end="")
	elif square == PLANET:
		print("a planet", end="")
	elif square == STAR:
		print("the local star", end="")
	elif square == OUTPOST:
		print("the outpost", end="")
	elif square > SHIPOFFS:
		print("that enemy ship", end="")
	print("!")

def fire_pulse(energy, ships):
	assert(ships[0].energy >= energy)
	ships[0].energy -= energy
	for i in range(1, MAXSHIPS):
		if ships[i] == None:
			continue
		elif ships[0].sector != ships[i].sector:
			continue
			
		damage = ships[0].shoot_at(ships[i], energy)
		
		if damage > 0:
			ships[0].kills += 1
			ships[0].sector.remove_ship(i)
			ships[i] = None
			print("Mechanoid ship destroyed, Captain!")
		else:
			print("Enemy shields down to {0:4.1f}%!".format(
				ships[i].shields / 300 * 100))
	report_energy(ships[0])

def fire_meteor(course, ships):
	assert(ships[0].missiles > 0)
	odds = ships[0].damage // 5
	if random.randint(1, 10) <= odds:
		print("Missile has misfired due to damage, Captain!")
		return
	ships[0].missiles -= 1
	x, y = ships[0].x, ships[0].y
	dx, dy = ships[0].launch_path(course)
	if __debug__:
		print("(debug) Missile trajectory:", dx, dy)
	if abs(dx) < 0.01: dx = 0
	if abs(dy) < 0.01: dy = 0
	print("Firing Meteor missile through:", end="")
	while 0 <= x <= 7 and 0 <= y <= 7:
		x += dx
		y += dy
		print(" ({0:1.0f}, {1:1.0f})".format(x + 1, y + 1), end="")
		if 0 <= x <= 7 and 0 <= y <= 7:
			if handle_impact(ships[0].sector, int(x), int(y)):
				break

def handle_impact(sector, x, y):
	assert(0 <= x <= 7 and 0 <= y <= 7)
	square = sector.squares[y][x]
	if square == SPACE or square == SHIPOFFS:
		return False
	elif square == ASTEROID:
		sector.squares[y][x] = SPACE
		print("\nOur missile has shattered an asteroid, Captain!")
		return True
	elif square == PLANET:
		print("\nOur missile has struck a planet, Captain!")
		return True
	elif square == STAR:
		print("\nOur missile has caused a solar flare, Captain!")
		strike_player(sector.galaxy.ships[0])
		for i in range(1, MAXSHIPS):
			if sector.galaxy.ships[i] == None:
				pass
			elif sector.galaxy.ships[i].sector == sector:
				strike_enemy(sector, i)
		return True
	elif square == OUTPOST:
		print("\nOur missile impacted the outpost, Captain!")
		print("Their shields can't take many hits like that!")
		return True
	elif square > SHIPOFFS:
		i = square - SHIPOFFS
		strike_enemy(sector, i)
		if sector.galaxy.ships[i] != None:
			sector.remove_ship(i)
			sector.add_ship(i)
			print("Mechanoid ship has moved, Captain!")
		return True

def strike_player(player):
	if player.shields > 250:
		player.shields -= 250
		print("Shields holding at {0:4.1f}%.".format(
			player.shields / player.max_s * 100))
	else:
		damage = 250 - player.shields
		player.shields = 0
		player.damage += int(damage / 10)
		print("Shields down! We are damaged!")

def strike_enemy(sector, index):
	galaxy = sector.galaxy
	ship = galaxy.ships[index]
	if ship.shields > 250:
		ship.shields -= 250
		print("\nEnemy shields down to {0:4.1f}%.".format(
			ship.shields / 300 * 100))
	else:
		sector.remove_ship(index)
		galaxy.ships[index] = None
		galaxy.ships[0].kills += 1
		print("\nMechanoid ship destroyed, Captain.")

def handle_enemy_fire(ships):
	for i in range(1, len(ships)):
		if ships[i] == None:
			continue
		elif ships[i].sector != ships[0].sector:
			continue
		elif ships[i].energy <= 1500:
			handle_enemy_jump(ships, i)
			continue
		
		energy = ships[i].distance_to(ships[0].x, ships[0].y)
		energy *= random.randint(8, 13) * 10
		ships[i].energy -= energy
		damage = ships[i].shoot_at(ships[0], energy)
		print("Mechanoid ship at ({}, {}) is firing on us!".format(
			ships[i].x + 1, ships[i].y + 1))
		if damage > 0:
			ships[0].damage += int(damage / 10)
			print("Shields down! We are damaged!")
			# TO DO: make the ship take localized damage.
		else:
			print("Shields holding at {0:4.1f}%.".format(
				ships[0].shields / ships[0].max_s * 100))

def handle_enemy_jump(ships, i):
	print("Mechanoid ship at ({}, {}) has jumped away, Captain!".format(
		ships[i].x + 1, ships[i].y + 1))
	x = random.randint(1, 8) - 1
	y = random.randint(1, 8) - 1
	galaxy = ships[i].sector.galaxy
	ships[i].sector.remove_ship(i)
	galaxy.sectors[y][x].add_ship(i)
	ships[i].energy += random.randint(5, 10) * 100
	ships[i].shields += random.randint(1, 2) * 100

def refuel_player(player):
	if player.sector.major:
		print("Can't collect hydrogen near a star, Captain!")
	elif player.sector.enemy_count() > 0:
		print("Can't refuel with enemy ships around, Captain!")
	else:
		if player.max_e - player.energy > player.sector.energy / 2:
			player.sector.energy /= 2
			player.energy += player.sector.energy
		else:
			player.sector.energy -= player.max_e - player.energy
			player.energy = player.max_e
		print("Deploying hydrogen collectors...")
		report_energy(player)

def dock_player(player):
	sec = player.sector
	if not sec.outpost:
		print("There's no outpost in this sector, Captain!")
	elif sec.enemy_count() > 0:
		print("We can't dock while under attack, Captain!")
	elif player.distance_to(sec.outpost_x, sec.outpost_y) > 1.5:
		print("We're too far from the outpost to dock!")
	elif player.dock_count >= 5:
		print("The outpost is out of supplies, Captain!")
	else:
		print("\nDocking with outpost DSO 8-{0}...\n".format(
			sec.y * 8 + sec.x))

		player.energy += 2500 - player.dock_count * 500
		report_energy(player)
		player.shields += 250 - player.dock_count * 50
		print("Shields at {0:4.1f}%.".format(
			player.shields / player.max_s * 100))
		player.missiles += 5 - player.dock_count
		print("Missile tubes loaded.")

		if player.damage == 0:
			print("No repairs needed.")
		elif player.damage <= 10:
			player.damage = 0
			print("Repairs complete.")
		else:
			player.damage -= 10
			print("Partial repairs performed.")
			
		player.dock_count += 1

def report_energy(ship):
	print("Energy reserves are at {0:4.1f}%.".format(
		ship.energy / ship.max_e * 100))

def reroute_energy(ship, energy):
	if energy > 0:
		if energy > ship.energy:
			print("We don't have that much energy, Captain!")
		elif ship.shields + energy > ship.max_s:
			print("That would overload the shields, Captain!")
		else:
			ship.energy -= energy
			ship.shields += energy
			print("Energy transferred to shields, Captain.")
	elif energy < 0:
		if energy > ship.shields:
			print("Our shields aren't that strong, Captain!")
		else:
			ship.shields -= -energy
			ship.energy += -energy
			print("Energy transferred from shields, Captain.")
	else:
		print("Zero units of energy rerouted, Captain!")

def repair_ship(ship):
	if ship.sector.enemy_count() > 0:
		print("Can't perform field repairs under fire, Captain!")
	elif ship.energy < 500:
		print("We don't have enough energy for field repairs!")
	elif ship.damage == 0:
		print("No repairs needed, Captain!")
	elif ship.damage <= 5:
		ship.energy -= ship.damage * 100
		ship.damage = 0
		print("Repairs complete, Captain.")
	else:
		ship.energy -= 500
		ship.damage -= 5
		print("Partial repairs performed, Captain.")

def score(galaxy):
	score = galaxy.ships[0].kills * 500
	for y in range(8):
		for x in range(8):
			if galaxy.sectors[y][x].scanned:
				score += 100
	return score

class Game(cmd.Cmd):
	intro = game_banner
	prompt = "> "
	
	def __init__(self):
		cmd.Cmd.__init__(self)
		self.galaxy = Galaxy()
		self.galaxy.reset()
		self.game_over = False

	def do_play(self, args):
		"""Start a new game at the given difficulty level."""
		self.galaxy.reset()
		self.game_over = False
		player = self.galaxy.ships[0]
		if args == "easy":
			player.energy = 8000
			player.shields = 800
			print("\nNew game started at easy difficulty.")
		elif args == "medium" or args == "":
			print("\nNew game started at medium difficulty.")
		elif args == "hard":
			player.energy = 3000
			player.shields = 300
			print("\nNew game started at hard difficulty.")
		else:
			print("Unknown difficulty level: " + args)
			print("Should be one of easy, medium or hard.")
			print("\nNew game started at medium difficulty.")

	def do_chart(self, args):
		"""Show a galactic chart of the entire mission area."""
		print_galaxy(self.galaxy)

	def do_visual(self, args):
		"""Show a close-range view of the sector you are in."""
		print_sector(self.galaxy.ships[0].sector)
	
	def do_scan(self, args):
		"""Perform a long-range scan of surrounding sectors."""
		scan_area(self.galaxy.ships[0].sector)
		print_galaxy(self.galaxy)
	
	def do_report(self, args):
		"""Show a report on game progress and ship status."""
		print_report(self.galaxy)
	
	def do_jump(self, args):
		"""Jump to another galactic sector in the mission area."""
		try:
			course, distance = [float(i) for i in args.split()]
		except ValueError as e:
			print("Please give course and distance as numbers.")
			return False
		if 1 <= course <= 9:
			g = self.galaxy
			if jump_player(g, course, distance):
				odds = g.ships[0].sector.enemy_count()
				if odds > 0 and random.randint(1, odds) == 1:
					handle_enemy_fire(g.ships)
		else:
			print("Course can only go from 1 to 9.")
	
	def do_rocket(self, args):
		"""Rocket to another square of the sector you are in."""
		try:
			course, distance = [float(i) for i in args.split()]
		except ValueError as e:
			print("Please give course and distance as numbers.")
			return False
		if 1 <= course <= 9:
			player = self.galaxy.ships[0]
			if rocket_player(player, course, distance):
				handle_enemy_fire(self.galaxy.ships)
		else:
			print("Course can only go from 1 to 9.")
	
	def do_pulse(self, args):
		"""Fire Pulsar guns at all enemy ships in the sector."""
		try:
			energy = abs(float(args))
		except ValueError as e:
			print("Please give amount of energy as a number.")
			return False
		ships = self.galaxy.ships
		if ships[0].sector.enemy_count() < 1:
			print("No enemy ships in weapon range, Captain.")
		elif energy > ships[0].energy:
			print("We don't have enough energy, Captain.")
		else:
			fire_pulse(energy, ships)
			handle_enemy_fire(ships)
	
	def do_meteor(self, args):
		"""Fire a Meteor missile along the given course."""
		try:
			course = float(args)
		except ValueError as e:
			print("Please give missile course as a number.")
			return False
		ships = self.galaxy.ships
		if ships[0].sector.enemy_count() < 1:
			print("No enemy ships in weapon range, Captain.")
		elif ships[0].missiles < 1:
			print("We don't have any missiles left, Captain.")
		else:
			fire_meteor(course, ships)
			handle_enemy_fire(ships)
	
	def do_refuel(self, args):
		"""Deploy hydrogen collectors to replenish energy."""
		refuel_player(self.galaxy.ships[0])
	
	def do_dock(self, args):
		"""Dock with an outpost for repairs and supplies."""
		dock_player(self.galaxy.ships[0])
	
	def do_reroute(self, args):
		"""Reroute energy to shields (with +) and back (with -)."""
		try:
			energy = float(args)
		except ValueError as e:
			print("Please give amount of energy as a number.")
			return False
		reroute_energy(self.galaxy.ships[0], energy)
	
	def do_repair(self, args):
		"""Perform field repairs, at the expense of energy."""
		repair_ship(self.galaxy.ships[0])
	
	def do_score(self, args):
		"""Show the current score given the game state."""
		print("\nYour score at this time:", score(self.galaxy))
	
	def do_quit(self, args):
		"""Quit the game and return to the operating system."""
		print("\nThanks for playing! See you next time.")
		return True
	
	def default(self, line):
		if line == "EOF":
			print("\nThanks for playing! See you next time.")
			return True
		else:
			print("\nUnknown command. Type HELP for a list.")
	
	def postcmd(self, stop, line):
		outposts = self.galaxy.outposts_found()
		enemies = self.galaxy.enemies_active()
		if outposts == 5 and enemies == 0:
			if not self.game_over:
				print("\nMission complete, Captain!\n")
				print("Current score:", score(self.galaxy))
				self.game_over = True
			return stop
		elif self.galaxy.ships[0].damage >= 50:
			print_report(self.galaxy)
			print("\nWe've taken too much damage, Captain!")
			print("Aborting the mission...\n")
			print("Final score:", score(self.galaxy))
			return True
		elif line == "dock" or line == "refuel":
			player = self.galaxy.ships[0]
			if player.energy + player.shields < 100:
				print_report(self.galaxy)
				print("\nWe're out of energy, Captain!")
				print("Aborting the mission...\n")
				print("Final score:", score(self.galaxy))
				return True
		else:
			return stop
		
	def help_course(self):
		print("\nCourse is entered as a number from 1 to 9,")
		print("corresponding to the following directions:")
		print(" 4  3  2 ")
		print("  \ | /  ")
		print("5 -- -- 1")
		print("  / | \  ")
		print(" 6  7  8 ")
		print("You can add decimals for fine tuning.")
	
	def help_energy(self):
		print("\nMany actions in game require energy:")
		print("- long range jumps use energy equal to")
		print("  the distance squared times 100;")
		print("- rocketing within a sector uses energy")
		print("  equal to the distance times 10;")
		print("- Pulsar guns deal damage to the target")
		print("  equal to energy divided by distance.")
	
	def help_map(self):
		print("\nMap symbols used in this game:\n")
		print(" ? not scanned * has star     ! has outpost")
		print("-@- your ship -M- enemy ship -!- outpost   ")
		print(".*. star      .O. planet     .o. asteroid  ")
	
	def help_hints(self):
		print("\nSome hints to help you play well:")
		print("- outposts are always found orbiting a star;")
		print("- you can only dock with outposts five times,")
		print("  once for each, but it can be the same outpost;")
		print("- your ship can rocket past any obstacles;")
		print("- missiles sometimes miss, or hit the wrong thing")
		print("  even when aimed in the right direction;")
		print("- the more enemies in a sector, the easier")
		print("  you can surprise them and shoot first;")
		print("- you can ignore any enemies not blockading")
		print("  an outpost, but they'll add to your score;")
		print("- you score 100 points for each scanned sector")
		print("  and 500 points for each enemy ship destroyed.")

if __name__ == "__main__":
	import sys
	
	game = Game()

	if len(sys.argv) < 2:
		pass
	elif sys.argv[1] == "-h" or sys.argv[1] == "--help":
		print("Usage:\n\torion.py [-h|-v] [easy|medium|hard]")
		sys.exit()
	elif sys.argv[1] == "-v" or sys.argv[1] == "--version":
		print("Space Cruiser Orion v2019-05-02 by No Time To Play")
		sys.exit()
	elif sys.argv[1] == "easy":
		player = game.galaxy.ships[0]
		player.energy = 8000
		player.shields = 800
	elif sys.argv[1] == "hard":
		player = game.galaxy.ships[0]
		player.energy = 3000
		player.shields = 300
	elif sys.argv[1] != "medium":
		print("Unknown command-line argument:", sys.argv[1])
		print("Usage:\n\torion.py [-h|-v] [easy|medium|hard]")
		sys.exit()
	
	game.cmdloop()