Skip to content

Instantly share code, notes, and snippets.

@Apsu

Apsu/infuse.py Secret

Last active October 2, 2015 02:12
Show Gist options
  • Save Apsu/a65b229d4a71be9992b7 to your computer and use it in GitHub Desktop.
Save Apsu/a65b229d4a71be9992b7 to your computer and use it in GitHub Desktop.
Destiny Item Infusion Calculator
#!/usr/bin/env python3
"""Destiny Item Infusion Calculator
Calculates infusion possibilities, showing costs and final light.
Usage:
infuse.py [-x] ITEM ITEM [ITEM ...]
Arguments:
Light levels of items to consider for infusion.
At least two items are required, but multiple items can be provided
in any order; duplicates will be pruned. The lowest light item is
considered the one to infuse, and the highest light item is considered
the target. All infusion paths will be calculated.
ITEM Integer light level of item (e.g., 280)
Options:
-x --exotic Base item is exotic
--version Show version
"""
from docopt import docopt
import functools
import itertools
# Legendary Mark cost per infusion
COST = 3
def permutate(low, high, mid):
"""
Calculate permutations
<- low:1, high:5, mid: 2 3
1 5
1 2 5
1 3 5
1 2 3 5
"""
# Initialize permutations
perms = [[low, high]]
# For each sublist of middle values
for l in range(1, len(mid) + 1):
# For each permutation of sublist
for perm in itertools.combinations(mid, l):
# Store [low, permutation, high] list
perms.append(list(itertools.chain([low], perm, [high])))
return perms
def infuse(base, target, exotic=False):
"""Infuse base item with target item"""
# Store difference in items
diff = target - base
# When items are close in light
if diff < (4 if exotic else 6):
# No penalty, just return target light
return target
# Otherwise assess penalty
else:
# Resulting light is 80% of the difference
return round(diff * 0.8) + base
def walk(items, exotic=False):
"""Walk an infusion path"""
# Store path reduction by chaining infusions
result = functools.reduce(lambda x, y: infuse(x, y, exotic), items)
# Send it back with the step cost
return (result, (len(items) - 1) * COST, items)
def calculate(args):
"""Calculate infusion paths"""
# Is item exotic?
exotic = args['--exotic']
# Get unique sorted list of items as integers
items = list(sorted(map(int, set(args['ITEM']))))
# Store lowest, highest and inbetween
low = items[0]
high = items[-1]
mid = items[1:-1]
print("##### Infusing {} light item towards {} light target #####".format(
low, high))
# Get permutations
perms = permutate(low, high, mid)
# Walk each path and store results, sorted by light result
paths = sorted([walk(perm, exotic)
for perm in perms], key=lambda index: index[0])
# Initialize best light/least marks and least marks/best light
light_marks = marks_light = (0, 100, )
# Collect results
for path in paths:
# Extract parts
light, marks, steps = path
# If light is best we've seen, or same light but least marks
if (light > light_marks[0] or
(light == light_marks[0] and marks < light_marks[1])):
# Store it
light_marks = (light, marks, steps)
# If marks is least we've seen, or same marks but best light
if (marks < marks_light[1] or
(marks == marks_light[1] and light > marks_light[0])):
# Store it
marks_light = (light, marks, steps)
# Print each possible path
print("Light: {}, Marks: {}, Infusion: {}".format(
light, marks, " -> ".join(map(str, steps))))
# Show best light, but least marks
light, marks, steps = light_marks
print()
print("##### Best light with least marks #####")
print("Light: {}, Marks: {}, Infusion: {}".format(
light, marks, " -> ".join(map(str, steps))))
# Show least marks, but best light
light, marks, steps = marks_light
print()
print("##### Least marks with best light #####")
print("Light: {}, Marks: {}, Infusion: {}".format(
light, marks, " -> ".join(map(str, steps))))
# Entry point
if __name__ == "__main__":
calculate(docopt(__doc__, version="Infuse 1.0"))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment