This commit is contained in:
Richard 2024-01-24 19:03:57 +01:00
parent b0ef68a721
commit d8eb1c4954
12 changed files with 208 additions and 198 deletions

View File

@ -324,8 +324,8 @@ class Api:
'shipSymbol': dship.symbol 'shipSymbol': dship.symbol
} }
data = self.request('post', f'my/ships/{sship.symbol}/transfer', data) data = self.request('post', f'my/ships/{sship.symbol}/transfer', data)
sship.log(f'transferred {amt} {typ} to {dship}') sship.log(f'tra {amt} {typ} to {dship}')
dship.log(f'received {amt} {typ} from {sship}') dship.log(f'rec {amt} {typ} from {sship}', 10)
if 'cargo' in data: if 'cargo' in data:
sship.update(data) sship.update(data)
dship.put_cargo(typ, amt) dship.put_cargo(typ, amt)

View File

@ -6,7 +6,7 @@ from random import choice, randrange
from time import sleep from time import sleep
from threading import Thread from threading import Thread
from nullptr.atlas_builder import AtlasBuilder from nullptr.atlas_builder import AtlasBuilder
from nullptr.analyzer import Analyzer from nullptr.analyzer import Analyzer, Point
class CentralCommandError(Exception): class CentralCommandError(Exception):
pass pass
@ -112,13 +112,20 @@ class CentralCommand:
if s in self.missions: if s in self.missions:
m = self.missions[s] m = self.missions[s]
def find_gas(self, s): def find_gas(self, system):
system = s.location.system
m = [w for w in self.store.all_members(system, 'Waypoint') if w.type == 'GAS_GIANT'] m = [w for w in self.store.all_members(system, 'Waypoint') if w.type == 'GAS_GIANT']
if len(m)==0: if len(m)==0:
raise CentralCommandError('no gas giant found') raise CentralCommandError('no gas giant found')
return m[0] return m[0]
def find_metal(self, system):
m = [w for w in self.store.all_members(system, Waypoint) if 'COMMON_METAL_DEPOSITS' in w.traits]
if len(m) == 0:
return None
origin = Point(0,0)
m = sorted(m, key=lambda w: w.distance(origin))
return m[0]
def assign_mission(self, s): def assign_mission(self, s):
if s.role == 'trader': if s.role == 'trader':
self.assign_trade(s) self.assign_trade(s)
@ -128,18 +135,34 @@ class CentralCommand:
self.assign_siphon(s) self.assign_siphon(s)
elif s.role == 'hauler': elif s.role == 'hauler':
self.assign_hauler(s) self.assign_hauler(s)
elif s.role == 'surveyor':
self.assign_survey(s)
def assign_survey(self, s):
if s.crew is None:
raise CentralCommandError('ship has no crew')
w = s.crew.site
self.init_mission(s, 'survey')
self.smipa(s, 'site', w)
def assign_hauler(self, s): def assign_hauler(self, s):
w = self.find_gas(s) if s.crew is None:
m = self.analyzer.best_sell_market(s.location.system, 'HYDROCARBON') raise CentralCommandError('ship has no crew')
resources = list(m.prices.keys()) w = s.crew.site
resources = s.crew.resources
resource = choice(resources)
m = self.analyzer.best_sell_market(s.location.system, resource)
s.log(f'assigning haul mission from {w} to {m}')
self.init_mission(s, 'haul') self.init_mission(s, 'haul')
self.smipa(s, 'site', w) self.smipa(s, 'site', w)
self.smipa(s, 'dest', m) self.smipa(s, 'dest', m)
self.smipa(s, 'resources', resources) self.smipa(s, 'resources', resources)
def assign_siphon(self, s): def assign_siphon(self, s):
w = self.find_gas(s) if s.crew is None:
raise CentralCommandError('ship has no crew')
w = s.crew.site
self.init_mission(s, 'siphon') self.init_mission(s, 'siphon')
self.smipa(s, 'site', w) self.smipa(s, 'site', w)
@ -149,7 +172,7 @@ class CentralCommand:
m = self.analyzer.solve_tsp(m) m = self.analyzer.solve_tsp(m)
hops = [w.symbol for w in m] hops = [w.symbol for w in m]
start_hop = randrange(0, len(hops)) start_hop = randrange(0, len(hops))
print(f'Assigning {s} to probe {len(hops)} starting at {hops[start_hop]}') s.log(f'Assigning {s} to probe {len(hops)} starting at {hops[start_hop]}')
self.init_mission(s, 'probe') self.init_mission(s, 'probe')
self.smipa(s, 'hops', hops) self.smipa(s, 'hops', hops)
self.smipa(s, 'next-hop', start_hop) self.smipa(s, 'next-hop', start_hop)
@ -161,7 +184,7 @@ class CentralCommand:
self.init_mission(s,'idle') self.init_mission(s,'idle')
self.smipa(s, 'seconds', 600) self.smipa(s, 'seconds', 600)
return return
print(f'assigning {s} to deliver {t.resource} from {t.source} to {t.dest} at a margin of {t.margin}') s.log(f'assigning {s} to deliver {t.resource} from {t.source} to {t.dest} at a margin of {t.margin}')
self.init_mission(s, 'trade') self.init_mission(s, 'trade')
self.smipa(s, 'site', t.source) self.smipa(s, 'site', t.source)
self.smipa(s, 'dest', t.dest) self.smipa(s, 'dest', t.dest)
@ -196,3 +219,18 @@ class CentralCommand:
def stop_mission(self, s): def stop_mission(self, s):
if s in self.missions: if s in self.missions:
del self.missions[s] del self.missions[s]
def create_default_crews(self):
system = self.api.agent.headquarters.system
gas_w = self.find_gas(system)
metal_w = self.find_metal(system)
metal = self.store.get('Crew', 'METAL', create=True)
metal.site = metal_w
metal.resources = ['COPPER_ORE','IRON_ORE']
gas = self.store.get('Crew', 'GAS', create=True)
gas.site = gas_w
gas.resources = ['HYDROCARBON','LIQUID_HYDROGEN','LIQUID_NITROGEN']
return [gas, metal]

