trade routes instead of resources
This commit is contained in:
parent
7d92a45d12
commit
560ac056ff
@ -27,6 +27,7 @@ class TradeOption:
|
||||
resource: str
|
||||
source: Waypoint
|
||||
dest: Waypoint
|
||||
buy: int
|
||||
margin: int
|
||||
dist: int
|
||||
score: float
|
||||
@ -159,31 +160,49 @@ class Analyzer:
|
||||
prices[r].append({
|
||||
'wp': m.waypoint,
|
||||
'buy': p.buy,
|
||||
'sell': p.sell
|
||||
'sell': p.sell,
|
||||
'volume': p.volume
|
||||
})
|
||||
return prices
|
||||
|
||||
def find_trade(self, system):
|
||||
prices = self.prices(system)
|
||||
occupied_resources = set()
|
||||
occupied_routes = set()
|
||||
for s in self.store.all('Ship'):
|
||||
if s.mission != 'trade':
|
||||
continue
|
||||
occupied_resources.add(s.mission_state['resource'])
|
||||
occupied_routes.add((s.mission_state['site'], s.mission_state['dest']))
|
||||
best = None
|
||||
for resource, markets in prices.items():
|
||||
if resource in occupied_resources:
|
||||
continue
|
||||
source = sorted(markets, key=lambda x: x['buy'])[0]
|
||||
dest = sorted(markets, key=lambda x: x['sell'])[-1]
|
||||
swp = source['wp']
|
||||
dwp = dest['wp']
|
||||
margin = dest['sell'] -source['buy']
|
||||
|
||||
dist = source['wp'].distance(dest['wp'])
|
||||
if (swp.symbol,dwp.symbol) in occupied_routes:
|
||||
continue
|
||||
dist = swp.distance(dwp)
|
||||
dist = max(dist, 0.0001)
|
||||
score = margin / dist
|
||||
if margin < 0:
|
||||
continue
|
||||
o = TradeOption(resource, source['wp'], dest['wp'], margin, dist, score)
|
||||
o = TradeOption(resource, swp, dwp, source['buy'], margin, dist, score)
|
||||
if best is None or best.score < o.score:
|
||||
best = o
|
||||
return best
|
||||
|
||||
def find_deal(self, smkt, dmkt):
|
||||
best_margin = 0
|
||||
best_resource = None
|
||||
print(f'finding deal from {smkt} to {dmkt}')
|
||||
for r, sp in smkt.prices.items():
|
||||
if not r in dmkt.prices:
|
||||
print(r, 'not in dmkt')
|
||||
continue
|
||||
dp = dmkt.prices[r]
|
||||
margin = dp.sell - sp.buy
|
||||
print(r, margin)
|
||||
if margin > best_margin:
|
||||
best_margin = margin
|
||||
best_resource = r
|
||||
return best_resource
|
||||
|
@ -131,10 +131,8 @@ class CentralCommand:
|
||||
return
|
||||
print(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.smipa(s, 'resource', t.resource)
|
||||
self.smipa(s, 'site', t.source)
|
||||
self.smipa(s, 'dest', t.dest)
|
||||
self.smipa(s, 'delivery', 'sell')
|
||||
|
||||
def init_mission(self, s, mtyp):
|
||||
if mtyp == 'none':
|
||||
|
@ -85,7 +85,7 @@ class Commander(CommandLine):
|
||||
elif len(matches) > 1:
|
||||
raise CommandError('multiple matches')
|
||||
else:
|
||||
raise CommandError('not found')
|
||||
raise CommandError(f'{arg} not found')
|
||||
|
||||
def resolve_system(self, system_str):
|
||||
if type(system_str) == System:
|
||||
@ -97,6 +97,20 @@ class Commander(CommandLine):
|
||||
system = self.store.get(System, system_str)
|
||||
return system
|
||||
|
||||
def resolve_waypoint(self, w):
|
||||
if type(w) == Waypoint:
|
||||
return w
|
||||
if w == '':
|
||||
if not self.has_ship(): return
|
||||
return self.ship.location
|
||||
p = w.split('-')
|
||||
if len(p) == 1:
|
||||
if not self.has_ship(): return
|
||||
s = self.ship.location.system
|
||||
w = f'{s}-{w}'
|
||||
return self.store.get(Waypoint, w)
|
||||
|
||||
|
||||
######## First run #########
|
||||
def agent_setup(self):
|
||||
symbol = input('agent name: ')
|
||||
@ -232,12 +246,17 @@ class Commander(CommandLine):
|
||||
r = self.api.jumps(waypoint)
|
||||
pprint(r)
|
||||
|
||||
def do_shipyard(self):
|
||||
if not self.has_ship(): return
|
||||
location = self.ship.location
|
||||
def do_shipyard(self, w=''):
|
||||
location = self.resolve_waypoint(w)
|
||||
if location is None:
|
||||
raise CommandError(f'waypoint {w} not found')
|
||||
data = self.api.shipyard(location)
|
||||
if 'ships' in data:
|
||||
for s in must_get(data, 'ships'):
|
||||
print(s['type'], s['purchasePrice'])
|
||||
else:
|
||||
for s in must_get(data, 'shipTypes'):
|
||||
print(s['type'])
|
||||
|
||||
######## Commerce #########
|
||||
def do_refuel(self, source='market'):
|
||||
@ -532,9 +551,12 @@ class Commander(CommandLine):
|
||||
system = self.ship.location.system
|
||||
prices = self.analyzer.prices(system)
|
||||
if resource is not None:
|
||||
pprint(prices[resource.upper()])
|
||||
else:
|
||||
pprint(prices)
|
||||
prices = {resource: prices[resource.upper()]}
|
||||
|
||||
for res, p in prices.items():
|
||||
print('==' + res)
|
||||
for m in p:
|
||||
print(f"{m['wp'].symbol:12s} {m['volume']:5d} {m['buy']:5d} {m['sell']:5d}")
|
||||
|
||||
def do_path(self, waypoint_str):
|
||||
if not self.has_ship(): return
|
||||
|
@ -61,6 +61,8 @@ class Mission:
|
||||
|
||||
def rst(self, typ, nm):
|
||||
symbol = self.st(nm)
|
||||
if symbol is None:
|
||||
return None
|
||||
return self.store.get(typ, symbol)
|
||||
|
||||
def st(self, nm):
|
||||
@ -186,21 +188,6 @@ class BaseMission(Mission):
|
||||
else:
|
||||
return 'more'
|
||||
|
||||
def step_load(self):
|
||||
credits = self.api.agent.credits
|
||||
cargo_space = self.ship.cargo_capacity - self.ship.cargo_units
|
||||
resource = self.st('resource')
|
||||
loc = self.ship.location
|
||||
market = self.store.get('Marketplace', loc.symbol)
|
||||
price = market.buy_price(resource)
|
||||
volume = market.volume(resource)
|
||||
affordable = credits // price
|
||||
amount = min(cargo_space, affordable)
|
||||
while amount > 0:
|
||||
amt = min(amount, volume)
|
||||
self.api.buy(self.ship, resource, amt)
|
||||
amount -= amt
|
||||
|
||||
def step_travel(self):
|
||||
traject = self.st('traject')
|
||||
if traject is None or traject == []:
|
||||
|
@ -6,14 +6,29 @@ class TradeMission(BaseMission):
|
||||
def start_state(self):
|
||||
return 'travel-to'
|
||||
|
||||
def step_load(self):
|
||||
credits = self.api.agent.credits
|
||||
cargo_space = self.ship.cargo_capacity - self.ship.cargo_units
|
||||
smkt = self.store.get('Marketplace', self.st('site'))
|
||||
dmkt = self.store.get('Marketplace', self.st('dest'))
|
||||
resource = self.analyzer.find_deal(smkt, dmkt)
|
||||
if resource is None:
|
||||
return 'done'
|
||||
price = smkt.buy_price(resource)
|
||||
volume = smkt.volume(resource)
|
||||
affordable = credits // price
|
||||
print(cargo_space, affordable, volume)
|
||||
amount = min(cargo_space, affordable, volume)
|
||||
if amount == 0:
|
||||
return 'done'
|
||||
self.api.buy(self.ship, resource, amount)
|
||||
return 'done' if amount == cargo_space else 'more'
|
||||
|
||||
@classmethod
|
||||
def params(cls):
|
||||
return {
|
||||
'site': MissionParam(Waypoint, True),
|
||||
'resource': MissionParam(str, True),
|
||||
'dest': MissionParam(Waypoint, True),
|
||||
'delivery': MissionParam(str, True, 'deliver'),
|
||||
'contract': MissionParam(Contract, False)
|
||||
}
|
||||
|
||||
def steps(self):
|
||||
@ -21,7 +36,10 @@ class TradeMission(BaseMission):
|
||||
**self.travel_steps('to', 'site', 'dock'),
|
||||
'dock': (self.step_dock, 'market-pre'),
|
||||
'market-pre': (self.step_market, 'load'),
|
||||
'load': (self.step_load, 'market-post'),
|
||||
'load': (self.step_load, {
|
||||
'more': 'market-pre',
|
||||
'done': 'market-post'
|
||||
}),
|
||||
'market-post': (self.step_market, 'travel-back'),
|
||||
**self.travel_steps('back', 'dest', 'dock-dest'),
|
||||
'dock-dest': (self.step_dock, 'unload'),
|
||||
|
@ -100,7 +100,7 @@ class Marketplace(Base):
|
||||
r += 'X: ' + ', '.join(self.exchange) + '\n'
|
||||
|
||||
r += '\n'
|
||||
for p in self.prices.values():
|
||||
t = self.rtype(p['symbol'])
|
||||
r += f'{t} {p["symbol"]:25s} {p["sell"]:5d} {p["buy"]:5d}\n'
|
||||
for res, p in self.prices.items():
|
||||
t = self.rtype(res)
|
||||
r += f'{t} {res:25s} {p.sell:5d} {p.buy:5d}\n'
|
||||
return r
|
||||
|
@ -99,6 +99,8 @@ class Ship(Base):
|
||||
|
||||
def deliverable_cargo(self, contract):
|
||||
result = []
|
||||
if contract is None:
|
||||
return result
|
||||
for d in contract.deliveries:
|
||||
if self.get_cargo(d['trade_symbol']) > 0:
|
||||
result.append(d['trade_symbol'])
|
||||
@ -126,6 +128,8 @@ class Ship(Base):
|
||||
mstatus = self.mission_status
|
||||
if mstatus == 'error':
|
||||
mstatus = mstatus.upper()
|
||||
if mstatus is None:
|
||||
mstatus = 'none'
|
||||
status = self.status.lower()
|
||||
if status.startswith('in_'):
|
||||
status = status[3:]
|
||||
|
Loading…
Reference in New Issue
Block a user