Update analyzer.py, api.py and four other files

This commit is contained in:
Richard Bronkhorst 2023-06-20 21:46:05 +02:00
parent 35ea9e2e04
commit 707f142e7a
6 changed files with 180 additions and 62 deletions

View File

@ -33,11 +33,23 @@ class Analyzer:
if resource in resources: if resource in resources:
yield m yield m
def find_closest_market(self, resource, sellbuy, location):
market = None
distance = None
for m in self.find_markets(resource, sellbuy):
system = self.store.get(System, m.system())
p = self.find_path(location, system)
if p is None: continue
if distance is None or len(p) < distance:
market = m
distance = len(p)
return market
def get_jumpgate(self, system): def get_jumpgate(self, system):
gates = self.store.all_members(system, Jumpgate) gates = self.store.all_members(system, Jumpgate)
return next(gates, None) return next(gates, None)
def find_path(self, orig, to, depth=100, seen=None): def find_path(self, orig, to, depth=100, seen=None):
if depth < 1: return None if depth < 1: return None
if seen is None: if seen is None:

View File

@ -221,8 +221,10 @@ class Api:
return ship return ship
def jump(self, ship, system): def jump(self, ship, system):
if type(system) == System:
system = system.symbol
data = { data = {
"systemSymbol": system.symbol "systemSymbol": system
} }
data = self.request('post', f'my/ships/{ship}/jump', data) data = self.request('post', f'my/ships/{ship}/jump', data)
if 'nav' in data: if 'nav' in data:

View File

@ -99,9 +99,8 @@ class Commander(CommandLine):
self.set_mission(arg) self.set_mission(arg)
self.print_mission() self.print_mission()
def do_mset(self, args): def do_mset(self, nm, val):
if not self.has_ship(): return if not self.has_ship(): return
nm, val = args.split(' ')
self.centcom.set_mission_param(self.ship, nm, val) self.centcom.set_mission_param(self.ship, nm, val)
def active_contract(self): def active_contract(self):
@ -125,6 +124,23 @@ class Commander(CommandLine):
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_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)
site = self.store.get(Waypoint, m.symbol)
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()
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 site = self.ship.location_str

View File