View File

@ -56,8 +56,8 @@ class Commander(CommandLine):
self.centcom.run_interactive() self.centcom.run_interactive()
def do_log(self, level): def do_log(self, level):
if not self.has_ship(): return ship = self.has_ship()
self.ship._log_level = int(level) ship._log_level = int(level)
######## Resolvers ######### ######## Resolvers #########
def ask_obj(self, typ, prompt): def ask_obj(self, typ, prompt):
@ -71,9 +71,9 @@ class Commander(CommandLine):
def has_ship(self): def has_ship(self):
if self.ship is not None: if self.ship is not None:
return True return self.ship
else: else:
print('set a ship') raise CommandError('set a ship')
def select_agent(self): def select_agent(self):
agents = self.store.all(Agent) agents = self.store.all(Agent)
@ -96,8 +96,8 @@ class Commander(CommandLine):
if type(system_str) == System: if type(system_str) == System:
return system_str return system_str
if system_str == '': if system_str == '':
if not self.has_ship(): return ship = self.has_ship()
system = self.ship.location.system system = ship.location.system
else: else:
system = self.store.get(System, system_str) system = self.store.get(System, system_str)
return system return system
@ -106,12 +106,12 @@ class Commander(CommandLine):
if type(w) == Waypoint: if type(w) == Waypoint:
return w return w
if w == '': if w == '':
if not self.has_ship(): return ship = self.has_ship()
return self.ship.location return ship.location
p = w.split('-') p = w.split('-')
if len(p) == 1: if len(p) == 1:
if not self.has_ship(): return ship = self.has_ship()
s = self.ship.location.system s = ship.location.system
w = f'{s}-{w}' w = f'{s}-{w}'
r = self.store.get(Waypoint, w) r = self.store.get(Waypoint, w)
if r is None: if r is None:
@ -203,8 +203,8 @@ class Commander(CommandLine):
def do_waypoints(self, system_str=''): def do_waypoints(self, system_str=''):
loc = None loc = None
if system_str == '': if system_str == '':
if not self.has_ship(): return ship = self.has_ship()
loc = self.ship.location loc = ship.location
system = loc.system system = loc.system
else: else:
system = self.store.get(System, system_str) system = self.store.get(System, system_str)
@ -224,8 +224,8 @@ class Commander(CommandLine):
print(f'{wname:4} {typ} {traits}') print(f'{wname:4} {typ} {traits}')
def do_members(self): def do_members(self):
if not self.has_ship(): return ship = self.has_ship()
system = self.ship.location.system system = ship.location.system
pprint(list(self.store.all_members(system))) pprint(list(self.store.all_members(system)))
def do_wp(self, s=''): def do_wp(self, s=''):
@ -245,8 +245,8 @@ class Commander(CommandLine):
def do_jumps(self, waypoint_str=None): def do_jumps(self, waypoint_str=None):
if waypoint_str is None: if waypoint_str is None:
if not self.has_ship(): return ship = self.has_ship()
waypoint = self.ship.location waypoint = ship.location
else: else:
waypoint = self.store.get(Waypoint, waypoint_str.upper()) waypoint = self.store.get(Waypoint, waypoint_str.upper())
r = self.api.jumps(waypoint) r = self.api.jumps(waypoint)
@ -266,49 +266,49 @@ class Commander(CommandLine):
######## Commerce ######### ######## Commerce #########
def do_refuel(self, source='market'): def do_refuel(self, source='market'):
if not self.has_ship(): return ship = self.has_ship()
from_cargo = source != 'market' from_cargo = source != 'market'
r = self.api.refuel(self.ship, from_cargo=from_cargo) r = self.api.refuel(ship, from_cargo=from_cargo)
pprint(r) pprint(r)
def do_cargo(self): def do_cargo(self):
if not self.has_ship(): return ship = self.has_ship()
print(f'== Cargo {self.ship.cargo_units}/{self.ship.cargo_capacity} ==') print(f'== Cargo {ship.cargo_units}/{ship.cargo_capacity} ==')
for c, units in self.ship.cargo.items(): for c, units in ship.cargo.items():
print(f'{units:4d} {c}') print(f'{units:4d} {c}')
def do_buy(self, resource, amt=None): def do_buy(self, resource, amt=None):
if not self.has_ship(): return ship = self.has_ship()
if amt is None: if amt is None:
amt = self.ship.cargo_capacity - self.ship.cargo_units amt = ship.cargo_capacity - ship.cargo_units
self.api.buy(self.ship, resource.upper(), amt) self.api.buy(ship, resource.upper(), amt)
self.do_cargo() self.do_cargo()
def do_sell(self, resource, amt=None): def do_sell(self, resource, amt=None):
if not self.has_ship(): return ship = self.has_ship()
self.api.sell(self.ship, resource.upper(), amt) self.api.sell(ship, resource.upper(), amt)
self.do_cargo() self.do_cargo()
def do_dump(self, resource): def do_dump(self, resource):
if not self.has_ship(): return ship = self.has_ship()
self.api.jettison(self.ship, resource.upper()) self.api.jettison(ship, resource.upper())
self.do_cargo() self.do_cargo()
def do_transfer(self, resource, dship, amount=None): def do_transfer(self, resource, dship, amount=None):
if not self.has_ship(): return ship = self.has_ship()
resource = resource.upper() resource = resource.upper()
avail = self.ship.get_cargo(resource) avail = ship.get_cargo(resource)
if amount is None: amount = avail if amount is None: amount = avail
amount = int(amount) amount = int(amount)
if avail < amount: if avail < amount:
raise CommandError('resource not in cargo') raise CommandError('resource not in cargo')
dship = self.resolve_ship(dship) dship = self.resolve_ship(dship)
self.api.transfer(self.ship, dship, resource, amount) self.api.transfer(ship, dship, resource, amount)
def do_purchase(self, ship_type): def do_purchase(self, ship_type):
if not self.has_ship(): return ship = self.has_ship()
location = self.ship.location location = ship.location
ship_type = ship_type.upper() ship_type = ship_type.upper()
if not ship_type.startswith('SHIP'): if not ship_type.startswith('SHIP'):
ship_type = 'SHIP_' + ship_type ship_type = 'SHIP_' + ship_type
@ -317,23 +317,23 @@ class Commander(CommandLine):
######## Mining ######### ######## Mining #########
def do_siphon(self): def do_siphon(self):
if not self.has_ship(): return ship = self.has_ship()
data = self.api.siphon(self.ship) data = self.api.siphon(ship)
def do_survey(self): def do_survey(self):
if not self.has_ship(): return ship = self.has_ship()
r = self.api.survey(self.ship) r = self.api.survey(ship)
pprint(r) pprint(r)
def do_surveys(self): def do_surveys(self):
pprint(list(self.store.all('Survey'))) pprint(list(self.store.all('Survey')))
def do_extract(self, survey_str=''): def do_extract(self, survey_str=''):
if not self.has_ship(): return ship = self.has_ship()
survey = None survey = None
if survey_str != '': if survey_str != '':
survey = self.resolve('Survey', survey_str) survey = self.resolve('Survey', survey_str)
result = self.api.extract(self.ship, survey) result = self.api.extract(ship, survey)
symbol = mg(result,'extraction.yield.symbol') symbol = mg(result,'extraction.yield.symbol')
units = mg(result,'extraction.yield.units') units = mg(result,'extraction.yield.units')
@ -346,39 +346,51 @@ class Commander(CommandLine):
pprint(self.ship.mission_state) pprint(self.ship.mission_state)
def do_role(self, role): def do_role(self, role):
roles = [None, 'trader', 'probe', 'siphon', 'hauler'] roles = [None, 'trader', 'probe', 'siphon', 'hauler', 'surveyor', 'miner']
if not self.has_ship(): return ship = self.has_ship()
if role == 'none': if role == 'none':
role = None role = None
if role not in roles: if role not in roles:
print(f'role {role} not found. Choose from {roles}') print(f'role {role} not found. Choose from {roles}')
return return
self.ship.role = role ship.role = role
def do_mission(self, arg=''): def do_mission(self, arg=''):
if not self.has_ship(): return ship = self.has_ship()
if arg: if arg:
self.centcom.init_mission(self.ship, arg) self.centcom.init_mission(ship, arg)
self.print_mission() self.print_mission()
def do_mrestart(self, status='init'): def do_mrestart(self, status='init'):
if not self.has_ship(): return ship = self.has_ship()
self.centcom.restart_mission(self.ship, status) self.centcom.restart_mission(ship, status)
self.print_mission() self.print_mission()
def do_mstep(self): def do_mstep(self):
if not self.has_ship(): return ship = self.has_ship()
self.centcom.single_step(self.ship) self.centcom.single_step(ship)
self.print_mission() self.print_mission()
def do_mreset(self): def do_mreset(self):
if not self.has_ship(): return ship = self.has_ship()
self.ship.mission_state = {} ship.mission_state = {}
def do_mset(self, nm, val): def do_mset(self, nm, val):
if not self.has_ship(): return ship = self.has_ship()
self.centcom.set_mission_param(self.ship, nm, val) self.centcom.set_mission_param(ship, nm, val)
def do_crew(self, arg):
ship = self.has_ship()
crew = self.resolve('Crew', arg)
ship.crew = crew
pprint(ship)
######## Crews #########
def do_create_crews(self):
crews = self.centcom.create_default_crews()
for c in crews:
print(f'{c.symbol:15s} {c.site}')
######## Contracts ######### ######## Contracts #########
def active_contract(self): def active_contract(self):
for c in self.store.all('Contract'): for c in self.store.all('Contract'):
@ -393,8 +405,8 @@ class Commander(CommandLine):
pprint(r) pprint(r)
def do_negotiate(self): def do_negotiate(self):
if not self.has_ship(): return ship = self.has_ship()
r = self.api.negotiate(self.ship) r = self.api.negotiate(ship)
pprint(r) pprint(r)
def do_accept(self, c): def do_accept(self, c):
@ -403,118 +415,59 @@ class Commander(CommandLine):
pprint(r) pprint(r)
def do_deliver(self): def do_deliver(self):
if not self.has_ship(): return ship = self.has_ship()
site = self.ship.location site = ship.location
contract = self.active_contract() contract = self.active_contract()
delivery = contract.unfinished_delivery() delivery = contract.unfinished_delivery()
if delivery is None: if delivery is None:
raise CommandError('no delivery') raise CommandError('no delivery')
resource = delivery['trade_symbol'] resource = delivery['trade_symbol']
self.api.deliver(self.ship, resource, contract) self.api.deliver(ship, resource, contract)
pprint(contract) pprint(contract)
def do_fulfill(self): def do_fulfill(self):
contract = self.active_contract() contract = self.active_contract()
self.api.fulfill(contract) self.api.fulfill(contract)
######## Automissions #########
def do_cmine(self):
if not self.has_ship(): return
site = self.ship.location
contract = self.active_contract()
delivery = contract.unfinished_delivery()
if delivery is None:
raise CommandError('no delivery')
resource = delivery['trade_symbol']
destination = delivery['destination']
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)
self.centcom.set_mission_param(self.ship, 'contract', contract)
self.print_mission()
def do_chaul(self):
if not self.has_ship(): return
if len(self.ship.cargo) > 0:
raise CommandError('please dump cargo first')
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', destination)
if len(m) == 0:
m = self.analyzer.find_closest_markets(resource, 'exchange', destination)
if len(m) == 0:
print('no market found')
return
_, m, _, _ = m[0]
site = self.store.get(Waypoint, m.symbol)
self.centcom.init_mission(self.ship, 'trade')
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)
self.centcom.set_mission_param(self.ship, 'contract', contract)
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) == 0:
print('no market found')
return
markets = [ mkt[1] for mkt in m]
markets = self.analyzer.solve_tsp(markets)
self.centcom.init_mission(self.ship, 'probe')
self.centcom.set_mission_param(self.ship, 'hops', markets)
self.print_mission()
######## Travel ######### ######## Travel #########
def do_travel(self, dest): def do_travel(self, dest):
ship = self.has_ship()
dest = self.resolve('Waypoint', dest) dest = self.resolve('Waypoint', dest)
self.centcom.init_mission(self.ship, 'travel') self.centcom.init_mission(ship, 'travel')
self.centcom.set_mission_param(self.ship, 'dest', dest) self.centcom.set_mission_param(ship, 'dest', dest)
self.print_mission() self.print_mission()
def do_go(self, arg): def do_go(self, arg):
if not self.has_ship(): return ship = self.has_ship()
system = self.ship.location.system system = ship.location.system
symbol = f'{system}-{arg}' symbol = f'{system}-{arg}'
dest = self.resolve('Waypoint', symbol) dest = self.resolve('Waypoint', symbol)
self.api.navigate(self.ship, dest) self.api.navigate(ship, dest)
pprint(self.ship) pprint(ship)
def do_dock(self): def do_dock(self):
if not self.has_ship(): return ship = self.has_ship()
self.api.dock(self.ship) self.api.dock(ship)
pprint(self.ship) pprint(ship)
def do_orbit(self): def do_orbit(self):
if not self.has_ship(): return ship = self.has_ship()
self.api.orbit(self.ship) self.api.orbit(ship)
pprint(self.ship) pprint(ship)
def do_speed(self, speed): def do_speed(self, speed):
if not self.has_ship(): return ship = self.has_ship()
speed = speed.upper() speed = speed.upper()
speeds = ['DRIFT', 'STEALTH','CRUISE','BURN'] speeds = ['DRIFT', 'STEALTH','CRUISE','BURN']
if speed not in speeds: if speed not in speeds:
print('please choose from:', speeds) print('please choose from:', speeds)
self.api.flight_mode(self.ship, speed) self.api.flight_mode(ship, speed)
def do_jump(self, waypoint_str): def do_jump(self, waypoint_str):
if not self.has_ship(): return ship = self.has_ship()
w = self.resolve('Waypoint', waypoint_str) w = self.resolve('Waypoint', waypoint_str)
self.api.jump(self.ship, w) self.api.jump(ship, w)
pprint(self.ship) pprint(ship)
######## Analysis ######### ######## Analysis #########
def do_server(self): def do_server(self):
@ -563,8 +516,8 @@ class Commander(CommandLine):
print('Dirty: ', obj in self.store.dirty_objects) print('Dirty: ', obj in self.store.dirty_objects)
def do_query(self, resource): def do_query(self, resource):
if not self.has_ship(): return ship = self.has_ship()
location = self.ship.location location = ship.location
resource = 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):
@ -574,14 +527,14 @@ class Commander(CommandLine):
print(m, typ[0], f'{plen-1:3} hops {price}') print(m, typ[0], f'{plen-1:3} hops {price}')
def do_findtrade(self): def do_findtrade(self):
if not self.has_ship(): return ship = self.has_ship()
system = self.ship.location.system system = ship.location.system
t = self.analyzer.find_trade(system) t = self.analyzer.find_trade(system)
pprint(t) pprint(t)
def do_prices(self, resource=None): def do_prices(self, resource=None):
if not self.has_ship(): return ship = self.has_ship()
system = self.ship.location.system system = ship.location.system
prices = self.analyzer.prices(system) prices = self.analyzer.prices(system)
if resource is not None: if resource is not None:
prices = {resource: prices[resource.upper()]} prices = {resource: prices[resource.upper()]}
@ -592,7 +545,7 @@ class Commander(CommandLine):
print(f"{m['wp'].symbol:12s} {m['category']} {m['volume']:5d} {m['buy']:5d} {m['sell']:5d}") print(f"{m['wp'].symbol:12s} {m['category']} {m['volume']:5d} {m['buy']:5d} {m['sell']:5d}")
def do_path(self, waypoint_str): def do_path(self, waypoint_str):
if not self.has_ship(): return ship = self.has_ship()
w = self.resolve('Waypoint', waypoint_str) w = self.resolve('Waypoint', waypoint_str)
p = self.analyzer.find_nav_path(self.ship.location, w, self.ship.fuel_capacity) p = self.analyzer.find_nav_path(ship.location, w, ship.fuel_capacity)
pprint(p) pprint(p)

