libram 0.7.2 → 0.7.4
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/combat.d.ts +18 -2
- package/dist/combat.js +35 -9
- package/dist/maximize.d.ts +25 -0
- package/dist/maximize.js +8 -6
- package/dist/resources/2017/AsdonMartin.js +12 -17
- package/dist/resources/2022/AutumnAton.js +3 -3
- package/package.json +1 -1
package/dist/combat.d.ts
CHANGED
|
@@ -7,6 +7,7 @@ import { Class, Effect, Item, Location, Monster, Skill, Stat } from "kolmafia";
|
|
|
7
7
|
*/
|
|
8
8
|
export declare function getMacroId(name?: string): number;
|
|
9
9
|
declare type ItemOrName = Item | string;
|
|
10
|
+
declare type PreBALLSPredicate = string | Monster | Monster[] | Effect | Skill | Item | Location | Class | Stat;
|
|
10
11
|
declare type SkillOrName = Skill | string;
|
|
11
12
|
declare type Constructor<T> = {
|
|
12
13
|
new (): T;
|
|
@@ -97,20 +98,35 @@ export declare class Macro {
|
|
|
97
98
|
* @returns {Macro} This object itself.
|
|
98
99
|
*/
|
|
99
100
|
static runaway<T extends Macro>(this: Constructor<T>): T;
|
|
101
|
+
private static makeBALLSPredicate;
|
|
100
102
|
/**
|
|
101
103
|
* Add an "if" statement to this macro.
|
|
102
104
|
* @param condition The BALLS condition for the if statement.
|
|
103
105
|
* @param ifTrue Continuation if the condition is true.
|
|
104
106
|
* @returns {Macro} This object itself.
|
|
105
107
|
*/
|
|
106
|
-
if_(condition:
|
|
108
|
+
if_(condition: PreBALLSPredicate, ifTrue: string | Macro): this;
|
|
107
109
|
/**
|
|
108
110
|
* Create a new macro with an "if" statement.
|
|
109
111
|
* @param condition The BALLS condition for the if statement.
|
|
110
112
|
* @param ifTrue Continuation if the condition is true.
|
|
111
113
|
* @returns {Macro} This object itself.
|
|
112
114
|
*/
|
|
113
|
-
static if_<T extends Macro>(this: Constructor<T>, condition:
|
|
115
|
+
static if_<T extends Macro>(this: Constructor<T>, condition: PreBALLSPredicate, ifTrue: string | Macro): T;
|
|
116
|
+
/**
|
|
117
|
+
* Add an "if" statement to this macro, inverting the condition.
|
|
118
|
+
* @param condition The BALLS condition for the if statement.
|
|
119
|
+
* @param ifTrue Continuation if the condition is true.
|
|
120
|
+
* @returns {Macro} This object itself.
|
|
121
|
+
*/
|
|
122
|
+
ifNot(condition: PreBALLSPredicate, ifTrue: string | Macro): this;
|
|
123
|
+
/**
|
|
124
|
+
* Create a new macro with an "if" statement, inverting the condition.
|
|
125
|
+
* @param condition The BALLS condition for the if statement.
|
|
126
|
+
* @param ifTrue Continuation if the condition is true.
|
|
127
|
+
* @returns {Macro} This object itself.
|
|
128
|
+
*/
|
|
129
|
+
static ifNot<T extends Macro>(this: Constructor<T>, condition: PreBALLSPredicate, ifTrue: string | Macro): T;
|
|
114
130
|
/**
|
|
115
131
|
* Add a "while" statement to this macro.
|
|
116
132
|
* @param condition The BALLS condition for the if statement.
|
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}¯otext=abort&action=save`);
|
|
17
|
-
return parseInt(xpath(newMacroText,
|
|
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
|
/**
|
|
@@ -197,13 +198,7 @@ export class Macro {
|
|
|
197
198
|
static runaway() {
|
|
198
199
|
return new this().runaway();
|
|
199
200
|
}
|
|
200
|
-
|
|
201
|
-
* Add an "if" statement to this macro.
|
|
202
|
-
* @param condition The BALLS condition for the if statement.
|
|
203
|
-
* @param ifTrue Continuation if the condition is true.
|
|
204
|
-
* @returns {Macro} This object itself.
|
|
205
|
-
*/
|
|
206
|
-
if_(condition, ifTrue) {
|
|
201
|
+
static makeBALLSPredicate(condition) {
|
|
207
202
|
let ballsCondition = "";
|
|
208
203
|
if (condition instanceof Monster) {
|
|
209
204
|
ballsCondition = `monsterid ${condition.id}`;
|
|
@@ -245,7 +240,18 @@ export class Macro {
|
|
|
245
240
|
else {
|
|
246
241
|
ballsCondition = condition;
|
|
247
242
|
}
|
|
248
|
-
return
|
|
243
|
+
return ballsCondition;
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* Add an "if" statement to this macro.
|
|
247
|
+
* @param condition The BALLS condition for the if statement.
|
|
248
|
+
* @param ifTrue Continuation if the condition is true.
|
|
249
|
+
* @returns {Macro} This object itself.
|
|
250
|
+
*/
|
|
251
|
+
if_(condition, ifTrue) {
|
|
252
|
+
return this.step(`if ${Macro.makeBALLSPredicate(condition)}`)
|
|
253
|
+
.step(ifTrue)
|
|
254
|
+
.step("endif");
|
|
249
255
|
}
|
|
250
256
|
/**
|
|
251
257
|
* Create a new macro with an "if" statement.
|
|
@@ -256,6 +262,26 @@ export class Macro {
|
|
|
256
262
|
static if_(condition, ifTrue) {
|
|
257
263
|
return new this().if_(condition, ifTrue);
|
|
258
264
|
}
|
|
265
|
+
/**
|
|
266
|
+
* Add an "if" statement to this macro, inverting the condition.
|
|
267
|
+
* @param condition The BALLS condition for the if statement.
|
|
268
|
+
* @param ifTrue Continuation if the condition is true.
|
|
269
|
+
* @returns {Macro} This object itself.
|
|
270
|
+
*/
|
|
271
|
+
ifNot(condition, ifTrue) {
|
|
272
|
+
return this.step(`if !(${Macro.makeBALLSPredicate(condition)})`)
|
|
273
|
+
.step(ifTrue)
|
|
274
|
+
.step("endif");
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* Create a new macro with an "if" statement, inverting the condition.
|
|
278
|
+
* @param condition The BALLS condition for the if statement.
|
|
279
|
+
* @param ifTrue Continuation if the condition is true.
|
|
280
|
+
* @returns {Macro} This object itself.
|
|
281
|
+
*/
|
|
282
|
+
static ifNot(condition, ifTrue) {
|
|
283
|
+
return new this().ifNot(condition, ifTrue);
|
|
284
|
+
}
|
|
259
285
|
/**
|
|
260
286
|
* Add a "while" statement to this macro.
|
|
261
287
|
* @param condition The BALLS condition for the if statement.
|
package/dist/maximize.d.ts
CHANGED
|
@@ -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
|
@@ -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
|
*
|
|
@@ -62,7 +64,7 @@ const modeableCommands = [
|
|
|
62
64
|
"retrocape",
|
|
63
65
|
"parka",
|
|
64
66
|
];
|
|
65
|
-
const modeableItems = {
|
|
67
|
+
export const modeableItems = {
|
|
66
68
|
backupcamera: $item `backup camera`,
|
|
67
69
|
umbrella: $item `unbreakable umbrella`,
|
|
68
70
|
snowsuit: $item `Snow Suit`,
|
|
@@ -70,7 +72,7 @@ const modeableItems = {
|
|
|
70
72
|
retrocape: $item `unwrapped knock-off retro superhero cape`,
|
|
71
73
|
parka: $item `Jurassic Parka`,
|
|
72
74
|
};
|
|
73
|
-
const modeableState = {
|
|
75
|
+
export const modeableState = {
|
|
74
76
|
backupcamera: () => getProperty("backupCameraMode"),
|
|
75
77
|
umbrella: () => getProperty("umbrellaState"),
|
|
76
78
|
snowsuit: () => getProperty("snowsuit"),
|
|
@@ -80,7 +82,7 @@ const modeableState = {
|
|
|
80
82
|
getProperty("retroCapeWashingInstructions"),
|
|
81
83
|
parka: () => getProperty("parkaMode"),
|
|
82
84
|
};
|
|
83
|
-
function getCurrentModes() {
|
|
85
|
+
export function getCurrentModes() {
|
|
84
86
|
const modes = {};
|
|
85
87
|
for (const key of modeableCommands) {
|
|
86
88
|
if (haveEquipped(modeableItems[key])) {
|
|
@@ -89,7 +91,7 @@ function getCurrentModes() {
|
|
|
89
91
|
}
|
|
90
92
|
return modes;
|
|
91
93
|
}
|
|
92
|
-
function applyModes(modes) {
|
|
94
|
+
export function applyModes(modes) {
|
|
93
95
|
for (const command of modeableCommands) {
|
|
94
96
|
if (haveEquipped(modeableItems[command])) {
|
|
95
97
|
if (modeableState[command]() !== modes[command]) {
|
|
@@ -247,7 +249,7 @@ function applyCached(entry, options) {
|
|
|
247
249
|
entry.rider.get($item `Buddy Bjorn`)) {
|
|
248
250
|
bjornifyFamiliar(entry.rider.get($item `Buddy Bjorn`) || $familiar.none);
|
|
249
251
|
}
|
|
250
|
-
applyModes(entry.modes);
|
|
252
|
+
applyModes({ ...entry.modes, ...options.modes });
|
|
251
253
|
}
|
|
252
254
|
const slotStructure = [
|
|
253
255
|
$slots `hat`,
|
|
@@ -335,7 +337,7 @@ function saveCached(cacheKey, options) {
|
|
|
335
337
|
rider.delete($item `Crown of Thrones`);
|
|
336
338
|
}
|
|
337
339
|
}
|
|
338
|
-
const entry = new CacheEntry(equipment, rider, myFamiliar(), canEquipItemCount(), getCurrentModes());
|
|
340
|
+
const entry = new CacheEntry(equipment, rider, myFamiliar(), canEquipItemCount(), { ...getCurrentModes(), ...options.modes });
|
|
339
341
|
cachedObjectives[cacheKey] = entry;
|
|
340
342
|
if (options.useOutfitCaching) {
|
|
341
343
|
const outfitName = outfitCache.insert(entry);
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import "core-js/modules/es.object.values";
|
|
2
|
-
import { autosellPrice, canInteract, cliExecute, getFuel, getWorkshed, haveEffect, historicalAge, historicalPrice, isNpcItem, Item, itemAmount, mallPrice, mallPrices,
|
|
2
|
+
import { autosellPrice, buy, canInteract, cliExecute, getFuel, getWorkshed, haveEffect, historicalAge, historicalPrice, isNpcItem, Item, itemAmount, mallPrice, mallPrices, toInt, visitUrl, } from "kolmafia";
|
|
3
3
|
import { getAverageAdventures, have as haveItem } from "../../lib";
|
|
4
|
-
import { PropertiesManager } from "../../property";
|
|
5
4
|
import { $effect, $item, $items } from "../../template-string";
|
|
6
5
|
import { clamp } from "../../utils";
|
|
7
6
|
var PriceAge;
|
|
@@ -57,9 +56,9 @@ function inventoryItems() {
|
|
|
57
56
|
[100, autosellPrice(item)].includes(price(item, PriceAge.RECENT)));
|
|
58
57
|
}
|
|
59
58
|
// Efficiency in meat per fuel.
|
|
60
|
-
function calculateFuelUnitCost(it,
|
|
59
|
+
function calculateFuelUnitCost(it, priceAge = PriceAge.RECENT) {
|
|
61
60
|
const units = getAverageAdventures(it);
|
|
62
|
-
return price(it, priceAge) /
|
|
61
|
+
return price(it, priceAge) / units;
|
|
63
62
|
}
|
|
64
63
|
function isFuelItem(it) {
|
|
65
64
|
return (!isNpcItem(it) &&
|
|
@@ -69,7 +68,7 @@ function isFuelItem(it) {
|
|
|
69
68
|
it.discardable &&
|
|
70
69
|
!fuelSkiplist.includes(it));
|
|
71
70
|
}
|
|
72
|
-
function getBestFuels(
|
|
71
|
+
function getBestFuels() {
|
|
73
72
|
// Three stages.
|
|
74
73
|
// 1. Filter to reasonable items using historical cost (within 5x of historical best).
|
|
75
74
|
const allFuel = Item.all().filter(isFuelItem);
|
|
@@ -77,7 +76,7 @@ function getBestFuels(targetUnits) {
|
|
|
77
76
|
mallPrices("food");
|
|
78
77
|
mallPrices("booze");
|
|
79
78
|
}
|
|
80
|
-
const keyHistorical = (item) => calculateFuelUnitCost(item,
|
|
79
|
+
const keyHistorical = (item) => calculateFuelUnitCost(item, PriceAge.HISTORICAL);
|
|
81
80
|
allFuel.sort((x, y) => keyHistorical(x) - keyHistorical(y));
|
|
82
81
|
const bestUnitCost = keyHistorical(allFuel[0]);
|
|
83
82
|
const firstBadIndex = allFuel.findIndex((item) => keyHistorical(item) > 5 * bestUnitCost);
|
|
@@ -88,14 +87,14 @@ function getBestFuels(targetUnits) {
|
|
|
88
87
|
mallPrices("booze");
|
|
89
88
|
}
|
|
90
89
|
const key1 = (item) => -getAverageAdventures(item);
|
|
91
|
-
const key2 = (item) => calculateFuelUnitCost(item,
|
|
90
|
+
const key2 = (item) => calculateFuelUnitCost(item, PriceAge.RECENT);
|
|
92
91
|
potentialFuel.sort((x, y) => key1(x) - key1(y));
|
|
93
92
|
potentialFuel.sort((x, y) => key2(x) - key2(y));
|
|
94
93
|
// 3. Find result using precise price for those top candidates.
|
|
95
94
|
const candidates = potentialFuel.slice(0, 10);
|
|
96
|
-
const key3 = (item) => calculateFuelUnitCost(item,
|
|
95
|
+
const key3 = (item) => calculateFuelUnitCost(item, PriceAge.TODAY);
|
|
97
96
|
candidates.sort((x, y) => key3(x) - key3(y));
|
|
98
|
-
if (calculateFuelUnitCost(candidates[0],
|
|
97
|
+
if (calculateFuelUnitCost(candidates[0], PriceAge.TODAY) > 100) {
|
|
99
98
|
throw new Error("Could not identify any fuel with efficiency better than 100 meat per fuel. " +
|
|
100
99
|
"This means something went wrong.");
|
|
101
100
|
}
|
|
@@ -119,26 +118,22 @@ export function insertFuel(it, quantity = 1) {
|
|
|
119
118
|
export function fillTo(targetUnits) {
|
|
120
119
|
if (!installed())
|
|
121
120
|
return false;
|
|
122
|
-
const manager = new PropertiesManager();
|
|
123
121
|
while (getFuel() < targetUnits) {
|
|
124
|
-
const remaining = targetUnits - getFuel();
|
|
125
122
|
// if in Hardcore/ronin, skip the price calculation and just use soda bread
|
|
126
123
|
const [bestFuel, secondBest] = canInteract()
|
|
127
|
-
? getBestFuels(
|
|
124
|
+
? getBestFuels()
|
|
128
125
|
: [$item `loaf of soda bread`, undefined];
|
|
129
126
|
const count = Math.ceil(targetUnits / getAverageAdventures(bestFuel));
|
|
127
|
+
let ceiling = undefined;
|
|
130
128
|
if (secondBest) {
|
|
131
129
|
const efficiencyOfSecondBest = mallPrice(secondBest) / getAverageAdventures(secondBest);
|
|
132
|
-
|
|
133
|
-
manager.setMaximumValue("autoBuyPriceLimit", ceiling);
|
|
130
|
+
ceiling = Math.ceil(efficiencyOfSecondBest * getAverageAdventures(bestFuel));
|
|
134
131
|
}
|
|
135
|
-
|
|
132
|
+
ceiling ? buy(count, bestFuel, ceiling) : buy(count, bestFuel);
|
|
136
133
|
if (!insertFuel(bestFuel, Math.min(itemAmount(bestFuel), count))) {
|
|
137
|
-
manager.resetAll();
|
|
138
134
|
throw new Error("Failed to fuel Asdon Martin.");
|
|
139
135
|
}
|
|
140
136
|
}
|
|
141
|
-
manager.resetAll();
|
|
142
137
|
return getFuel() >= targetUnits;
|
|
143
138
|
}
|
|
144
139
|
function fillWithBestInventoryItem(targetUnits) {
|
|
@@ -47,7 +47,7 @@ export function sendTo(target, upgrade = true) {
|
|
|
47
47
|
return null;
|
|
48
48
|
runChoice(2, `heythereprogrammer=${location.id}`);
|
|
49
49
|
if (handlingChoice())
|
|
50
|
-
|
|
50
|
+
visitUrl("main.php");
|
|
51
51
|
return location;
|
|
52
52
|
}
|
|
53
53
|
/**
|
|
@@ -59,7 +59,7 @@ export function upgrade() {
|
|
|
59
59
|
const canUpgrade = availableChoiceOptions()[1] !== undefined;
|
|
60
60
|
if (canUpgrade)
|
|
61
61
|
runChoice(1);
|
|
62
|
-
|
|
62
|
+
visitUrl("main.php");
|
|
63
63
|
return canUpgrade;
|
|
64
64
|
}
|
|
65
65
|
/**
|
|
@@ -69,7 +69,7 @@ export function availableLocations() {
|
|
|
69
69
|
if (!available())
|
|
70
70
|
return [];
|
|
71
71
|
const pageHtml = use();
|
|
72
|
-
|
|
72
|
+
visitUrl("main.php");
|
|
73
73
|
return checkLocations(pageHtml);
|
|
74
74
|
}
|
|
75
75
|
/**
|