libram 0.6.4 → 0.6.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.
Files changed (103) hide show
  1. package/dist/Clan.d.ts +2 -4
  2. package/dist/Clan.js +15 -60
  3. package/dist/Copier.d.ts +1 -0
  4. package/dist/Kmail.d.ts +1 -0
  5. package/dist/Kmail.js +2 -4
  6. package/dist/Path.d.ts +2 -0
  7. package/dist/Path.js +2 -0
  8. package/dist/actions/ActionSource.d.ts +4 -3
  9. package/dist/actions/ActionSource.js +2 -2
  10. package/dist/actions/FreeKill.js +1 -1
  11. package/dist/actions/FreeRun.js +2 -2
  12. package/dist/ascend.d.ts +4 -2
  13. package/dist/ascend.js +17 -11
  14. package/dist/challengePaths/2015/CommunityService.d.ts +2 -1
  15. package/dist/challengePaths/2015/CommunityService.js +37 -25
  16. package/dist/combat.d.ts +1 -0
  17. package/dist/combat.js +4 -6
  18. package/dist/console.d.ts +12 -4
  19. package/dist/console.js +0 -1
  20. package/dist/diet/index.d.ts +1 -0
  21. package/dist/diet/index.js +2 -2
  22. package/dist/dungeons/Dreadsylvania.d.ts +1 -0
  23. package/dist/dungeons/Dungeon.d.ts +1 -0
  24. package/dist/dungeons/Dungeon.js +1 -1
  25. package/dist/dungeons/Hobopolis.d.ts +1 -0
  26. package/dist/dungeons/SlimeTube.d.ts +1 -0
  27. package/dist/index.d.ts +7 -2
  28. package/dist/index.js +2 -0
  29. package/dist/lib.d.ts +1 -0
  30. package/dist/lib.js +2 -2
  31. package/dist/maximize.d.ts +1 -0
  32. package/dist/maximize.js +2 -2
  33. package/dist/modifier.d.ts +1 -0
  34. package/dist/modifier.js +1 -1
  35. package/dist/mood.d.ts +1 -0
  36. package/dist/mood.js +9 -8
  37. package/dist/property.d.ts +8 -3
  38. package/dist/property.js +7 -1
  39. package/dist/propertyTypes.d.ts +4 -4
  40. package/dist/propertyTypes.js +4 -4
  41. package/dist/resources/2007/CandyHearts.d.ts +2 -1
  42. package/dist/resources/2007/CandyHearts.js +1 -1
  43. package/dist/resources/2008/DivineFavors.d.ts +2 -1
  44. package/dist/resources/2008/DivineFavors.js +1 -1
  45. package/dist/resources/2009/Bandersnatch.d.ts +2 -1
  46. package/dist/resources/2009/Bandersnatch.js +1 -1
  47. package/dist/resources/2009/LoveSongs.d.ts +2 -1
  48. package/dist/resources/2009/LoveSongs.js +1 -1
  49. package/dist/resources/2009/SpookyPutty.d.ts +2 -1
  50. package/dist/resources/2010/Brickos.d.ts +2 -1
  51. package/dist/resources/2010/Brickos.js +1 -1
  52. package/dist/resources/2010/CrownOfThrones.d.ts +1 -0
  53. package/dist/resources/2010/CrownOfThrones.js +1 -1
  54. package/dist/resources/2010/LookingGlass.d.ts +25 -0
  55. package/dist/resources/2010/LookingGlass.js +85 -0
  56. package/dist/resources/2011/Gygaxian.d.ts +2 -1
  57. package/dist/resources/2011/Gygaxian.js +1 -1
  58. package/dist/resources/2011/ObtuseAngel.d.ts +2 -1
  59. package/dist/resources/2011/StompingBoots.d.ts +1 -1
  60. package/dist/resources/2011/StompingBoots.js +1 -1
  61. package/dist/resources/2012/RainDoh.d.ts +2 -1
  62. package/dist/resources/2012/Resolutions.d.ts +2 -1
  63. package/dist/resources/2012/Resolutions.js +1 -1
  64. package/dist/resources/2013/Florist.d.ts +1 -0
  65. package/dist/resources/2013/PulledTaffy.d.ts +2 -1
  66. package/dist/resources/2013/PulledTaffy.js +1 -1
  67. package/dist/resources/2014/DNALab.d.ts +1 -0
  68. package/dist/resources/2014/DNALab.js +3 -3
  69. package/dist/resources/2014/WinterGarden.d.ts +1 -0
  70. package/dist/resources/2014/WinterGarden.js +1 -1
  71. package/dist/resources/2015/ChateauMantegna.d.ts +1 -0
  72. package/dist/resources/2015/ChateauMantegna.js +1 -1
  73. package/dist/resources/2015/MayoClinic.d.ts +1 -0
  74. package/dist/resources/2016/SourceTerminal.d.ts +1 -0
  75. package/dist/resources/2016/SourceTerminal.js +1 -1
  76. package/dist/resources/2016/Witchess.d.ts +2 -1
  77. package/dist/resources/2016/Witchess.js +1 -1
  78. package/dist/resources/2017/AsdonMartin.d.ts +12 -4
  79. package/dist/resources/2017/AsdonMartin.js +39 -6
  80. package/dist/resources/2017/MummingTrunk.d.ts +7 -0
  81. package/dist/resources/2017/MummingTrunk.js +26 -0
  82. package/dist/resources/2017/Pantogram.d.ts +1 -0
  83. package/dist/resources/2017/Pantogram.js +1 -1
  84. package/dist/resources/2017/TunnelOfLove.d.ts +1 -0
  85. package/dist/resources/2018/LatteLoversMembersMug.d.ts +1 -0
  86. package/dist/resources/2018/SongBoom.d.ts +1 -1
  87. package/dist/resources/2019/BeachComb.d.ts +1 -0
  88. package/dist/resources/2019/Snapper.d.ts +1 -0
  89. package/dist/resources/2019/Snapper.js +2 -2
  90. package/dist/resources/2020/Guzzlr.d.ts +1 -0
  91. package/dist/resources/2020/Guzzlr.js +1 -1
  92. package/dist/resources/2021/CrystalBall.d.ts +1 -0
  93. package/dist/resources/2021/CrystalBall.js +1 -1
  94. package/dist/resources/2021/DaylightShavings.d.ts +3 -2
  95. package/dist/resources/2022/CombatLoversLocket.d.ts +36 -0
  96. package/dist/resources/2022/CombatLoversLocket.js +73 -0
  97. package/dist/resources/LibramSummon.d.ts +1 -0
  98. package/dist/resources/index.d.ts +20 -18
  99. package/dist/resources/index.js +20 -18
  100. package/dist/session.d.ts +1 -0
  101. package/dist/template-string.d.ts +1 -0
  102. package/dist/template-string.js +1 -0
  103. package/package.json +17 -14