View File

@ -111,7 +111,7 @@ class Mission:
} }
def step_done(self): def step_done(self):
self.ship.log(f'mission finished with balance {self.balance()}', 3) self.ship.log(f'mission {type(self).__name__} finished with balance {self.balance()}', 3)
def is_waiting(self): def is_waiting(self):
if self.next_step > time() or self.ship.cooldown > time() or self.ship.arrival > time(): if self.next_step > time() or self.ship.cooldown > time() or self.ship.arrival > time():

View File

@ -9,39 +9,23 @@ class MiningMission(BaseMission):
def params(cls): def params(cls):
return { return {
'site': MissionParam(Waypoint, True), 'site': MissionParam(Waypoint, True),
'resource': MissionParam(str, True), 'resources': MissionParam(list, True)
'dest': MissionParam(Waypoint, True),
'delivery': MissionParam(str, True, 'deliver'),
'contract': MissionParam(Contract, False)
} }
p
def start_state(self): def start_state(self):
return 'travel-to' return 'travel-to'
def steps(self): def steps(self):
return { return {
**self.travel_steps('to', 'site', 'orbit1'), **self.travel_steps('to', 'site', 'extract'),
'orbit1': (self.step_orbit, 'extract'), 'extract': (self.step_extract, {
'extract': (self.step_extract, { 'more': 'extract',
'done': 'dock', 'full': 'unload'
'more': 'extract' }),
}), 'unload': (self.step_unload, {
'dock': (self.step_dock, 'sell'), 'more': 'unload',
'sell': (self.step_sell, { 'done': 'done'
'more': 'sell', })
'done': 'orbit2',
}),
'orbit2': (self.step_orbit, 'jettison'),
'jettison': (self.step_dispose, {
'more': 'jettison',
'done': 'extract',
'full': 'travel-back'
}),
**self.travel_steps('back', 'dest', 'unload'),
'unload': (self.step_unload, {
'done': 'travel-to',
'more': 'unload'
}),
} }
def get_survey(self): def get_survey(self):

