libram 0.9.3 → 0.9.5

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.
@@ -16,7 +16,7 @@ describe(Macro, () => {
16
16
  expect(Macro.if_("mock", Macro.abort()).toString()).toEqual(`if mock;abort;endif;`);
17
17
  });
18
18
  it("ifNot", () => {
19
- expect(Macro.ifNot("mock", Macro.abort()).toString()).toEqual(`if !(mock);abort;endif;`);
19
+ expect(Macro.ifNot("mock", Macro.abort()).toString()).toEqual(`if !mock;abort;endif;`);
20
20
  });
21
21
  it("while_", () => {
22
22
  expect(Macro.while_("mock", Macro.abort()).toString()).toEqual(`while mock;abort;endwhile;`);
@@ -1,7 +1,7 @@
1
1
  import { mallPrice, useFamiliar } from "kolmafia";
2
2
  import { Macro } from "../combat.js";
3
3
  import { Requirement } from "../maximize.js";
4
- import { sum, flat } from "../utils.js";
4
+ import { sum } from "../utils.js";
5
5
  /**
6
6
  * Merge a set of constraints into one
7
7
  *
@@ -97,7 +97,7 @@ export class ActionSource {
97
97
  // Inconsistent constraints - no path forward here.
98
98
  return null;
99
99
  }
100
- return new ActionSource([...flat(actions.map((action) => action.source))], () => sum(actions, (action) => action.potential()), Macro.step(...actions.map((action) => action.macro)), constraints);
100
+ return new ActionSource(actions.flatMap((action) => action.source), () => sum(actions, (action) => action.potential()), Macro.step(...actions.map((action) => action.macro)), constraints);
101
101
  }
102
102
  /**
103
103
  * Perform all preparation necessary to make this action available.
package/dist/combat.js CHANGED
@@ -349,9 +349,7 @@ export class Macro {
349
349
  * @returns {Macro} This object itself.
350
350
  */
351
351
  ifNot(condition, ifTrue) {
352
- return this.step(`if !(${Macro.makeBALLSPredicate(condition)})`)
353
- .step(ifTrue)
354
- .step("endif");
352
+ return this.if_(`!${Macro.makeBALLSPredicate(condition)}`, ifTrue);
355
353
  }
356
354
  /**
357
355
  * Create a new macro with an "if" statement, inverting the condition.
package/dist/lib.d.ts CHANGED
@@ -507,4 +507,16 @@ export declare function haveIntrinsic(effect: Effect): boolean;
507
507
  */
508
508
  export declare function extractItems(text: string): Map<Item, number>;
509
509
  export type CombatParams = Parameters<typeof runCombat>;
510
+ /**
511
+ * Calculate & return the scaling rate of a monster--`0` for non-scalers.
512
+ * @param monster The monster to check
513
+ * @returns The current scaling rate of the monster, based on your current in-game state
514
+ */
515
+ export declare const getScalingRate: (monster: Monster) => number;
516
+ /**
517
+ * Calculate & return the scaling cap of a monster--`0` for non-scalers.
518
+ * @param monster The monster to check
519
+ * @returns The current scaling cap of the monster, based on your current in-game state
520
+ */
521
+ export declare const getScalingCap: (monster: Monster) => number;
510
522
  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, } 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, } 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, flat, notNull } from "./utils.js";
6
+ import { makeByXFunction, chunk, notNull } from "./utils.js";
7
7
  /**
8
8
  * Determines the current maximum Accordion Thief songs the player can have in their head
9
9
  *
@@ -645,9 +645,9 @@ export const holidayWanderers = new Map([
645
645
  * @returns List of holiday wanderer Monsters
646
646
  */
647
647
  export function getTodaysHolidayWanderers() {
648
- return flat(holiday()
648
+ return holiday()
649
649
  .split("/")
650
- .map((holiday) => holidayWanderers.get(holiday) ?? []));
650
+ .flatMap((holiday) => holidayWanderers.get(holiday) ?? []);
651
651
  }
652
652
  /**
653
653
  * Determines whether or not we can safely call visitUrl(), based on whether we're in a fight, multi-fight, choice, etc
@@ -924,10 +924,10 @@ export function getCombatFlags(flags = [...ACCOUNT_COMBAT_FLAGS]) {
924
924
  */
