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)))
return results
def solve_tsp(self, waypoints):
# todo actually try to solve it
return waypoints
def get_jumpgate(self, system):
gates = self.store.all_members(system, Jumpgate)

View File

@ -1,10 +1,13 @@
from nullptr.store import Store
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 time import sleep
from threading import Thread
class CentralCommandError(Exception):
pass
class CentralCommand:
def __init__(self, store, api):
self.missions = {}
@ -86,6 +89,21 @@ class CentralCommand:
m = self.missions[s]
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):
mtype = s.mission
m = create_mission(mtype, s, self.store, self.api)

View File

@ -41,7 +41,7 @@ class CommandLine:
print(f'command not found; {c}')
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):
pass

View File

@ -82,15 +82,6 @@ class Commander(CommandLine):
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'
if 'traject' in self.ship.mission_state:
del self.ship.mission_state['traject']
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)
@ -98,7 +89,7 @@ class Commander(CommandLine):
def do_mission(self, arg=''):
if not self.has_ship(): return
if arg:
self.set_mission(arg)
self.centcom.init_mission(self.ship, arg)
self.print_mission()
def do_mreset(self):
@ -123,7 +114,7 @@ class Commander(CommandLine):
raise CommandError('no delivery')
resource = delivery['trade_symbol']
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, 'resource', resource)
self.centcom.set_mission_param(self.ship, 'dest', destination)
@ -146,26 +137,41 @@ class Commander(CommandLine):
return
_, m, _, _ = m[0]
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, 'resource', resource)
self.centcom.set_mission_param(self.ship, 'dest', destination)
self.centcom.set_mission_param(self.ship, 'contract', contract.symbol)
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):
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.print_mission()
def do_register(self, faction):
self.api.register(faction.upper())
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)
pprint(self.api.agent)
def do_universe(self, page=1):
self.atlas_builder.run(page)
@ -218,13 +224,16 @@ class Commander(CommandLine):
r = self.api.jumps(waypoint)
pprint(r)
def do_query(self):
def do_query(self, resource):
if not self.has_ship(): return
location = self.ship.location()
resource = input('what resource?').upper()
resource = resource.upper()
print('Found markets:')
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):
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.haul import HaulMission
from nullptr.missions.travel import TravelMission
from nullptr.missions.probe import ProbeMission
def create_mission(mtype, ship, store, api):
def get_mission_class( mtype):
types = {
'survey': SurveyMission,
'mine': MiningMission,
'haul': HaulMission,
'travel': TravelMission
'travel': TravelMission,
'probe': ProbeMission
}
if mtype not in types:
logging.warning(f'invalid mission type {mtype}')
return
m = types[mtype](ship, store, api)
raise ValueError(f'invalid mission type {mtype}')
return types[mtype]
def create_mission(mtype, ship, store, api):
typ = get_mission_class(mtype)
m = typ(ship, store, api)
return m

View File

@ -25,6 +25,8 @@ class MissionParam:
return str(val)
elif self.cls == int:
return int(val)
elif self.cls == list:
return [i.strip() for i in val.split(',')]
elif issubclass(self.cls, Base):
data = store.get(self.cls, val)
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))