2023-06-11 18:51:03 +00:00
|
|
|
from nullptr.command_line import CommandLine
|
|
|
|
from nullptr.store import Store
|
2023-06-13 07:27:13 +00:00
|
|
|
from nullptr.analyzer import Analyzer
|
2023-06-11 18:51:03 +00:00
|
|
|
import argparse
|
|
|
|
from nullptr.models.agent import Agent
|
|
|
|
from nullptr.models.system import System
|
|
|
|
from nullptr.models.waypoint import Waypoint
|
2023-06-12 12:32:58 +00:00
|
|
|
from nullptr.models.marketplace import Marketplace
|
2023-06-12 12:41:27 +00:00
|
|
|
from nullptr.models.jumpgate import Jumpgate
|
2023-06-11 18:51:03 +00:00
|
|
|
from nullptr.api import Api
|
|
|
|
from .util import *
|
2023-06-12 12:41:27 +00:00
|
|
|
from time import sleep, time
|
2023-06-11 18:51:03 +00:00
|
|
|
from threading import Thread
|
2023-06-12 09:03:54 +00:00
|
|
|
from nullptr.atlas_builder import AtlasBuilder
|
2023-06-18 17:15:51 +00:00
|
|
|
from nullptr.central_command import CentralCommand
|
2023-06-16 12:41:11 +00:00
|
|
|
class CommandError(Exception):
|
|
|
|
pass
|
|
|
|
|
2023-06-11 18:51:03 +00:00
|
|
|
class Commander(CommandLine):
|
2023-06-15 19:10:33 +00:00
|
|
|
def __init__(self, store_dir='data'):
|
2023-06-11 18:51:03 +00:00
|
|
|
self.store_dir = store_dir
|
|
|
|
self.store = Store(store_dir)
|
2023-06-12 21:13:40 +00:00
|
|
|
self.store.load()
|
2023-06-15 19:10:33 +00:00
|
|
|
self.agent = self.select_agent()
|
2023-06-11 18:51:03 +00:00
|
|
|
self.api = Api(self.store, self.agent)
|
2023-06-12 09:03:54 +00:00
|
|
|
self.atlas_builder = AtlasBuilder(self.store, self.api)
|
2023-06-18 17:15:51 +00:00
|
|
|
self.centcom = CentralCommand(self.store, self.api)
|
2023-06-13 07:27:13 +00:00
|
|
|
self.analyzer = Analyzer(self.store)
|
2023-06-15 20:37:33 +00:00
|
|
|
self.ship = None
|
2023-06-12 21:13:40 +00:00
|
|
|
|
2023-06-11 18:51:03 +00:00
|
|
|
self.stop_auto= False
|
|
|
|
super().__init__()
|
|
|
|
|
2023-06-15 20:37:33 +00:00
|
|
|
def prompt(self):
|
|
|
|
if self.ship:
|
|
|
|
return f'{self.ship.symbol}> '
|
|
|
|
else:
|
|
|
|
return '> '
|
|
|
|
|
|
|
|
def has_ship(self):
|
|
|
|
if self.ship is not None:
|
|
|
|
return True
|
|
|
|
else:
|
|
|
|
print('set a ship')
|
|
|
|
|
2023-06-13 07:27:13 +00:00
|
|
|
def ask_obj(self, typ, prompt):
|
|
|
|
obj = None
|
|
|
|
while obj is None:
|
2023-06-18 17:15:51 +00:00
|
|
|
symbol = input(prompt).strip()
|
2023-06-13 07:27:13 +00:00
|
|
|
obj = self.store.get(typ, symbol.upper())
|
|
|
|
if obj is None:
|
|
|
|
print('not found')
|
|
|
|
return obj
|
|
|
|
|
2023-06-15 19:10:33 +00:00
|
|
|
def select_agent(self):
|
|
|
|
agents = self.store.all(Agent)
|
|
|
|
agent = next(agents, None)
|
|
|
|
if agent is None:
|
|
|
|
symbol = input('agent name: ')
|
2023-06-16 12:41:11 +00:00
|
|
|
agent = self.store.get(Agent, symbol, create=True)
|
2023-06-15 19:10:33 +00:00
|
|
|
return agent
|
2023-06-16 12:41:11 +00:00
|
|
|
|
|
|
|
def resolve(self, typ, arg):
|
|
|
|
arg = arg.upper()
|
|
|
|
matches = [c for c in self.store.all(typ) if c.symbol.startswith(arg)]
|
|
|
|
if len(matches) == 1:
|
|
|
|
return matches[0]
|
|
|
|
elif len(matches) > 1:
|
|
|
|
raise CommandError('multiple matches')
|
|
|
|
else:
|
|
|
|
raise CommandError('not found')
|
2023-06-11 18:51:03 +00:00
|
|
|
|
|
|
|
def after_cmd(self):
|
|
|
|
self.store.flush()
|
|
|
|
|
2023-06-16 21:05:47 +00:00
|
|
|
def do_info(self, arg=''):
|
|
|
|
if arg.startswith('r'):
|
|
|
|
self.api.info()
|
|
|
|
|
|
|
|
pprint(self.agent, 100)
|
2023-06-18 17:15:51 +00:00
|
|
|
|
|
|
|
def do_auto(self):
|
|
|
|
self.centcom.run_interactive()
|
|
|
|
|
|
|
|
def set_mission(self, arg=''):
|
|
|
|
if arg == 'none':
|
|
|
|
arg = None
|
|
|
|
self.ship.mission = arg
|
|
|
|
self.ship.mission_status = 'init'
|
2023-06-22 06:46:47 +00:00
|
|
|
self.centcom.set_mission_param(self.ship, 'traject', [])
|
2023-06-18 17:15:51 +00:00
|
|
|
self.centcom.start_mission(self.ship)
|
|
|
|
|
|
|
|
def print_mission(self):
|
|
|
|
print(f'mission: {self.ship.mission} ({self.ship.mission_status})')
|
|
|
|
pprint(self.ship.mission_state)
|
|
|
|
|
|
|
|
def do_mission(self, arg=''):
|
|
|
|
if not self.has_ship(): return
|
|
|
|
if arg:
|
|
|
|
self.set_mission(arg)
|
|
|
|
self.print_mission()
|
|
|
|
|
2023-06-20 21:14:17 +00:00
|
|
|
def do_mreset(self):
|
2023-06-20 21:12:57 +00:00
|
|
|
if not self.has_ship(): return
|
|
|
|
self.ship.mission_state = {}
|
|
|
|
|
2023-06-20 19:46:05 +00:00
|
|
|
def do_mset(self, nm, val):
|
2023-06-18 17:15:51 +00:00
|
|
|
if not self.has_ship(): return
|
|
|
|
self.centcom.set_mission_param(self.ship, nm, val)
|
|
|
|
|
|
|
|
def active_contract(self):
|
|
|
|
for c in self.store.all('Contract'):
|
|
|
|
if c.accepted and not c.fulfilled: return c
|
|
|
|
raise CommandError('no active contract')
|
|
|
|
|
|
|
|
def do_cmine(self):
|
|
|
|
if not self.has_ship(): return
|
|
|
|
site = self.ship.location_str
|
|
|
|
contract = self.active_contract()
|
|
|
|
delivery = contract.unfinished_delivery()
|
|
|
|
if delivery is None:
|
|
|
|
raise CommandError('no delivery')
|
|
|
|
resource = delivery['trade_symbol']
|
|
|
|
destination = delivery['destination']
|
|
|
|
self.set_mission('mine')
|
|
|
|
self.centcom.set_mission_param(self.ship, 'site', site)
|
|
|
|
self.centcom.set_mission_param(self.ship, 'resource', resource)
|
|
|
|
self.centcom.set_mission_param(self.ship, 'destination', destination)
|
|
|
|
self.centcom.set_mission_param(self.ship, 'contract', contract.symbol)
|
|
|
|
self.print_mission()
|
2023-06-20 19:46:05 +00:00
|
|
|
|
|
|
|
def do_chaul(self):
|
|
|
|
if not self.has_ship(): return
|
|
|
|
contract = self.active_contract()
|
|
|
|
delivery = contract.unfinished_delivery()
|
|
|
|
if delivery is None:
|
|
|
|
raise CommandError('no delivery')
|
|
|
|
resource = delivery['trade_symbol']
|
|
|
|
destination = delivery['destination']
|
|
|
|
m = self.analyzer.find_closest_market(resource, 'buy', destination)
|
2023-06-21 07:32:31 +00:00
|
|
|
if m is None:
|
|
|
|
m = self.analyzer.find_closest_market(resource, 'exchange', destination)
|
|
|
|
if m is None:
|
|
|
|
print('no market found')
|
|
|
|
return
|
2023-06-20 19:46:05 +00:00
|
|
|
site = self.store.get(Waypoint, m.symbol)
|
2023-06-21 07:37:14 +00:00
|
|
|
self.set_mission('haul')
|
2023-06-21 07:32:31 +00:00
|
|
|
self.centcom.set_mission_param(self.ship, 'site', site.symbol)
|
2023-06-20 19:46:05 +00:00
|
|
|
self.centcom.set_mission_param(self.ship, 'resource', resource)
|
|
|
|
self.centcom.set_mission_param(self.ship, 'destination', destination)
|
|
|
|
self.centcom.set_mission_param(self.ship, 'contract', contract.symbol)
|
|
|
|
self.print_mission()
|
2023-06-11 18:51:03 +00:00
|
|
|
|
|
|
|
def do_register(self, faction):
|
|
|
|
self.api.register(faction.upper())
|
2023-06-18 17:15:51 +00:00
|
|
|
site = self.ship.location_str
|
|
|
|
contract = self.active_contract()
|
|
|
|
self.do_mission('mine')
|
|
|
|
self.centcom.set_mission_param(self.ship, 'site', site)
|
|
|
|
self.centcom.set_mission_param(self.ship, 'contract', contract)
|
|
|
|
|
2023-06-12 08:51:01 +00:00
|
|
|
def do_universe(self, page=1):
|
2023-06-12 09:03:54 +00:00
|
|
|
self.atlas_builder.run(page)
|
2023-06-11 18:51:03 +00:00
|
|
|
|
|
|
|
def do_systems(self, page=1):
|
|
|
|
r = self.api.list_systems(int(page))
|
|
|
|
pprint(self.api.last_meta)
|
2023-06-15 20:37:33 +00:00
|
|
|
|
2023-06-18 05:23:01 +00:00
|
|
|
def do_stats(self):
|
|
|
|
total = 0
|
|
|
|
for t in self.store.data:
|
|
|
|
num = len(self.store.data[t])
|
|
|
|
nam = t.__name__
|
|
|
|
total += num
|
|
|
|
print(f'{num:5d} {nam}')
|
|
|
|
print(f'{total:5d} total')
|
|
|
|
|
2023-06-15 20:37:33 +00:00
|
|
|
def do_waypoints(self, system_str=''):
|
|
|
|
if system_str == '':
|
|
|
|
if not self.has_ship(): return
|
|
|
|
system = self.ship.location().system()
|
|
|
|
else:
|
|
|
|
system = self.store.get(System, system_str)
|
|
|
|
r = self.store.all_members(system, 'Waypoint')
|
|
|
|
for w in r:
|
2023-06-16 11:03:19 +00:00
|
|
|
traits = []
|
|
|
|
if 'MARKETPLACE' in w.traits:
|
|
|
|
traits.append('MARKET')
|
|
|
|
if 'SHIPYARD' in w.traits:
|
|
|
|
traits.append('SHIPYARD')
|
|
|
|
if w.type == 'JUMP_GATE':
|
|
|
|
traits.append('JUMP')
|
2023-06-17 18:18:14 +00:00
|
|
|
if w.type == 'ASTEROID_FIELD':
|
|
|
|
traits.append('ASTROIDS')
|
2023-06-16 11:03:19 +00:00
|
|
|
print(w.symbol.split('-')[2], ', '.join(traits))
|
2023-06-17 18:23:24 +00:00
|
|
|
|
|
|
|
def do_wp(self, s=''):
|
|
|
|
self.do_waypoints(s)
|
|
|
|
|
2023-06-11 18:51:03 +00:00
|
|
|
def do_marketplace(self, waypoint_str):
|
|
|
|
waypoint = self.store.get(Waypoint, waypoint_str.upper())
|
|
|
|
r = self.api.marketplace(waypoint)
|
2023-06-12 08:51:01 +00:00
|
|
|
|
2023-06-17 12:59:52 +00:00
|
|
|
def do_jumps(self, waypoint_str=None):
|
|
|
|
if waypoint_str is None:
|
|
|
|
if not self.has_ship(): return
|
|
|
|
waypoint = self.ship.location()
|
|
|
|
else:
|
|
|
|
waypoint = self.store.get(Waypoint, waypoint_str.upper())
|
2023-06-12 08:51:01 +00:00
|
|
|
r = self.api.jumps(waypoint)
|
|
|
|
pprint(r)
|
2023-06-12 12:32:58 +00:00
|
|
|
|
2023-06-13 07:27:13 +00:00
|
|
|
def do_query(self):
|
2023-06-14 14:55:45 +00:00
|
|
|
location = self.ask_obj(System, 'Where are you? ')
|
2023-06-13 07:27:13 +00:00
|
|
|
resource = input('what resource?').upper()
|
2023-06-22 05:34:45 +00:00
|
|
|
sellbuy = self.ask_multichoice(['sell','buy','exchange'], 'do you want to sell or buy?')
|
2023-06-13 07:27:13 +00:00
|
|
|
print('Found markets:')
|
2023-06-14 14:55:45 +00:00
|
|
|
for m in self.analyzer.find_markets(resource, sellbuy):
|
|
|
|
system = self.store.get(System, m.system())
|
|
|
|
p = self.analyzer.find_path(location, system)
|
|
|
|
if p is None: continue
|
2023-06-14 19:20:47 +00:00
|
|
|
print(m, f'{len(p)-1} hops')
|
2023-06-14 14:55:45 +00:00
|
|
|
|
2023-06-13 14:33:22 +00:00
|
|
|
def do_path(self):
|
|
|
|
orig = self.ask_obj(System, 'from: ')
|
|
|
|
dest = self.ask_obj(System, 'to: ')
|
2023-06-14 13:37:48 +00:00
|
|
|
# orig = self.store.get(System, 'X1-KS52')
|
|
|
|
# dest = self.store.get(System, 'X1-DA90')
|
2023-06-13 14:33:22 +00:00
|
|
|
path = self.analyzer.find_path(orig, dest)
|
|
|
|
pprint(path)
|
2023-06-15 19:10:33 +00:00
|
|
|
|
|
|
|
def do_ships(self, arg=''):
|
|
|
|
if arg.startswith('r'):
|
|
|
|
r = self.api.list_ships()
|
|
|
|
else:
|
|
|
|
r = list(self.store.all('Ship'))
|
|
|
|
pprint(r)
|
|
|
|
|
2023-06-16 11:03:19 +00:00
|
|
|
def do_contracts(self, arg=''):
|
|
|
|
if arg.startswith('r'):
|
|
|
|
r = self.api.list_contracts()
|
|
|
|
else:
|
|
|
|
r = list(self.store.all('Contract'))
|
|
|
|
pprint(r)
|
2023-06-18 19:56:49 +00:00
|
|
|
|
|
|
|
def do_deliver(self):
|
|
|
|
if not self.has_ship(): return
|
|
|
|
site = self.ship.location_str
|
|
|
|
contract = self.active_contract()
|
|
|
|
delivery = contract.unfinished_delivery()
|
|
|
|
if delivery is None:
|
|
|
|
raise CommandError('no delivery')
|
|
|
|
resource = delivery['trade_symbol']
|
|
|
|
self.api.deliver(self.ship, resource, contract)
|
|
|
|
pprint(contract)
|
2023-06-19 08:36:30 +00:00
|
|
|
|
|
|
|
def do_fulfill(self):
|
|
|
|
contract = self.active_contract()
|
|
|
|
self.api.fulfill(contract)
|
2023-06-16 11:03:19 +00:00
|
|
|
|
2023-06-15 20:37:33 +00:00
|
|
|
def do_ship(self, arg=''):
|
|
|
|
if arg != '':
|
|
|
|
symbol = f'{self.agent.symbol}-{arg}'
|
|
|
|
ship = self.store.get('Ship', symbol)
|
|
|
|
if ship is None:
|
|
|
|
print('not found')
|
|
|
|
return
|
|
|
|
else:
|
|
|
|
self.ship = ship
|
2023-06-16 11:03:19 +00:00
|
|
|
pprint(self.ship)
|
2023-06-15 20:37:33 +00:00
|
|
|
|
2023-06-15 19:10:33 +00:00
|
|
|
def do_pp(self):
|
|
|
|
pprint(self.api.last_result)
|
2023-06-15 20:37:33 +00:00
|
|
|
|
|
|
|
def do_go(self, arg):
|
|
|
|
if not self.has_ship(): return
|
|
|
|
system = self.ship.location().system()
|
|
|
|
symbol = f'{system}-{arg}'
|
2023-06-16 12:41:11 +00:00
|
|
|
dest = self.resolve('Waypoint', symbol)
|
2023-06-15 20:37:33 +00:00
|
|
|
self.api.navigate(self.ship, dest)
|
|
|
|
pprint(self.ship)
|
|
|
|
|
|
|
|
def do_dock(self):
|
|
|
|
if not self.has_ship(): return
|
|
|
|
self.api.dock(self.ship)
|
|
|
|
pprint(self.ship)
|
|
|
|
|
|
|
|
def do_orbit(self):
|
|
|
|
if not self.has_ship(): return
|
|
|
|
self.api.orbit(self.ship)
|
|
|
|
pprint(self.ship)
|
|
|
|
|
2023-06-16 11:03:19 +00:00
|
|
|
def do_negotiate(self):
|
|
|
|
if not self.has_ship(): return
|
|
|
|
r = self.api.negotiate(self.ship)
|
|
|
|
pprint(r)
|
|
|
|
|
2023-06-16 12:41:11 +00:00
|
|
|
def do_refuel(self):
|
|
|
|
if not self.has_ship(): return
|
|
|
|
r = self.api.refuel(self.ship)
|
|
|
|
pprint(self.ship)
|
|
|
|
|
|
|
|
def do_accept(self, c):
|
|
|
|
contract = self.resolve('Contract', c)
|
|
|
|
r = self.api.accept_contract(contract)
|
|
|
|
pprint(r)
|
|
|
|
|
|
|
|
def do_market(self, arg=''):
|
|
|
|
if arg == '':
|
|
|
|
if not self.has_ship(): return
|
|
|
|
waypoint = self.ship.location()
|
|
|
|
else:
|
|
|
|
waypoint = self.resolve('Waypoint', arg)
|
|
|
|
r = self.api.marketplace(waypoint)
|
|
|
|
pprint(r)
|
2023-06-16 21:05:47 +00:00
|
|
|
|
|
|
|
def do_cargo(self):
|
|
|
|
if not self.has_ship(): return
|
|
|
|
for c, units in self.ship.cargo.items():
|
|
|
|
print(f'{units:4d} {c}')
|
|
|
|
|
|
|
|
def do_buy(self, resource, amt=None):
|
|
|
|
if not self.has_ship(): return
|
|
|
|
if amt is None:
|
|
|
|
amt = self.ship.cargo_capacity - self.ship.cargo_units
|
|
|
|
self.api.buy(self.ship, resource.upper(), amt)
|
|
|
|
self.do_cargo()
|
|
|
|
|
|
|
|
def do_sell(self, resource):
|
|
|
|
if not self.has_ship(): return
|
|
|
|
self.api.sell(self.ship, resource.upper())
|
|
|
|
self.do_cargo()
|
|
|
|
|
|
|
|
def do_dump(self, resource):
|
|
|
|
if not self.has_ship(): return
|
|
|
|
self.api.jettison(self.ship, resource.upper())
|
|
|
|
self.do_cargo()
|
2023-06-17 12:59:52 +00:00
|
|
|
|
|
|
|
def do_shipyard(self):
|
|
|
|
if not self.has_ship(): return
|
|
|
|
location = self.ship.location()
|
2023-06-21 07:32:31 +00:00
|
|
|
data = self.api.shipyard(location)
|
|
|
|
for s in must_get(data, 'ships'):
|
|
|
|
print(s['type'], s['purchasePrice'])
|
2023-06-17 12:59:52 +00:00
|
|
|
|
|
|
|
def do_jump(self, system_str):
|
|
|
|
if not self.has_ship(): return
|
2023-06-17 18:23:24 +00:00
|
|
|
if '-' not in system_str:
|
|
|
|
sector = self.ship.location_str.split('-')[0]
|
|
|
|
system_str = f'{sector}-{system_str}'
|
2023-06-17 12:59:52 +00:00
|
|
|
system = self.resolve('System', system_str)
|
|
|
|
self.api.jump(self.ship, system)
|
|
|
|
pprint(self.ship)
|
2023-06-16 21:05:47 +00:00
|
|
|
|
2023-06-17 12:59:52 +00:00
|
|
|
def do_purchase(self, ship_type):
|
|
|
|
if not self.has_ship(): return
|
|
|
|
location = self.ship.location()
|
|
|
|
ship_type = ship_type.upper()
|
|
|
|
if not ship_type.startswith('SHIP'):
|
|
|
|
ship_type = 'SHIP_' + ship_type
|
|
|
|
s = self.api.purchase(ship_type, location)
|
|
|
|
pprint(s)
|
2023-06-17 18:18:14 +00:00
|
|
|
|
|
|
|
def do_survey(self):
|
|
|
|
if not self.has_ship(): return
|
|
|
|
r = self.api.survey(self.ship)
|
2023-06-17 21:07:53 +00:00
|
|
|
pprint(r)
|
|
|
|
|
2023-06-18 05:06:32 +00:00
|
|
|
def do_surveys(self):
|
|
|
|
pprint(list(self.store.all('Survey')))
|
|
|
|
|
2023-06-17 21:07:53 +00:00
|
|
|
def do_extract(self, survey_str=''):
|
|
|
|
if not self.has_ship(): return
|
|
|
|
survey = None
|
|
|
|
if survey_str != '':
|
|
|
|
survey = self.resolve('Survey', survey_str)
|
|
|
|
result = self.api.extract(self.ship, survey)
|
|
|
|
|
|
|
|
symbol = mg(result,'extraction.yield.symbol')
|
|
|
|
units = mg(result,'extraction.yield.units')
|
|
|
|
print(units, symbol)
|