925
925
  export function setCombatFlags(...flags) {
926
926
  return visitUrl(`account.php?${([
927
- ...flat(flags.map(({ flag, value }) => [
927
+ ...flags.flatMap(({ flag, value }) => [
928
928
  `actions[]=flag_${flag}`,
929
929
  `flag_${flag}=${Number(value)}`,
930
- ])),
930
+ ]),
931
931
  "action=Update",
932
932
  "am=1",
933
933
  "ajax=1",
@@ -970,3 +970,29 @@ export function haveIntrinsic(effect) {
970
970
  export function extractItems(text) {
971
971
  return new Map(Object.entries(kolmafiaExtractItems(text)).map(([itemName, quantity]) => [Item.get(itemName), quantity]));
972
972
  }
973
+ function makeScalerCalcFunction(cache, pattern) {
974
+ return function (monster) {
975
+ const current = cache.get(monster);
976
+ if (current !== undefined)
977
+ return monsterEval(current);
978
+ const result = pattern.exec(monster.attributes)?.[1] ?? "0";
979
+ cache.set(monster, result);
980
+ return monsterEval(result);
981
+ };
982
+ }
983
+ const scalerRates = new Map();
984
+ const scalerCaps = new Map();
985
+ const SCALE_RATE_PATTERN = /Scale: (?:\[([^\]]*)\]|(\d*))/;
986
+ const SCALE_CAP_PATTERN = /Cap: (?:\[([^\]]*)\]|(\d*))/;
987
+ /**
988
+ * Calculate & return the scaling rate of a monster--`0` for non-scalers.
989
+ * @param monster The monster to check
990
+ * @returns The current scaling rate of the monster, based on your current in-game state
991
+ */
992
+ export const getScalingRate = makeScalerCalcFunction(scalerRates, SCALE_RATE_PATTERN);
993
+ /**
994
+ * Calculate & return the scaling cap of a monster--`0` for non-scalers.
995
+ * @param monster The monster to check
996
+ * @returns The current scaling cap of the monster, based on your current in-game state
997
+ */
998
+ export const getScalingCap = makeScalerCalcFunction(scalerCaps, SCALE_CAP_PATTERN);
@@ -3,7 +3,7 @@ import { have as have_ } from "../../lib.js";
3
3
  import logger from "../../logger.js";
4
4
  import { get } from "../../property.js";
5
5
  import { $item } from "../../template-string.js";
6
- import { clamp, flat } from "../../utils.js";
6
+ import { clamp } from "../../utils.js";
7
7
  const item = $item `cursed monkey's paw`;
8
8
  /**
9
9
  * @returns Whether or not we currently `have` the cursed monkey's paw
@@ -25,15 +25,15 @@ export function wishes() {
25
25
  * @returns A set of all items we expect to be able to wish; this doesn't actually constitute all items
26
26
  */
27
27
  export function wishableItems(filters = {}) {
28
- return new Set(flat(Location.all()
28
+ return new Set(Location.all()
29
29
  .filter((l) => canAdventure(l) && (filters.location?.(l) ?? true))
30
- .map((l) => getMonsters(l)
30
+ .flatMap((l) => getMonsters(l)
31
31
  .filter((m) => m.copyable && (filters.monster?.(m) ?? true))
32
- .map((m) => itemDropsArray(m)
32
+ .flatMap((m) => itemDropsArray(m)
33
33
  .filter(({ type, rate, drop }) => !drop.quest &&
34
34
  (type !== "c" || rate >= 1) && // Remove random roll drops
35
35
  (filters.drop?.({ type, rate, drop }) ?? true))
36
- .map(({ drop }) => drop)))));
36
+ .map(({ drop }) => drop))));
37
37
  }
38
38
  const INVALID_CHARACTERS = /[^a-z\d -]/g;
39
39
  let _unwishableEffects;
@@ -8,6 +8,10 @@ export type CombinationString = `${Ring<0>} ${Ring<1>} ${Ring<2>} ${Ring<3>}`;
8
8
  * @returns Whether you `have` the Mayam calendar
9
9
  */
10
10
  export declare function have(): boolean;
11
+ /**
12
+ * @returns The Mayam calendar symbols you've used so far today.
13
+ */
14
+ export declare function symbolsUsed(): MayamSymbol[];
11
15
  /**
12
16
  * Determine whether a certain Mayam symbol is available for use today
13
17
  *
@@ -57,6 +61,7 @@ export declare const RESONANCES: Readonly<{
57
61
  "chair yam2 yam3 clock": Effect;
58
62
  "yam1 yam2 cheese clock": Effect;
59
63
  }>;
64
+ export declare const RESONANCE_KEYS: ("sword yam2 eyepatch explosion" | "yam1 meat cheese yam4" | "yam1 meat eyepatch yam4" | "yam1 lightning yam3 clock" | "yam1 yam2 yam3 explosion" | "yam1 yam2 cheese clock" | "eye yam2 eyepatch yam4" | "chair yam2 yam3 clock" | "fur lightning eyepatch yam4" | "fur yam2 wall yam4" | "vessel yam2 cheese explosion")[];
60
65
  /**
61
66
  * Find the combination needed to get a particular resonance
62
67
  * @param target The Item or Effect granted by the resonance
@@ -14,7 +14,12 @@ export const RINGS = Object.freeze([
14
14
  export function have() {
15
15
  return have_($item `Mayam Calendar`);
16
16
  }
17
- const symbolsUsed = () => get("_mayamSymbolsUsed").split(",");
17
+ /**
18
+ * @returns The Mayam calendar symbols you've used so far today.
19
+ */
20
+ export function symbolsUsed() {
21
+ return get("_mayamSymbolsUsed").split(",");
22
+ }
18
23
  /**
19
24
  * Determine whether certain Mayam symbols are available for use today
20
25
  *
@@ -59,7 +64,7 @@ export function submit(...combination) {
59
64
  if (!available(...toCombination(combination))) {
60
65
  return false;
61
66
  }
62
- return cliExecute(`mayam ring ${combination.join(" ").replace(/yam\d/g, "yam")}`);
67
+ return cliExecute(`mayam rings ${combination.join(" ").replace(/yam\d/g, "yam")}`);
63
68
  }
64
69
  export const RESONANCES = Object.freeze({
65
70
  "eye yam2 eyepatch yam4": $item `Mayam spinach`,
@@ -74,6 +79,7 @@ export const RESONANCES = Object.freeze({
74
79
  "chair yam2 yam3 clock": $effect `Caught Yam-Handed`,
75
80
  "yam1 yam2 cheese clock": $effect `Memories of Cheesier Age`,
76
81
  });
82
+ export const RESONANCE_KEYS = Object.keys(RESONANCES);
77
83
  /**
78
84
  * Find the combination needed to get a particular resonance
79
85
  * @param target The Item or Effect granted by the resonance
package/dist/utils.d.ts CHANGED
@@ -116,6 +116,13 @@ export declare function maxBy<T>(array: T[] | readonly T[], optimizer: (element:
116
116
  export declare function maxBy<S extends string | number | symbol, T extends {
117
117
  [x in S]: number;
118
118
  }>(array: T[] | readonly T[], key: S, reverse?: boolean): T;
119
+ /**
120
+ * Let Typescript see that you're working with tuples!
121
+ *
122
+ * @param args A spread array to interpret as a tuple
123
+ * @returns The given arg, its type now interpreted as a tuple
124
+ */
125
+ export declare function tuple<T extends any[]>(...args: T): T;
119
126
  export type Tuple<T, N extends number> = N extends N ? number extends N ? T[] : _tupleOf<T, N, []> : never;
120
127
  type _tupleOf<T, N extends number, R extends unknown[]> = R["length"] extends N ? R : _tupleOf<T, N, [T, ...R]>;
121
128
  /**
@@ -159,6 +166,7 @@ export type Switch<T extends string, S> = Record<T, S> | (Partial<{
159
166
  export declare function makeByXFunction<T extends string>(source: Delayed<T>): <S>(options: Switch<T, S>, alternateSource?: Delayed<T>) => S;
160
167
  /**
161
168
  * Flattens an array. Basically replacing Array.prototype.flat for which Rhino doesn't yet have an implementation
169
+ * @deprecated KoLMafia now supports the `flat` and `flatMap` methods
162
170
  *
163
171
  * @param arr Array to flatten
164
172
  * @param depth Number of layers to flatten by; Infinity for a fully flat array
package/dist/utils.js CHANGED
@@ -189,6 +189,16 @@ export function maxBy(array, optimizer, reverse = false) {
189
189
  return array.reduce((a, b) => a[optimizer] >= b[optimizer] !== reverse ? a : b);
190
190
  }
191
191
  }
192
+ /**
193
+ * Let Typescript see that you're working with tuples!
194
+ *
195
+ * @param args A spread array to interpret as a tuple
196
+ * @returns The given arg, its type now interpreted as a tuple
197
+ */
198
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
199
+ export function tuple(...args) {
200
+ return args;
201
+ }
192
202
  /**
193
203
  * Compare arrays shallowly
194
204
  *
@@ -230,6 +240,7 @@ export function makeByXFunction(source) {
230
240
  }
231
241
  /**
232
242
  * Flattens an array. Basically replacing Array.prototype.flat for which Rhino doesn't yet have an implementation
243
+ * @deprecated KoLMafia now supports the `flat` and `flatMap` methods
233
244
  *
234
245
  * @param arr Array to flatten
235
246
  * @param depth Number of layers to flatten by; Infinity for a fully flat array
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "libram",
3
- "version": "0.9.3",
3
+ "version": "0.9.5",
4
4
  "description": "JavaScript helper library for KoLmafia",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",