Skip to content

Commit

Permalink
Added "--towards" option to "run" command for building a route that r…
Browse files Browse the repository at this point in the history
…equires every hop be at least as close to the goal system as the previous hop. Hops that reduce the distance are significantly favored in scoring.
  • Loading branch information
kfsone committed Feb 7, 2015
1 parent 3a1aa4e commit ec592b2
Show file tree
Hide file tree
Showing 4 changed files with 90 additions and 12 deletions.
5 changes: 4 additions & 1 deletion CHANGES.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@
TradeDangerous, Copyright (C) Oliver "kfsone" Smith, July 2014
==============================================================================

[wip] Feb 05 2015
v6.9.0 Feb 06 2015
. (kfsone) Added "--towards" option to "run" command:
--towards GOALSYSTEM will restrict the route to destinations which
move the player towards GOALSYSTEM.
. (kfsone) Added "distanceTo" function to "System" which returns the
distance in ly to a second system,
. (kfsone) Minor performance gain in distance calculations,
Expand Down
8 changes: 8 additions & 0 deletions README.txt
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,14 @@ RUN sub-command:
--to Beagle2
--to lhs64

--towards <goal system>
Builds a route that tries to shorten the distance from your origin
and goal. Destinations that would increase the distance are ignored.
Tries to avoid routes that go backwards or detour. If you want to
avoid multiple visits in the same system, use --unique.
e.g.
--from iBootis --to LiuBese

--start-jumps N
-s N
Considers stations from systems upto this many jumps from your
Expand Down
34 changes: 28 additions & 6 deletions commands/run_cmd.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,23 @@
dest='starting',
metavar='STATION',
),
ParseArgument('--to',
help='Final system/station.',
dest='ending',
metavar='PLACE',
MutuallyExclusiveGroup(
ParseArgument('--to',
help='Final system/station.',
dest='ending',
metavar='PLACE',
default=None,
),
ParseArgument('--towards',
help=(
'Choose a route that continually reduces the '
'distance towards this system.'
),
dest='goalSystem',
metavar='SYSTEM',
default=None,
),
),
ParseArgument('--via',
help='Require specified systems/stations to be en-route.',
action='append',
Expand Down Expand Up @@ -532,6 +544,11 @@ def validateRunArguments(tdb, cmdenv):
else:
if cmdenv.endJumps:
raise CommandLineError("--end-jumps (-e) only works with --to")
if cmdenv.goalSystem:
if not cmdenv.origPlace:
raise CommandLineError("--towards requires --from")
dest = tdb.lookupPlace(cmdenv.goalSystem)
cmdenv.goalSystem = dest.system

origins, destns = cmdenv.origins or [], cmdenv.destinations or []

Expand Down Expand Up @@ -692,6 +709,7 @@ def run(results, cmdenv, tdb):
origPlace, viaSet = cmdenv.origPlace, cmdenv.viaSet
avoidPlaces = cmdenv.avoidPlaces
stopStations = cmdenv.destinations
goalSystem = cmdenv.goalSystem

startCr = cmdenv.credits - cmdenv.insurance

Expand Down Expand Up @@ -775,6 +793,10 @@ def run(results, cmdenv, tdb):
)
break
routes = newRoutes
if goalSystem:
if any(route.route[-1].system is goalSystem for route in routes):
cmdenv.NOTE("Goal system reached!")
break

if not routes:
raise NoDataError("No profitable trades matched your critera, or price data along the route is missing.")
Expand Down Expand Up @@ -803,8 +825,8 @@ def render(results, cmdenv, tdb):

routes = results.data

for i in range(0, min(len(routes), cmdenv.routes)):
print(routes[i].detail(detail=cmdenv.detail))
for i in range(min(len(routes), cmdenv.routes)):
print(routes[i].detail(cmdenv))

# User wants to be guided through the route.
if cmdenv.checklist:
Expand Down
55 changes: 50 additions & 5 deletions tradecalc.py
Original file line number Diff line number Diff line change
Expand Up @@ -163,11 +163,13 @@ def __eq__(self, rhs):
def str(self):
return "%s -> %s" % (self.route[0].name(), self.route[-1].name())

def detail(self, detail=0):
def detail(self, tdenv):
"""
Return a string describing this route to a given level of detail.
"""

detail, goalSystem = tdenv.detail, tdenv.goalSystem

credits = self.startCr
gainCr = 0
route = self.route
Expand Down Expand Up @@ -250,6 +252,16 @@ def decorateStation(station):
def decorateStation(station):
return station.name()

if detail and goalSystem:
def goalDistance(station):
return " [Distance to {}: {:.2f} ly]\n".format(
goalSystem.name(),
station.system.distanceTo(goalSystem),
)
else:
def goalDistance(station):
return ""

for i, hop in enumerate(hops):
hopGainCr, hopTonnes = hop[1], 0
purchases = ""
Expand All @@ -274,6 +286,7 @@ def decorateStation(station):
age=age,
)
hopTonnes += qty
text += goalDistance(route[i])
text += hopFmt.format(
station=decorateStation(route[i]),
purchases=purchases
Expand All @@ -298,6 +311,8 @@ def decorateStation(station):

gainCr += hopGainCr

if route[-1].system is not goalSystem:
text += goalDistance(route[-1])
text += footer or ""
text += endFmt.format(
station=decorateStation(route[-1]),
Expand Down Expand Up @@ -637,6 +652,8 @@ def getBestHops(self, routes, restrictTo=None):
else:
lsPenalty = 0

goalSystem = tdenv.goalSystem

restrictStations = set()
if restrictTo:
for place in restrictTo:
Expand Down Expand Up @@ -667,7 +684,13 @@ def getBestHops(self, routes, restrictTo=None):
except KeyError:
pass

def considerStation(dstStation, dest):
if goalSystem:
origSystem = route.route[0].system
srcSystem = srcStation.system
srcGoalDist = srcSystem.distanceTo(goalSystem)
srcOrigDist = srcSystem.distanceTo(origSystem)

def considerStation(dstStation, dest, multiplier):
# Do we have something to trade?
try:
trading = srcTradingWith[dstStation]
Expand All @@ -694,7 +717,9 @@ def considerStation(dstStation, dest):
# http://goo.gl/Otj2XP
penalty = ((cruiseKls ** 2) - cruiseKls) / 3
penalty *= lsPenalty
score *= (1 - penalty)
multiplier *= (1 - penalty)

score *= multiplier

dstID = dstStation.ID
try:
Expand Down Expand Up @@ -750,11 +775,31 @@ def considerStation(dstStation, dest):
dest.distLy
)

multiplier = 1.0
if restrictStations:
if dstStation not in restricting:
continue

considerStation(dstStation, dest)
elif goalSystem:
# Bias in favor of getting closer
dstSys = dstStation.system
if dstSys == srcSystem:
if tdenv.unique:
continue
else:
dstGoalDist = dstSys.distanceTo(goalSystem)
if dstGoalDist >= srcGoalDist:
continue
dstOrigDist = dstSys.distanceTo(origSystem)
if dstOrigDist < srcOrigDist:
# Did this put us back towards the orig?
# It may be valid to do so but it's not "profitable".
multiplier *= 0.6
else:
# The closer dst is, the smaller the divider
# will be, so the larger the remainder.
multiplier *= 1 + (srcGoalDist / dstGoalDist)

considerStation(dstStation, dest, multiplier)

if restrictStations:
restricting.remove(dstStation)
Expand Down

0 comments on commit ec592b2

Please sign in to comment.