Update analyzer.py, central_command.py and five other files

This commit is contained in:
Richard Bronkhorst 2023-06-25 17:35:06 +02:00
parent 5fbce54285
commit 4d51ad53c0
7 changed files with 99 additions and 30 deletions

View File

@ -59,7 +59,9 @@ class Analyzer:
results.append((typ,m,d,len(p))) results.append((typ,m,d,len(p)))
return results return results
def solve_tsp(self, waypoints):
# todo actually try to solve it
return waypoints
def get_jumpgate(self, system): def get_jumpgate(self, system):
gates = self.store.all_members(system, Jumpgate) gates = self.store.all_members(system, Jumpgate)

View File

@ -1,10 +1,13 @@
from nullptr.store import Store from nullptr.store import Store
from nullptr.models.ship import Ship from nullptr.models.ship import Ship
from nullptr.missions import create_mission from nullptr.missions import create_mission, get_mission_class
from random import choice from random import choice
from time import sleep from time import sleep
from threading import Thread from threading import Thread
class CentralCommandError(Exception):
pass
class CentralCommand: class CentralCommand:
def __init__(self, store, api): def __init__(self, store, api):
self.missions = {} self.missions = {}
@ -86,6 +89,21 @@ class CentralCommand:
m = self.missions[s] m = self.missions[s]
m.next_step = max(s.cooldown, s.arrival) m.next_step = max(s.cooldown, s.arrival)
def init_mission(self, s, mtyp):
if mtyp == 'none':
s.mission_state = {}
s.mission_status = None
s.mission = None
return
try:
mclass = get_mission_class(mtyp)
except ValueError:
raise CentralCommandError('no such mission')
s.mission = mtyp
s.mission_status = 'init'
s.mission_state = {k: v.default for k,v in mclass.params().items()}
self.start_mission(s)
def start_mission(self, s): def start_mission(self, s):
mtype = s.mission mtype = s.mission
m = create_mission(mtype, s, self.store, self.api) m = create_mission(mtype, s, self.store, self.api)

View File

@ -41,7 +41,7 @@ class CommandLine:
print(f'command not found; {c}') print(f'command not found; {c}')
def handle_error(self, cmd, args, e): def handle_error(self, cmd, args, e):
logging.error(e, exc_info=type(e).__name__ not in ['ApiError','CommandError']) logging.error(e, exc_info=type(e).__name__ not in ['ApiError','CommandError', 'CentralCommandError'])
def handle_empty(self): def handle_empty(self):
pass pass

View File

