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:
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):
gates = self.store.all_members(system, Jumpgate)
return next(gates, None)
def find_path(self, orig, to, depth=100, seen=None):
if depth < 1: return None
if seen is None:

View File

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

View File

@ -99,9 +99,8 @@ class Commander(CommandLine):
self.set_mission(arg)
self.print_mission()
def do_mset(self, args):
def do_mset(self, nm, val):
if not self.has_ship(): return
nm, val = args.split(' ')
self.centcom.set_mission_param(self.ship, nm, val)
def active_contract(self):
@ -125,6 +124,23 @@ class Commander(CommandLine):
self.centcom.set_mission_param(self.ship, 'contract', contract.symbol)
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):
self.api.register(faction.upper())
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.waypoint import Waypoint
from nullptr.models.contract import Contract
from nullptr.models.system import System
from nullptr.models.survey import Survey
from nullptr.models.ship import Ship
from nullptr.analyzer import Analyzer
from time import time
import logging
from nullptr.util import *
@ -42,6 +44,7 @@ class Mission:
self.store = store
self.api = api
self.next_step = 0
self.analyzer = Analyzer(self.store)
def sts(self, nm, v):
if issubclass(type(v), Base):
@ -121,8 +124,109 @@ class Mission:
self.status(next_step[result])
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
def params(cls):
return {
@ -186,47 +290,6 @@ class MiningMission(Mission):
else:
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):
contract = self.rst(Contract, 'contract')
typs = self.ship.nondeliverable_cargo(contract)
@ -239,22 +302,10 @@ class MiningMission(Mission):
else:
return 'done'
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):
class SurveyMission(BaseMission):
def start_state(self):
return 'survey'
def steps(self):
return {
'survey': (self.step_survey, 'survey')
@ -265,10 +316,45 @@ class SurveyMission(Mission):
#pprint(result, 2)
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):
types = {
'survey': SurveyMission,
'mine': MiningMission
'mine': MiningMission,
'haul': HaulMission
}
if mtype not in types:
logging.warning(f'invalid mission type {mtype}')

View File

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

View File

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