@ -2,8 +2,10 @@ from nullptr.store import Store
from nullptr.models.base import Base from nullptr.models.base import Base
from nullptr.models.waypoint import Waypoint from nullptr.models.waypoint import Waypoint
from nullptr.models.contract import Contract from nullptr.models.contract import Contract
from nullptr.models.system import System
from nullptr.models.survey import Survey from nullptr.models.survey import Survey
from nullptr.models.ship import Ship from nullptr.models.ship import Ship
from nullptr.analyzer import Analyzer
from time import time from time import time
import logging import logging
from nullptr.util import * from nullptr.util import *
@ -42,6 +44,7 @@ class Mission:
self.store = store self.store = store
self.api = api self.api = api
self.next_step = 0 self.next_step = 0
self.analyzer = Analyzer(self.store)
def sts(self, nm, v): def sts(self, nm, v):
if issubclass(type(v), Base): if issubclass(type(v), Base):
@ -121,8 +124,109 @@ class Mission:
self.status(next_step[result]) self.status(next_step[result])
print(f'{self.ship} {status} -> {self.status()}') print(f'{self.ship} {status} -> {self.status()}')
class BaseMission(Mission):
def step_go_dest(self):
destination = self.rst(Waypoint, 'destination')
if self.ship.location() == destination:
return
self.api.navigate(self.ship, destination)
self.next_step = self.ship.arrival
class MiningMission(Mission): def step_go_site(self):
site = self.rst(Waypoint,'site')
if self.ship.location() == site:
return
self.api.navigate(self.ship, site)
self.next_step = self.ship.arrival
def step_unload(self):
contract = self.rst(Contract, 'contract')
delivery = self.st('delivery')
if delivery == 'sell':
return self.step_sell(False)
typs = self.ship.deliverable_cargo(contract)
if len(typs) == 0:
return 'done'
self.api.deliver(self.ship, typs[0], contract)
if len(typs) == 1:
return 'done'
else:
return 'more'
def step_sell(self, except_resource=True):
target = self.st('resource')
market = self.store.get('Marketplace', self.ship.location_str)
sellables = market.sellable_items(self.ship.cargo.keys())
if target in sellables and except_resource:
sellables.remove(target)
if len(sellables) == 0:
return 'done'
self.api.sell(self.ship, sellables[0])
if len(sellables) == 1:
return 'done'
else:
return 'more'
def step_load(self):
cargo_space = self.ship.cargo_capacity - self.ship.cargo_units
resource = self.st('resource')
self.api.buy(self.ship, resource, cargo_space)
def travel(self, nm):
dest = self.rst(Waypoint, nm)
traject = self.st('traject')
loc = self.ship.location()
if dest == loc:
self.sts('traject', None)
return 'done'
elif traject is None:
print(f'calculating path to {dest}')
traject = self.calculate_traject(dest)
hop = traject.pop(0)
if len(hop.split('-')) == 3:
self.api.navigate(self.ship, hop)
self.next_step = self.ship.arrival
else:
self.api.jump(self.ship, hop)
self.next_step = self.ship.cooldown
self.sts('traject', traject)
return 'more'
def calculate_traject(self, dest):
loc = self.ship.location()
loc_sys = self.store.get(System, loc.system())
loc_jg = self.analyzer.get_jumpgate(loc_sys)
dest_sys = self.store.get(System, dest.system())
dest_jg = self.analyzer.get_jumpgate(dest_sys)
path = self.analyzer.find_path(loc_sys, dest_sys)
result = []
print(loc.symbol, loc_jg.symbol)
if loc.symbol != loc_jg.symbol:
result.append(loc_jg.symbol)
result += [s.symbol for s in path[1:]]
if dest_jg.symbol != dest.symbol:
result.append(dest.symbol)
print(result)
return result
def step_travel_site(self):
return self.travel('site')
def step_travel_dest(self):
return self.travel('destination')
def step_dock(self):
self.api.dock(self.ship)
def step_refuel(self):
if self.ship.fuel_current < 100:
self.api.refuel(self.ship)
def step_orbit(self):
self.api.orbit(self.ship)
class MiningMission(BaseMission):
@classmethod @classmethod
def params(cls): def params(cls):
return { return {
@ -186,47 +290,6 @@ class MiningMission(Mission):
else: else:
return 'done' return 'done'
def step_sell(self, except_resource=True):
target = self.st('resource')
market = self.store.get('Marketplace', self.ship.location_str)
sellables = market.sellable_items(self.ship.cargo.keys())
if target in sellables and except_resource:
sellables.remove(target)
if len(sellables) == 0:
return 'done'
self.api.sell(self.ship, sellables[0])
if len(sellables) == 1:
return 'done'
else:
return 'more'
def step_go_dest(self):
destination = self.rst(Waypoint, 'destination')
if self.ship.location() == destination:
return
self.api.navigate(self.ship, destination)
self.next_step = self.ship.arrival
def step_dock(self):
self.api.dock(self.ship)
def step_unload(self):
contract = self.rst(Contract, 'contract')
delivery = self.st('delivery')
if delivery == 'sell':
return self.step_sell(False)
typs = self.ship.deliverable_cargo(contract)
if len(typs) == 0:
return 'done'
self.api.deliver(self.ship, typs[0], contract)
if len(typs) == 1:
return 'done'
else:
return 'more'
def step_refuel(self):
self.api.refuel(self.ship)
def step_dispose(self): def step_dispose(self):
contract = self.rst(Contract, 'contract') contract = self.rst(Contract, 'contract')
typs = self.ship.nondeliverable_cargo(contract) typs = self.ship.nondeliverable_cargo(contract)
@ -239,22 +302,10 @@ class MiningMission(Mission):
else: else:
return 'done' return 'done'
class SurveyMission(BaseMission):
def step_orbit(self):
self.api.orbit(self.ship)
def step_go_site(self):
site = self.rst(Waypoint,'site')
if self.ship.location() == site:
return
self.api.navigate(self.ship, site)
self.next_step = self.ship.arrival
class SurveyMission(Mission):
def start_state(self): def start_state(self):
return 'survey' return 'survey'
def steps(self): def steps(self):
return { return {
'survey': (self.step_survey, 'survey') 'survey': (self.step_survey, 'survey')
@ -265,10 +316,45 @@ class SurveyMission(Mission):
#pprint(result, 2) #pprint(result, 2)
self.next_step = self.ship.cooldown self.next_step = self.ship.cooldown
class HaulMission(BaseMission):
def start_state(self):
return 'orbit2'
@classmethod
def params(cls):
return {
'site': MissionParam(Waypoint, True),
'resource': MissionParam(str, True),
'destination': MissionParam(Waypoint, True),
'delivery': MissionParam(str, True, 'deliver'),
'contract': MissionParam(Contract, False)
}
def steps(self):
return {
'travel': (self.step_travel_site, {
'more': 'travel',
'done': 'dock'
}),
'dock': (self.step_dock, 'load'),
'load': (self.step_load, 'orbit'),
'orbit': (self.step_orbit, 'travel_back'),
'travel_back': (self.step_travel_dest, {
'more': 'travel_back',
'done': 'dock2'
}),
'dock2': (self.step_dock, 'unload'),
'unload': (self.step_unload, 'refuel'),
'refuel': (self.step_refuel, 'orbit2'),
'orbit2': (self.step_orbit, 'travel')
}
def create_mission(mtype, ship, store, api): def create_mission(mtype, ship, store, api):
types = { types = {
'survey': SurveyMission, 'survey': SurveyMission,
'mine': MiningMission 'mine': MiningMission,
'haul': HaulMission
} }
if mtype not in types: if mtype not in types:
logging.warning(f'invalid mission type {mtype}') logging.warning(f'invalid mission type {mtype}')

View File

@ -7,10 +7,11 @@ class Base:
store: object store: object
def __init__(self, symbol, store): def __init__(self, symbol, store):
self.disable_dirty = False self.disable_dirty = True
self.store = store self.store = store
self.symbol = symbol self.symbol = symbol
self.define() self.define()
self.disable_dirty = False
def define(self): def define(self):
pass pass

View File

@ -124,6 +124,7 @@ class Store:
if system not in self.system_members: if system not in self.system_members:
return return
print('typ', typ)
for m in self.system_members[system]: for m in self.system_members[system]:
if typ is None or type(m) == typ: if typ is None or type(m) == typ:
yield m yield m