@ -82,15 +82,6 @@ class Commander(CommandLine):
def do_auto(self): def do_auto(self):
self.centcom.run_interactive() self.centcom.run_interactive()
def set_mission(self, arg=''):
if arg == 'none':
arg = None
self.ship.mission = arg
self.ship.mission_status = 'init'
if 'traject' in self.ship.mission_state:
del self.ship.mission_state['traject']
self.centcom.start_mission(self.ship)
def print_mission(self): def print_mission(self):
print(f'mission: {self.ship.mission} ({self.ship.mission_status})') print(f'mission: {self.ship.mission} ({self.ship.mission_status})')
pprint(self.ship.mission_state) pprint(self.ship.mission_state)
@ -98,7 +89,7 @@ class Commander(CommandLine):
def do_mission(self, arg=''): def do_mission(self, arg=''):
if not self.has_ship(): return if not self.has_ship(): return
if arg: if arg:
self.set_mission(arg) self.centcom.init_mission(self.ship, arg)
self.print_mission() self.print_mission()
def do_mreset(self): def do_mreset(self):
@ -123,7 +114,7 @@ class Commander(CommandLine):
raise CommandError('no delivery') raise CommandError('no delivery')
resource = delivery['trade_symbol'] resource = delivery['trade_symbol']
destination = delivery['destination'] destination = delivery['destination']
self.set_mission('mine') self.centcom.init_mission(self.ship, 'mine')
self.centcom.set_mission_param(self.ship, 'site', site) 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, 'resource', resource)
self.centcom.set_mission_param(self.ship, 'dest', destination) self.centcom.set_mission_param(self.ship, 'dest', destination)
@ -146,26 +137,41 @@ class Commander(CommandLine):
return return
_, m, _, _ = m[0] _, m, _, _ = m[0]
site = self.store.get(Waypoint, m.symbol) site = self.store.get(Waypoint, m.symbol)
self.set_mission('haul') self.centcom.init_mission(self.ship, 'haul')
self.centcom.set_mission_param(self.ship, 'site', site.symbol) self.centcom.set_mission_param(self.ship, 'site', site.symbol)
self.centcom.set_mission_param(self.ship, 'resource', resource) self.centcom.set_mission_param(self.ship, 'resource', resource)
self.centcom.set_mission_param(self.ship, 'dest', destination) self.centcom.set_mission_param(self.ship, 'dest', destination)
self.centcom.set_mission_param(self.ship, 'contract', contract.symbol) self.centcom.set_mission_param(self.ship, 'contract', contract.symbol)
self.print_mission() self.print_mission()
def do_cprobe(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_markets(resource, 'buy,exchange', destination)
if len(m) is None:
print('no market found')
return
markets = [ mkt[1] for mkt in m]
markets = self.analyzer.solve_tsp(markets)
hops = ','.join([m.symbol for m in markets])
self.centcom.init_mission(self.ship, 'probe')
self.centcom.set_mission_param(self.ship, 'hops', hops)
self.print_mission()
def do_travel(self, dest): def do_travel(self, dest):
dest = self.resolve('Waypoint', dest) dest = self.resolve('Waypoint', dest)
self.set_mission('travel') self.centcom.init_mission(self.ship, 'travel')
self.centcom.set_mission_param(self.ship, 'dest', dest.symbol) self.centcom.set_mission_param(self.ship, 'dest', dest.symbol)
self.print_mission() self.print_mission()
def do_register(self, faction): def do_register(self, faction):
self.api.register(faction.upper()) self.api.register(faction.upper())
site = self.ship.location_str pprint(self.api.agent)
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)
def do_universe(self, page=1): def do_universe(self, page=1):
self.atlas_builder.run(page) self.atlas_builder.run(page)
@ -218,13 +224,16 @@ class Commander(CommandLine):
r = self.api.jumps(waypoint) r = self.api.jumps(waypoint)
pprint(r) pprint(r)
def do_query(self): def do_query(self, resource):
if not self.has_ship(): return if not self.has_ship(): return
location = self.ship.location() location = self.ship.location()
resource = input('what resource?').upper() resource = resource.upper()
print('Found markets:') print('Found markets:')
for typ, m, d, plen in self.analyzer.find_closest_markets(resource, 'buy,exchange',location): for typ, m, d, plen in self.analyzer.find_closest_markets(resource, 'buy,exchange',location):
print(m, typ[0], f'{plen-1} hops') price = '?'
if resource in m.prices:
price = m.prices[resource]['buy']
print(m, typ[0], f'{plen-1:3} hops {price}')
def do_path(self): def do_path(self):
orig = self.ask_obj(System, 'from: ') orig = self.ask_obj(System, 'from: ')

View File

@ -2,17 +2,22 @@ from nullptr.missions.survey import SurveyMission
from nullptr.missions.mine import MiningMission from nullptr.missions.mine import MiningMission
from nullptr.missions.haul import HaulMission from nullptr.missions.haul import HaulMission
from nullptr.missions.travel import TravelMission from nullptr.missions.travel import TravelMission
from nullptr.missions.probe import ProbeMission
def get_mission_class( mtype):
def create_mission(mtype, ship, store, api):
types = { types = {
'survey': SurveyMission, 'survey': SurveyMission,
'mine': MiningMission, 'mine': MiningMission,
'haul': HaulMission, 'haul': HaulMission,
'travel': TravelMission 'travel': TravelMission,
'probe': ProbeMission
} }
if mtype not in types: if mtype not in types:
logging.warning(f'invalid mission type {mtype}') raise ValueError(f'invalid mission type {mtype}')
return return types[mtype]
m = types[mtype](ship, store, api)
def create_mission(mtype, ship, store, api):
typ = get_mission_class(mtype)
m = typ(ship, store, api)
return m return m

View File

@ -25,6 +25,8 @@ class MissionParam:
return str(val) return str(val)
elif self.cls == int: elif self.cls == int:
return int(val) return int(val)
elif self.cls == list:
return [i.strip() for i in val.split(',')]
elif issubclass(self.cls, Base): elif issubclass(self.cls, Base):
data = store.get(self.cls, val) data = store.get(self.cls, val)
if data is None: if data is None:

33
nullptr/missions/probe.py Normal file
View File

@ -0,0 +1,33 @@
from nullptr.missions.base import BaseMission, MissionParam
from nullptr.models.waypoint import Waypoint
class ProbeMission(BaseMission):
def start_state(self):
return 'next-hop'
@classmethod
def params(cls):
return {
'hops': MissionParam(list, True),
'next-hop': MissionParam(int, True, 0)
}
def steps(self):
return {
'next-hop': (self.step_next_hop, 'travel-to'),
**self.travel_steps('to', 'site', 'market'),
'market': (self.step_market, 'next-hop'),
}
def step_market(self):
loc = self.ship.location()
self.api.marketplace(loc)
def step_next_hop(self):
hops = self.st('hops')
next_hop = self.st('next-hop')
hop = hops[next_hop]
self.sts('site', hop)
self.sts('next-hop', (next_hop+1) % len(hops))