View File

@ -41,7 +41,8 @@ class SiphonMission(BaseMission):
else: else:
space = h.cargo_space() space = h.cargo_space()
amt = min(space, amt) amt = min(space, amt)
self.api.transfer(self.ship, h, r, amt) if amt > 0:
self.api.transfer(self.ship, h, r, amt)
return 'more' return 'more'
def steps(self): def steps(self):

View File

@ -1,11 +1,19 @@
from nullptr.missions.base import BaseMission, MissionParam from nullptr.missions.base import BaseMission, MissionParam
from nullptr.models.waypoint import Waypoint
class SurveyMission(BaseMission): class SurveyMission(BaseMission):
def start_state(self): def start_state(self):
return 'survey' return 'travel-to'
@classmethod
def params(cls):
return {
'site': MissionParam(Waypoint, True),
}
def steps(self): def steps(self):
return { return {
**self.travel_steps('to', 'site', 'survey'),
'survey': (self.step_survey, 'survey') 'survey': (self.step_survey, 'survey')
} }

View File

@ -9,5 +9,6 @@ from nullptr.models.ship import Ship
from nullptr.models.contract import Contract from nullptr.models.contract import Contract
from nullptr.models.survey import Survey from nullptr.models.survey import Survey
from nullptr.models.atlas import Atlas from nullptr.models.atlas import Atlas
from nullptr.models.crew import Crew
__all__ = [ 'Waypoint', 'Sector', 'Ship', 'Survey', 'System', 'Agent', 'Marketplace', 'Jumpgate', 'Contract', 'Base', 'Atlas' ] __all__ = [ 'Waypoint', 'Sector', 'Ship', 'Survey', 'System', 'Agent', 'Marketplace', 'Jumpgate', 'Contract', 'Base', 'Atlas', 'Crew' ]

View File

@ -1,12 +1,16 @@
from .base import Base from .base import Base
from nullptr.models.waypoint import Waypoint
class Agent(Base): class Agent(Base):
def define(self): def define(self):
self.token: str = None self.token: str = None
self.credits: int = 0 self.credits: int = 0
self.headquarters: Waypoint = None
def update(self, d): def update(self, d):
self.seta('credits', d) self.seta('credits', d)
getter = self.store.getter(Waypoint, create=True)
self.seta('headquarters', d, interp=getter)
@classmethod @classmethod
def ext(self): def ext(self):

16
nullptr/models/crew.py Normal file
View File

@ -0,0 +1,16 @@
from .base import Base
class Crew(Base):
@classmethod
def ext(self):
return 'crw'
def define(self):
self.site = None
self.resources = []
def f(self, detail=1):
r = super().f(detail)
if detail >2:
r += f'\nSite: {self.site}'
return r

View File

@ -19,6 +19,7 @@ class Ship(Base):
self.mission:str = None self.mission:str = None
self.mission_status:str = 'init' self.mission_status:str = 'init'
self.role = None self.role = None
self.crew = None
self.frame = '' self.frame = ''
self.speed = "CRUISE" self.speed = "CRUISE"
self._log_file = None self._log_file = None
@ -29,11 +30,12 @@ class Ship(Base):
fn = os.path.join(self.store.data_dir, f'{self.symbol}.{self.ext()}.log') fn = os.path.join(self.store.data_dir, f'{self.symbol}.{self.ext()}.log')
self._log_file = open(fn, 'a') self._log_file = open(fn, 'a')
ts = strftime('%Y%m%d %H%M%S') ts = strftime('%Y%m%d %H%M%S')
sts = strftime('%H%M%S')
m = m.strip() m = m.strip()
self._log_file.write(f'{ts} {m}\n') self._log_file.write(f'{ts} {m}\n')
self._log_file.flush() self._log_file.flush()
if l <= self._log_level: if l <= self._log_level:
print(f'{self} {ts} {m}') print(f'{self} {sts} {m}')
@classmethod @classmethod
def ext(self): def ext(self):
@ -139,6 +141,9 @@ class Ship(Base):
role = self.role role = self.role
if role is None: if role is None:
role = 'none' role = 'none'
crew = 'none'
if self.crew is not None:
crew = self.crew.symbol
mstatus = self.mission_status mstatus = self.mission_status
if mstatus == 'error': if mstatus == 'error':
mstatus = mstatus.upper() mstatus = mstatus.upper()
@ -160,7 +165,7 @@ class Ship(Base):
r += f' [C: {cooldown}]' r += f' [C: {cooldown}]'
else: else:
r = f'== {self.symbol} {self.frame} ==\n' r = f'== {self.symbol} {self.frame} ==\n'
r += f'Role: {role}\n' r += f'Role: {crew} / {role}\n'
r += f'Mission: {self.mission} ({mstatus})\n' r += f'Mission: {self.mission} ({mstatus})\n'
for k, v in self.mission_state.items(): for k, v in self.mission_state.items():
if type(v) == list: if type(v) == list:

View File

@ -47,15 +47,15 @@ class Waypoint(Base):
traits.append('MARKET') traits.append('MARKET')
if self.type == 'ASTEROID':
if 'COMMON_METAL_DEPOSITS' in self.traits: if 'COMMON_METAL_DEPOSITS' in self.traits:
traits.append('METAL') traits.append('METAL')
if 'PRECIOUS_METAL_DEPOSITS' in self.traits: if 'PRECIOUS_METAL_DEPOSITS' in self.traits:
traits.append('GOLD') traits.append('GOLD')
if 'MINERAL_DEPOSITS' in self.traits: if 'MINERAL_DEPOSITS' in self.traits:
traits.append('MINS') traits.append('MINS')
if 'STRIPPED' in self.traits: if 'STRIPPED' in self.traits:
traits.append('STRIPPED') traits.append('STRIPPED')
return traits return traits
def f(self, detail=1): def f(self, detail=1):