libram 0.6.14 → 0.6.17

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.
@@ -142,9 +142,9 @@ function filterAction(action, constraints) {
142
142
  */
143
143
  export function findActionSource(actions, constraints = {}) {
144
144
  const validActions = actions.filter((actions) => filterAction(actions, constraints));
145
- return validActions.length
146
- ? validActions.reduce((a, b) => (a.cost() > b.cost() ? a : b))
147
- : null;
145
+ if (validActions.length < 1)
146
+ return null;
147
+ return validActions.reduce((a, b) => (a.cost() <= b.cost() ? a : b));
148
148
  }
149
149
  /**
150
150
  * Count available action sources subject to constraints. Note that, if
package/dist/ascend.d.ts CHANGED
@@ -1,6 +1,6 @@
1
- import { Skill, Class, Item } from "kolmafia";
1
+ import { Skill, Class, Item, MafiaClass } from "kolmafia";
2
2
  import { Path } from "./Path";
3
- import { Ceiling, Desk, Nightstand } from "./resources/2015/ChateauMantegna";
3
+ import { ChateauMantegna } from "./resources";
4
4
  export declare enum Lifestyle {
5
5
  casual = 1,
6
6
  softcore = 2,
@@ -8,8 +8,18 @@ export declare enum Lifestyle {
8
8
  hardcore = 3
9
9
  }
10
10
  export declare class AscendError extends Error {
11
- cause?: Skill | Item | Class | Path;
12
- constructor(cause?: Skill | Item | Class | Path);
11
+ cause?: Skill | Item | Class | Path | string;
12
+ constructor(cause?: Skill | Item | Class | Path | string);
13
+ }
14
+ declare const worksheds: readonly ["warbear LP-ROM burner", "warbear jackhammer drill press", "warbear induction oven", "warbear high-efficiency still", "warbear chemistry lab", "warbear auto-anvil", "spinning wheel", "snow machine", "Little Geneticist DNA-Splicing Lab", "portable Mayo Clinic", "Asdon Martin keyfob", "diabolic pizza cube", "cold medicine cabinet"];
15
+ declare type Workshed = typeof worksheds[number];
16
+ declare const gardens: readonly ["packet of pumpkin seeds", "Peppermint Pip Packet", "packet of dragon's teeth", "packet of beer seeds", "packet of winter seeds", "packet of thanksgarden seeds", "packet of tall grass seeds", "packet of mushroom spores"];
17
+ declare type Garden = typeof gardens[number];
18
+ declare const eudorae: readonly ["My Own Pen Pal kit", "GameInformPowerDailyPro subscription card", "Xi Receiver Unit", "New-You Club Membership Form", "Our Daily Candles™ order form"];
19
+ declare type Eudora = typeof eudorae[number];
20
+ export declare class AscensionPrepError extends Error {
21
+ cause: string;
22
+ constructor(cause: string, original?: MafiaClass | string);
13
23
  }
14
24
  declare type MoonSign = number | "mongoose" | "wallaby" | "vole" | "platypus" | "opossum" | "marmot" | "wombat" | "blender" | "packrat" | "degrassi" | "degrassi knoll" | "friendly degrassi knoll" | "knoll" | "canada" | "canadia" | "little canadia" | "gnomads" | "gnomish" | "gnomish gnomads camp";
15
25
  /**
@@ -22,12 +32,6 @@ declare type MoonSign = number | "mongoose" | "wallaby" | "vole" | "platypus" |
22
32
  * @param pet From the astral pet store.
23
33
  */
24
34
  export declare function ascend(path: Path, playerClass: Class, lifestyle: Lifestyle, moon: MoonSign, consumable?: Item | undefined, pet?: Item | undefined, permSkills?: Map<Skill, Lifestyle> | undefined): void;
25
- declare const worksheds: readonly ["warbear LP-ROM burner", "warbear jackhammer drill press", "warbear induction oven", "warbear high-efficiency still", "warbear chemistry lab", "warbear auto-anvil", "spinning wheel", "snow machine", "Little Geneticist DNA-Splicing Lab", "portable Mayo Clinic", "Asdon Martin keyfob", "diabolic pizza cube", "cold medicine cabinet"];
26
- declare type Workshed = typeof worksheds[number];
27
- declare const gardens: readonly ["packet of pumpkin seeds", "Peppermint Pip Packet", "packet of dragon's teeth", "packet of beer seeds", "packet of winter seeds", "packet of thanksgarden seeds", "packet of tall grass seeds", "packet of mushroom spores"];
28
- declare type Garden = typeof gardens[number];
29
- declare const eudorae: readonly ["My Own Pen Pal kit", "GameInformPowerDailyPro subscription card", "Xi Receiver Unit", "New-You Club Membership Form", "Our Daily Candles™ order form"];
30
- declare type Eudora = typeof eudorae[number];
31
35
  /**
32
36
  * Sets up various iotms you may want to use in the coming ascension
33
37
  * @param ascensionItems.workshed Workshed to switch to.
@@ -40,9 +44,9 @@ export declare function prepareAscension({ workshed, garden, eudora, chateau, th
40
44
  garden?: Garden;
41
45
  eudora?: Eudora;
42
46
  chateau?: {
43
- desk?: Desk;
44
- ceiling?: Ceiling;
45
- nightstand?: Nightstand;
47
+ desk?: ChateauMantegna.Desk;
48
+ ceiling?: ChateauMantegna.Ceiling;
49
+ nightstand?: ChateauMantegna.Nightstand;
46
50
  };
47
51
  throwOnFail?: boolean;
48
52
  }): void;
package/dist/ascend.js CHANGED
@@ -1,6 +1,8 @@
1
1
  import { Skill, Class, containsText, eudoraItem, getCampground, getWorkshed, Item, toInt, use, visitUrl, xpath, haveSkill, } from "kolmafia";
2
+ import { Path } from "./Path";
2
3
  import { ChateauMantegna } from "./resources";
3
4
  import { $item, $items, $stat } from "./template-string";
5
+ import { createStringUnionTypeGuardFunction } from "./utils";
4
6
  export var Lifestyle;
5
7
  (function (Lifestyle) {
6
8
  Lifestyle[Lifestyle["casual"] = 1] = "casual";
@@ -28,9 +30,75 @@ export class AscendError extends Error {
28
30
  else if (cause instanceof Class) {
29
31
  super(`Invalid class ${cause} for this path!`);
30
32
  }
31
- else {
33
+ else if (cause instanceof Path) {
32
34
  super(`Invalid path ${cause}!`);
33
35
  }
36
+ else
37
+ super(cause);
38
+ this.cause = cause;
39
+ }
40
+ }
41
+ const worksheds = [
42
+ "warbear LP-ROM burner",
43
+ "warbear jackhammer drill press",
44
+ "warbear induction oven",
45
+ "warbear high-efficiency still",
46
+ "warbear chemistry lab",
47
+ "warbear auto-anvil",
48
+ "spinning wheel",
49
+ "snow machine",
50
+ "Little Geneticist DNA-Splicing Lab",
51
+ "portable Mayo Clinic",
52
+ "Asdon Martin keyfob",
53
+ "diabolic pizza cube",
54
+ "cold medicine cabinet",
55
+ ];
56
+ const gardens = [
57
+ "packet of pumpkin seeds",
58
+ "Peppermint Pip Packet",
59
+ "packet of dragon's teeth",
60
+ "packet of beer seeds",
61
+ "packet of winter seeds",
62
+ "packet of thanksgarden seeds",
63
+ "packet of tall grass seeds",
64
+ "packet of mushroom spores",
65
+ ];
66
+ const eudorae = [
67
+ "My Own Pen Pal kit",
68
+ "GameInformPowerDailyPro subscription card",
69
+ "Xi Receiver Unit",
70
+ "New-You Club Membership Form",
71
+ "Our Daily Candles™ order form",
72
+ ];
73
+ const isWorkshed = createStringUnionTypeGuardFunction(worksheds);
74
+ const isGarden = createStringUnionTypeGuardFunction(gardens);
75
+ const isEudora = createStringUnionTypeGuardFunction(eudorae);
76
+ const isDesk = createStringUnionTypeGuardFunction(ChateauMantegna.desks);
77
+ const isNightstand = createStringUnionTypeGuardFunction(ChateauMantegna.nightstands);
78
+ const isCeiling = createStringUnionTypeGuardFunction(ChateauMantegna.ceilings);
79
+ export class AscensionPrepError extends Error {
80
+ cause;
81
+ constructor(cause, original) {
82
+ if (isWorkshed(cause)) {
83
+ super(`Unable to swap workshed to ${cause}; workshed is currently ${original}.`);
84
+ }
85
+ else if (isGarden(cause)) {
86
+ super(`Unable to swap garden to ${cause}; garden is currently ${original}.`);
87
+ }
88
+ else if (isEudora(cause)) {
89
+ super(`Unable to swap eudora to ${cause}; eudora is currently ${original}.`);
90
+ }
91
+ else if (isDesk(cause)) {
92
+ super(`Unable to swap chateau desk to ${cause}; desk is currently ${original}.`);
93
+ }
94
+ else if (isNightstand(cause)) {
95
+ super(`Unable to swap chateau nightstand to ${cause}; nightstand is currently ${original}.`);
96
+ }
97
+ else if (isCeiling(cause)) {
98
+ super(`Unable to swap chateau ceiling to ${cause}; ceiling is currently ${original}.`);
99
+ }
100
+ else
101
+ super(cause);
34
102
  this.cause = cause;
35
103
  }
36
104
  }
@@ -46,7 +114,7 @@ function toMoonId(moon, playerClass) {
46
114
  case $stat `Moxie`:
47
115
  return 2;
48
116
  default:
49
- throw new Error(`unknown prime stat for ${playerClass}`);
117
+ throw new AscendError(`unknown prime stat for ${playerClass}`);
50
118
  }
51
119
  };
52
120
  switch (moon.toLowerCase()) {
@@ -82,7 +150,7 @@ function toMoonId(moon, playerClass) {
82
150
  case "gnomish gnomads camp":
83
151
  return 7 + offset();
84
152
  default:
85
- return -1;
153
+ throw new AscendError("Invalid moon sign!");
86
154
  }
87
155
  }
88
156
  /**
@@ -108,7 +176,7 @@ export function ascend(path, playerClass, lifestyle, moon, consumable = $item `a
108
176
  throw new AscendError(consumable);
109
177
  }
110
178
  if (pet &&
111
- !$items `astral bludgeon, astral shield, astral chapeau, astral bracer, astral longbow, astral shorts, astral mace, astral ring, astral statuette, astral pistol, astral mask, astral pet sweater, astral shirt, astral belt`.includes(pet)) {
179
+ !$items `astral bludgeon, astral shield, astral chapeau, astral bracer, astral longbow, astral shorts, astral mace, astral trousers, astral ring, astral statuette, astral pistol, astral mask, astral pet sweater, astral shirt, astral belt`.includes(pet)) {
112
180
  throw new AscendError(pet);
113
181
  }
114
182
  const illegalSkill = permSkills
@@ -139,38 +207,6 @@ export function ascend(path, playerClass, lifestyle, moon, consumable = $item `a
139
207
  }
140
208
  visitUrl(`afterlife.php?action=ascend&confirmascend=1&whichsign=${moonId}&gender=2&whichclass=${toInt(playerClass)}&whichpath=${path.id}&asctype=${lifestyle}&nopetok=1&noskillsok=1&lamepathok=1&lamesignok=1&pwd`, true);
141
209
  }
142
- const worksheds = [
143
- "warbear LP-ROM burner",
144
- "warbear jackhammer drill press",
145
- "warbear induction oven",
146
- "warbear high-efficiency still",
147
- "warbear chemistry lab",
148
- "warbear auto-anvil",
149
- "spinning wheel",
150
- "snow machine",
151
- "Little Geneticist DNA-Splicing Lab",
152
- "portable Mayo Clinic",
153
- "Asdon Martin keyfob",
154
- "diabolic pizza cube",
155
- "cold medicine cabinet",
156
- ];
157
- const gardens = [
158
- "packet of pumpkin seeds",
159
- "Peppermint Pip Packet",
160
- "packet of dragon's teeth",
161
- "packet of beer seeds",
162
- "packet of winter seeds",
163
- "packet of thanksgarden seeds",
164
- "packet of tall grass seeds",
165
- "packet of mushroom spores",
166
- ];
167
- const eudorae = [
168
- "My Own Pen Pal kit",
169
- "GameInformPowerDailyPro subscription card",
170
- "Xi Receiver Unit",
171
- "New-You Club Membership Form",
172
- "Our Daily Candles™ order form",
173
- ];
174
210
  /**
175
211
  * Sets up various iotms you may want to use in the coming ascension
176
212
  * @param ascensionItems.workshed Workshed to switch to.
@@ -183,44 +219,44 @@ export function prepareAscension({ workshed, garden, eudora, chateau, throwOnFai
183
219
  if (workshed && getWorkshed() !== Item.get(workshed)) {
184
220
  use(Item.get(workshed));
185
221
  if (getWorkshed().name !== workshed && throwOnFail) {
186
- throw new Error(`Failed to switch workshed to ${workshed}; it is currently still ${getWorkshed()}.`);
222
+ throw new AscensionPrepError(workshed, getWorkshed());
187
223
  }
188
224
  }
189
225
  if (garden && !Object.getOwnPropertyNames(getCampground()).includes(garden)) {
190
226
  use(Item.get(garden));
191
- if (!Object.getOwnPropertyNames(getCampground()).includes(garden) &&
192
- throwOnFail) {
193
- throw new Error(`We really thought we changed your garden to a ${garden}, but Mafia is saying otherwise.`);
227
+ const gardenName = Object.getOwnPropertyNames(getCampground()).find(isGarden);
228
+ if (gardenName !== garden && throwOnFail) {
229
+ throw new AscensionPrepError(garden, gardenName);
194
230
  }
195
231
  }
196
232
  if (eudora && eudoraItem().name !== eudora) {
197
233
  const eudoraNumber = 1 + eudorae.indexOf(eudora);
198
234
  if (!xpath(visitUrl("account.php?tab=correspondence"), `//select[@name="whichpenpal"]/option/@value`).includes(eudoraNumber.toString()) &&
199
235
  throwOnFail) {
200
- throw new Error(`I'm sorry buddy, but you don't seem to be subscribed to ${eudora}. Which makes it REALLY hard to correspond with them.`);
236
+ throw new AscensionPrepError(`Unable to swap eudora to ${eudora} because you are not subscribed to it.`);
201
237
  }
202
238
  else {
203
239
  visitUrl(`account.php?actions[]=whichpenpal&whichpenpal=${eudoraNumber}&action=Update`, true);
204
240
  }
205
241
  if (eudoraItem() !== Item.get(eudora) && throwOnFail) {
206
- throw new Error(`We really thought we changed your eudora to a ${eudora}, but Mafia is saying otherwise.`);
242
+ throw new AscensionPrepError(eudora, eudoraItem());
207
243
  }
208
244
  }
209
245
  if (chateau && ChateauMantegna.have()) {
210
246
  const { desk, ceiling, nightstand } = chateau;
211
247
  if (ceiling && ChateauMantegna.getCeiling() !== ceiling) {
212
248
  if (!ChateauMantegna.changeCeiling(ceiling) && throwOnFail) {
213
- throw new Error(`We tried, but were unable to change your chateau ceiling to ${ceiling}. Probably.`);
249
+ throw new AscensionPrepError(ceiling, ChateauMantegna.getCeiling() ?? "unknown");
214
250
  }
215
251
  }
216
252
  if (desk && ChateauMantegna.getDesk() !== desk) {
217
253
  if (!ChateauMantegna.changeDesk(desk) && throwOnFail) {
218
- throw new Error(`We tried, but were unable to change your chateau desk to ${desk}. Probably.`);
254
+ throw new AscensionPrepError(desk, ChateauMantegna.getDesk() ?? "unknown");
219
255
  }
220
256
  }
221
257
  if (nightstand && ChateauMantegna.getNightstand() !== nightstand) {
222
258
  if (!ChateauMantegna.changeNightstand(nightstand) && throwOnFail) {
223
- throw new Error(`We tried, but were unable to change your chateau nightstand to ${nightstand}. Probably.`);
259
+ throw new AscensionPrepError(nightstand, ChateauMantegna.getNightstand() ?? "unknown");
224
260
  }
225
261
  }
226
262
  }
@@ -8,6 +8,7 @@ export declare type MaximizeOptions = {
8
8
  bonusEquip: Map<Item, number>;
9
9
  onlySlot: Slot[];
10
10
  preventSlot: Slot[];
11
+ forceUpdate: boolean;
11
12
  };
12
13
  /**
13
14
  *
package/dist/maximize.js CHANGED
@@ -28,6 +28,7 @@ function mergeMaximizeOptions(defaultOptions, addendums) {
28
28
  ...defaultOptions.preventSlot,
29
29
  ...(addendums.preventSlot ?? []),
30
30
  ],
31
+ forceUpdate: addendums.forceUpdate ?? defaultOptions.forceUpdate,
31
32
  };
32
33
  }
33
34
  const defaultMaximizeOptions = {
@@ -39,6 +40,7 @@ const defaultMaximizeOptions = {
39
40
  bonusEquip: new Map(),
40
41
  onlySlot: [],
41
42
  preventSlot: [],
43
+ forceUpdate: false,
42
44
  };
43
45
  /**
44
46
  *
@@ -307,7 +309,7 @@ function saveCached(cacheKey, options) {
307
309
  */
308
310
  export function maximizeCached(objectives, options = {}) {
309
311
  const fullOptions = mergeMaximizeOptions(defaultMaximizeOptions, options);
310
- const { forceEquip, preventEquip, bonusEquip, onlySlot, preventSlot, } = fullOptions;
312
+ const { forceEquip, preventEquip, bonusEquip, onlySlot, preventSlot, forceUpdate, } = fullOptions;
311
313
  // Sort each group in objective to ensure consistent ordering in string
312
314
  const objective = [
313
315
  ...objectives.sort(),
@@ -321,7 +323,7 @@ export function maximizeCached(objectives, options = {}) {
321
323
  .sort(),
322
324
  ].join(", ");
323
325
  const cacheEntry = checkCache(objective, fullOptions);
324
- if (cacheEntry) {
326
+ if (cacheEntry && !forceUpdate) {
325
327
  logger.info("Equipment found in maximize cache, equipping...");
326
328
  applyCached(cacheEntry, fullOptions);
327
329
  if (verifyCached(cacheEntry)) {
@@ -381,6 +383,7 @@ export class Requirement {
381
383
  ...(optionsA.preventSlot ?? []),
382
384
  ...(optionsB.preventSlot ?? []),
383
385
  ],
386
+ forceUpdate: optionsA.forceUpdate || optionsB.forceUpdate,
384
387
  });
385
388
  }
386
389
  /**
package/dist/mood.d.ts CHANGED
@@ -25,6 +25,7 @@ declare type MoodOptions = {
25
25
  songSlots: Effect[][];
26
26
  mpSources: MpSource[];
27
27
  reserveMp: number;
28
+ useNativeRestores: boolean;
28
29
  };
29
30
  declare abstract class MoodElement {
30
31
  mpCostPerTurn(): number;
package/dist/mood.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import "core-js/modules/es.object.values";
2
- import { availableAmount, buy, cliExecute, eat, effectModifier, haveEffect, haveSkill, hpCost, mallPrice, mpCost, myHp, myMaxmp, myMp, numericModifier, retrieveItem, toEffect, toSkill, turnsPerCast, use, useSkill, } from "kolmafia";
2
+ import { availableAmount, buy, cliExecute, eat, effectModifier, haveEffect, haveSkill, hpCost, mallPrice, mpCost, myHp, myMaxmp, myMp, numericModifier, restoreMp, retrieveItem, toEffect, toSkill, turnsPerCast, use, useSkill, } from "kolmafia";
3
3
  import { getActiveSongs, have, isSong } from "./lib";
4
4
  import { get } from "./property";
5
5
  import { AsdonMartin } from "./resources";
@@ -92,8 +92,10 @@ class SkillMoodElement extends MoodElement {
92
92
  const activeSongs = getActiveSongs();
93
93
  for (const song of activeSongs) {
94
94
  const slot = mood.options.songSlots.find((slot) => slot.includes(song));
95
- if (!slot || slot.includes(effect))
95
+ if (!slot || slot.includes(effect)) {
96
96
  cliExecute(`shrug ${song}`);
97
+ break;
98
+ }
97
99
  }
98
100
  }
99
101
  let oldRemainingCasts = -1;
@@ -107,8 +109,9 @@ class SkillMoodElement extends MoodElement {
107
109
  else {
108
110
  const cost = mpCost(this.skill);
109
111
  maxCasts = Math.floor(Math.min(mood.availableMp(), myMp()) / cost);
110
- if (maxCasts === 0) {
111
- mood.moreMp(cost);
112
+ if (maxCasts < remainingCasts) {
113
+ const bestMp = Math.min(remainingCasts * mpCost(this.skill), myMaxmp());
114
+ mood.moreMp(bestMp);
112
115
  maxCasts = Math.floor(Math.min(mood.availableMp(), myMp()) / cost);
113
116
  }
114
117
  }
@@ -216,6 +219,7 @@ export class Mood {
216
219
  songSlots: [],
217
220
  mpSources: [MagicalSausages.instance, OscusSoda.instance],
218
221
  reserveMp: 0,
222
+ useNativeRestores: false,
219
223
  };
220
224
  /**
221
225
  * Set default options for new Mood instances.
@@ -237,7 +241,9 @@ export class Mood {
237
241
  * Get the MP available for casting skills.
238
242
  */
239
243
  availableMp() {
240
- return (sum(this.options.mpSources, (mpSource) => mpSource.availableMpMin()) + Math.max(myMp() - this.options.reserveMp, 0));
244
+ return this.options.useNativeRestores
245
+ ? Infinity
246
+ : sum(this.options.mpSources, (mpSource) => mpSource.availableMpMin()) + Math.max(myMp() - this.options.reserveMp, 0);
241
247
  }
242
248
  moreMp(minimumTarget) {
243
249
  if (myMp() >= minimumTarget)
@@ -249,6 +255,9 @@ export class Mood {
249
255
  break;
250
256
  }
251
257
  }
258
+ if (this.options.useNativeRestores) {
259
+ restoreMp(minimumTarget);
260
+ }
252
261
  }
253
262
  /**
254
263
  * Add a skill to the mood.