libram 0.7.1 → 0.7.3

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/ascend.d.ts CHANGED
@@ -6,6 +6,7 @@ export declare enum Lifestyle {
6
6
  normal = 2,
7
7
  hardcore = 3
8
8
  }
9
+ export declare function permedSkills(): Map<Skill, Lifestyle>;
9
10
  export declare class AscendError extends Error {
10
11
  cause?: Skill | Item | Class | Path | string;
11
12
  constructor(cause?: Skill | Item | Class | Path | string);
@@ -29,8 +30,12 @@ declare type MoonSign = number | "mongoose" | "wallaby" | "vole" | "platypus" |
29
30
  * @param moon Your moon sign as a string, or the zone you're looking for as a string
30
31
  * @param consumable From the astral deli. Pick the container item, not the product.
31
32
  * @param pet From the astral pet store.
33
+ * @param permSkills A Map<Skill, Lifestyle> of skills you'd like to perm, ordered by priority.
32
34
  */
33
- export declare function ascend(path: Path, playerClass: Class, lifestyle: Lifestyle, moon: MoonSign, consumable?: Item | undefined, pet?: Item | undefined, permSkills?: Map<Skill, Lifestyle> | undefined): void;
35
+ export declare function ascend(path: Path, playerClass: Class, lifestyle: Lifestyle, moon: MoonSign, consumable?: Item | undefined, pet?: Item | undefined, permOptions?: {
36
+ permSkills: Map<Skill, Lifestyle>;
37
+ neverAbort: boolean;
38
+ }): void;
34
39
  /**
35
40
  * Sets up various iotms you may want to use in the coming ascension
36
41
  * @param ascensionItems.workshed Workshed to switch to.
package/dist/ascend.js CHANGED
@@ -1,4 +1,5 @@
1
- import { Skill, Class, containsText, eudoraItem, getCampground, getWorkshed, Item, Path, toInt, use, visitUrl, xpath, haveSkill, } from "kolmafia";
1
+ import { Skill, Class, containsText, eudoraItem, getCampground, getWorkshed, Item, Path, toInt, use, visitUrl, xpath, haveSkill, getPermedSkills, toSkill, } from "kolmafia";
2
+ import { get } from "./property";
2
3
  import { ChateauMantegna } from "./resources";
3
4
  import { $item, $items, $stat } from "./template-string";
4
5
  import { createStringUnionTypeGuardFunction } from "./utils";
@@ -9,6 +10,12 @@ export var Lifestyle;
9
10
  Lifestyle[Lifestyle["normal"] = 2] = "normal";
10
11
  Lifestyle[Lifestyle["hardcore"] = 3] = "hardcore";
11
12
  })(Lifestyle || (Lifestyle = {}));
13
+ export function permedSkills() {
14
+ return new Map(Array.from(Object.entries(getPermedSkills())).map(([skillName, isHardcore]) => [
15
+ toSkill(skillName),
16
+ isHardcore ? Lifestyle.hardcore : Lifestyle.softcore,
17
+ ]));
18
+ }
12
19
  export class AscendError extends Error {
13
20
  cause;
14
21
  constructor(cause) {
@@ -18,7 +25,7 @@ export class AscendError extends Error {
18
25
  else if (cause instanceof Skill) {
19
26
  const reason = cause.permable
20
27
  ? haveSkill(cause)
21
- ? "invalid for mysterious reasons"
28
+ ? "too karmaically expensive"
22
29
  : "not a skill you currently know"
23
30
  : "unpermable";
24
31
  super(`Skill ${cause} is ${reason}!`);
@@ -160,8 +167,9 @@ function toMoonId(moon, playerClass) {
160
167
  * @param moon Your moon sign as a string, or the zone you're looking for as a string
161
168
  * @param consumable From the astral deli. Pick the container item, not the product.
162
169
  * @param pet From the astral pet store.
170
+ * @param permSkills A Map<Skill, Lifestyle> of skills you'd like to perm, ordered by priority.
163
171
  */
164
- export function ascend(path, playerClass, lifestyle, moon, consumable = $item `astral six-pack`, pet = undefined, permSkills = undefined) {
172
+ export function ascend(path, playerClass, lifestyle, moon, consumable = $item `astral six-pack`, pet = undefined, permOptions) {
165
173
  if (playerClass.path !== (path.avatar ? path : Path.none)) {
166
174
  throw new AscendError(playerClass);
167
175
  }
@@ -178,8 +186,8 @@ export function ascend(path, playerClass, lifestyle, moon, consumable = $item `a
178
186
  !$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)) {
179
187
  throw new AscendError(pet);
180
188
  }
181
- const illegalSkill = permSkills
182
- ? Array.from(permSkills.keys()).find((skill) => !skill.permable || !haveSkill(skill))
189
+ const illegalSkill = permOptions
190
+ ? Array.from(permOptions.permSkills.keys()).find((skill) => !skill.permable || !haveSkill(skill))
183
191
  : undefined;
184
192
  if (illegalSkill) {
185
193
  throw new AscendError(illegalSkill);
@@ -196,10 +204,20 @@ export function ascend(path, playerClass, lifestyle, moon, consumable = $item `a
196
204
  }
197
205
  if (pet)
198
206
  visitUrl(`afterlife.php?action=buyarmory&whichitem=${toInt(pet)}`);
199
- if (permSkills) {
200
- for (const [skill, permLevel] of permSkills.entries()) {
201
- if (permLevel !== Lifestyle.casual) {
202
- const permText = permLevel === Lifestyle.hardcore ? "hcperm" : "scperm";
207
+ if (permOptions) {
208
+ const currentPerms = permedSkills();
209
+ let karma = get("bankedKarma");
210
+ for (const [skill, prospectivePermLevel,] of permOptions.permSkills.entries()) {
211
+ const currentPermLevel = currentPerms.get(skill) ?? Lifestyle.casual;
212
+ if (prospectivePermLevel > currentPermLevel) {
213
+ const expectedKarma = 100 * (prospectivePermLevel - currentPermLevel);
214
+ if (karma < expectedKarma) {
215
+ if (!permOptions.neverAbort)
216
+ throw new AscendError(skill);
217
+ continue;
218
+ }
219
+ karma -= expectedKarma;
220
+ const permText = prospectivePermLevel === Lifestyle.hardcore ? "hcperm" : "scperm";
203
221
  visitUrl(`afterlife.php?action=${permText}&whichskill=${toInt(skill)}`);
204
222
  }
205
223
  }
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Visits the Cooling Tank on level 8 of the Fallout shelter to gain 300 rads
3
+ */
4
+ export declare function coolingTank(): void;
5
+ /**
6
+ * Visits the Spa Simulation Chamber on level 4 of the Fallout shelter for 100 turns of "100% all stats"
7
+ */
8
+ export declare function spa(): void;
9
+ /**
10
+ * Visits the Chronodynamics Laboratory on level 5 of the Fallout shelter to permanently increase radiation level by 3
11
+ */
12
+ export declare function chronoLab(): void;
@@ -0,0 +1,19 @@
1
+ import { visitUrl } from "kolmafia";
2
+ /**
3
+ * Visits the Cooling Tank on level 8 of the Fallout shelter to gain 300 rads
4
+ */
5
+ export function coolingTank() {
6
+ visitUrl("place.php?whichplace=falloutshelter&action=vault8");
7
+ }
8
+ /**
9
+ * Visits the Spa Simulation Chamber on level 4 of the Fallout shelter for 100 turns of "100% all stats"
10
+ */
11
+ export function spa() {
12
+ visitUrl("place.php?whichplace=falloutshelter&action=vault3");
13
+ }
14
+ /**
15
+ * Visits the Chronodynamics Laboratory on level 5 of the Fallout shelter to permanently increase radiation level by 3
16
+ */
17
+ export function chronoLab() {
18
+ visitUrl("place.php?whichplace=falloutshelter&action=vault5");
19
+ }
@@ -1,2 +1,3 @@
1
1
  import CommunityService from "./2015/CommunityService";
2
- export { CommunityService };
2
+ import * as NuclearAutumn from "./2016/NuclearAutumn";
3
+ export { CommunityService, NuclearAutumn };
@@ -1,2 +1,3 @@
1
1
  import CommunityService from "./2015/CommunityService";
2
- export { CommunityService };
2
+ import * as NuclearAutumn from "./2016/NuclearAutumn";
3
+ export { CommunityService, NuclearAutumn };
package/dist/combat.js CHANGED
@@ -14,7 +14,7 @@ export function getMacroId(name = MACRO_NAME) {
14
14
  if (macroMatches.length === 0) {
15
15
  visitUrl("account_combatmacros.php?action=new");
16
16
  const newMacroText = visitUrl(`account_combatmacros.php?macroid=0&name=${name}&macrotext=abort&action=save`);
17
- return parseInt(xpath(newMacroText, "//input[@name=macroid]/@value")[0], 10);
17
+ return parseInt(xpath(newMacroText, `//input[@name=${name}]/@value`)[0], 10);
18
18
  }
19
19
  else {
20
20
  return parseInt(macroMatches[0], 10);
@@ -167,6 +167,7 @@ export class Macro {
167
167
  const id = Macro.cachedMacroIds.get(name) ?? getMacroId(name);
168
168
  visitUrl(`account_combatmacros.php?macroid=${id}&action=edit&what=Delete&confirm=1`);
169
169
  Macro.cachedAutoAttacks.delete(name);
170
+ Macro.cachedMacroIds.delete(name);
170
171
  }
171
172
  }
172
173
  /**
@@ -15,7 +15,7 @@ function expectedAdventures(item, modifiers) {
15
15
  if (item.adventures === "")
16
16
  return 0;
17
17
  const [min, recordedMax] = item.adventures
18
- .split(/[-–—]/)
18
+ .split(/[-]/)
19
19
  .map((s) => parseInt(s));
20
20
  const max = recordedMax ?? min;
21
21
  const interpolated = [...new Array(max - min + 1).keys()].map((n) => n + min);
@@ -23,6 +23,7 @@ function expectedAdventures(item, modifiers) {
23
23
  (itemType(item) === "booze" && item.notes?.includes("BEER"))
24
24
  ? 1.5
25
25
  : 1.3;
26
+ const seasoningAdventures = max - min <= 1 ? 1 : 0.5;
26
27
  const garish = modifiers.garish && item.notes?.includes("LASAGNA") && !isMonday();
27
28
  const refinedPalate = modifiers.refinedPalate && item.notes?.includes("WINE");
28
29
  const pinkyRing = modifiers.pinkyRing && item.notes?.includes("WINE");
@@ -46,7 +47,7 @@ function expectedAdventures(item, modifiers) {
46
47
  if (itemType(item) === "food" && modifiers.mayoflex)
47
48
  adventures++;
48
49
  if (itemType(item) === "food" && modifiers.seasoning)
49
- adventures += 0.5;
50
+ adventures += seasoningAdventures;
50
51
  return adventures;
51
52
  }) / interpolated.length);
52
53
  }
@@ -223,11 +224,6 @@ class DietPlanner {
223
224
  */
224
225
  consumptionHelpersAndValue(menuItem, overrideModifiers) {
225
226
  const helpers = [];
226
- if (this.seasoning &&
227
- itemType(menuItem.item) === "food" &&
228
- this.mpa * 0.5 > mallPrice($item `Special Seasoning`)) {
229
- helpers.push(this.seasoning);
230
- }
231
227
  if (itemType(menuItem.item) === "food" && this.mayoLookup.size) {
232
228
  const mayo = menuItem.mayo
233
229
  ? this.mayoLookup.get(menuItem.mayo)
@@ -248,6 +244,20 @@ class DietPlanner {
248
244
  tuxedoShirt: have($item `tuxedo shirt`) && canEquip($item `tuxedo shirt`),
249
245
  ...overrideModifiers,
250
246
  };
247
+ if (this.seasoning &&
248
+ itemType(menuItem.item) === "food" &&
249
+ this.mpa *
250
+ (expectedAdventures(menuItem.item, {
251
+ ...defaultModifiers,
252
+ seasoning: true,
253
+ }) -
254
+ expectedAdventures(menuItem.item, {
255
+ ...defaultModifiers,
256
+ seasoning: false,
257
+ })) >
258
+ mallPrice($item `Special Seasoning`)) {
259
+ helpers.push(this.seasoning);
260
+ }
251
261
  const forkMug = itemType(menuItem.item) === "food"
252
262
  ? this.fork
253
263
  : itemType(menuItem.item) === "booze"
@@ -340,7 +350,7 @@ class DietPlanner {
340
350
  const [helpersAndItem, value] = this.consumptionHelpersAndValue(trialItem, {});
341
351
  return valueWithout > valueWith + value
342
352
  ? [valueWithout, planWithout]
343
- : [valueWith, [...planWith, [helpersAndItem, 1]]];
353
+ : [valueWith + value, [...planWith, [helpersAndItem, 1]]];
344
354
  }
345
355
  }
346
356
  /**
package/dist/lib.js CHANGED
@@ -327,6 +327,9 @@ export function getBanishedMonsters() {
327
327
  if (banisher.toLowerCase() === "saber force") {
328
328
  result.set($skill `Use the Force`, Monster.get(foe));
329
329
  }
330
+ else if (banisher.toLowerCase() === "nanorhino") {
331
+ result.set($skill `Unleash Nanites`, Monster.get(foe));
332
+ }
330
333
  else if ([
331
334
  Item.none,
332
335
  Item.get(`training scroll: Snokebomb`),
@@ -9,6 +9,7 @@ export declare type MaximizeOptions = {
9
9
  onlySlot: Slot[];
10
10
  preventSlot: Slot[];
11
11
  forceUpdate: boolean;
12
+ modes: Modes;
12
13
  };
13
14
  /**
14
15
  *
@@ -20,6 +21,29 @@ export declare type MaximizeOptions = {
20
21
  * @param options.bonusEquip Equipment to apply a bonus to ("200 bonus X").
21
22
  */
22
23
  export declare function setDefaultMaximizeOptions(options: Partial<MaximizeOptions>): void;
24
+ declare const modeableCommands: readonly ["backupcamera", "umbrella", "snowsuit", "edpiece", "retrocape", "parka"];
25
+ export declare type Mode = typeof modeableCommands[number];
26
+ export declare type Modes = Partial<{
27
+ [x in Mode]: string;
28
+ }>;
29
+ export declare const modeableItems: {
30
+ readonly backupcamera: Item;
31
+ readonly umbrella: Item;
32
+ readonly snowsuit: Item;
33
+ readonly edpiece: Item;
34
+ readonly retrocape: Item;
35
+ readonly parka: Item;
36
+ };
37
+ export declare const modeableState: {
38
+ readonly backupcamera: () => string;
39
+ readonly umbrella: () => string;
40
+ readonly snowsuit: () => string;
41
+ readonly edpiece: () => string;
42
+ readonly retrocape: () => string;
43
+ readonly parka: () => string;
44
+ };
45
+ export declare function getCurrentModes(): Modes;
46
+ export declare function applyModes(modes: Modes): void;
23
47
  /**
24
48
  * Run the maximizer, but only if the objective and certain pieces of game state haven't changed since it was last run.
25
49
  * @param objectives Objectives to maximize for.
@@ -63,3 +87,4 @@ export declare class Requirement {
63
87
  */
64
88
  static maximize(...requirements: Requirement[]): void;
65
89
  }
90
+ export {};
package/dist/maximize.js CHANGED
@@ -1,4 +1,4 @@
1
- import { availableAmount, bjornifyFamiliar, canEquip, cliExecute, enthroneFamiliar, equip, equippedAmount, equippedItem, 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, outfit, Slot, } from "kolmafia";
2
2
  import logger from "./logger";
3
3
  import { $familiar, $item, $slot, $slots, $stats } from "./template-string";
4
4
  import { setEqual } from "./utils";
@@ -29,6 +29,7 @@ function mergeMaximizeOptions(defaultOptions, addendums) {
29
29
  ...(addendums.preventSlot ?? []),
30
30
  ],
31
31
  forceUpdate: addendums.forceUpdate ?? defaultOptions.forceUpdate,
32
+ modes: { ...defaultOptions.modes, ...(addendums.modes ?? {}) },
32
33
  };
33
34
  }
34
35
  const defaultMaximizeOptions = {
@@ -41,6 +42,7 @@ const defaultMaximizeOptions = {
41
42
  onlySlot: [],
42
43
  preventSlot: [],
43
44
  forceUpdate: false,
45
+ modes: {},
44
46
  };
45
47
  /**
46
48
  *
@@ -54,6 +56,50 @@ const defaultMaximizeOptions = {
54
56
  export function setDefaultMaximizeOptions(options) {
55
57
  Object.assign(defaultMaximizeOptions, options);
56
58
  }
59
+ const modeableCommands = [
60
+ "backupcamera",
61
+ "umbrella",
62
+ "snowsuit",
63
+ "edpiece",
64
+ "retrocape",
65
+ "parka",
66
+ ];
67
+ export const modeableItems = {
68
+ backupcamera: $item `backup camera`,
69
+ umbrella: $item `unbreakable umbrella`,
70
+ snowsuit: $item `Snow Suit`,
71
+ edpiece: $item `The Crown of Ed the Undying`,
72
+ retrocape: $item `unwrapped knock-off retro superhero cape`,
73
+ parka: $item `Jurassic Parka`,
74
+ };
75
+ export const modeableState = {
76
+ backupcamera: () => getProperty("backupCameraMode"),
77
+ umbrella: () => getProperty("umbrellaState"),
78
+ snowsuit: () => getProperty("snowsuit"),
79
+ edpiece: () => getProperty("edPiece"),
80
+ retrocape: () => getProperty("retroCapeSuperhero") +
81
+ " " +
82
+ getProperty("retroCapeWashingInstructions"),
83
+ parka: () => getProperty("parkaMode"),
84
+ };
85
+ export function getCurrentModes() {
86
+ const modes = {};
87
+ for (const key of modeableCommands) {
88
+ if (haveEquipped(modeableItems[key])) {
89
+ modes[key] = modeableState[key]();
90
+ }
91
+ }
92
+ return modes;
93
+ }
94
+ export function applyModes(modes) {
95
+ for (const command of modeableCommands) {
96
+ if (haveEquipped(modeableItems[command])) {
97
+ if (modeableState[command]() !== modes[command]) {
98
+ cliExecute(command + " " + modes[command]);
99
+ }
100
+ }
101
+ }
102
+ }
57
103
  // Subset of slots that are valid for caching.
58
104
  const cachedSlots = $slots `hat, weapon, off-hand, back, shirt, pants, acc1, acc2, acc3, familiar`;
59
105
  class CacheEntry {
@@ -61,11 +107,13 @@ class CacheEntry {
61
107
  rider;
62
108
  familiar;
63
109
  canEquipItemCount;
64
- constructor(equipment, rider, familiar, canEquipItemCount) {
110
+ modes;
111
+ constructor(equipment, rider, familiar, canEquipItemCount, modes) {
65
112
  this.equipment = equipment;
66
113
  this.rider = rider;
67
114
  this.familiar = familiar;
68
115
  this.canEquipItemCount = canEquipItemCount;
116
+ this.modes = modes;
69
117
  }
70
118
  }
71
119
  class OutfitLRUCache {
@@ -201,6 +249,7 @@ function applyCached(entry, options) {
201
249
  entry.rider.get($item `Buddy Bjorn`)) {
202
250
  bjornifyFamiliar(entry.rider.get($item `Buddy Bjorn`) || $familiar.none);
203
251
  }
252
+ applyModes({ ...entry.modes, ...options.modes });
204
253
  }
205
254
  const slotStructure = [
206
255
  $slots `hat`,
@@ -288,7 +337,7 @@ function saveCached(cacheKey, options) {
288
337
  rider.delete($item `Crown of Thrones`);
289
338
  }
290
339
  }
291
- const entry = new CacheEntry(equipment, rider, myFamiliar(), canEquipItemCount());
340
+ const entry = new CacheEntry(equipment, rider, myFamiliar(), canEquipItemCount(), { ...getCurrentModes(), ...options.modes });
292
341
  cachedObjectives[cacheKey] = entry;
293
342
  if (options.useOutfitCaching) {
294
343
  const outfitName = outfitCache.insert(entry);