Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,11 @@ export const args = Args.create("Beret Busk Tester", "Be good, be kind", {
default: false,
}),
busk: Args.number({
help: `Check a specific busk by passing a number to check (1-5)`
})
help: `Check a specific busk by passing a number to check (1-5)`,
}),
checkhammertime: Args.boolean({
help: `Pretend we have effect hammertime to widen the pants scope`,
}),
});

function parseWeightedModifiers(input: string): [Modifier, number][] {
Expand Down
113 changes: 56 additions & 57 deletions src/utils.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {
beretBuskingEffects,
canEquip,
Effect,
getPower,
Item,
Expand All @@ -10,7 +11,7 @@ import {
toInt,
toSlot,
} from "kolmafia";
import { $familiar, $item, $skill, $slot, clamp, get, have, sum } from "libram";
import { $effect, $familiar, $item, $skill, $slot, clamp, get, have, sum } from "libram";
import { args } from "./main";

export interface Busk {
Expand All @@ -27,7 +28,10 @@ export interface BuskResult {

// eslint-disable-next-line libram/verify-constants
const beret = $item`prismatic beret`;
const taoMultiplier = have($skill`Tao of the Terrapin`) ? 2 : 1;
const taoHatMultiplier = have($skill`Tao of the Terrapin`) ? 2 : 1;
const taoPantsMultiplier = have($skill`Tao of the Terrapin`) ? 1 : 0;
const hammerTimeMultiplier = have($effect`Hammertime`) || args.checkhammertime ? 3 : 0;
const totalPantsMultiplier = 1 + hammerTimeMultiplier + taoPantsMultiplier;

function scoreBusk(
effects: Effect[],
Expand All @@ -45,57 +49,56 @@ function scoreBusk(
export function findTopBusksFast(
weightedModifiers: [Modifier, number][],
uselessEffects: Effect[],
busknumber?: number,
busknumber?: number
): BuskResult | null {
const BUSKNUM = args.allbusks ? 5 : clamp(5 - toInt(get("_beretBuskingUses")), 0, 5);
const startBuskIndex = 5 - BUSKNUM;
const allBusks =
busknumber !== undefined
? beretDASum.map((daRaw) => {
const buskIndex = busknumber - 1;
const rawEffects = beretBuskingEffects(daRaw, buskIndex);
const effects: Effect[] = Array.from(
new Set(
Object.keys(rawEffects)
.map((name) => {
try {
return toEffect(name);
} catch {
print(`Invalid effect name: ${name}`, "red");
return null;
}
})
.filter((e): e is Effect => e !== null)
)
);
const score = scoreBusk(effects, weightedModifiers, uselessEffects);
return { daRaw, effects, score, buskIndex };
})
:
beretDASum.flatMap((daRaw) => {
return Array(BUSKNUM)
.fill(null)
.map((_, i) => {
const buskIndex = startBuskIndex + i;
const rawEffects = beretBuskingEffects(daRaw, buskIndex);
const effects: Effect[] = Array.from(
new Set(
Object.keys(rawEffects)
.map((name) => {
try {
return toEffect(name);
} catch {
print(`Invalid effect name: ${name}`, "red");
return null;
}
})
.filter((e): e is Effect => e !== null)
)
);
const score = scoreBusk(effects, weightedModifiers, uselessEffects);
return { daRaw, effects, score, buskIndex };
});
});
? beretDASum.map((daRaw) => {
const buskIndex = busknumber - 1;
const rawEffects = beretBuskingEffects(daRaw, buskIndex);
const effects: Effect[] = Array.from(
new Set(
Object.keys(rawEffects)
.map((name) => {
try {
return toEffect(name);
} catch {
print(`Invalid effect name: ${name}`, "red");
return null;
}
})
.filter((e): e is Effect => e !== null)
)
);
const score = scoreBusk(effects, weightedModifiers, uselessEffects);
return { daRaw, effects, score, buskIndex };
})
: beretDASum.flatMap((daRaw) => {
return Array(BUSKNUM)
.fill(null)
.map((_, i) => {
const buskIndex = startBuskIndex + i;
const rawEffects = beretBuskingEffects(daRaw, buskIndex);
const effects: Effect[] = Array.from(
new Set(
Object.keys(rawEffects)
.map((name) => {
try {
return toEffect(name);
} catch {
print(`Invalid effect name: ${name}`, "red");
return null;
}
})
.filter((e): e is Effect => e !== null)
)
);
const score = scoreBusk(effects, weightedModifiers, uselessEffects);
return { daRaw, effects, score, buskIndex };
});
});

const bestBusksByIndex = new Map<number, Busk>();
for (const busk of allBusks) {
Expand All @@ -113,15 +116,11 @@ export function findTopBusksFast(

function reconstructOutfit(daRaw: number): { hat?: Item; shirt?: Item; pants?: Item } {
for (const hat of allHats) {
const hatPower = have($skill`Tao of the Terrapin`)
? taoMultiplier * getPower(hat)
: getPower(hat);
const hatPower = taoHatMultiplier * getPower(hat);
for (const shirt of allShirts) {
const shirtPower = getPower(shirt);
for (const pants of allPants) {
const pantsPower = have($skill`Tao of the Terrapin`)
? taoMultiplier * getPower(pants)
: getPower(pants);
const pantsPower = totalPantsMultiplier * getPower(pants);
if (shirtPower + hatPower + pantsPower === daRaw) {
return { hat, shirt, pants };
}
Expand Down Expand Up @@ -172,16 +171,16 @@ export function printBuskResult(result: BuskResult | null, modifiers: Modifier[]
}

// Equipment setup
const allItems = Item.all().filter((i) => have(i));
const allItems = Item.all().filter((i) => have(i) && canEquip(i));
const allHats = have($familiar`Mad Hatrack`)
? allItems.filter((i) => toSlot(i) === $slot`hat`)
: [beret];
const allPants = allItems.filter((i) => toSlot(i) === $slot`pants`);
const allShirts = allItems.filter((i) => toSlot(i) === $slot`shirt`);

const hats = [...new Set(allHats.map((i) => taoMultiplier * getPower(i)))];
const hats = [...new Set(allHats.map((i) => taoHatMultiplier * getPower(i)))];

const pants = [...new Set(allPants.map((i) => taoMultiplier * getPower(i)))];
const pants = [...new Set(allPants.map((i) => totalPantsMultiplier * getPower(i)))];
const shirts = [...new Set(allShirts.map((i) => getPower(i)))];

export const beretDASum = [
Expand Down