store fixes and probe role
This commit is contained in:
parent
188ef320cc
commit
7d92a45d12
@ -153,8 +153,7 @@ class Analyzer:
|
|||||||
def prices(self, system):
|
def prices(self, system):
|
||||||
prices = {}
|
prices = {}
|
||||||
for m in self.store.all_members(system, Marketplace):
|
for m in self.store.all_members(system, Marketplace):
|
||||||
for p in m.prices.values():
|
for r, p in m.prices.items():
|
||||||
r = p['symbol']
|
|
||||||
if not r in prices:
|
if not r in prices:
|
||||||
prices[r] = []
|
prices[r] = []
|
||||||
prices[r].append({
|
prices[r].append({
|
||||||
@ -168,7 +167,7 @@ class Analyzer:
|
|||||||
prices = self.prices(system)
|
prices = self.prices(system)
|
||||||
occupied_resources = set()
|
occupied_resources = set()
|
||||||
for s in self.store.all('Ship'):
|
for s in self.store.all('Ship'):
|
||||||
if s.mission != 'haul':
|
if s.mission != 'trade':
|
||||||
continue
|
continue
|
||||||
occupied_resources.add(s.mission_state['resource'])
|
occupied_resources.add(s.mission_state['resource'])
|
||||||
best = None
|
best = None
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
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, get_mission_class
|
from nullptr.missions import create_mission, get_mission_class
|
||||||
from random import choice
|
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
|
||||||
@ -106,10 +106,23 @@ class CentralCommand:
|
|||||||
|
|
||||||
|
|
||||||
def assign_mission(self, s):
|
def assign_mission(self, s):
|
||||||
if s.role == 'hauler':
|
if s.role == 'trader':
|
||||||
self.assign_haul(s)
|
self.assign_trade(s)
|
||||||
|
elif s.role == 'probe':
|
||||||
|
self.assign_probe(s)
|
||||||
|
|
||||||
def assign_haul(self, s):
|
def assign_probe(self, s):
|
||||||
|
system = s.location.system
|
||||||
|
m = [m.waypoint for m in self.store.all_members(system, 'Marketplace')]
|
||||||
|
m = self.analyzer.solve_tsp(m)
|
||||||
|
hops = [w.symbol for w in m]
|
||||||
|
start_hop = randrange(0, len(hops))
|
||||||
|
print(f'Assigning {s} to probe {len(hops)} starting at {hops[start_hop]}')
|
||||||
|
self.init_mission(s, 'probe')
|
||||||
|
self.smipa(s, 'hops', hops)
|
||||||
|
self.smipa(s, 'next-hop', start_hop)
|
||||||
|
|
||||||
|
def assign_trade(self, s):
|
||||||
t = self.analyzer.find_trade(s.location.system)
|
t = self.analyzer.find_trade(s.location.system)
|
||||||
if t is None:
|
if t is None:
|
||||||
print(f"No trade for {s} found. Idling")
|
print(f"No trade for {s} found. Idling")
|
||||||
@ -117,7 +130,7 @@ class CentralCommand:
|
|||||||
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}')
|
print(f'assigning {s} to deliver {t.resource} from {t.source} to {t.dest} at a margin of {t.margin}')
|
||||||
self.init_mission(s, 'haul')
|
self.init_mission(s, 'trade')
|
||||||
self.smipa(s, 'resource', t.resource)
|
self.smipa(s, 'resource', t.resource)
|
||||||
self.smipa(s, 'site', t.source)
|
self.smipa(s, 'site', t.source)
|
||||||
self.smipa(s, 'dest', t.dest)
|
self.smipa(s, 'dest', t.dest)
|
||||||
|
@ -20,6 +20,7 @@ class Commander(CommandLine):
|
|||||||
def __init__(self, data_dir='data'):
|
def __init__(self, data_dir='data'):
|
||||||
store_file = os.path.join(data_dir, 'store.npt')
|
store_file = os.path.join(data_dir, 'store.npt')
|
||||||
hist_file = os.path.join(data_dir, 'cmd.hst')
|
hist_file = os.path.join(data_dir, 'cmd.hst')
|
||||||
|
self.cred_file = os.path.join(data_dir, 'creds.txt')
|
||||||
self.hist_file = hist_file
|
self.hist_file = hist_file
|
||||||
if os.path.isfile(hist_file):
|
if os.path.isfile(hist_file):
|
||||||
readline.read_history_file(hist_file)
|
readline.read_history_file(hist_file)
|
||||||
@ -107,7 +108,7 @@ class Commander(CommandLine):
|
|||||||
if len(faction) > 50:
|
if len(faction) > 50:
|
||||||
self.agent.token = faction
|
self.agent.token = faction
|
||||||
else:
|
else:
|
||||||
api.register(faction.upper().strip())
|
self.do_register(faction)
|
||||||
print('=== agent:')
|
print('=== agent:')
|
||||||
print(agent)
|
print(agent)
|
||||||
print('=== ships')
|
print('=== ships')
|
||||||
@ -126,6 +127,10 @@ class Commander(CommandLine):
|
|||||||
|
|
||||||
def do_register(self, faction):
|
def do_register(self, faction):
|
||||||
self.api.register(faction.upper())
|
self.api.register(faction.upper())
|
||||||
|
with open(self.cred_file, 'w') as f:
|
||||||
|
f.write(self.api.agent.symbol)
|
||||||
|
f.write('\n')
|
||||||
|
f.write(self.api.agent.token)
|
||||||
pprint(self.api.agent)
|
pprint(self.api.agent)
|
||||||
|
|
||||||
######## Fleet #########
|
######## Fleet #########
|
||||||
@ -306,7 +311,7 @@ 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, 'hauler']
|
roles = [None, 'trader', 'probe']
|
||||||
if not self.has_ship(): return
|
if not self.has_ship(): return
|
||||||
if role == 'none':
|
if role == 'none':
|
||||||
role = None
|
role = None
|
||||||
@ -407,7 +412,7 @@ 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.centcom.init_mission(self.ship, 'haul')
|
self.centcom.init_mission(self.ship, 'trade')
|
||||||
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)
|
||||||
@ -432,18 +437,6 @@ class Commander(CommandLine):
|
|||||||
self.centcom.set_mission_param(self.ship, 'hops', markets)
|
self.centcom.set_mission_param(self.ship, 'hops', markets)
|
||||||
self.print_mission()
|
self.print_mission()
|
||||||
|
|
||||||
def do_sprobe(self):
|
|
||||||
if not self.has_ship(): return
|
|
||||||
system = self.ship.location.system
|
|
||||||
m = [m.waypoint for m in self.store.all_members(system, 'Marketplace')]
|
|
||||||
print("pre", path_dist(m))
|
|
||||||
m = self.analyzer.solve_tsp(m)
|
|
||||||
print("post", path_dist(m))
|
|
||||||
hops = [w.symbol for w in m]
|
|
||||||
self.centcom.init_mission(self.ship, 'probe')
|
|
||||||
self.centcom.set_mission_param(self.ship, 'hops', hops)
|
|
||||||
self.print_mission()
|
|
||||||
|
|
||||||
######## Travel #########
|
######## Travel #########
|
||||||
def do_travel(self, dest):
|
def do_travel(self, dest):
|
||||||
dest = self.resolve('Waypoint', dest)
|
dest = self.resolve('Waypoint', dest)
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
from nullptr.missions.survey import SurveyMission
|
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.trade import TradeMission
|
||||||
from nullptr.missions.travel import TravelMission
|
from nullptr.missions.travel import TravelMission
|
||||||
from nullptr.missions.probe import ProbeMission
|
from nullptr.missions.probe import ProbeMission
|
||||||
from nullptr.missions.idle import IdleMission
|
from nullptr.missions.idle import IdleMission
|
||||||
@ -10,7 +10,7 @@ def get_mission_class( mtype):
|
|||||||
types = {
|
types = {
|
||||||
'survey': SurveyMission,
|
'survey': SurveyMission,
|
||||||
'mine': MiningMission,
|
'mine': MiningMission,
|
||||||
'haul': HaulMission,
|
'trade': TradeMission,
|
||||||
'travel': TravelMission,
|
'travel': TravelMission,
|
||||||
'probe': ProbeMission,
|
'probe': ProbeMission,
|
||||||
'idle': IdleMission
|
'idle': IdleMission
|
||||||
|
@ -49,7 +49,7 @@ class MiningMission(BaseMission):
|
|||||||
site = self.rst(Waypoint,'site')
|
site = self.rst(Waypoint,'site')
|
||||||
# todo optimize
|
# todo optimize
|
||||||
for s in self.store.all(Survey):
|
for s in self.store.all(Survey):
|
||||||
if resource in s.deposits and site.symbol == s.waypoint():
|
if resource in s.deposits and site.symbol == s.waypoint:
|
||||||
return s
|
return s
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@ from nullptr.missions.base import BaseMission, MissionParam
|
|||||||
from nullptr.models.waypoint import Waypoint
|
from nullptr.models.waypoint import Waypoint
|
||||||
from nullptr.models.survey import Survey
|
from nullptr.models.survey import Survey
|
||||||
from nullptr.models.contract import Contract
|
from nullptr.models.contract import Contract
|
||||||
class HaulMission(BaseMission):
|
class TradeMission(BaseMission):
|
||||||
def start_state(self):
|
def start_state(self):
|
||||||
return 'travel-to'
|
return 'travel-to'
|
||||||
|
|
@ -15,6 +15,9 @@ class Reference:
|
|||||||
def resolve(self):
|
def resolve(self):
|
||||||
return self.store.get(self.typ, self.symbol)
|
return self.store.get(self.typ, self.symbol)
|
||||||
|
|
||||||
|
def f(self, detail):
|
||||||
|
return f'{self.symbol}.{self.typ.ext()}'
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return f'*REF*{self.symbol}.{self.typ.ext()}'
|
return f'*REF*{self.symbol}.{self.typ.ext()}'
|
||||||
|
|
||||||
@ -46,6 +49,9 @@ class Base:
|
|||||||
def define(self):
|
def define(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def created(self):
|
||||||
|
pass
|
||||||
|
|
||||||
def __hash__(self):
|
def __hash__(self):
|
||||||
return hash((str(type(self)), self.symbol))
|
return hash((str(type(self)), self.symbol))
|
||||||
|
|
||||||
@ -84,12 +90,16 @@ class Base:
|
|||||||
|
|
||||||
def __setattr__(self, name, value):
|
def __setattr__(self, name, value):
|
||||||
if not name.startswith('_') and not self._disable_dirty:
|
if not name.startswith('_') and not self._disable_dirty:
|
||||||
self.store.dirty(self)
|
self.dirty()
|
||||||
if issubclass(type(value), Base):
|
if issubclass(type(value), Base):
|
||||||
value = Reference.create(value)
|
value = Reference.create(value)
|
||||||
super().__setattr__(name, value)
|
super().__setattr__(name, value)
|
||||||
|
|
||||||
def __getattribute__(self, nm):
|
def __getattribute__(self, nm):
|
||||||
|
if nm == 'system':
|
||||||
|
return self.get_system()
|
||||||
|
if nm == 'waypoint':
|
||||||
|
return self.get_waypoint()
|
||||||
val = super().__getattribute__(nm)
|
val = super().__getattribute__(nm)
|
||||||
if type(val) == Reference:
|
if type(val) == Reference:
|
||||||
val = val.resolve()
|
val = val.resolve()
|
||||||
|
@ -5,7 +5,6 @@ from dataclasses import field
|
|||||||
class Jumpgate(Base):
|
class Jumpgate(Base):
|
||||||
def define(self):
|
def define(self):
|
||||||
self.connections: list = []
|
self.connections: list = []
|
||||||
self.system = self.get_system()
|
|
||||||
|
|
||||||
def update(self, d):
|
def update(self, d):
|
||||||
getter = self.store.getter(Waypoint, create=True)
|
getter = self.store.getter(Waypoint, create=True)
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
|
|
||||||
from .base import Base
|
from .base import Base, Reference
|
||||||
from time import time
|
from time import time
|
||||||
from nullptr.util import *
|
from nullptr.util import *
|
||||||
from dataclasses import field, dataclass
|
from dataclasses import field, dataclass
|
||||||
@ -32,12 +32,9 @@ class Marketplace(Base):
|
|||||||
self.exchange:list = []
|
self.exchange:list = []
|
||||||
self.prices:dict = {}
|
self.prices:dict = {}
|
||||||
self.last_prices:int = 0
|
self.last_prices:int = 0
|
||||||
self.set_waypoint()
|
|
||||||
self.system = self.get_system()
|
|
||||||
|
|
||||||
def set_waypoint(self):
|
def get_waypoint(self):
|
||||||
waypoint = self.store.get(Waypoint, self.symbol, create=True)
|
return self.store.get('Waypoint', self.symbol, create=True)
|
||||||
self.waypoint = waypoint
|
|
||||||
|
|
||||||
def is_fuel(self):
|
def is_fuel(self):
|
||||||
return self.imports + self.exports + self.exchange == ['FUEL']
|
return self.imports + self.exports + self.exchange == ['FUEL']
|
||||||
@ -51,7 +48,7 @@ class Marketplace(Base):
|
|||||||
e = self.prices[symbol] = MarketEntry()
|
e = self.prices[symbol] = MarketEntry()
|
||||||
buy = mg(g, 'purchasePrice')
|
buy = mg(g, 'purchasePrice')
|
||||||
sell = mg(g, 'sellPrice')
|
sell = mg(g, 'sellPrice')
|
||||||
volume = mg(g, 'tradeVolumes')
|
volume = mg(g, 'tradeVolume')
|
||||||
supply = SUPPLY.index(mg(g, 'supply'))
|
supply = SUPPLY.index(mg(g, 'supply'))
|
||||||
activity = ACTIVITY.index(sg(g, 'activity','STRONG'))
|
activity = ACTIVITY.index(sg(g, 'activity','STRONG'))
|
||||||
e.add(buy, sell, volume, supply, activity)
|
e.add(buy, sell, volume, supply, activity)
|
||||||
@ -68,12 +65,12 @@ class Marketplace(Base):
|
|||||||
def buy_price(self, resource):
|
def buy_price(self, resource):
|
||||||
if resource not in self.prices:
|
if resource not in self.prices:
|
||||||
return None
|
return None
|
||||||
return self.prices[resource]['buy']
|
return self.prices[resource].buy
|
||||||
|
|
||||||
def volume(self, resource):
|
def volume(self, resource):
|
||||||
if resource not in self.prices:
|
if resource not in self.prices:
|
||||||
return None
|
return None
|
||||||
return self.prices[resource]['volume']
|
return self.prices[resource].volume
|
||||||
|
|
||||||
def sellable_items(self, resources):
|
def sellable_items(self, resources):
|
||||||
return [r for r in resources if r in self.prices]
|
return [r for r in resources if r in self.prices]
|
||||||
|
@ -28,7 +28,7 @@ class Survey(Base):
|
|||||||
def api_dict(self):
|
def api_dict(self):
|
||||||
return {
|
return {
|
||||||
'signature': self.symbol,
|
'signature': self.symbol,
|
||||||
'symbol': self.waypoint(),
|
'symbol': self.waypoint,
|
||||||
'deposits': [{'symbol': d} for d in self.deposits],
|
'deposits': [{'symbol': d} for d in self.deposits],
|
||||||
'expiration': self.expires_str,
|
'expiration': self.expires_str,
|
||||||
'size': size_names[self.size]
|
'size': size_names[self.size]
|
||||||
|
@ -12,7 +12,6 @@ class Waypoint(Base):
|
|||||||
self.traits:list = []
|
self.traits:list = []
|
||||||
self.faction:str = ''
|
self.faction:str = ''
|
||||||
self.is_under_construction:bool = False
|
self.is_under_construction:bool = False
|
||||||
self.system = self.get_system()
|
|
||||||
self.uncharted = True
|
self.uncharted = True
|
||||||
|
|
||||||
|
|
||||||
@ -25,6 +24,9 @@ class Waypoint(Base):
|
|||||||
self.setlst('traits', d, 'traits', 'symbol')
|
self.setlst('traits', d, 'traits', 'symbol')
|
||||||
self.uncharted = 'UNCHARTED' in self.traits
|
self.uncharted = 'UNCHARTED' in self.traits
|
||||||
|
|
||||||
|
def created(self):
|
||||||
|
self.get_system()
|
||||||
|
|
||||||
def distance(self, other):
|
def distance(self, other):
|
||||||
return int(sqrt((self.x - other.x) ** 2 + (self.y - other.y) ** 2))
|
return int(sqrt((self.x - other.x) ** 2 + (self.y - other.y) ** 2))
|
||||||
|
|
||||||
|
@ -72,6 +72,7 @@ class ChunkHeader:
|
|||||||
class Store:
|
class Store:
|
||||||
def __init__(self, data_file, verbose=False):
|
def __init__(self, data_file, verbose=False):
|
||||||
self.init_models()
|
self.init_models()
|
||||||
|
self.data_file = data_file
|
||||||
self.data_dir = os.path.dirname(data_file)
|
self.data_dir = os.path.dirname(data_file)
|
||||||
self.fil = open_file(data_file)
|
self.fil = open_file(data_file)
|
||||||
self.data = {m: {} for m in self.models}
|
self.data = {m: {} for m in self.models}
|
||||||
@ -90,6 +91,9 @@ class Store:
|
|||||||
return
|
return
|
||||||
print(m)
|
print(m)
|
||||||
|
|
||||||
|
def f(self, detail):
|
||||||
|
return f'Store {self.data_file}'
|
||||||
|
|
||||||
def close(self):
|
def close(self):
|
||||||
self.flush()
|
self.flush()
|
||||||
self.fil.close()
|
self.fil.close()
|
||||||
@ -112,6 +116,9 @@ class Store:
|
|||||||
buf = BytesIO(data)
|
buf = BytesIO(data)
|
||||||
p = StoreUnpickler(buf, self)
|
p = StoreUnpickler(buf, self)
|
||||||
obj = p.load()
|
obj = p.load()
|
||||||
|
x = self.get(type(obj), obj.symbol)
|
||||||
|
if x is not None and x in self.dirty_objects:
|
||||||
|
self.dirty_objects.remove(obj)
|
||||||
obj._file_offset = offset
|
obj._file_offset = offset
|
||||||
self.hold(obj)
|
self.hold(obj)
|
||||||
|
|
||||||
@ -138,6 +145,8 @@ class Store:
|
|||||||
offset = self.fil.tell()
|
offset = self.fil.tell()
|
||||||
|
|
||||||
dur = time() - start_time
|
dur = time() - start_time
|
||||||
|
# just in case any temp objects were created
|
||||||
|
self.dirty_objects = set()
|
||||||
self.p(f'Loaded {cnt} objects in {dur:.2f} seconds')
|
self.p(f'Loaded {cnt} objects in {dur:.2f} seconds')
|
||||||
self.p(f'Fragmented space: {free} / {total} bytes')
|
self.p(f'Fragmented space: {free} / {total} bytes')
|
||||||
|
|
||||||
@ -210,14 +219,15 @@ class Store:
|
|||||||
symbol = obj.symbol
|
symbol = obj.symbol
|
||||||
obj.store = self
|
obj.store = self
|
||||||
self.data[typ][symbol] = obj
|
self.data[typ][symbol] = obj
|
||||||
if hasattr(obj, 'system'):
|
if type(obj).__name__ in ['Waypoint','Marketplace', 'Jumpgate', 'Survey']:
|
||||||
system_str = obj.get_system().symbol
|
system_str = obj.system.symbol
|
||||||
if system_str not in self.system_members:
|
if system_str not in self.system_members:
|
||||||
self.system_members[system_str] = set()
|
self.system_members[system_str] = set()
|
||||||
self.system_members[system_str].add(obj)
|
self.system_members[system_str].add(obj)
|
||||||
|
|
||||||
def create(self, typ, symbol):
|
def create(self, typ, symbol):
|
||||||
obj = typ(symbol, self)
|
obj = typ(symbol, self)
|
||||||
|
obj.created()
|
||||||
self.hold(obj)
|
self.hold(obj)
|
||||||
self.dirty(obj)
|
self.dirty(obj)
|
||||||
return obj
|
return obj
|
||||||
|
Loading…
Reference in New Issue
Block a user