libram 0.9.5 → 0.9.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/Clan.js +1 -1
- package/dist/challengePaths/2015/CommunityService.js +11 -11
- package/dist/diet/index.d.ts +3 -0
- package/dist/diet/index.js +55 -44
- package/dist/lib.d.ts +43 -3
- package/dist/lib.js +138 -28
- package/dist/lib.test.js +21 -1
- package/dist/maximize.d.ts +1 -0
- package/dist/maximize.js +5 -2
- package/dist/modifierTypes.d.ts +1 -1
- package/dist/modifierTypes.js +1 -1
- package/dist/propertyTypes.d.ts +3 -3
- package/dist/propertyTypes.js +3 -3
- package/dist/resources/2009/Bandersnatch.js +3 -4
- package/dist/resources/2011/StompingBoots.js +3 -4
- package/dist/resources/2014/ConspiracyIsland.d.ts +47 -0
- package/dist/resources/2014/ConspiracyIsland.js +128 -0
- package/dist/resources/2015/Dinseylandfill.js +1 -1
- package/dist/resources/2017/AsdonMartin.js +3 -1
- package/dist/resources/2017/Spacegate.js +0 -1
- package/dist/resources/2019/PocketProfessor.d.ts +26 -0
- package/dist/resources/2019/PocketProfessor.js +41 -0
- package/dist/resources/2020/RetroCape.d.ts +1 -1
- package/dist/resources/2021/DaylightShavings.d.ts +3 -2
- package/dist/resources/2021/DaylightShavings.js +7 -6
- package/dist/resources/2024/MayamCalendar.d.ts +1 -1
- package/dist/resources/2024/TearawayPants.d.ts +22 -0
- package/dist/resources/2024/TearawayPants.js +52 -0
- package/dist/resources/index.d.ts +4 -1
- package/dist/resources/index.js +4 -1
- package/dist/template-string.d.ts +37 -20
- package/dist/template-string.js +35 -31
- package/package.json +27 -28
package/dist/Clan.js
CHANGED
|
@@ -92,7 +92,7 @@ export class Clan {
|
|
|
92
92
|
startingClan.join();
|
|
93
93
|
}
|
|
94
94
|
}
|
|
95
|
-
static withStash(clanIdOrName, items, // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
95
|
+
static withStash(clanIdOrName, items, // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
96
96
|
callback) {
|
|
97
97
|
return Clan._withStash(() => Clan.with(clanIdOrName, (clan) => clan.take(items)), (borrowed) => Clan.with(clanIdOrName, (clan) => clan.put(borrowed)), callback);
|
|
98
98
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { equippedItem,
|
|
2
|
-
import { have } from "../../lib.js";
|
|
1
|
+
import { equippedItem, getPower, haveEquipped, myAdventures, myBasestat, myBuffedstat, myFamiliar, myMaxhp, myThrall, myTurncount, numericModifier, print, runChoice, toSlot, visitUrl, } from "kolmafia";
|
|
2
|
+
import { have, totalFamiliarWeight } from "../../lib.js";
|
|
3
3
|
import { Requirement } from "../../maximize.js";
|
|
4
4
|
import { get } from "../../property.js";
|
|
5
5
|
import { MummingTrunk } from "../../resources/index.js";
|
|
@@ -18,7 +18,6 @@ const statCommunityServicePredictor = (stat) => {
|
|
|
18
18
|
: stat)));
|
|
19
19
|
};
|
|
20
20
|
const visitCouncil = () => visitUrl("council.php");
|
|
21
|
-
const baseWeight = () => have($effect `Fidoxene`) ? 20 : familiarWeight(myFamiliar());
|
|
22
21
|
function hypotheticalModifier(modifier, ...effects) {
|
|
23
22
|
const newEffects = effects.filter((e) => !have(e));
|
|
24
23
|
return (numericModifier(modifier) +
|
|
@@ -240,7 +239,8 @@ export default class CommunityService {
|
|
|
240
239
|
static Mysticality = new CommunityService(3, "Mysticality", "Build Playground Mazes", statCommunityServicePredictor($stat `Mysticality`), new Requirement(["Mysticality"], {}));
|
|
241
240
|
static Moxie = new CommunityService(4, "Moxie", "Feed Conspirators", statCommunityServicePredictor($stat `Moxie`), new Requirement(["Moxie"], {}));
|
|
242
241
|
static FamiliarWeight = new CommunityService(5, "Familiar Weight", "Breed More Collies", (...effects) => 60 -
|
|
243
|
-
Math.floor((
|
|
242
|
+
Math.floor((totalFamiliarWeight(myFamiliar(), false) +
|
|
243
|
+
hypotheticalModifier("Familiar Weight", ...effects)) /
|
|
244
244
|
5), new Requirement(["Familiar Weight"], {}));
|
|
245
245
|
static WeaponDamage = new CommunityService(6, "Weapon Damage", "Reduce Gazelle Population", (...effects) => {
|
|
246
246
|
const weaponPower = getPower(equippedItem($slot `weapon`));
|
|
@@ -266,7 +266,7 @@ export default class CommunityService {
|
|
|
266
266
|
}, new Requirement(["Weapon Damage", "Weapon Damage Percent"], {}));
|
|
267
267
|
static SpellDamage = new CommunityService(7, "Spell Damage", "Make Sausage", (...effects) => {
|
|
268
268
|
const dragonfishDamage = myFamiliar() === $familiar `Magic Dragonfish`
|
|
269
|
-
? numericModifier($familiar `Magic Dragonfish`, "Spell Damage Percent",
|
|
269
|
+
? numericModifier($familiar `Magic Dragonfish`, "Spell Damage Percent", totalFamiliarWeight(), $item.none)
|
|
270
270
|
: 0;
|
|
271
271
|
// We add 0.001 because the floor function sometimes introduces weird rounding errors
|
|
272
272
|
return (60 -
|
|
@@ -280,9 +280,9 @@ export default class CommunityService {
|
|
|
280
280
|
const noncombatRate = -1 * hypotheticalModifier("Combat Rate", ...effects);
|
|
281
281
|
const unsoftcappedRate = (rate) => rate > 25 ? 25 + (rate - 25) * 5 : rate;
|
|
282
282
|
const currentFamiliarModifier = -1 *
|
|
283
|
-
numericModifier(myFamiliar(), "Combat Rate",
|
|
283
|
+
numericModifier(myFamiliar(), "Combat Rate", totalFamiliarWeight(), equippedItem($slot `familiar`));
|
|
284
284
|
const newFamiliarModifier = -1 *
|
|
285
|
-
numericModifier(myFamiliar(), "Combat Rate",
|
|
285
|
+
numericModifier(myFamiliar(), "Combat Rate", totalFamiliarWeight(myFamiliar(), false) +
|
|
286
286
|
hypotheticalModifier("Familiar Weight", ...effects), equippedItem($slot `familiar`));
|
|
287
287
|
const adjustedRate = unsoftcappedRate(noncombatRate) -
|
|
288
288
|
unsoftcappedRate(currentFamiliarModifier) +
|
|
@@ -294,10 +294,10 @@ export default class CommunityService {
|
|
|
294
294
|
const mummingBuff = mummingCostume && mummingCostume[0] === "Item Drop"
|
|
295
295
|
? mummingCostume[1]
|
|
296
296
|
: 0;
|
|
297
|
-
const familiarItemDrop = numericModifier(myFamiliar(), "Item Drop",
|
|
297
|
+
const familiarItemDrop = numericModifier(myFamiliar(), "Item Drop", totalFamiliarWeight(), equippedItem($slot `familiar`)) +
|
|
298
298
|
mummingBuff -
|
|
299
299
|
numericModifier(equippedItem($slot `familiar`), "Item Drop");
|
|
300
|
-
const familiarBoozeDrop = numericModifier(myFamiliar(), "Booze Drop",
|
|
300
|
+
const familiarBoozeDrop = numericModifier(myFamiliar(), "Booze Drop", totalFamiliarWeight(), equippedItem($slot `familiar`)) - numericModifier(equippedItem($slot `familiar`), "Booze Drop");
|
|
301
301
|
// Champagne doubling does NOT count for CS, so we undouble
|
|
302
302
|
const multiplier = haveEquipped($item `broken champagne bottle`) &&
|
|
303
303
|
get("garbageChampagneCharge") > 0
|
|
@@ -318,8 +318,8 @@ export default class CommunityService {
|
|
|
318
318
|
preventEquip: $items `broken champagne bottle`,
|
|
319
319
|
}));
|
|
320
320
|
static HotRes = new CommunityService(10, "Hot Resistance", "Clean Steam Tunnels", (...effects) => {
|
|
321
|
-
const currentFamiliarModifier = numericModifier(myFamiliar(), "Hot Resistance",
|
|
322
|
-
const newFamiliarModifier = numericModifier(myFamiliar(), "Hot Resistance",
|
|
321
|
+
const currentFamiliarModifier = numericModifier(myFamiliar(), "Hot Resistance", totalFamiliarWeight(), equippedItem($slot `familiar`));
|
|
322
|
+
const newFamiliarModifier = numericModifier(myFamiliar(), "Hot Resistance", totalFamiliarWeight(myFamiliar(), false) +
|
|
323
323
|
hypotheticalModifier("Familiar Weight", ...effects), equippedItem($slot `familiar`));
|
|
324
324
|
return (60 -
|
|
325
325
|
(hypotheticalModifier("Hot Resistance", ...effects) -
|
package/dist/diet/index.d.ts
CHANGED
|
@@ -22,6 +22,8 @@ export declare class MenuItem<T> {
|
|
|
22
22
|
priceOverride?: number;
|
|
23
23
|
mayo?: Item;
|
|
24
24
|
data?: T;
|
|
25
|
+
private priceCached?;
|
|
26
|
+
private itemTypeCached?;
|
|
25
27
|
static defaultPriceFunction: (item: Item) => number;
|
|
26
28
|
static defaultOptions<T>(): Map<Item, MenuItemOptions<T>>;
|
|
27
29
|
/**
|
|
@@ -41,6 +43,7 @@ export declare class MenuItem<T> {
|
|
|
41
43
|
equals(other: MenuItem<T>): boolean;
|
|
42
44
|
toString(): string;
|
|
43
45
|
price(): number;
|
|
46
|
+
itemType(): string;
|
|
44
47
|
}
|
|
45
48
|
declare const organs: readonly ["food", "booze", "spleen item"];
|
|
46
49
|
type Organ = (typeof organs)[number];
|
package/dist/diet/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { canEquip, fullnessLimit, historicalAge, historicalPrice, inebrietyLimit, itemType, mallPrice, mallPrices, myFullness, myInebriety, myLevel, myPrimestat, mySpleenUse, npcPrice, spleenLimit, } from "kolmafia";
|
|
2
|
-
import { have } from "../lib.js";
|
|
2
|
+
import { getRange, have } from "../lib.js";
|
|
3
3
|
import { get as getModifier } from "../modifier.js";
|
|
4
4
|
import { get } from "../property.js";
|
|
5
5
|
import { Mayo, installed as mayoInstalled, } from "../resources/2015/MayoClinic.js";
|
|
@@ -10,27 +10,29 @@ function isMonday() {
|
|
|
10
10
|
// Checking Tuesday's ruby is a hack to see if it's Monday in Arizona.
|
|
11
11
|
return getModifier("Muscle Percent", $item `Tuesday's ruby`) > 0;
|
|
12
12
|
}
|
|
13
|
+
function seasoningAdventures(item) {
|
|
14
|
+
const [min, max] = getRange(item.adventures);
|
|
15
|
+
return max - min <= 1 ? 1 : 0.5;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
13
18
|
/**
|
|
14
19
|
* Expected adventures from an item given a specified state
|
|
15
20
|
*
|
|
16
21
|
* @todo Include Salty Mouth and potentially other modifiers.
|
|
17
|
-
* @param item
|
|
22
|
+
* @param menuItem Menu item to consider
|
|
18
23
|
* @param modifiers Consumption modifiers to consider
|
|
19
24
|
* @returns Adventures expected
|
|
20
25
|
*/
|
|
21
|
-
function expectedAdventures(
|
|
26
|
+
function expectedAdventures(menuItem, modifiers) {
|
|
27
|
+
const item = menuItem.item;
|
|
22
28
|
if (item.adventures === "")
|
|
23
29
|
return 0;
|
|
24
|
-
const [min,
|
|
25
|
-
.split(/[-]/)
|
|
26
|
-
.map((s) => parseInt(s));
|
|
27
|
-
const max = recordedMax ?? min;
|
|
30
|
+
const [min, max] = getRange(item.adventures);
|
|
28
31
|
const interpolated = [...new Array(max - min + 1).keys()].map((n) => n + min);
|
|
29
|
-
const forkMugMultiplier = (itemType(
|
|
30
|
-
(itemType(
|
|
32
|
+
const forkMugMultiplier = (menuItem.itemType() === "food" && item.notes?.includes("SALAD")) ||
|
|
33
|
+
(menuItem.itemType() === "booze" && item.notes?.includes("BEER"))
|
|
31
34
|
? 1.5
|
|
32
35
|
: 1.3;
|
|
33
|
-
const seasoningAdventures = max - min <= 1 ? 1 : 0.5;
|
|
34
36
|
const aioliAdventures = item.fullness;
|
|
35
37
|
const garish = modifiers.garish && item.notes?.includes("LASAGNA") && !isMonday();
|
|
36
38
|
const refinedPalate = modifiers.refinedPalate && item.notes?.includes("WINE");
|
|
@@ -52,13 +54,15 @@ function expectedAdventures(item, modifiers) {
|
|
|
52
54
|
if (item.notes?.includes("MARTINI") && modifiers.tuxedoShirt) {
|
|
53
55
|
adventures += 2;
|
|
54
56
|
}
|
|
55
|
-
if (itemType(
|
|
57
|
+
if (menuItem.itemType() === "food" && modifiers.mayoflex)
|
|
56
58
|
adventures++;
|
|
57
|
-
if (itemType(
|
|
58
|
-
adventures += seasoningAdventures;
|
|
59
|
-
|
|
59
|
+
if (menuItem.itemType() === "food" && modifiers.seasoning) {
|
|
60
|
+
adventures += seasoningAdventures(item);
|
|
61
|
+
}
|
|
62
|
+
if (menuItem.itemType() === "food" && modifiers.aioli) {
|
|
60
63
|
adventures += aioliAdventures;
|
|
61
|
-
|
|
64
|
+
}
|
|
65
|
+
if (menuItem.itemType() === "food" && modifiers.whetStone)
|
|
62
66
|
adventures++;
|
|
63
67
|
return adventures;
|
|
64
68
|
}) / interpolated.length);
|
|
@@ -73,6 +77,8 @@ export class MenuItem {
|
|
|
73
77
|
priceOverride;
|
|
74
78
|
mayo;
|
|
75
79
|
data;
|
|
80
|
+
priceCached;
|
|
81
|
+
itemTypeCached;
|
|
76
82
|
static defaultPriceFunction = (item) => npcPrice(item) > 0 ? npcPrice(item) : mallPrice(item);
|
|
77
83
|
static defaultOptions() {
|
|
78
84
|
return new Map([
|
|
@@ -218,7 +224,17 @@ export class MenuItem {
|
|
|
218
224
|
return this.item.toString();
|
|
219
225
|
}
|
|
220
226
|
price() {
|
|
221
|
-
|
|
227
|
+
if (!this.priceCached) {
|
|
228
|
+
this.priceCached =
|
|
229
|
+
this.priceOverride ?? MenuItem.defaultPriceFunction(this.item);
|
|
230
|
+
}
|
|
231
|
+
return this.priceCached;
|
|
232
|
+
}
|
|
233
|
+
itemType() {
|
|
234
|
+
if (!this.itemTypeCached) {
|
|
235
|
+
this.itemTypeCached = itemType(this.item);
|
|
236
|
+
}
|
|
237
|
+
return this.itemTypeCached;
|
|
222
238
|
}
|
|
223
239
|
}
|
|
224
240
|
const organs = ["food", "booze", "spleen item"];
|
|
@@ -239,6 +255,18 @@ class DietPlanner {
|
|
|
239
255
|
whetStone;
|
|
240
256
|
aioli;
|
|
241
257
|
spleenValue = 0;
|
|
258
|
+
baseDefaultModifiers = {
|
|
259
|
+
forkMug: false,
|
|
260
|
+
seasoning: false,
|
|
261
|
+
whetStone: false,
|
|
262
|
+
aioli: false,
|
|
263
|
+
mayoflex: false,
|
|
264
|
+
refinedPalate: have($effect `Refined Palate`),
|
|
265
|
+
garish: have($effect `Gar-ish`),
|
|
266
|
+
saucemaven: have($skill `Saucemaven`),
|
|
267
|
+
pinkyRing: have($item `mafia pinky ring`) && canEquip($item `mafia pinky ring`),
|
|
268
|
+
tuxedoShirt: have($item `tuxedo shirt`) && canEquip($item `tuxedo shirt`),
|
|
269
|
+
};
|
|
242
270
|
constructor(mpa, menu) {
|
|
243
271
|
this.mpa = mpa;
|
|
244
272
|
const fork = menu.find((item) => item.item === $item `Ol' Scratch's salad fork`);
|
|
@@ -301,7 +329,7 @@ class DietPlanner {
|
|
|
301
329
|
*/
|
|
302
330
|
consumptionHelpersAndValue(menuItem, overrideModifiers) {
|
|
303
331
|
const helpers = [];
|
|
304
|
-
if (itemType(
|
|
332
|
+
if (menuItem.itemType() === "food" && this.mayoLookup.size) {
|
|
305
333
|
const mayo = menuItem.mayo
|
|
306
334
|
? this.mayoLookup.get(menuItem.mayo)
|
|
307
335
|
: this.mayoLookup.get(Mayo.flex);
|
|
@@ -309,55 +337,38 @@ class DietPlanner {
|
|
|
309
337
|
helpers.push(mayo);
|
|
310
338
|
}
|
|
311
339
|
const defaultModifiers = {
|
|
312
|
-
|
|
313
|
-
seasoning: this.seasoning ? helpers.includes(this.seasoning) : false,
|
|
314
|
-
whetStone: this.whetStone ? helpers.includes(this.whetStone) : false,
|
|
315
|
-
aioli: this.aioli ? helpers.includes(this.aioli) : false,
|
|
340
|
+
...this.baseDefaultModifiers,
|
|
316
341
|
mayoflex: this.mayoLookup.size
|
|
317
342
|
? helpers.some((item) => item.item === Mayo.flex)
|
|
318
343
|
: false,
|
|
319
|
-
refinedPalate: have($effect `Refined Palate`),
|
|
320
|
-
garish: have($effect `Gar-ish`),
|
|
321
|
-
saucemaven: have($skill `Saucemaven`),
|
|
322
|
-
pinkyRing: have($item `mafia pinky ring`) && canEquip($item `mafia pinky ring`),
|
|
323
|
-
tuxedoShirt: have($item `tuxedo shirt`) && canEquip($item `tuxedo shirt`),
|
|
324
344
|
...overrideModifiers,
|
|
325
345
|
};
|
|
326
346
|
if (this.seasoning &&
|
|
327
|
-
itemType(
|
|
328
|
-
this.mpa *
|
|
329
|
-
(expectedAdventures(menuItem.item, {
|
|
330
|
-
...defaultModifiers,
|
|
331
|
-
seasoning: true,
|
|
332
|
-
}) -
|
|
333
|
-
expectedAdventures(menuItem.item, {
|
|
334
|
-
...defaultModifiers,
|
|
335
|
-
seasoning: false,
|
|
336
|
-
})) >
|
|
337
|
-
this.seasoning.price()) {
|
|
347
|
+
menuItem.itemType() === "food" &&
|
|
348
|
+
this.mpa * seasoningAdventures(menuItem.item) > this.seasoning.price()) {
|
|
338
349
|
helpers.push(this.seasoning);
|
|
339
350
|
}
|
|
340
351
|
if (this.whetStone &&
|
|
341
|
-
itemType(
|
|
352
|
+
menuItem.itemType() === "food" &&
|
|
342
353
|
this.mpa > this.whetStone.price()) {
|
|
343
354
|
helpers.push(this.whetStone);
|
|
344
355
|
}
|
|
345
356
|
if (this.aioli &&
|
|
346
|
-
itemType(
|
|
357
|
+
menuItem.itemType() === "food" &&
|
|
347
358
|
this.mpa * menuItem.item.fullness > this.aioli.price()) {
|
|
348
359
|
helpers.push(this.aioli);
|
|
349
360
|
}
|
|
350
|
-
const forkMug = itemType(
|
|
361
|
+
const forkMug = menuItem.itemType() === "food"
|
|
351
362
|
? this.fork
|
|
352
|
-
: itemType(
|
|
363
|
+
: menuItem.itemType() === "booze"
|
|
353
364
|
? this.mug
|
|
354
365
|
: null;
|
|
355
366
|
const forkMugPrice = forkMug ? forkMug.price() : Infinity;
|
|
356
367
|
const baseCost = menuItem.price() + sum(helpers, (item) => item.price());
|
|
357
|
-
const valueRaw = expectedAdventures(menuItem
|
|
368
|
+
const valueRaw = expectedAdventures(menuItem, defaultModifiers) * this.mpa -
|
|
358
369
|
baseCost +
|
|
359
370
|
(menuItem.additionalValue ?? 0);
|
|
360
|
-
const valueForkMug = expectedAdventures(menuItem
|
|
371
|
+
const valueForkMug = expectedAdventures(menuItem, {
|
|
361
372
|
...defaultModifiers,
|
|
362
373
|
forkMug: true,
|
|
363
374
|
}) *
|
|
@@ -599,7 +610,7 @@ class DietEntry {
|
|
|
599
610
|
const mug = itemType(targetItem) === "booze" &&
|
|
600
611
|
items.includes($item `Frosty's frosty mug`);
|
|
601
612
|
return (this.quantity *
|
|
602
|
-
expectedAdventures(this.menuItems[this.menuItems.length - 1]
|
|
613
|
+
expectedAdventures(this.menuItems[this.menuItems.length - 1], {
|
|
603
614
|
forkMug: fork || mug,
|
|
604
615
|
seasoning: items.includes($item `Special Seasoning`),
|
|
605
616
|
whetStone: items.includes($item `whet stone`),
|
package/dist/lib.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/** @module GeneralLibrary */
|
|
2
|
-
import { Effect, Element, Familiar, Item, Location, Monster, runCombat, Servant, Skill, Slot, Stat, Thrall } from "kolmafia";
|
|
2
|
+
import { Effect, Element, Familiar, Item, Location, Monster, runCombat, Servant, Skill, Slot, Stat, Thrall, Coinmaster, MafiaClass } from "kolmafia";
|
|
3
3
|
/**
|
|
4
4
|
* Determines the current maximum Accordion Thief songs the player can have in their head
|
|
5
5
|
*
|
|
@@ -220,12 +220,18 @@ export declare function canUse(item: Item): boolean;
|
|
|
220
220
|
* @param thing Thing that can have a mafia "none" value
|
|
221
221
|
* @returns The thing specified or `null`
|
|
222
222
|
*/
|
|
223
|
-
export declare function noneToNull<T>(thing: T): T | null;
|
|
223
|
+
export declare function noneToNull<T extends MafiaClass>(thing: T): T | null;
|
|
224
|
+
/**
|
|
225
|
+
* Parse the sort of range that KoLmafia encodes as a string
|
|
226
|
+
* @param range KoLmafia-style range string
|
|
227
|
+
* @returns Tuple of integers representing range
|
|
228
|
+
*/
|
|
229
|
+
export declare function getRange(range: string): [number, number];
|
|
224
230
|
/**
|
|
225
231
|
* Determine the average value from the sort of range that KoLmafia encodes as a string
|
|
226
232
|
*
|
|
227
233
|
* @param range KoLmafia-style range string
|
|
228
|
-
* @returns Average value
|
|
234
|
+
* @returns Average value for range
|
|
229
235
|
*/
|
|
230
236
|
export declare function getAverage(range: string): number;
|
|
231
237
|
/**
|
|
@@ -519,4 +525,38 @@ export declare const getScalingRate: (monster: Monster) => number;
|
|
|
519
525
|
* @returns The current scaling cap of the monster, based on your current in-game state
|
|
520
526
|
*/
|
|
521
527
|
export declare const getScalingCap: (monster: Monster) => number;
|
|
528
|
+
/**
|
|
529
|
+
* Wrap a specified action in mafia's `batchOpen` and `batchClose`
|
|
530
|
+
*
|
|
531
|
+
* @param action Action to perform while using mafia's batching feature
|
|
532
|
+
* @returns The return value of the action
|
|
533
|
+
*/
|
|
534
|
+
export declare function withBatch<T>(action: () => T): T;
|
|
535
|
+
export declare const bulkAutosell: (items: Map<Item, number>) => boolean;
|
|
536
|
+
export declare const bulkPutCloset: (items: Map<Item, number>) => boolean;
|
|
537
|
+
export declare const bulkPutDisplay: (items: Map<Item, number>) => boolean;
|
|
538
|
+
export declare const bulkPutStash: (items: Map<Item, number>) => boolean;
|
|
539
|
+
export declare const bulkTakeCloset: (items: Map<Item, number>) => boolean;
|
|
540
|
+
export declare const bulkTakeDisplay: (items: Map<Item, number>) => boolean;
|
|
541
|
+
export declare const bulkTakeShop: (items: Map<Item, number>) => boolean;
|
|
542
|
+
export declare const bulkTakeStash: (items: Map<Item, number>) => boolean;
|
|
543
|
+
export declare const bulkTakeStorage: (items: Map<Item, number>) => boolean;
|
|
544
|
+
export declare const bulkPutShop: (items: Map<Item, {
|
|
545
|
+
quantity?: number;
|
|
546
|
+
limit?: number;
|
|
547
|
+
price: number;
|
|
548
|
+
}>) => boolean;
|
|
549
|
+
export declare const bulkSell: (coinmaster: Coinmaster, items: Map<Item, number>) => boolean;
|
|
550
|
+
export declare const bulkRepriceShop: (items: Map<Item, {
|
|
551
|
+
quantity?: number;
|
|
552
|
+
limit?: number;
|
|
553
|
+
price: number;
|
|
554
|
+
}>) => boolean;
|
|
555
|
+
/**
|
|
556
|
+
* Calculate the total weight of a given familiar, including soup & modifiers
|
|
557
|
+
* @param familiar The familiar to use--defaults to your current one
|
|
558
|
+
* @param considerAdjustment Whether to include your `weightAdjustment` in the calculation
|
|
559
|
+
* @returns The total weight of the given familiar
|
|
560
|
+
*/
|
|
561
|
+
export declare function totalFamiliarWeight(familiar?: Familiar, considerAdjustment?: boolean): number;
|
|
522
562
|
export {};
|
package/dist/lib.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
/** @module GeneralLibrary */
|
|
2
|
-
import { appearanceRates, autosellPrice, availableAmount, booleanModifier, choiceFollowsFight, cliExecute, currentRound, Effect, elementalResistance, equip, equippedItem, extractItems as kolmafiaExtractItems, Familiar, fullnessLimit, getCampground, getCounters, getPlayerId, getPlayerName, getRelated, handlingChoice, haveEffect, haveFamiliar, haveServant, haveSkill, holiday, inebrietyLimit, inMultiFight, Item, Location, mallPrice, Monster, myClass, myEffects, myFamiliar, myFullness, myInebriety, myPath, myPrimestat, mySpleenUse, myThrall, myTurncount, numericModifier, Path, Servant, Skill, Slot, spleenLimit, Thrall, todayToString, toItem, toSkill, totalTurnsPlayed, visitUrl, xpath, monsterEval, } from "kolmafia";
|
|
2
|
+
import { appearanceRates, autosellPrice, availableAmount, booleanModifier, choiceFollowsFight, cliExecute, currentRound, Effect, elementalResistance, equip, equippedItem, extractItems as kolmafiaExtractItems, Familiar, fullnessLimit, getCampground, getCounters, getPlayerId, getPlayerName, getRelated, handlingChoice, haveEffect, haveFamiliar, haveServant, haveSkill, holiday, inebrietyLimit, inMultiFight, Item, Location, mallPrice, Monster, myClass, myEffects, myFamiliar, myFullness, myInebriety, myPath, myPrimestat, mySpleenUse, myThrall, myTurncount, numericModifier, Path, Servant, Skill, Slot, spleenLimit, Thrall, todayToString, toItem, toSkill, totalTurnsPlayed, visitUrl, xpath, monsterEval, batchOpen, batchClose, autosell, putCloset, putDisplay, putShop, putStash, sell, takeCloset, takeDisplay, takeShop, takeStash, takeStorage, repriceShop, familiarWeight, weightAdjustment, MafiaClasses, } from "kolmafia";
|
|
3
3
|
import logger from "./logger.js";
|
|
4
4
|
import { get } from "./property.js";
|
|
5
5
|
import { $class, $effect, $element, $familiar, $item, $items, $monsters, $skill, $stat, } from "./template-string.js";
|
|
6
|
-
import { makeByXFunction, chunk, notNull } from "./utils.js";
|
|
6
|
+
import { makeByXFunction, chunk, notNull, clamp } from "./utils.js";
|
|
7
7
|
/**
|
|
8
8
|
* Determines the current maximum Accordion Thief songs the player can have in their head
|
|
9
9
|
*
|
|
@@ -362,12 +362,10 @@ export function getBanishedMonsters() {
|
|
|
362
362
|
Item.get(`tomayohawk-style reflex hammer`),
|
|
363
363
|
null,
|
|
364
364
|
].includes(banisherItem)) {
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
result.set(Skill.get(banisher), Monster.get(foe));
|
|
370
|
-
}
|
|
365
|
+
const skill = $skill.get(banisher);
|
|
366
|
+
if (!skill)
|
|
367
|
+
continue;
|
|
368
|
+
result.set(skill, Monster.get(foe));
|
|
371
369
|
}
|
|
372
370
|
else {
|
|
373
371
|
result.set(banisherItem, Monster.get(foe));
|
|
@@ -407,32 +405,30 @@ export function canUse(item) {
|
|
|
407
405
|
* @returns The thing specified or `null`
|
|
408
406
|
*/
|
|
409
407
|
export function noneToNull(thing) {
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
408
|
+
const type = MafiaClasses.find((t) => thing instanceof t);
|
|
409
|
+
return type && thing === type.none ? null : thing;
|
|
410
|
+
}
|
|
411
|
+
/**
|
|
412
|
+
* Parse the sort of range that KoLmafia encodes as a string
|
|
413
|
+
* @param range KoLmafia-style range string
|
|
414
|
+
* @returns Tuple of integers representing range
|
|
415
|
+
*/
|
|
416
|
+
export function getRange(range) {
|
|
417
|
+
const [lower, upper] = range
|
|
418
|
+
.match(/^(-?\d+)(?:-(-?\d+))?$/)
|
|
419
|
+
?.slice(1, 3)
|
|
420
|
+
.map((v) => parseInt(v)) ?? [0];
|
|
421
|
+
return [lower, Number.isNaN(upper) || upper === undefined ? lower : upper];
|
|
420
422
|
}
|
|
421
423
|
/**
|
|
422
424
|
* Determine the average value from the sort of range that KoLmafia encodes as a string
|
|
423
425
|
*
|
|
424
426
|
* @param range KoLmafia-style range string
|
|
425
|
-
* @returns Average value
|
|
427
|
+
* @returns Average value for range
|
|
426
428
|
*/
|
|
427
429
|
export function getAverage(range) {
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
const [, lower, upper] = range.match(/(-?[0-9]+)-(-?[0-9]+)/) ?? [
|
|
431
|
-
"0",
|
|
432
|
-
"0",
|
|
433
|
-
"0",
|
|
434
|
-
];
|
|
435
|
-
return (Number(lower) + Number(upper)) / 2;
|
|
430
|
+
const [min, max] = getRange(range);
|
|
431
|
+
return (min + max) / 2;
|
|
436
432
|
}
|
|
437
433
|
/**
|
|
438
434
|
* Deternube tge average adventures expected from consuming an Item
|
|
@@ -623,6 +619,10 @@ export function findFairyMultiplier(familiar) {
|
|
|
623
619
|
const itemBonus = numericModifier(familiar, "Item Drop", 1, $item.none);
|
|
624
620
|
if (itemBonus === 0)
|
|
625
621
|
return 0;
|
|
622
|
+
// Assumes you're using LED candle; returns effective weight multiplier
|
|
623
|
+
if (familiar === $familiar `Jill-of-All-Trades`)
|
|
624
|
+
return 1.5;
|
|
625
|
+
// Working out the multiplier based on the Item Drop at 1lb
|
|
626
626
|
return Math.pow(Math.sqrt(itemBonus + 55 / 4 + 3) - Math.sqrt(55) / 2, 2);
|
|
627
627
|
}
|
|
628
628
|
export const holidayWanderers = new Map([
|
|
@@ -832,7 +832,6 @@ export function freeCrafts(type = "all") {
|
|
|
832
832
|
: 0) +
|
|
833
833
|
effectCrafts($effect `Inigo's Incantation of Inspiration`) +
|
|
834
834
|
effectCrafts($effect `Craft Tea`) +
|
|
835
|
-
// eslint-disable-next-line libram/verify-constants
|
|
836
835
|
effectCrafts($effect `Cooking Concentrate`);
|
|
837
836
|
const food = type === "food" ? 5 - get("_cookbookbatCrafting") : 0;
|
|
838
837
|
const smith = type === "smith" ? 5 - get("_thorsPliersCrafting") : 0;
|
|
@@ -996,3 +995,114 @@ export const getScalingRate = makeScalerCalcFunction(scalerRates, SCALE_RATE_PAT
|
|
|
996
995
|
* @returns The current scaling cap of the monster, based on your current in-game state
|
|
997
996
|
*/
|
|
998
997
|
export const getScalingCap = makeScalerCalcFunction(scalerCaps, SCALE_CAP_PATTERN);
|
|
998
|
+
/**
|
|
999
|
+
* Wrap a specified action in mafia's `batchOpen` and `batchClose`
|
|
1000
|
+
*
|
|
1001
|
+
* @param action Action to perform while using mafia's batching feature
|
|
1002
|
+
* @returns The return value of the action
|
|
1003
|
+
*/
|
|
1004
|
+
export function withBatch(action) {
|
|
1005
|
+
batchOpen();
|
|
1006
|
+
try {
|
|
1007
|
+
return action();
|
|
1008
|
+
}
|
|
1009
|
+
finally {
|
|
1010
|
+
batchClose();
|
|
1011
|
+
}
|
|
1012
|
+
}
|
|
1013
|
+
const makeBulkFunction = (action) => (items) => {
|
|
1014
|
+
batchOpen();
|
|
1015
|
+
for (const [item, quantity] of items.entries())
|
|
1016
|
+
action(quantity, item);
|
|
1017
|
+
return batchClose();
|
|
1018
|
+
};
|
|
1019
|
+
/*
|
|
1020
|
+
* Autosell items in bulk
|
|
1021
|
+
*/
|
|
1022
|
+
export const bulkAutosell = makeBulkFunction(autosell);
|
|
1023
|
+
/*
|
|
1024
|
+
* Closet items in bulk
|
|
1025
|
+
* Note: each item transfer will still consume one request
|
|
1026
|
+
*/
|
|
1027
|
+
export const bulkPutCloset = makeBulkFunction(putCloset);
|
|
1028
|
+
/*
|
|
1029
|
+
* Display items in bulk
|
|
1030
|
+
*/
|
|
1031
|
+
export const bulkPutDisplay = makeBulkFunction(putDisplay);
|
|
1032
|
+
/*
|
|
1033
|
+
* Deposit items into your clan stash in bulk
|
|
1034
|
+
*/
|
|
1035
|
+
export const bulkPutStash = makeBulkFunction(putStash);
|
|
1036
|
+
/*
|
|
1037
|
+
* Remove items from your closet in bulk
|
|
1038
|
+
* Note: each item transfer will still consume one request
|
|
1039
|
+
*/
|
|
1040
|
+
export const bulkTakeCloset = makeBulkFunction(takeCloset);
|
|
1041
|
+
/*
|
|
1042
|
+
* Remove items from your display case in bulk
|
|
1043
|
+
*/
|
|
1044
|
+
export const bulkTakeDisplay = makeBulkFunction(takeDisplay);
|
|
1045
|
+
/*
|
|
1046
|
+
* Remove items from your shop in bulk
|
|
1047
|
+
*/
|
|
1048
|
+
export const bulkTakeShop = makeBulkFunction(takeShop);
|
|
1049
|
+
/*
|
|
1050
|
+
* Withdraw items from your clan stash in bulk
|
|
1051
|
+
* Note: each item transfer will still consume one request
|
|
1052
|
+
*/
|
|
1053
|
+
export const bulkTakeStash = makeBulkFunction(takeStash);
|
|
1054
|
+
/*
|
|
1055
|
+
* Remove items from your Hagnk's in bulk
|
|
1056
|
+
*/
|
|
1057
|
+
export const bulkTakeStorage = makeBulkFunction(takeStorage);
|
|
1058
|
+
/*
|
|
1059
|
+
* Mallsell items in bulk
|
|
1060
|
+
*/
|
|
1061
|
+
export const bulkPutShop = (items) => {
|
|
1062
|
+
batchOpen();
|
|
1063
|
+
for (const [item, { quantity, limit, price }] of items.entries()) {
|
|
1064
|
+
if (quantity) {
|
|
1065
|
+
putShop(price, limit ?? 0, quantity, item);
|
|
1066
|
+
}
|
|
1067
|
+
else {
|
|
1068
|
+
putShop(price, limit ?? 0, item);
|
|
1069
|
+
}
|
|
1070
|
+
}
|
|
1071
|
+
return batchClose();
|
|
1072
|
+
};
|
|
1073
|
+
/*
|
|
1074
|
+
* Coinmaster-sell items to the same coinmaster in bulk
|
|
1075
|
+
*/
|
|
1076
|
+
export const bulkSell = (coinmaster, items) => {
|
|
1077
|
+
batchOpen();
|
|
1078
|
+
for (const [item, quantity] of items.entries())
|
|
1079
|
+
sell(coinmaster, quantity, item);
|
|
1080
|
+
return batchClose();
|
|
1081
|
+
};
|
|
1082
|
+
/*
|
|
1083
|
+
* Reprice items in your mallstore in bulk
|
|
1084
|
+
*/
|
|
1085
|
+
export const bulkRepriceShop = (items) => {
|
|
1086
|
+
batchOpen();
|
|
1087
|
+
for (const [item, { limit, price }] of items.entries()) {
|
|
1088
|
+
if (limit) {
|
|
1089
|
+
repriceShop(price, limit, item);
|
|
1090
|
+
}
|
|
1091
|
+
else {
|
|
1092
|
+
repriceShop(price, item);
|
|
1093
|
+
}
|
|
1094
|
+
}
|
|
1095
|
+
return batchClose();
|
|
1096
|
+
};
|
|
1097
|
+
/**
|
|
1098
|
+
* Calculate the total weight of a given familiar, including soup & modifiers
|
|
1099
|
+
* @param familiar The familiar to use--defaults to your current one
|
|
1100
|
+
* @param considerAdjustment Whether to include your `weightAdjustment` in the calculation
|
|
1101
|
+
* @returns The total weight of the given familiar
|
|
1102
|
+
*/
|
|
1103
|
+
export function totalFamiliarWeight(familiar = myFamiliar(), considerAdjustment = true) {
|
|
1104
|
+
return (clamp(familiarWeight(myFamiliar()), have($effect `Fidoxene`) ? 20 : 0, Infinity) +
|
|
1105
|
+
familiar.soupWeight +
|
|
1106
|
+
(considerAdjustment ? weightAdjustment() : 0) +
|
|
1107
|
+
(familiar.feasted ? 10 : 0));
|
|
1108
|
+
}
|
package/dist/lib.test.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { getPlayerId, getPlayerName } from "kolmafia";
|
|
2
2
|
import { describe, it, expect, vi } from "vitest";
|
|
3
|
-
import { getPlayerFromIdOrName, getPlayerIdFromName, getPlayerNameFromId, } from "./lib.js";
|
|
3
|
+
import { getPlayerFromIdOrName, getPlayerIdFromName, getPlayerNameFromId, getRange, } from "./lib.js";
|
|
4
4
|
vi.mocked(getPlayerName).mockImplementation((id) => {
|
|
5
5
|
switch (id) {
|
|
6
6
|
case 1:
|
|
@@ -140,3 +140,23 @@ describe(getPlayerFromIdOrName, () => {
|
|
|
140
140
|
});
|
|
141
141
|
});
|
|
142
142
|
});
|
|
143
|
+
describe("getRange", () => {
|
|
144
|
+
it.each([
|
|
145
|
+
// Normal range
|
|
146
|
+
["1-2", [1, 2]],
|
|
147
|
+
// Single number
|
|
148
|
+
["1", [1, 1]],
|
|
149
|
+
// Negative single number
|
|
150
|
+
["-1", [-1, -1]],
|
|
151
|
+
// Invalid
|
|
152
|
+
["1-", [0, 0]],
|
|
153
|
+
// Negative upper bound
|
|
154
|
+
["-5--1", [-5, -1]],
|
|
155
|
+
// Unusual order (let this slide)
|
|
156
|
+
["10--1", [10, -1]],
|
|
157
|
+
// Ending in zero
|
|
158
|
+
["-5-0", [-5, 0]],
|
|
159
|
+
])("should return the range for %p", (input, expected) => {
|
|
160
|
+
expect(getRange(input)).toEqual(expected);
|
|
161
|
+
});
|
|
162
|
+
});
|
package/dist/maximize.d.ts
CHANGED
package/dist/maximize.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { availableAmount, bjornifyFamiliar, canEquip, cliExecute, enthroneFamiliar, equip, equippedAmount, equippedItem, getProperty, haveEquipped, isWearingOutfit, Item, maximize, myBasestat, myBjornedFamiliar, myEnthronedFamiliar, myFamiliar, outfit, Slot, } from "kolmafia";
|
|
1
|
+
import { availableAmount, bjornifyFamiliar, canEquip, cliExecute, enthroneFamiliar, equip, equippedAmount, equippedItem, getProperty, haveEquipped, isWearingOutfit, Item, maximize, myBasestat, myBjornedFamiliar, myEnthronedFamiliar, myFamiliar, myLocation, outfit, Slot, } from "kolmafia";
|
|
2
2
|
import { have } from "./lib.js";
|
|
3
3
|
import logger from "./logger.js";
|
|
4
4
|
import { $effect, $familiar, $item, $slot, $slots, $stats, } from "./template-string.js";
|
|
@@ -18,6 +18,7 @@ export function mergeMaximizeOptions(defaultOptions, addendums) {
|
|
|
18
18
|
updateOnFamiliarChange: addendums.updateOnFamiliarChange ?? defaultOptions.updateOnFamiliarChange,
|
|
19
19
|
updateOnCanEquipChanged: addendums.updateOnCanEquipChanged ??
|
|
20
20
|
defaultOptions.updateOnCanEquipChanged,
|
|
21
|
+
updateOnLocationChange: addendums.updateOnLocationChange ?? defaultOptions.updateOnLocationChange,
|
|
21
22
|
useOutfitCaching: addendums.useOutfitCaching ?? defaultOptions.useOutfitCaching,
|
|
22
23
|
forceEquip: [...defaultOptions.forceEquip, ...(addendums.forceEquip ?? [])],
|
|
23
24
|
preventEquip: [
|
|
@@ -41,6 +42,7 @@ export function mergeMaximizeOptions(defaultOptions, addendums) {
|
|
|
41
42
|
const defaultMaximizeOptions = {
|
|
42
43
|
updateOnFamiliarChange: true,
|
|
43
44
|
updateOnCanEquipChanged: true,
|
|
45
|
+
updateOnLocationChange: false,
|
|
44
46
|
useOutfitCaching: true,
|
|
45
47
|
forceEquip: [],
|
|
46
48
|
preventEquip: [],
|
|
@@ -420,6 +422,7 @@ export function maximizeCached(objectives, options = {}) {
|
|
|
420
422
|
.map((slot) => `${slot}:${equippedItem(slot)}`)
|
|
421
423
|
.sort(),
|
|
422
424
|
have($effect `Offhand Remarkable`),
|
|
425
|
+
options.updateOnLocationChange && myLocation(),
|
|
423
426
|
].join("; ");
|
|
424
427
|
const cacheEntry = checkCache(cacheKey, fullOptions);
|
|
425
428
|
if (cacheEntry && !forceUpdate) {
|
|
@@ -473,7 +476,7 @@ export class Requirement {
|
|
|
473
476
|
merge(other) {
|
|
474
477
|
const optionsA = this.maximizeOptions;
|
|
475
478
|
const optionsB = other.maximizeOptions;
|
|
476
|
-
const optionalBooleans = mergeOptionalOptions(optionsA, optionsB, "updateOnFamiliarChange", "updateOnCanEquipChanged", "forceUpdate");
|
|
479
|
+
const optionalBooleans = mergeOptionalOptions(optionsA, optionsB, "updateOnFamiliarChange", "updateOnCanEquipChanged", "updateOnLocationChange", "forceUpdate");
|
|
477
480
|
return new Requirement([...this.maximizeParameters, ...other.maximizeParameters], {
|
|
478
481
|
...optionalBooleans,
|
|
479
482
|
forceEquip: [
|