package/dist/Clan.d.ts CHANGED
@@ -1,12 +1,9 @@
1
+ import { Item, Monster } from "kolmafia";
1
2
  export interface Rank {
2
3
  name: string;
3
4
  degree: number;
4
5
  id: number;
5
6
  }
6
- export declare class ClanError extends Error {
7
- reason?: Error;
8
- constructor(message: string, reason?: Error);
9
- }
10
7
  export declare class Clan {
11
8
  readonly id: number;
12
9
  readonly name: string;
@@ -42,6 +39,7 @@ export declare class Clan {
42
39
  */
43
40
  static getWhitelisted(): Clan[];
44
41
  private constructor();
42
+ private _check;
45
43
  /**
46
44
  * Join clan
47
45
  */
package/dist/Clan.js CHANGED
@@ -1,39 +1,7 @@
1
- var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
- else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
- return c > 3 && r && Object.defineProperty(target, key, r), r;
6
- };
7
- import { availableAmount, cliExecute, getClanId, getClanName, getPlayerId, putStash, refreshStash, retrieveItem, stashAmount, takeStash, visitUrl, xpath, } from "kolmafia";
1
+ import { availableAmount, cliExecute, getClanId, getClanName, getPlayerId, Monster, putStash, refreshStash, retrieveItem, stashAmount, takeStash, visitUrl, xpath, } from "kolmafia";
8
2
  import { getFoldGroup } from "./lib";
9
3
  import logger from "./logger";
10
4
  import { arrayToCountedMap, countedMapToArray, countedMapToString, notNull, parseNumber, } from "./utils";
11
- export class ClanError extends Error {
12
- reason;
13
- constructor(message, reason) {
14
- super(message);
15
- this.reason = reason;
16
- Object.setPrototypeOf(this, ClanError.prototype);
17
- }
18
- }
19
- // It would be fantastic to have this function properly typed
20
- // But until someone can work out how to do it, it gets the
21
- // comment blocks of shame
22
- /* eslint-disable */
23
- function validate(target, propertyName, descriptor) {
24
- if (!descriptor?.value)
25
- return;
26
- const method = descriptor.value;
27
- // @ts-ignore
28
- descriptor.value = function (...args) {
29
- // @ts-ignore
30
- if (this.id !== getClanId()) {
31
- throw new Error("You are no longer a member of this clan");
32
- }
33
- return method.apply(this, args);
34
- };
35
- }
36
- /* eslint-enable */
37
5
  const clanIdCache = {};
38
6
  const toPlayerId = (player) => typeof player === "string" ? getPlayerId(player) : player;
39
7
  const LOG_FAX_PATTERN = /(\d{2}\/\d{2}\/\d{2}, \d{2}:\d{2}(?:AM|PM): )<a [^>]+>([^<]+)<\/a>(?: faxed in a (?<monster>.*?))<br>/;
@@ -146,6 +114,11 @@ export class Clan {
146
114
  this.id = id;
147
115
  this.name = name;
148
116
  }
117
+ _check() {
118
+ if (this.id !== getClanId()) {
119
+ throw new Error("You are no longer a member of this clan");
120
+ }
121
+ }
149
122
  /**
150
123
  * Join clan
151
124
  */
@@ -159,6 +132,7 @@ export class Clan {
159
132
  * Return the monster that is currently in the current clan's fax machine if any
160
133
  */
161
134
  getCurrentFax() {
135
+ this._check();
162
136
  const logs = visitUrl("clan_log.php");
163
137
  const lastFax = logs.match(LOG_FAX_PATTERN);
164
138
  if (!lastFax)
@@ -172,6 +146,7 @@ export class Clan {
172
146
  * List available ranks (name, degree and id) from the current clan
173
147
  */
174
148
  getRanks() {
149
+ this._check();
175
150
  const page = visitUrl("clan_whitelist.php");
176
151
  return xpath(page, '//select[@name="level"]//option')
177
152
  .map((option) => {
@@ -197,6 +172,7 @@ export class Clan {
197
172
  * @param title Title to give the player. If not provided, will be blank
198
173
  */
199
174
  addPlayerToWhitelist(player, rankName, title = "") {
175
+ this._check();
200
176
  const playerId = toPlayerId(player);
201
177
  const ranks = this.getRanks();
202
178
  const rank = rankName
@@ -213,6 +189,7 @@ export class Clan {
213
189
  * @param player Player id or name
214
190
  */
215
191
  removePlayerFromWhitelist(player) {
192
+ this._check();
216
193
  const playerId = toPlayerId(player);
217
194
  const result = visitUrl(`clan_whitelist.php?action=updatewl&pwd&who=${playerId}&remove=Remove`);
218
195
  return result.includes("Whitelist updated.");
@@ -221,6 +198,7 @@ export class Clan {
221
198
  * Return the amount of meat in the current clan's coffer.
222
199
  */
223
200
  getMeatInCoffer() {
201
+ this._check();
224
202
  const page = visitUrl("clan_stash.php");
225
203
  const [, meat] = page.match(/Your <b>Clan Coffer<\/b> contains ([\d,]+) Meat./) || ["0", "0"];
226
204
  return parseNumber(meat);
@@ -230,10 +208,12 @@ export class Clan {
230
208
  * @param amount Amount of meat to put in coffer
231
209
  */
232
210
  putMeatInCoffer(amount) {
211
+ this._check();
233
212
  const result = visitUrl(`clan_stash.php?pwd&action=contribute&howmuch=${amount}`);
234
213
  return result.includes("You contributed");
235
214
  }
236
215
  take(items) {
216
+ this._check();
237
217
  const map = arrayToCountedMap(items);
238
218
  map.forEach((quantity, item) => {
239
219
  let needed = Math.max(0, quantity - availableAmount(item));
@@ -271,6 +251,7 @@ export class Clan {
271
251
  return Array.isArray(items) ? countedMapToArray(map) : map;
272
252
  }
273
253
  put(items) {
254
+ this._check();
274
255
  const map = arrayToCountedMap(items);
275
256
  if (!this.check())
276
257
  throw new Error(`Wanted to return ${countedMapToString(map)} to ${this.name} but KoLmafia's clan data is out of sync`);
@@ -284,34 +265,8 @@ export class Clan {
284
265
  }
285
266
  withStash(items, callback // eslint-disable-line @typescript-eslint/no-explicit-any
286
267
  ) {
268
+ this._check();
287
269
  const map = arrayToCountedMap(items);
288
270
  return Clan._withStash(() => this.take(map), (borrowed) => this.put(borrowed), callback);
289
271
  }
290
272
  }
291
- __decorate([
292
- validate
293
- ], Clan.prototype, "getCurrentFax", null);
294
- __decorate([
295
- validate
296
- ], Clan.prototype, "getRanks", null);
297
- __decorate([
298
- validate
299
- ], Clan.prototype, "addPlayerToWhitelist", null);
300
- __decorate([
301
- validate
302
- ], Clan.prototype, "removePlayerFromWhitelist", null);
303
- __decorate([
304
- validate
305
- ], Clan.prototype, "getMeatInCoffer", null);
306
- __decorate([
307
- validate
308
- ], Clan.prototype, "putMeatInCoffer", null);
309
- __decorate([
310
- validate
311
- ], Clan.prototype, "take", null);
312
- __decorate([
313
- validate
314
- ], Clan.prototype, "put", null);
315
- __decorate([
316
- validate
317
- ], Clan.prototype, "withStash", null);
package/dist/Copier.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import { Monster } from "kolmafia";
1
2
  export declare class Copier {
2
3
  private couldCopy;
3
4
  private prepare;
package/dist/Kmail.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import "core-js/modules/es.object.entries";
2
+ import { Item } from "kolmafia";
2
3
  declare type RawKmail = {
3
4
  id: string;
4
5
  type: string;
package/dist/Kmail.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import "core-js/modules/es.object.entries";
2
- import { extractItems, extractMeat, isGiftable, toInt, visitUrl, } from "kolmafia";
2
+ import { extractItems, extractMeat, isGiftable, Item, toInt, visitUrl, } from "kolmafia";
3
3
  import { arrayToCountedMap, chunk } from "./utils";
4
4
  export default class Kmail {
5
5
  id;
@@ -40,9 +40,7 @@ export default class Kmail {
40
40
  }
41
41
  static _genericSend(to, message, items, meat, chunkSize, constructUrl, successString) {
42
42
  let m = meat;
43
- const sendableItems = [
44
- ...arrayToCountedMap(items).entries(),
45
- ].filter(([item]) => isGiftable(item));
43
+ const sendableItems = [...arrayToCountedMap(items).entries()].filter(([item]) => isGiftable(item));
46
44
  let result = true;
47
45
  const chunks = chunk(sendableItems, chunkSize);
48
46
  // Split the items to be sent into chunks of max 11 item types
package/dist/Path.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import { Class } from "kolmafia";
1
2
  export declare class Path {
2
3
  name: string;
3
4
  id: number;
@@ -64,4 +65,5 @@ export declare const Paths: {
64
65
  readonly YouRobot: Path;
65
66
  readonly QuantumTerrarium: Path;
66
67
  readonly Wildfire: Path;
68
+ readonly GreyYou: Path;
67
69
  };
package/dist/Path.js CHANGED
@@ -75,4 +75,6 @@ export const Paths = {
75
75
  YouRobot: new Path("You, Robot", 41, false, false, true, 0, 0, 0),
76
76
  QuantumTerrarium: new Path("Quantum Terrarium", 42, true, true, false),
77
77
  Wildfire: new Path("Wildfire", 43),
78
+ GreyYou: new Path("Grey You", 44, false, true, true, 0, 0, 0, // eslint-disable-next-line libram/verify-constants
79
+ $classes `Grey Goo`),
78
80
  };
@@ -1,3 +1,4 @@
1
+ import { Familiar, Item, Skill } from "kolmafia";
1
2
  import { Macro } from "../combat";
2
3
  import { Requirement } from "../maximize";
3
4
  export declare type FindActionSourceConstraints = {
@@ -57,17 +58,17 @@ export declare type ActionConstraints = {
57
58
  * A combat-based action resource in the game (e.g. a free run or free kill).
58
59
  */
59
60
  export declare class ActionSource {
60
- source: Item | Skill | Familiar;
61
+ source: Item | Skill | Familiar | Array<Item | Skill | Familiar>;
61
62
  potential: () => number;
62
63
  macro: Macro;
63
64
  constraints: ActionConstraints;
64
65
  /**
65
- * @param source Source of the action (e.g. item or skill needed).
66
+ * @param source Source(s) of the action (e.g. item, skill, or familiar needed).
66
67
  * @param potential Function returning how many times this action can be used.
67
68
  * @param macro Macro to execute this action in combat.
68
69
  * @param constraints Constraints required for this action to be available.
69
70
  */
70
- constructor(source: Item | Skill | Familiar, potential: () => number, macro: Macro, constraints?: ActionConstraints);
71
+ constructor(source: Item | Skill | Familiar | Array<Item | Skill | Familiar>, potential: () => number, macro: Macro, constraints?: ActionConstraints);
71
72
  /**
72
73
  * @returns Name of the action source.
73
74
  */
@@ -35,7 +35,7 @@ export class ActionSource {
35
35
  macro;
36
36
  constraints;
37
37
  /**
38
- * @param source Source of the action (e.g. item or skill needed).
38
+ * @param source Source(s) of the action (e.g. item, skill, or familiar needed).
39
39
  * @param potential Function returning how many times this action can be used.
40
40
  * @param macro Macro to execute this action in combat.
41
41
  * @param constraints Constraints required for this action to be available.
@@ -88,7 +88,7 @@ export class ActionSource {
88
88
  // Inconsistent constraints - no path forward here.
89
89
  return null;
90
90
  }
91
- return new ActionSource(this.source, () => sum(actions, (action) => action.potential()), Macro.step(...actions.map((action) => action.macro)), constraints);
91
+ return new ActionSource([...actions.map((action) => action.source).flat()], () => sum(actions, (action) => action.potential()), Macro.step(...actions.map((action) => action.macro)), constraints);
92
92
  }
93
93
  /**
94
94
  * Perform all preparation necessary to make this action available.
@@ -3,9 +3,9 @@ import { Macro } from "../combat";
3
3
  import { have } from "../lib";
4
4
  import { Requirement } from "../maximize";
5
5
  import { get } from "../property";
6
+ import * as AsdonMartin from "../resources/2017/AsdonMartin";
6
7
  import { $familiar, $item, $items, $skill } from "../template-string";
7
8
  import { ActionSource, findActionSource, } from "./ActionSource";
8
- import * as AsdonMartin from "../resources/2017/AsdonMartin";
9
9
  const freeKillSources = [
10
10
  // Free limited sources
11
11
  new ActionSource($skill `Gingerbread Mob Hit`, () => !get("_gingerbreadMobHitUsed") && have($skill `Gingerbread Mob Hit`)
@@ -3,11 +3,11 @@ import { Macro } from "../combat";
3
3
  import { ensureEffect, getFoldGroup, getSongCount, getSongLimit, have, } from "../lib";
4
4
  import { Requirement } from "../maximize";
5
5
  import { get } from "../property";
6
- import { $effect, $item, $items, $skill } from "../template-string";
7
- import { ActionSource, findActionSource, } from "./ActionSource";
8
6
  import * as Bandersnatch from "../resources/2009/Bandersnatch";
9
7
  import * as StompingBoots from "../resources/2011/StompingBoots";
10
8
  import * as AsdonMartin from "../resources/2017/AsdonMartin";
9
+ import { $effect, $item, $items, $skill } from "../template-string";
10
+ import { ActionSource, findActionSource, } from "./ActionSource";
11
11
  // Value of _lastCombatStarted the last time we updated scrapbook charges.
12
12
  let scrapbookChargesLastUpdated = get("_lastCombatStarted");
13
13
  // Free unlimited source every 30 turns.
package/dist/ascend.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import { Class, Item } from "kolmafia";
1
2
  import { Path } from "./Path";
2
3
  import { Ceiling, Desk, Nightstand } from "./resources/2015/ChateauMantegna";
3
4
  export declare enum Lifestyle {
@@ -27,10 +28,10 @@ declare type Eudora = typeof eudorae[number];
27
28
  * Sets up various iotms you may want to use in the coming ascension
28
29
  * @param ascensionItems.workshed Workshed to switch to.
29
30
  * @param ascensionItems.garden Garden to switch to.
30
- * @param ascensionItems An object potentially containing your workshed, garden, and eudora, all as items
31
+ * @param ascensionItems An object potentially containing your workshed, garden, chateau, and eudora, all as strings
31
32
  * @param throwOnFail If true, this will throw an error when it fails to switch something
32
33
  */
33
- export declare function prepareAscension({ workshed, garden, eudora, chateau, }?: {
34
+ export declare function prepareAscension({ workshed, garden, eudora, chateau, throwOnFail, }?: {
34
35
  workshed?: Workshed;
35
36
  garden?: Garden;
36
37
  eudora?: Eudora;
@@ -39,5 +40,6 @@ export declare function prepareAscension({ workshed, garden, eudora, chateau, }?
39
40
  ceiling?: Ceiling;
40
41
  nightstand?: Nightstand;
41
42
  };
43
+ throwOnFail?: boolean;
42
44
  }): void;
43
45
  export {};
package/dist/ascend.js CHANGED
@@ -1,6 +1,6 @@
1
- import { containsText, eudoraItem, getCampground, getWorkshed, toInt, toItem, use, visitUrl, xpath, } from "kolmafia";
2
- import { $item, $items, $stat } from "./template-string";
1
+ import { containsText, eudoraItem, getCampground, getWorkshed, Item, toInt, use, visitUrl, xpath, } from "kolmafia";
3
2
  import { ChateauMantegna } from "./resources";
3
+ import { $item, $items, $stat } from "./template-string";
4
4
  export var Lifestyle;
5
5
  (function (Lifestyle) {
6
6
  Lifestyle[Lifestyle["casual"] = 1] = "casual";
@@ -135,45 +135,51 @@ const eudorae = [
135
135
  * Sets up various iotms you may want to use in the coming ascension
136
136
  * @param ascensionItems.workshed Workshed to switch to.
137
137
  * @param ascensionItems.garden Garden to switch to.
138
- * @param ascensionItems An object potentially containing your workshed, garden, and eudora, all as items
138
+ * @param ascensionItems An object potentially containing your workshed, garden, chateau, and eudora, all as strings
139
139
  * @param throwOnFail If true, this will throw an error when it fails to switch something
140
140
  */
141
- export function prepareAscension({ workshed, garden, eudora, chateau, } = {}) {
142
- if (workshed && getWorkshed() !== toItem(workshed)) {
141
+ export function prepareAscension({ workshed, garden, eudora, chateau, throwOnFail, } = {}) {
142
+ throwOnFail = throwOnFail ?? true;
143
+ if (workshed && getWorkshed() !== Item.get(workshed)) {
143
144
  use(Item.get(workshed));
145
+ if (getWorkshed().name !== workshed && throwOnFail) {
146
+ throw new Error(`Failed to switch workshed to ${workshed}; it is currently still ${getWorkshed()}.`);
147
+ }
144
148
  }
145
149
  if (garden && !Object.getOwnPropertyNames(getCampground()).includes(garden)) {
146
150
  use(Item.get(garden));
147
- if (!Object.getOwnPropertyNames(getCampground()).includes(garden)) {
151
+ if (!Object.getOwnPropertyNames(getCampground()).includes(garden) &&
152
+ throwOnFail) {
148
153
  throw new Error(`We really thought we changed your garden to a ${garden}, but Mafia is saying otherwise.`);
149
154
  }
150
155
  }
151
156
  if (eudora && eudoraItem().name !== eudora) {
152
157
  const eudoraNumber = 1 + eudorae.indexOf(eudora);
153
- if (!xpath(visitUrl("account.php?tab=correspondence"), `//select[@name="whichpenpal"]/option/@value`).includes(eudoraNumber.toString())) {
158
+ if (!xpath(visitUrl("account.php?tab=correspondence"), `//select[@name="whichpenpal"]/option/@value`).includes(eudoraNumber.toString()) &&
159
+ throwOnFail) {
154
160
  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.`);
155
161
  }
156
162
  else {
157
163
  visitUrl(`account.php?actions[]=whichpenpal&whichpenpal=${eudoraNumber}&action=Update`, true);
158
164
  }
159
- if (eudoraItem() !== toItem(eudora)) {
165
+ if (eudoraItem() !== Item.get(eudora) && throwOnFail) {
160
166
  throw new Error(`We really thought we changed your eudora to a ${eudora}, but Mafia is saying otherwise.`);
161
167
  }
162
168
  }
163
169
  if (chateau && ChateauMantegna.have()) {
164
170
  const { desk, ceiling, nightstand } = chateau;
165
171
  if (ceiling && ChateauMantegna.getCeiling() !== ceiling) {
166
- if (!ChateauMantegna.changeCeiling(ceiling)) {
172
+ if (!ChateauMantegna.changeCeiling(ceiling) && throwOnFail) {
167
173
  throw new Error(`We tried, but were unable to change your chateau ceiling to ${ceiling}. Probably.`);
168
174
  }
169
175
  }
170
176
  if (desk && ChateauMantegna.getDesk() !== desk) {
171
- if (!ChateauMantegna.changeDesk(desk)) {
177
+ if (!ChateauMantegna.changeDesk(desk) && throwOnFail) {
172
178
  throw new Error(`We tried, but were unable to change your chateau desk to ${desk}. Probably.`);
173
179
  }
174
180
  }
175
181
  if (nightstand && ChateauMantegna.getNightstand() !== nightstand) {
176
- if (!ChateauMantegna.changeNightstand(nightstand)) {
182
+ if (!ChateauMantegna.changeNightstand(nightstand) && throwOnFail) {
177
183
  throw new Error(`We tried, but were unable to change your chateau nightstand to ${nightstand}. Probably.`);
178
184
  }
179
185
  }
@@ -56,9 +56,10 @@ declare class Test {
56
56
  * Wrapper function that prepares for a test and then completes it, adding time and turn details to the log.
57
57
  * @param prepare A function that does all necessary preparations for this CS test, including choosing your outfit.
58
58
  * @param beCertain Whether we should check council.php instead of mafia to determine whether the test is complete.
59
+ * @param maxTurns We will run the test iff the predicted turns is less than or equal to this parameter.
59
60
  * @returns The output of the prepare function given, or null if the test is already complete.
60
61
  */
61
- run<T>(prepare: () => T, beCertain?: boolean): T | null;
62
+ run(prepare: () => void, beCertain?: boolean, maxTurns?: number): boolean;
62
63
  /**
63
64
  * Checks council.php to verify that a test is complete; more reliable than isDone, but requires an additional pagehit.
64
65
  * @returns Whether council.php suggests that the test is complete.
@@ -1,10 +1,10 @@
1
- import { equippedItem, familiarWeight, getPower, haveEquipped, myBasestat, myBuffedstat, myClass, myFamiliar, myLevel, myMaxhp, myThrall, myTurncount, numericModifier, print, runChoice, toSlot, visitUrl, weightAdjustment, } from "kolmafia";
2
- import { get } from "../../property";
1
+ import { equippedItem, familiarWeight, getPower, haveEquipped, myBasestat, myBuffedstat, myFamiliar, myLevel, myMaxhp, myThrall, myTurncount, numericModifier, print, runChoice, toSlot, visitUrl, weightAdjustment, } from "kolmafia";
2
+ import { have } from "../../lib";
3
3
  import { Requirement } from "../../maximize";
4
- import { $class, $effect, $familiar, $item, $items, $slot, $stat, $thrall, } from "../../template-string";
5
4
  import { get as getModifier } from "../../modifier";
6
- import { have } from "../../lib";
7
- import { SongBoom } from "../../resources";
5
+ import { get } from "../../property";
6
+ import { MummingTrunk, SongBoom } from "../../resources";
7
+ import { $effect, $familiar, $item, $items, $slot, $stat, $thrall, } from "../../template-string";
8
8
  import { sum } from "../../utils";
9
9
  /**
10
10
  * A log of the predicted turns, actual turns, and duration of each CS test performed.
@@ -79,29 +79,34 @@ class Test {
79
79
  * Wrapper function that prepares for a test and then completes it, adding time and turn details to the log.
80
80
  * @param prepare A function that does all necessary preparations for this CS test, including choosing your outfit.
81
81
  * @param beCertain Whether we should check council.php instead of mafia to determine whether the test is complete.
82
+ * @param maxTurns We will run the test iff the predicted turns is less than or equal to this parameter.
82
83
  * @returns The output of the prepare function given, or null if the test is already complete.
83
84
  */
84
- run(prepare, beCertain = false) {
85
- const finishedFunction = beCertain ? this.verifyIsDone : this.isDone;
85
+ run(prepare, beCertain = false, maxTurns = Infinity) {
86
+ const finishedFunction = () => beCertain ? this.verifyIsDone() : this.isDone();
86
87
  if (finishedFunction())
87
- return null;
88
+ return false;
88
89
  const startTime = Date.now();
89
90
  const startTurns = myTurncount();
90
91
  try {
91
- return prepare();
92
+ prepare();
92
93
  }
93
- finally {
94
- const prediction = this.predictor();
94
+ catch {
95
+ return false;
96
+ }
97
+ const prediction = this.predictor();
98
+ if (prediction <= maxTurns) {
95
99
  this.do();
96
- const loggedTest = {
100
+ }
101
+ if (finishedFunction()) {
102
+ log[this.property] = {
97
103
  predictedTurns: prediction,
98
104
  turnCost: myTurncount() - startTurns,
99
105
  seconds: (Date.now() - startTime) / 1000,
100
106
  };
101
- if (finishedFunction()) {
102
- log[this.property] = loggedTest;
103
- }
107
+ return true;
104
108
  }
109
+ return false;
105
110
  }
106
111
  /**
107
112
  * Checks council.php to verify that a test is complete; more reliable than isDone, but requires an additional pagehit.
@@ -116,13 +121,10 @@ const thralls = new Map([
116
121
  [$stat `moxie`, $thrall `Penne Dreadful`],
117
122
  ]);
118
123
  const statTestPredictor = (stat) => {
119
- let baseStat = stat;
120
- if (myClass() === $class `Pastamancer`) {
121
- const thrall = thralls.get(stat);
122
- if (thrall && myThrall() === thrall)
123
- baseStat = $stat `mysticality`;
124
- }
125
- return () => 60 - Math.floor((1 / 30) * (myBuffedstat(stat) - myBasestat(baseStat)));
124
+ return () => 60 -
125
+ Math.floor((1 / 30) *
126
+ (myBuffedstat(stat) -
127
+ myBasestat(thralls.get(stat) === myThrall() ? $stat `mysticality` : stat)));
126
128
  };
127
129
  export const HP = new Test(1, "Donate Blood", () => 60 - Math.floor((myMaxhp() - myBuffedstat($stat `muscle`) - 3) / 30), new Requirement(["HP"], {}));
128
130
  export const Muscle = new Test(2, "Feed The Children", statTestPredictor($stat `Muscle`), new Requirement(["Muscle"], {}));
@@ -140,6 +142,7 @@ export const WeaponDamage = new Test(6, "Reduce Gazelle Population", () => {
140
142
  const songDamage = SongBoom.song() === "These Fists Were Made for Punchin'" ? myLevel() : 0;
141
143
  // mafia does not currently count swagger
142
144
  const multiplier = have($effect `Bow-Legged Swagger`) ? 2 : 1;
145
+ // We add 0.001 because the floor function sometimes introduces weird rounding errors
143
146
  return (60 -
144
147
  Math.floor((multiplier *
145
148
  (getModifier("Weapon Damage") -
@@ -153,6 +156,7 @@ export const SpellDamage = new Test(7, "Make Sausage", () => {
153
156
  const dragonfishDamage = myFamiliar() === $familiar `Magic Dragonfish`
154
157
  ? numericModifier($familiar `Magic Dragonfish`, "Spell Damage Percent", familiarWeight($familiar `Magic Dragonfish`) + weightAdjustment(), $item `none`)
155
158
  : 0;
159
+ // We add 0.001 because the floor function sometimes introduces weird rounding errors
156
160
  return (60 -
157
161
  Math.floor(getModifier("Spell Damage") / 50 + 0.001) -
158
162
  Math.floor((getModifier("Spell Damage Percent") - dragonfishDamage) / 50 + 0.001));
@@ -163,16 +167,24 @@ export const Noncombat = new Test(8, "Be a Living Statue", () => {
163
167
  return 60 - 3 * Math.floor(unsoftcappedRate / 5);
164
168
  }, new Requirement(["-combat"], {}));
165
169
  export const BoozeDrop = new Test(9, "Make Margaritas", () => {
166
- const familiarItemDrop = numericModifier(myFamiliar(), "Item Drop", familiarWeight(myFamiliar()) + weightAdjustment(), equippedItem($slot `familiar`));
170
+ const mummingCostume = MummingTrunk.currentCostumes().get(myFamiliar());
171
+ const mummingBuff = mummingCostume && mummingCostume[0] === "Item Drop"
172
+ ? mummingCostume[1]
173
+ : 0;
174
+ const familiarItemDrop = numericModifier(myFamiliar(), "Item Drop", familiarWeight(myFamiliar()) + weightAdjustment(), equippedItem($slot `familiar`)) +
175
+ mummingBuff -
176
+ numericModifier(equippedItem($slot `familiar`), "Item Drop");
177
+ const familiarBoozeDrop = numericModifier(myFamiliar(), "Booze Drop", familiarWeight(myFamiliar()) + weightAdjustment(), equippedItem($slot `familiar`)) - numericModifier(equippedItem($slot `familiar`), "Booze Drop");
167
178
  //Champagne doubling does NOT count for CS, so we undouble
168
179
  const multiplier = haveEquipped($item `broken champagne bottle`) &&
169
180
  get("garbageChampagneCharge") > 0
170
181
  ? 0.5
171
182
  : 1;
183
+ // We add 0.001 because the floor function sometimes introduces weird rounding errors
172
184
  return (60 -
173
185
  multiplier *
174
186
  Math.floor((getModifier("Item Drop") - familiarItemDrop) / 30 + 0.001) -
175
- Math.floor(getModifier("Booze Drop") / 15 + 0.001));
187
+ Math.floor((getModifier("Booze Drop") - familiarBoozeDrop) / 15 + 0.001));
176
188
  }, new Requirement(["Item Drop", "2 Booze Drop"], {
177
189
  preventEquip: $items `broken champagne bottle`,
178
190
  }));
@@ -193,5 +205,5 @@ export function printLog(colour = "blue") {
193
205
  }
194
206
  export const donate = () => {
195
207
  visitUrl("council.php");
196
- runChoice(30);
208
+ visitUrl("choice.php?whichchoice=1089&option=30");
197
209
  };
package/dist/combat.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import { Class, Effect, Item, Location, Monster, Skill, Stat } from "kolmafia";
1
2
  /**
2
3
  * Get the KoL native ID of the macro with name name.
3
4
  *
package/dist/combat.js CHANGED
@@ -1,7 +1,7 @@
1
- import { adv1, choiceFollowsFight, getAutoAttack, inMultiFight, removeProperty, runCombat, setAutoAttack, toInt, urlEncode, visitUrl, xpath, } from "kolmafia";
2
- import { $items, $skills } from "./template-string";
3
- import { get, set } from "./property";
1
+ import { adv1, choiceFollowsFight, Class, Effect, getAutoAttack, inMultiFight, Item, Location, Monster, removeProperty, runCombat, setAutoAttack, Skill, Stat, toInt, urlEncode, visitUrl, xpath, } from "kolmafia";
4
2
  import { getTodaysHolidayWanderers } from "./lib";
3
+ import { get, set } from "./property";
4
+ import { $items, $skills } from "./template-string";
5
5
  const MACRO_NAME = "Script Autoattack Macro";
6
6
  /**
7
7
  * Get the KoL native ID of the macro with name name.
@@ -561,9 +561,7 @@ export class StrictMacro extends Macro {
561
561
  * @returns {StrictMacro} This object itself.
562
562
  */
563
563
  trySkillRepeat(...skills) {
564
- return this.step(...skills.map((skill) => {
565
- return StrictMacro.if_(`hasskill ${skillBallsMacroName(skill)}`, StrictMacro.skill(skill).repeat());
566
- }));
564
+ return super.trySkillRepeat(...skills);
567
565
  }
568
566
  /**
569
567
  * Create a new macro with one or more skill-cast-and-repeat steps, where each step checks if you have the skill first.
package/dist/console.d.ts CHANGED
@@ -1,4 +1,12 @@
1
- export declare const log: (...args: any[]) => void;
2
- export declare const info: (...args: any[]) => void;
3
- export declare const warn: (...args: any[]) => void;
4
- export declare const error: (...args: any[]) => void;
1
+ export declare const log: (...args: {
2
+ toString(): string;
3
+ }[]) => void;
4
+ export declare const info: (...args: {
5
+ toString(): string;
6
+ }[]) => void;
7
+ export declare const warn: (...args: {
8
+ toString(): string;
9
+ }[]) => void;
10
+ export declare const error: (...args: {
11
+ toString(): string;
12
+ }[]) => void;
package/dist/console.js CHANGED
@@ -1,5 +1,4 @@
1
1
  import { print } from "kolmafia";
2
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
3
2
  const logColor = (color) => (...args) => {
4
3
  const output = args.map((x) => x.toString()).join(" ");
5
4
  if (color) {
@@ -1,3 +1,4 @@
1
+ import { Effect, Item } from "kolmafia";
1
2
  declare type RawDietEntry<T> = [MenuItem<T>[], number];
2
3
  declare type RawDiet<T> = RawDietEntry<T>[];
3
4
  declare type MenuItemOptions<T> = {
@@ -1,11 +1,11 @@
1
1
  import { canEquip, fullnessLimit, historicalAge, historicalPrice, inebrietyLimit, itemType, mallPrice, mallPrices, myFullness, myInebriety, myLevel, myPrimestat, mySpleenUse, npcPrice, spleenLimit, } from "kolmafia";
2
- import { knapsack } from "./knapsack";
3
2
  import { have } from "../lib";
4
3
  import { get as getModifier } from "../modifier";
5
4
  import { get } from "../property";
5
+ import { Mayo, installed as mayoInstalled } from "../resources/2015/MayoClinic";
6
6
  import { $effect, $item, $items, $skill, $stat } from "../template-string";
7
7
  import { sum, sumNumbers } from "../utils";
8
- import { Mayo, installed as mayoInstalled } from "../resources/2015/MayoClinic";
8
+ import { knapsack } from "./knapsack";
9
9
  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;
@@ -1,3 +1,4 @@
1
+ import { Item } from "kolmafia";
1
2
  export declare function close(): boolean;
2
3
  export declare function open(paymentPolicy?: "None" | "All" | "Difference"): boolean;
3
4
  export declare function distribute(idOrName?: number | string, loot?: Item | Item[] | Map<Item, number>, distributeAllOfAGivenItem?: boolean): void;
@@ -1,3 +1,4 @@
1
+ import { Item } from "kolmafia";
1
2
  export declare type Dungeon = {
2
3
  name: string;
3
4
  loot: Item[];
@@ -1,7 +1,7 @@
1
1
  import { getClanName, myId, toItem, visitUrl, xpath } from "kolmafia";
2
- import { $items } from "../template-string";
3
2
  import { Clan } from "../Clan";
4
3
  import { getPlayerFromIdOrName } from "../lib";
4
+ import { $items } from "../template-string";
5
5
  import { countedMapToArray } from "../utils";
6
6
  /**
7
7
  * Distributes loot from given dungeon
@@ -1,3 +1,4 @@
1
+ import { Item } from "kolmafia";
1
2
  export declare function close(): boolean;
2
3
  export declare function open(paymentPolicy?: "None" | "All" | "Difference"): boolean;
3
4
  export declare function distribute(idOrName?: number | string, loot?: Item | Item[] | Map<Item, number>, distributeAllOfAGivenItem?: boolean): void;
@@ -1,3 +1,4 @@
1
+ import { Item } from "kolmafia";
1
2
  export declare function close(): boolean;
2
3
  export declare function open(paymentPolicy?: "None" | "All" | "Difference"): boolean;
3
4
  export declare function distribute(idOrName?: number | string, loot?: Item | Item[] | Map<Item, number>, distributeAllOfAGivenItem?: boolean): void;