diff --git a/skillpoint_test.py b/skillpoint_test.py index 0738100..9cdc68d 100644 --- a/skillpoint_test.py +++ b/skillpoint_test.py @@ -69,93 +69,153 @@ for item in build_items: setup(item) if all(x == 0 for x in item["reqs"]): fixed.append(item) - elif all(x == 0 for x in item["skillpoints"]): + elif all(x == 0 for x in item["skillpoints"]) and item["set"] is None: noboost.append(item) else: consider.append(item) setup(build_weapon) fixed = tuple(fixed) noboost = tuple(noboost) +consider = tuple(consider) + +""" +The way this code expects this to work: +sets is a map: setName -> setObject { + bonuses: array[bonusObject] +} + +where each bonusObject is a mapping from id to boost value. +And the bonuses array describes the effect of equipping set items (0 index = 1 item). +""" +sets = dict() # Apply the skillpoints an item gives to the build. -def apply_skillpoints(skillpoints, item): +""" +skillPoints: current skillpoint totals. +item: Item in uestion. +activeSetCounts: Mapping from setname to number of items currently worn (not including this one). +""" +def apply_skillpoints(skillpoints, item, activeSetCounts): for i in range(5): skillpoints[i] += item["skillpoints"][i] -def remove_skillpoints(skillpoints, item): - for i in range(5): - skillpoints[i] -= item["skillpoints"][i] + if item["set"] is not None: + setName = item["set"] + old_bonus = dict() + if setName in activeSetCounts: + setCount = activeSetCounts[setName] + old_bonus = sets[setName]["bonuses"][setCount-1] + activeSetCounts[setName] = setCount + 1 + else: + setCount = 0 + activeSetCounts[setName] = 1 + new_bonus = sets[setName]["bonuses"][setCount] + skp_order = ["str","dex","int","def","agi"] + for i, skp in enumerate(skp_order): + delta = new_bonus[skp] - old_bonus[skp] + skillpoints[i] += delta # Figure out (naively) how many skillpoints need to be applied to get the current item to fit. # Doesn't handle -skp. -def apply_to_fit(skillpoints, item): +def apply_to_fit(skillpoints, item, skillpoint_filter, activeSetCounts): applied = [0, 0, 0, 0, 0] total = 0 for i, req, cur in zip(range(5), item["reqs"], skillpoints): + if item["skillpoints"][i] < 0 and skillpoint_filter[i]: + applied[i] -= item["skillpoints"][i] + total -= item["skillpoints"][i] if (item["reqs"][i] == 0): continue + skillpoint_filter[i] = True if req > cur: diff = req - cur applied[i] += diff total += diff + + if item["set"] is not None: + setName = item["set"] + old_bonus = dict() + if setName in activeSetCounts: + setCount = activeSetCounts[setName] + old_bonus = sets[setName]["bonuses"][setCount-1] + activeSetCounts[setName] = setCount + 1 + else: + setCount = 0; + activeSetCounts[setName] = 1 + new_bonus = sets[setName]["bonuses"][setCount] + skp_order = ["str","dex","int","def","agi"] + for i, skp in enumerate(skp_order): + delta = new_bonus[skp] - old_bonus[skp] + if delta < 0 and skillpoint_filter[i]: + applied[i] -= delta + total -= delta return applied, total # Permutations in js reference (also cool algorithm): # https://stackoverflow.com/a/41068709 static_skillpoints_base = [0, 0, 0, 0, 0] +static_activeSetCounts = dict() # Separate out the no req items and add them to the static skillpoint base. for item in fixed: - apply_skillpoints(static_skillpoints_base, item) + apply_skillpoints(static_skillpoints_base, item, static_activeSetCounts) -best = None -final_skillpoints = None +best = consider + noboost; +final_skillpoints = static_skillpoints_base[:] best_skillpoints = [0, 0, 0, 0, 0] best_total = math.inf +best_activeSetCounts = dict() -# Try every combination and pick the best one. -import itertools -for permutation in itertools.permutations(consider): +allFalse = [False] * 5 - permutation += noboost +if len(consider) or len(noboost): - skillpoints_applied = [0, 0, 0, 0, 0] - skillpoints = copy.copy(static_skillpoints_base) - total_applied = 0 - for item in permutation: - needed_skillpoints, total_diff = apply_to_fit(skillpoints, item) - for i in range(5): - skillpoints_applied[i] += needed_skillpoints[i] - skillpoints[i] += needed_skillpoints[i] - apply_skillpoints(skillpoints, item) - total_applied += total_diff - if total_applied >= best_total: - break - if total_applied < best_total: + # Try every combination and pick the best one. + import itertools + for permutation in itertools.permutations(consider): + activeSetCounts = dict(best_activeSetCounts) + has_skillpoint = allFalse[:] + + permutation += noboost + + skillpoints_applied = [0, 0, 0, 0, 0] + skillpoints = static_skillpoints_base[:] + total_applied = 0 for item in permutation: - remove_skillpoints(skillpoints, item) - needed_skillpoints, total_diff = apply_to_fit(skillpoints, item) + needed_skillpoints, total_diff = apply_to_fit(skillpoints, item, has_skillpoint, activeSetCounts) for i in range(5): skillpoints_applied[i] += needed_skillpoints[i] skillpoints[i] += needed_skillpoints[i] - apply_skillpoints(skillpoints, item) + apply_skillpoints(skillpoints, item, activeSetCounts) total_applied += total_diff if total_applied >= best_total: break - needed_skillpoints, total_diff = apply_to_fit(skillpoints, build_weapon) - for i in range(5): - skillpoints_applied[i] += needed_skillpoints[i] - skillpoints[i] += needed_skillpoints[i] - apply_skillpoints(skillpoints, build_weapon) - total_applied += total_diff + needed_skillpoints, total_diff = apply_to_fit(skillpoints, build_weapon, has_skillpoint, activeSetCounts) + for i in range(5): + skillpoints_applied[i] += needed_skillpoints[i] + skillpoints[i] += needed_skillpoints[i] + apply_skillpoints(skillpoints, build_weapon, activeSetCounts) + total_applied += total_diff - if total_applied < best_total: - best = permutation - final_skillpoints = skillpoints - best_skillpoints = skillpoints_applied - best_total = total_applied + if total_applied < best_total: + best = permutation + final_skillpoints = skillpoints + best_skillpoints = skillpoints_applied + best_total = total_applied + best_activeSetCounts = activeSetCounts +else: + best_total = 0 + needed_skillpoints, total_diff = apply_to_fit(skillpoints, build_weapon, allFalse, best_activeSetCounts) + for i in range(5): + best_skillpoints[i] += needed_skillpoints[i] + final_skillpoints[i] += needed_skillpoints[i] + apply_skillpoints(skillpoints, build_weapon, best_activeSetCounts) + best_total += total_diff + +equip_order = fixed + best +results = [equip_order, best_skillpoints, final_skillpoints, best_total, best_activeSetCounts]; print([i["displayName"] for i in fixed + best]) print(best_skillpoints) diff --git a/skillpoints.js b/skillpoints.js index 5e02fd1..dbbaf48 100644 --- a/skillpoints.js +++ b/skillpoints.js @@ -44,8 +44,6 @@ function calculate_skillpoints(equipment, weapon) { } } - // Figure out (naively) how many skillpoints need to be applied to get the current item to fit. - // Doesn't handle -skp. function apply_to_fit(skillpoints, item, skillpoint_filter, activeSetCounts) { let applied = [0, 0, 0, 0, 0]; let total = 0; @@ -145,8 +143,6 @@ function calculate_skillpoints(equipment, weapon) { total_applied += total_diff; if (total_applied < best_total) { - console.log(pre); - console.log(skillpoints); best = permutation; final_skillpoints = skillpoints; best_skillpoints = skillpoints_applied; @@ -165,7 +161,7 @@ function calculate_skillpoints(equipment, weapon) { best_skillpoints[i] += needed_skillpoints[i]; final_skillpoints[i] += needed_skillpoints[i]; } - apply_skillpoints(final_skillpoints, weapon); + apply_skillpoints(final_skillpoints, weapon, best_activeSetCounts); best_total += total_diff; } let equip_order = fixed.concat(best);