Active play and the Watchtower Depths dungeon
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
db1a00e8aa
commit
9d61de2012
9 changed files with 790 additions and 56 deletions
|
|
@ -1,7 +1,13 @@
|
|||
#!/usr/bin/env python3
|
||||
"""Balance report: an hour of fighting for each trade with its own weapon, at each tier.
|
||||
|
||||
python3 tools/balance.py [solo|party] [seeds] [levels, e.g. 22,52] [potions]
|
||||
python3 tools/balance.py [solo|party|bosses] [seeds] [levels, e.g. 22,52] [potions]
|
||||
python3 tools/balance.py dungeon [seeds] [level] [perfect]
|
||||
|
||||
`dungeon` plays each pull of every dungeon for a group of four and a pair, everyone with the
|
||||
tier's gear, food and health potions. `perfect` stands in for active play: real cooldowns, no
|
||||
waiting on auto's rules, quick interrupts. Bosses should beat an all-auto group and fall to one
|
||||
that plays.
|
||||
|
||||
Each row is one encounter: wins and losses in the hour, XP an hour, food eaten an hour,
|
||||
and the share of a kill's time spent fighting (the rest is resting between fights).
|
||||
|
|
@ -97,8 +103,41 @@ def report(groups: dict, seeds: int, levels: set | None = None) -> None:
|
|||
BOSSES = ["fight_ruins", "fight_barrow_king", "fight_green_dragon", "fight_blue_dragon", "fight_red_dragon"]
|
||||
|
||||
|
||||
def dungeon(seeds: int, level: int | None) -> None:
|
||||
for key, spec in game.DUNGEONS.items():
|
||||
tier = spec["tier"]
|
||||
at = level or spec["level"] + 3
|
||||
action = game.ACTION_BY_ID[key]
|
||||
for group in (["builder", "homesteader", "miner", "ranger"], ["builder", "homesteader"]):
|
||||
global POTIONS
|
||||
POTIONS = True
|
||||
print(f"{spec['name']}: {'+'.join(group)} at {at}")
|
||||
print(f"{'pull':18} {'win':>5} {'secs':>5} {'downs':>5} {'potions':>7}")
|
||||
for index, (name, _pack) in enumerate(spec["pulls"]):
|
||||
wins, secs, downs, drunk = 0, [], [], []
|
||||
for seed in range(seeds):
|
||||
world = game.new_world(T0)
|
||||
players = [fighter(world, f"p{i}", cls, at, tier) for i, cls in enumerate(group)]
|
||||
fight = game.draw_pull(world, players, action, {"pull": index, "wipes": 0}, random.Random(seed), T0)
|
||||
if fight["result"] == "won":
|
||||
wins += 1
|
||||
secs.append(fight["duration"] - fight["rest"])
|
||||
downs.append(sum(1 for m in fight["members"] if m["down"]))
|
||||
drunk.append(sum(1 for m in fight["members"] if m["drank"]))
|
||||
mean = lambda xs: statistics.mean(xs) if xs else 0
|
||||
print(f"{name:18} {wins / seeds:>5.0%} {mean(secs):>5.0f} {mean(downs):>5.1f} {mean(drunk):>7.1f}")
|
||||
print()
|
||||
|
||||
|
||||
def main() -> None:
|
||||
mode = sys.argv[1] if len(sys.argv) > 1 else "solo"
|
||||
if mode == "dungeon":
|
||||
if "perfect" in sys.argv:
|
||||
game.combat.AUTO_CD, game.combat.AUTO_DELAY, game.combat.AUTO_REACT = 1.0, 0.0, 0.25
|
||||
print("-- perfect hands --")
|
||||
dungeon(int(sys.argv[2]) if len(sys.argv) > 2 else 20,
|
||||
int(sys.argv[3]) if len(sys.argv) > 3 and sys.argv[3].isdigit() else None)
|
||||
return
|
||||
seeds = int(sys.argv[2]) if len(sys.argv) > 2 else 3
|
||||
levels = {int(level) for level in sys.argv[3].split(",")} if len(sys.argv) > 3 and sys.argv[3] != "all" else None
|
||||
global POTIONS
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue