libram 0.8.26 → 0.8.28
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/package.json +9 -8
- package/dist/Clan.d.ts +0 -128
- package/dist/Clan.js +0 -300
- package/dist/Copier.d.ts +0 -9
- package/dist/Copier.js +0 -15
- package/dist/Dungeon.d.ts +0 -45
- package/dist/Dungeon.js +0 -115
- package/dist/Kmail.d.ts +0 -104
- package/dist/Kmail.js +0 -182
- package/dist/actions/ActionSource.d.ts +0 -131
- package/dist/actions/ActionSource.js +0 -177
- package/dist/actions/Banish.d.ts +0 -16
- package/dist/actions/Banish.js +0 -121
- package/dist/actions/FreeKill.d.ts +0 -16
- package/dist/actions/FreeKill.js +0 -94
- package/dist/actions/FreeRun.d.ts +0 -16
- package/dist/actions/FreeRun.js +0 -77
- package/dist/actions/index.d.ts +0 -4
- package/dist/actions/index.js +0 -4
- package/dist/ascend.d.ts +0 -83
- package/dist/ascend.js +0 -268
- package/dist/challengePaths/2014/HeavyRains.d.ts +0 -22
- package/dist/challengePaths/2014/HeavyRains.js +0 -75
- package/dist/challengePaths/2015/CommunityService.d.ts +0 -125
- package/dist/challengePaths/2015/CommunityService.js +0 -334
- package/dist/challengePaths/2016/NuclearAutumn.d.ts +0 -13
- package/dist/challengePaths/2016/NuclearAutumn.js +0 -21
- package/dist/challengePaths/index.d.ts +0 -4
- package/dist/challengePaths/index.js +0 -4
- package/dist/combat.d.ts +0 -414
- package/dist/combat.js +0 -711
- package/dist/console.d.ts +0 -12
- package/dist/console.js +0 -14
- package/dist/counter.d.ts +0 -22
- package/dist/counter.js +0 -37
- package/dist/diet/index.d.ts +0 -80
- package/dist/diet/index.js +0 -662
- package/dist/diet/knapsack.d.ts +0 -8
- package/dist/diet/knapsack.js +0 -128
- package/dist/index.d.ts +0 -29
- package/dist/index.js +0 -26
- package/dist/lib.d.ts +0 -497
- package/dist/lib.js +0 -958
- package/dist/logger.d.ts +0 -35
- package/dist/logger.js +0 -62
- package/dist/maximize.d.ts +0 -121
- package/dist/maximize.js +0 -525
- package/dist/modifier.d.ts +0 -41
- package/dist/modifier.js +0 -160
- package/dist/modifierTypes.d.ts +0 -16
- package/dist/modifierTypes.js +0 -9
- package/dist/mood.d.ts +0 -105
- package/dist/mood.js +0 -349
- package/dist/moonSign.d.ts +0 -13
- package/dist/moonSign.js +0 -25
- package/dist/overlappingNames.d.ts +0 -3
- package/dist/overlappingNames.js +0 -42
- package/dist/property.d.ts +0 -222
- package/dist/property.js +0 -385
- package/dist/propertyTypes.d.ts +0 -19
- package/dist/propertyTypes.js +0 -10
- package/dist/propertyTyping.d.ts +0 -65
- package/dist/propertyTyping.js +0 -91
- package/dist/resources/2007/CandyHearts.d.ts +0 -9
- package/dist/resources/2007/CandyHearts.js +0 -24
- package/dist/resources/2008/DivineFavors.d.ts +0 -9
- package/dist/resources/2008/DivineFavors.js +0 -27
- package/dist/resources/2008/Stickers.d.ts +0 -49
- package/dist/resources/2008/Stickers.js +0 -84
- package/dist/resources/2009/Bandersnatch.d.ts +0 -56
- package/dist/resources/2009/Bandersnatch.js +0 -93
- package/dist/resources/2009/LoveSongs.d.ts +0 -9
- package/dist/resources/2009/LoveSongs.js +0 -24
- package/dist/resources/2009/SpookyPutty.d.ts +0 -31
- package/dist/resources/2009/SpookyPutty.js +0 -49
- package/dist/resources/2010/Brickos.d.ts +0 -9
- package/dist/resources/2010/Brickos.js +0 -21
- package/dist/resources/2010/CrownOfThrones.d.ts +0 -68
- package/dist/resources/2010/CrownOfThrones.js +0 -418
- package/dist/resources/2010/LookingGlass.d.ts +0 -29
- package/dist/resources/2010/LookingGlass.js +0 -89
- package/dist/resources/2011/Gygaxian.d.ts +0 -9
- package/dist/resources/2011/Gygaxian.js +0 -24
- package/dist/resources/2011/ObtuseAngel.d.ts +0 -33
- package/dist/resources/2011/ObtuseAngel.js +0 -51
- package/dist/resources/2011/StompingBoots.d.ts +0 -37
- package/dist/resources/2011/StompingBoots.js +0 -57
- package/dist/resources/2012/RainDoh.d.ts +0 -25
- package/dist/resources/2012/RainDoh.js +0 -37
- package/dist/resources/2012/ReagnimatedGnome.d.ts +0 -31
- package/dist/resources/2012/ReagnimatedGnome.js +0 -46
- package/dist/resources/2012/Resolutions.d.ts +0 -9
- package/dist/resources/2012/Resolutions.js +0 -28
- package/dist/resources/2013/Florist.d.ts +0 -81
- package/dist/resources/2013/Florist.js +0 -245
- package/dist/resources/2013/JungMan.d.ts +0 -33
- package/dist/resources/2013/JungMan.js +0 -69
- package/dist/resources/2013/PulledTaffy.d.ts +0 -9
- package/dist/resources/2013/PulledTaffy.js +0 -33
- package/dist/resources/2014/CrimboShrub.d.ts +0 -42
- package/dist/resources/2014/CrimboShrub.js +0 -89
- package/dist/resources/2014/DNALab.d.ts +0 -56
- package/dist/resources/2014/DNALab.js +0 -162
- package/dist/resources/2014/WinterGarden.d.ts +0 -23
- package/dist/resources/2014/WinterGarden.js +0 -35
- package/dist/resources/2015/BarrelShrine.d.ts +0 -8
- package/dist/resources/2015/BarrelShrine.js +0 -25
- package/dist/resources/2015/ChateauMantegna.d.ts +0 -52
- package/dist/resources/2015/ChateauMantegna.js +0 -99
- package/dist/resources/2015/DeckOfEveryCard.d.ts +0 -29
- package/dist/resources/2015/DeckOfEveryCard.js +0 -122
- package/dist/resources/2015/Dinseylandfill.d.ts +0 -89
- package/dist/resources/2015/Dinseylandfill.js +0 -205
- package/dist/resources/2015/MayoClinic.d.ts +0 -23
- package/dist/resources/2015/MayoClinic.js +0 -49
- package/dist/resources/2016/GingerBread.d.ts +0 -32
- package/dist/resources/2016/GingerBread.js +0 -73
- package/dist/resources/2016/SourceTerminal.d.ts +0 -181
- package/dist/resources/2016/SourceTerminal.js +0 -275
- package/dist/resources/2016/Witchess.d.ts +0 -17
- package/dist/resources/2016/Witchess.js +0 -47
- package/dist/resources/2017/AsdonMartin.d.ts +0 -59
- package/dist/resources/2017/AsdonMartin.js +0 -238
- package/dist/resources/2017/Horsery.d.ts +0 -19
- package/dist/resources/2017/Horsery.js +0 -42
- package/dist/resources/2017/MummingTrunk.d.ts +0 -8
- package/dist/resources/2017/MummingTrunk.js +0 -33
- package/dist/resources/2017/Pantogram.d.ts +0 -92
- package/dist/resources/2017/Pantogram.js +0 -174
- package/dist/resources/2017/Robortender.d.ts +0 -30
- package/dist/resources/2017/Robortender.js +0 -90
- package/dist/resources/2017/Spacegate.d.ts +0 -86
- package/dist/resources/2017/Spacegate.js +0 -178
- package/dist/resources/2017/TunnelOfLove.d.ts +0 -39
- package/dist/resources/2017/TunnelOfLove.js +0 -120
- package/dist/resources/2018/LatteLoversMembersMug.d.ts +0 -392
- package/dist/resources/2018/LatteLoversMembersMug.js +0 -303
- package/dist/resources/2018/SongBoom.d.ts +0 -33
- package/dist/resources/2018/SongBoom.js +0 -55
- package/dist/resources/2019/BeachComb.d.ts +0 -72
- package/dist/resources/2019/BeachComb.js +0 -118
- package/dist/resources/2019/CampAway.d.ts +0 -39
- package/dist/resources/2019/CampAway.js +0 -72
- package/dist/resources/2019/Snapper.d.ts +0 -33
- package/dist/resources/2019/Snapper.js +0 -73
- package/dist/resources/2020/Cartography.d.ts +0 -16
- package/dist/resources/2020/Cartography.js +0 -48
- package/dist/resources/2020/Guzzlr.d.ts +0 -160
- package/dist/resources/2020/Guzzlr.js +0 -275
- package/dist/resources/2020/RetroCape.d.ts +0 -51
- package/dist/resources/2020/RetroCape.js +0 -115
- package/dist/resources/2021/CrystalBall.d.ts +0 -14
- package/dist/resources/2021/CrystalBall.js +0 -39
- package/dist/resources/2021/DaylightShavings.d.ts +0 -40
- package/dist/resources/2021/DaylightShavings.js +0 -74
- package/dist/resources/2022/AutumnAton.d.ts +0 -78
- package/dist/resources/2022/AutumnAton.js +0 -182
- package/dist/resources/2022/CombatLoversLocket.d.ts +0 -44
- package/dist/resources/2022/CombatLoversLocket.js +0 -82
- package/dist/resources/2022/GreyGoose.d.ts +0 -59
- package/dist/resources/2022/GreyGoose.js +0 -90
- package/dist/resources/2022/JuneCleaver.d.ts +0 -47
- package/dist/resources/2022/JuneCleaver.js +0 -69
- package/dist/resources/2022/TrainSet.d.ts +0 -146
- package/dist/resources/2022/TrainSet.js +0 -228
- package/dist/resources/2023/AugustScepter.d.ts +0 -25
- package/dist/resources/2023/AugustScepter.js +0 -40
- package/dist/resources/2023/BurningLeaves.d.ts +0 -25
- package/dist/resources/2023/BurningLeaves.js +0 -74
- package/dist/resources/2023/CinchoDeMayo.d.ts +0 -25
- package/dist/resources/2023/CinchoDeMayo.js +0 -45
- package/dist/resources/2023/ClosedCircuitPayphone.d.ts +0 -80
- package/dist/resources/2023/ClosedCircuitPayphone.js +0 -129
- package/dist/resources/2023/CursedMonkeyPaw.d.ts +0 -46
- package/dist/resources/2023/CursedMonkeyPaw.js +0 -113
- package/dist/resources/2024/AprilingBandHelmet.d.ts +0 -50
- package/dist/resources/2024/AprilingBandHelmet.js +0 -103
- package/dist/resources/2024/ChestMimic.d.ts +0 -35
- package/dist/resources/2024/ChestMimic.js +0 -108
- package/dist/resources/LibramSummon.d.ts +0 -18
- package/dist/resources/LibramSummon.js +0 -74
- package/dist/resources/index.d.ts +0 -54
- package/dist/resources/index.js +0 -54
- package/dist/resources/putty-likes.d.ts +0 -21
- package/dist/resources/putty-likes.js +0 -33
- package/dist/session.d.ts +0 -169
- package/dist/session.js +0 -284
- package/dist/since.d.ts +0 -51
- package/dist/since.js +0 -108
- package/dist/template-string.d.ts +0 -324
- package/dist/template-string.js +0 -265
- package/dist/url.d.ts +0 -35
- package/dist/url.js +0 -67
- package/dist/utils.d.ts +0 -178
- package/dist/utils.js +0 -255
package/dist/lib.js
DELETED
|
@@ -1,958 +0,0 @@
|
|
|
1
|
-
/** @module GeneralLibrary */
|
|
2
|
-
import { appearanceRates, autosellPrice, availableAmount, booleanModifier, choiceFollowsFight, cliExecute, currentRound, Effect, elementalResistance, equip, equippedItem, 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";
|
|
3
|
-
import logger from "./logger";
|
|
4
|
-
import { get } from "./property";
|
|
5
|
-
import { $class, $effect, $element, $familiar, $item, $items, $monsters, $skill, $stat, } from "./template-string";
|
|
6
|
-
import { makeByXFunction, chunk, flat, notNull } from "./utils";
|
|
7
|
-
/**
|
|
8
|
-
* Determines the current maximum Accordion Thief songs the player can have in their head
|
|
9
|
-
*
|
|
10
|
-
* @category General
|
|
11
|
-
* @returns Maximum number of songs for player
|
|
12
|
-
*/
|
|
13
|
-
export function getSongLimit() {
|
|
14
|
-
return (3 +
|
|
15
|
-
(booleanModifier("Four Songs") ? 1 : 0) +
|
|
16
|
-
numericModifier("Additional Song"));
|
|
17
|
-
}
|
|
18
|
-
/**
|
|
19
|
-
* Determine whether the Skill or Effect provided is an Accordion Thief song
|
|
20
|
-
*
|
|
21
|
-
* @category General
|
|
22
|
-
* @param skillOrEffect The Skill or Effect
|
|
23
|
-
* @returns Whether it's a song
|
|
24
|
-
*/
|
|
25
|
-
export function isSong(skillOrEffect) {
|
|
26
|
-
if (skillOrEffect instanceof Effect &&
|
|
27
|
-
skillOrEffect.attributes.includes("song")) {
|
|
28
|
-
return true;
|
|
29
|
-
}
|
|
30
|
-
else {
|
|
31
|
-
const skill = skillOrEffect instanceof Effect ? toSkill(skillOrEffect) : skillOrEffect;
|
|
32
|
-
return skill.class === $class `Accordion Thief` && skill.buff;
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
/**
|
|
36
|
-
* List all active Effects
|
|
37
|
-
*
|
|
38
|
-
* @category General
|
|
39
|
-
* @returns List of Effects
|
|
40
|
-
*/
|
|
41
|
-
export function getActiveEffects() {
|
|
42
|
-
return Object.keys(myEffects()).map((e) => Effect.get(e));
|
|
43
|
-
}
|
|
44
|
-
/**
|
|
45
|
-
* List currently active Accordion Thief songs
|
|
46
|
-
*
|
|
47
|
-
* @category General
|
|
48
|
-
* @returns List of song Effects
|
|
49
|
-
*/
|
|
50
|
-
export function getActiveSongs() {
|
|
51
|
-
return getActiveEffects().filter(isSong);
|
|
52
|
-
}
|
|
53
|
-
/**
|
|
54
|
-
* List number of active Accordion Thief songs
|
|
55
|
-
*
|
|
56
|
-
* @category General
|
|
57
|
-
* @returns Number of songs
|
|
58
|
-
*/
|
|
59
|
-
export function getSongCount() {
|
|
60
|
-
return getActiveSongs().length;
|
|
61
|
-
}
|
|
62
|
-
/**
|
|
63
|
-
* Determine whether player can remember another Accordion Thief song
|
|
64
|
-
*
|
|
65
|
-
* @category General
|
|
66
|
-
* @param quantity Number of songs to test the space for
|
|
67
|
-
* @returns Whether player can remember another song
|
|
68
|
-
*/
|
|
69
|
-
export function canRememberSong(quantity = 1) {
|
|
70
|
-
return getSongLimit() - getSongCount() >= quantity;
|
|
71
|
-
}
|
|
72
|
-
/**
|
|
73
|
-
* Determine the locations in which the given monster can be encountered naturally
|
|
74
|
-
*
|
|
75
|
-
* @category General
|
|
76
|
-
* @param monster Monster to find
|
|
77
|
-
* @returns Locations for monster
|
|
78
|
-
*/
|
|
79
|
-
export function getMonsterLocations(monster) {
|
|
80
|
-
return Location.all().filter((location) => monster.name in appearanceRates(location));
|
|
81
|
-
}
|
|
82
|
-
/**
|
|
83
|
-
* Determine the player's remaining liver space
|
|
84
|
-
*
|
|
85
|
-
* @category General
|
|
86
|
-
* @returns Remaining liver space
|
|
87
|
-
*/
|
|
88
|
-
export function getRemainingLiver() {
|
|
89
|
-
return inebrietyLimit() - myInebriety();
|
|
90
|
-
}
|
|
91
|
-
/**
|
|
92
|
-
* Determine the player's remaining stomach space
|
|
93
|
-
*
|
|
94
|
-
* @category General
|
|
95
|
-
* @returns Remaining stomach space
|
|
96
|
-
*/
|
|
97
|
-
export function getRemainingStomach() {
|
|
98
|
-
return fullnessLimit() - myFullness();
|
|
99
|
-
}
|
|
100
|
-
/**
|
|
101
|
-
* Determine the player's remaining spleen space
|
|
102
|
-
*
|
|
103
|
-
* @category General
|
|
104
|
-
* @returns Remaining spleen space
|
|
105
|
-
*/
|
|
106
|
-
export function getRemainingSpleen() {
|
|
107
|
-
return spleenLimit() - mySpleenUse();
|
|
108
|
-
}
|
|
109
|
-
/**
|
|
110
|
-
* Determine whether the player "has" any entity which one could feasibly "have".
|
|
111
|
-
*
|
|
112
|
-
* @category General
|
|
113
|
-
* @param thing Thing to check
|
|
114
|
-
* @param quantity Minimum quantity the player must have to pass
|
|
115
|
-
* @returns Whether the player meets the requirements of owning the supplied thing
|
|
116
|
-
*/
|
|
117
|
-
export function have(thing, quantity = 1) {
|
|
118
|
-
if (thing instanceof Effect) {
|
|
119
|
-
return haveEffect(thing) >= quantity;
|
|
120
|
-
}
|
|
121
|
-
if (thing instanceof Familiar) {
|
|
122
|
-
return haveFamiliar(thing);
|
|
123
|
-
}
|
|
124
|
-
if (thing instanceof Item) {
|
|
125
|
-
return availableAmount(thing) >= quantity;
|
|
126
|
-
}
|
|
127
|
-
if (thing instanceof Servant) {
|
|
128
|
-
return haveServant(thing);
|
|
129
|
-
}
|
|
130
|
-
if (thing instanceof Skill) {
|
|
131
|
-
return haveSkill(thing);
|
|
132
|
-
}
|
|
133
|
-
if (thing instanceof Thrall) {
|
|
134
|
-
const thrall = myThrall();
|
|
135
|
-
return thrall.id === thing.id && thrall.level >= quantity;
|
|
136
|
-
}
|
|
137
|
-
return false;
|
|
138
|
-
}
|
|
139
|
-
/**
|
|
140
|
-
* Determine whether a given item is in the player's campground
|
|
141
|
-
*
|
|
142
|
-
* @category General
|
|
143
|
-
* @param item The Item KoLmafia uses to represent the campground item
|
|
144
|
-
* @returns Whether the item is in the campground
|
|
145
|
-
*/
|
|
146
|
-
export function haveInCampground(item) {
|
|
147
|
-
return Object.keys(getCampground())
|
|
148
|
-
.map((i) => Item.get(i))
|
|
149
|
-
.includes(item);
|
|
150
|
-
}
|
|
151
|
-
export var Wanderer;
|
|
152
|
-
(function (Wanderer) {
|
|
153
|
-
Wanderer["Digitize"] = "Digitize Monster";
|
|
154
|
-
Wanderer["Enamorang"] = "Enamorang Monster";
|
|
155
|
-
Wanderer["Familiar"] = "Familiar";
|
|
156
|
-
Wanderer["Holiday"] = "Holiday Monster";
|
|
157
|
-
Wanderer["Kramco"] = "Kramco";
|
|
158
|
-
Wanderer["Nemesis"] = "Nemesis Assassin";
|
|
159
|
-
Wanderer["Portscan"] = "portscan.edu";
|
|
160
|
-
Wanderer["Romantic"] = "Romantic Monster";
|
|
161
|
-
Wanderer["Vote"] = "Vote Monster";
|
|
162
|
-
})(Wanderer || (Wanderer = {}));
|
|
163
|
-
const deterministicWanderers = [Wanderer.Digitize, Wanderer.Portscan];
|
|
164
|
-
/**
|
|
165
|
-
* Determine whether the player has the specified counter
|
|
166
|
-
*
|
|
167
|
-
* @param counterName Name of the counter
|
|
168
|
-
* @param minTurns Minimum turns the counter is set to
|
|
169
|
-
* @param maxTurns Maximum turns the counter is set to
|
|
170
|
-
* @category General
|
|
171
|
-
* @returns Whether player has the counter
|
|
172
|
-
*/
|
|
173
|
-
export function haveCounter(counterName, minTurns = 0, maxTurns = 500) {
|
|
174
|
-
return getCounters(counterName, minTurns, maxTurns) === counterName;
|
|
175
|
-
}
|
|
176
|
-
/**
|
|
177
|
-
* Determine whether the player has the specified wanderer's counter
|
|
178
|
-
*
|
|
179
|
-
* @param wanderer Wanderer to check
|
|
180
|
-
* @category Wanderers
|
|
181
|
-
* @returns Whether player has the wanderer counter
|
|
182
|
-
*/
|
|
183
|
-
export function haveWandererCounter(wanderer) {
|
|
184
|
-
if (deterministicWanderers.includes(wanderer)) {
|
|
185
|
-
return haveCounter(wanderer);
|
|
186
|
-
}
|
|
187
|
-
const begin = wanderer + " window begin";
|
|
188
|
-
const end = wanderer + " window end";
|
|
189
|
-
return haveCounter(begin) || haveCounter(end);
|
|
190
|
-
}
|
|
191
|
-
/**
|
|
192
|
-
* Determine whether the player will encounter a vote wanderer on the next turn,
|
|
193
|
-
* providing an "I Voted!" sticker is equipped.
|
|
194
|
-
*
|
|
195
|
-
* @category Wanderers
|
|
196
|
-
* @returns Whether the vote wanderer is due
|
|
197
|
-
*/
|
|
198
|
-
export function isVoteWandererNow() {
|
|
199
|
-
return (totalTurnsPlayed() % 11 === 1 &&
|
|
200
|
-
get("lastVoteMonsterTurn") < totalTurnsPlayed());
|
|
201
|
-
}
|
|
202
|
-
/**
|
|
203
|
-
* Tells us whether we can expect a given wanderer now. Behaves differently
|
|
204
|
-
* for different types of wanderer.
|
|
205
|
-
*
|
|
206
|
-
* - For deterministic wanderers, return whether the player will encounter
|
|
207
|
-
* the queried wanderer on the next turn
|
|
208
|
-
*
|
|
209
|
-
* - For variable wanderers (window), return whether the player is within
|
|
210
|
-
* an encounter window for the queried wanderer
|
|
211
|
-
*
|
|
212
|
-
* - For variable wanderers (chance per turn), returns true unless the player
|
|
213
|
-
* has exhausted the number of wanderers possible
|
|
214
|
-
*
|
|
215
|
-
* @category Wanderers
|
|
216
|
-
* @param wanderer Wanderer to check
|
|
217
|
-
* @returns Whether the wanderer is due
|
|
218
|
-
*/
|
|
219
|
-
export function isWandererNow(wanderer) {
|
|
220
|
-
if (deterministicWanderers.includes(wanderer)) {
|
|
221
|
-
return haveCounter(wanderer, 0, 0);
|
|
222
|
-
}
|
|
223
|
-
if (wanderer === Wanderer.Kramco) {
|
|
224
|
-
return true;
|
|
225
|
-
}
|
|
226
|
-
if (wanderer === Wanderer.Vote) {
|
|
227
|
-
return isVoteWandererNow();
|
|
228
|
-
}
|
|
229
|
-
if (wanderer === Wanderer.Familiar) {
|
|
230
|
-
return get("_hipsterAdv") < 7;
|
|
231
|
-
}
|
|
232
|
-
const begin = wanderer + " window begin";
|
|
233
|
-
const end = wanderer + " window end";
|
|
234
|
-
return !haveCounter(begin, 1) && haveCounter(end);
|
|
235
|
-
}
|
|
236
|
-
/**
|
|
237
|
-
* Determines the chance the player will encounter a sausage goblin on the
|
|
238
|
-
* next turn, providing the Kramco Sausage-o-Matic is equipped.
|
|
239
|
-
*
|
|
240
|
-
* @category Wanderers
|
|
241
|
-
* @returns Chance that the sausage goblin is due (as a number between 0 and 1)
|
|
242
|
-
*/
|
|
243
|
-
export function getKramcoWandererChance() {
|
|
244
|
-
const fights = get("_sausageFights");
|
|
245
|
-
const lastFight = get("_lastSausageMonsterTurn");
|
|
246
|
-
const totalTurns = totalTurnsPlayed();
|
|
247
|
-
if (fights < 1) {
|
|
248
|
-
return lastFight === totalTurns && myTurncount() < 1 ? 0.5 : 1.0;
|
|
249
|
-
}
|
|
250
|
-
const turnsSinceLastFight = totalTurns - lastFight;
|
|
251
|
-
return Math.min(1.0, (turnsSinceLastFight + 1) / (5 + fights * 3 + Math.max(0, fights - 5) ** 3));
|
|
252
|
-
}
|
|
253
|
-
/**
|
|
254
|
-
* Determines the chance the player will encounter an Artistic Goth Kid or
|
|
255
|
-
* Mini-Hipster wanderer on the next turn, providing a familiar is equipped.
|
|
256
|
-
*
|
|
257
|
-
* NOTE: You must complete one combat with the Artistic Goth Kid before you
|
|
258
|
-
* can encounter any wanderers. Consequently,ƒ the first combat with the
|
|
259
|
-
* Artist Goth Kid is effectively 0% chance to encounter a wanderer.
|
|
260
|
-
*
|
|
261
|
-
* @category Wanderers
|
|
262
|
-
* @returns Chance that the familiar wanderer is due (as a number between 0 and 1)
|
|
263
|
-
*/
|
|
264
|
-
export function getFamiliarWandererChance() {
|
|
265
|
-
const totalFights = get("_hipsterAdv");
|
|
266
|
-
const probability = [0.5, 0.4, 0.3, 0.2];
|
|
267
|
-
if (totalFights < 4) {
|
|
268
|
-
return probability[totalFights];
|
|
269
|
-
}
|
|
270
|
-
return totalFights > 7 ? 0.0 : 0.1;
|
|
271
|
-
}
|
|
272
|
-
/**
|
|
273
|
-
* Determines the chance the player will encounter the specified wanderer
|
|
274
|
-
* on the next turn.
|
|
275
|
-
*
|
|
276
|
-
* @category Wanderers
|
|
277
|
-
* @param wanderer Wanderer to check
|
|
278
|
-
* @returns Chance that the specified wanderer is due (as a number between 0 and 1)
|
|
279
|
-
*/
|
|
280
|
-
export function getWandererChance(wanderer) {
|
|
281
|
-
if (deterministicWanderers.includes(wanderer)) {
|
|
282
|
-
return haveCounter(wanderer, 0, 0) ? 1.0 : 0.0;
|
|
283
|
-
}
|
|
284
|
-
if (wanderer === Wanderer.Kramco) {
|
|
285
|
-
getKramcoWandererChance();
|
|
286
|
-
}
|
|
287
|
-
if (wanderer === Wanderer.Vote) {
|
|
288
|
-
return isVoteWandererNow() ? 1.0 : 0.0;
|
|
289
|
-
}
|
|
290
|
-
if (wanderer === Wanderer.Familiar) {
|
|
291
|
-
getFamiliarWandererChance();
|
|
292
|
-
}
|
|
293
|
-
const begin = wanderer + " window begin";
|
|
294
|
-
const end = wanderer + " window end";
|
|
295
|
-
if (haveCounter(begin, 1, 100)) {
|
|
296
|
-
return 0.0;
|
|
297
|
-
}
|
|
298
|
-
const counters = get("relayCounters");
|
|
299
|
-
const re = new RegExp("(\\d+):" + end);
|
|
300
|
-
const matches = counters.match(re);
|
|
301
|
-
if (matches && matches.length === 2) {
|
|
302
|
-
const window = Number.parseInt(matches[1]) - myTurncount();
|
|
303
|
-
return 1.0 / window;
|
|
304
|
-
}
|
|
305
|
-
return 0.0;
|
|
306
|
-
}
|
|
307
|
-
/**
|
|
308
|
-
* Determines whether the player's current familiar is equal to the one supplied
|
|
309
|
-
*
|
|
310
|
-
* @category General
|
|
311
|
-
* @param familiar Familiar to check
|
|
312
|
-
* @returns Whether it is the player's current familiar
|
|
313
|
-
*/
|
|
314
|
-
export function isCurrentFamiliar(familiar) {
|
|
315
|
-
return myFamiliar() === familiar;
|
|
316
|
-
}
|
|
317
|
-
/**
|
|
318
|
-
* Determines the fold group (if any) of which the given item is a part
|
|
319
|
-
*
|
|
320
|
-
* @category General
|
|
321
|
-
* @param item Item that is part of the required fold group
|
|
322
|
-
* @returns List of items in the fold group
|
|
323
|
-
*/
|
|
324
|
-
export function getFoldGroup(item) {
|
|
325
|
-
return Object.entries(getRelated(item, "fold"))
|
|
326
|
-
.sort(([, a], [, b]) => a - b)
|
|
327
|
-
.map(([i]) => Item.get(i));
|
|
328
|
-
}
|
|
329
|
-
/**
|
|
330
|
-
* Determines the zap group (if any) of which the given item is a part
|
|
331
|
-
*
|
|
332
|
-
* @category General
|
|
333
|
-
* @param item Item that is part of the required zap group
|
|
334
|
-
* @returns List of items in the zap group
|
|
335
|
-
*/
|
|
336
|
-
export function getZapGroup(item) {
|
|
337
|
-
return Object.keys(getRelated(item, "zap")).map((i) => Item.get(i));
|
|
338
|
-
}
|
|
339
|
-
/**
|
|
340
|
-
* Get a map of banished monsters keyed by what banished them
|
|
341
|
-
*
|
|
342
|
-
* @category General
|
|
343
|
-
* @returns Map of banished monsters
|
|
344
|
-
*/
|
|
345
|
-
export function getBanishedMonsters() {
|
|
346
|
-
const banishes = chunk(get("banishedMonsters").split(":"), 3);
|
|
347
|
-
const result = new Map();
|
|
348
|
-
for (const [foe, banisher] of banishes) {
|
|
349
|
-
if (foe === undefined || banisher === undefined)
|
|
350
|
-
break;
|
|
351
|
-
// toItem doesn"t error if the item doesn"t exist, so we have to use that.
|
|
352
|
-
const banisherItem = toItem(banisher);
|
|
353
|
-
if (banisher.toLowerCase() === "saber force") {
|
|
354
|
-
result.set($skill `Use the Force`, Monster.get(foe));
|
|
355
|
-
}
|
|
356
|
-
else if (banisher.toLowerCase() === "nanorhino") {
|
|
357
|
-
result.set($skill `Unleash Nanites`, Monster.get(foe));
|
|
358
|
-
}
|
|
359
|
-
else if ([
|
|
360
|
-
Item.none,
|
|
361
|
-
Item.get(`training scroll: Snokebomb`),
|
|
362
|
-
Item.get(`tomayohawk-style reflex hammer`),
|
|
363
|
-
null,
|
|
364
|
-
].includes(banisherItem)) {
|
|
365
|
-
if (Skill.get(banisher) === $skill.none) {
|
|
366
|
-
break;
|
|
367
|
-
}
|
|
368
|
-
else {
|
|
369
|
-
result.set(Skill.get(banisher), Monster.get(foe));
|
|
370
|
-
}
|
|
371
|
-
}
|
|
372
|
-
else {
|
|
373
|
-
result.set(banisherItem, Monster.get(foe));
|
|
374
|
-
}
|
|
375
|
-
}
|
|
376
|
-
return result;
|
|
377
|
-
}
|
|
378
|
-
/**
|
|
379
|
-
* Determines whether the item is usable
|
|
380
|
-
*
|
|
381
|
-
* This function will be an ongoing work in progress
|
|
382
|
-
*
|
|
383
|
-
* @param item Item to check
|
|
384
|
-
* @returns Whether item is usable
|
|
385
|
-
*/
|
|
386
|
-
export function canUse(item) {
|
|
387
|
-
const path = myPath();
|
|
388
|
-
if (path !== Path.get("Nuclear Autumn")) {
|
|
389
|
-
if ($items `Shrieking Weasel holo-record, Power-Guy 2000 holo-record, Lucky Strikes holo-record, EMD holo-record, Superdrifter holo-record, The Pigs holo-record, Drunk Uncles holo-record`.includes(item)) {
|
|
390
|
-
return false;
|
|
391
|
-
}
|
|
392
|
-
}
|
|
393
|
-
if (path === Path.get("G-Lover")) {
|
|
394
|
-
if (!item.name.toLowerCase().includes("g"))
|
|
395
|
-
return false;
|
|
396
|
-
}
|
|
397
|
-
if (path === Path.get("Bees Hate You")) {
|
|
398
|
-
if (item.name.toLowerCase().includes("b"))
|
|
399
|
-
return false;
|
|
400
|
-
}
|
|
401
|
-
return true;
|
|
402
|
-
}
|
|
403
|
-
/**
|
|
404
|
-
* Turn KoLmafia `none`s to JavaScript `null`s
|
|
405
|
-
*
|
|
406
|
-
* @param thing Thing that can have a mafia "none" value
|
|
407
|
-
* @returns The thing specified or `null`
|
|
408
|
-
*/
|
|
409
|
-
export function noneToNull(thing) {
|
|
410
|
-
if (thing instanceof Effect) {
|
|
411
|
-
return thing === Effect.none ? null : thing;
|
|
412
|
-
}
|
|
413
|
-
if (thing instanceof Familiar) {
|
|
414
|
-
return thing === Familiar.none ? null : thing;
|
|
415
|
-
}
|
|
416
|
-
if (thing instanceof Item) {
|
|
417
|
-
return thing === Item.none ? null : thing;
|
|
418
|
-
}
|
|
419
|
-
return thing;
|
|
420
|
-
}
|
|
421
|
-
/**
|
|
422
|
-
* Determine the average value from the sort of range that KoLmafia encodes as a string
|
|
423
|
-
*
|
|
424
|
-
* @param range KoLmafia-style range string
|
|
425
|
-
* @returns Average value fo range
|
|
426
|
-
*/
|
|
427
|
-
export function getAverage(range) {
|
|
428
|
-
if (range.indexOf("-") < 0)
|
|
429
|
-
return Number(range);
|
|
430
|
-
const [, lower, upper] = range.match(/(-?[0-9]+)-(-?[0-9]+)/) ?? [
|
|
431
|
-
"0",
|
|
432
|
-
"0",
|
|
433
|
-
"0",
|
|
434
|
-
];
|
|
435
|
-
return (Number(lower) + Number(upper)) / 2;
|
|
436
|
-
}
|
|
437
|
-
/**
|
|
438
|
-
* Deternube tge average adventures expected from consuming an Item
|
|
439
|
-
*
|
|
440
|
-
* If item is not a consumable, will just return "0".
|
|
441
|
-
*
|
|
442
|
-
* @param item Consumable item
|
|
443
|
-
* @returns Average aventures from consumable
|
|
444
|
-
*/
|
|
445
|
-
export function getAverageAdventures(item) {
|
|
446
|
-
return getAverage(item.adventures);
|
|
447
|
-
}
|
|
448
|
-
/**
|
|
449
|
-
* Remove an effect
|
|
450
|
-
*
|
|
451
|
-
* @category General
|
|
452
|
-
* @param effect Effect to remove
|
|
453
|
-
* @returns Success
|
|
454
|
-
*/
|
|
455
|
-
export function uneffect(effect) {
|
|
456
|
-
return cliExecute(`uneffect ${effect.name}`);
|
|
457
|
-
}
|
|
458
|
-
/**
|
|
459
|
-
* Get the player id from a player name (if it exists)
|
|
460
|
-
* @param name the name of the player
|
|
461
|
-
* @param onMissing Pass "throw" to throw an error if the player is not found, or "return-null" to return null
|
|
462
|
-
* @returns the player id if the player exists, or handles according to onMissing
|
|
463
|
-
*/
|
|
464
|
-
export function getPlayerIdFromName(name, onMissing = "throw") {
|
|
465
|
-
const playerId = getPlayerId(name);
|
|
466
|
-
// KoLmafia returns the input when not found
|
|
467
|
-
if (playerId === name) {
|
|
468
|
-
if (onMissing === "throw") {
|
|
469
|
-
throw new Error(`Player not found: ${name}`);
|
|
470
|
-
}
|
|
471
|
-
return null;
|
|
472
|
-
}
|
|
473
|
-
return parseInt(playerId);
|
|
474
|
-
}
|
|
475
|
-
/**
|
|
476
|
-
* Get the player id from a player name (if it exists)
|
|
477
|
-
* @param id the id of the player
|
|
478
|
-
* @param onMissing Pass "throw" to throw an error if the player is not found, or "return-null" to return null
|
|
479
|
-
* @returns the player id if the player exists, or handles according to onMissing
|
|
480
|
-
*/
|
|
481
|
-
export function getPlayerNameFromId(id, onMissing = "throw") {
|
|
482
|
-
const playerName = getPlayerName(id);
|
|
483
|
-
// KoLmafia returns the input when not found
|
|
484
|
-
if (playerName === id.toString()) {
|
|
485
|
-
if (onMissing === "throw") {
|
|
486
|
-
throw new Error(`Player not found: ${playerName}`);
|
|
487
|
-
}
|
|
488
|
-
return null;
|
|
489
|
-
}
|
|
490
|
-
return playerName;
|
|
491
|
-
}
|
|
492
|
-
/**
|
|
493
|
-
* Get both the name and id of a player from either their name or id
|
|
494
|
-
*
|
|
495
|
-
* @param idOrName Id or name of player
|
|
496
|
-
* @param onMissing Pass "throw" to throw an error if the player is not found, or "return-null" to return null
|
|
497
|
-
* @returns Object containing id and name of player if it exists, or handles according to onMissing
|
|
498
|
-
*/
|
|
499
|
-
export function getPlayerFromIdOrName(idOrName, onMissing = "throw") {
|
|
500
|
-
if (typeof idOrName === "number") {
|
|
501
|
-
const name = getPlayerNameFromId(idOrName, onMissing);
|
|
502
|
-
if (name === null)
|
|
503
|
-
return null;
|
|
504
|
-
return { name, id: idOrName };
|
|
505
|
-
}
|
|
506
|
-
else {
|
|
507
|
-
const id = getPlayerIdFromName(idOrName, onMissing);
|
|
508
|
-
if (id === null)
|
|
509
|
-
return null;
|
|
510
|
-
// load from KoLmafia to get the right capitalization
|
|
511
|
-
const name = getPlayerName(id);
|
|
512
|
-
return { name, id };
|
|
513
|
-
}
|
|
514
|
-
}
|
|
515
|
-
/**
|
|
516
|
-
* Determine the step as a number for a given quest property.
|
|
517
|
-
*
|
|
518
|
-
* @param questName Name of quest property to check.
|
|
519
|
-
* @returns Quest step
|
|
520
|
-
*/
|
|
521
|
-
export function questStep(questName) {
|
|
522
|
-
const stringStep = get(questName);
|
|
523
|
-
if (stringStep === "unstarted")
|
|
524
|
-
return -1;
|
|
525
|
-
else if (stringStep === "started")
|
|
526
|
-
return 0;
|
|
527
|
-
else if (stringStep === "finished" || stringStep === "")
|
|
528
|
-
return 999;
|
|
529
|
-
else {
|
|
530
|
-
if (stringStep.substring(0, 4) !== "step") {
|
|
531
|
-
throw new Error("Quest state parsing error.");
|
|
532
|
-
}
|
|
533
|
-
return parseInt(stringStep.substring(4), 10);
|
|
534
|
-
}
|
|
535
|
-
}
|
|
536
|
-
export class EnsureError extends Error {
|
|
537
|
-
constructor(cause, reason) {
|
|
538
|
-
super(`Failed to ensure ${cause.name}!${reason ? ` ${reason}` : ""}`);
|
|
539
|
-
this.name = "Ensure Error";
|
|
540
|
-
}
|
|
541
|
-
}
|
|
542
|
-
/**
|
|
543
|
-
* Tries to get an effect using the default method
|
|
544
|
-
*
|
|
545
|
-
* @param ef effect to try to get
|
|
546
|
-
* @param turns turns to aim for; default of 1
|
|
547
|
-
* @throws {EnsureError} Throws an error if the effect cannot be guaranteed
|
|
548
|
-
*/
|
|
549
|
-
export function ensureEffect(ef, turns = 1) {
|
|
550
|
-
if (haveEffect(ef) < turns) {
|
|
551
|
-
if (ef.default === null) {
|
|
552
|
-
throw new EnsureError(ef, "No default action");
|
|
553
|
-
}
|
|
554
|
-
if (!cliExecute(ef.default) || haveEffect(ef) === 0) {
|
|
555
|
-
throw new EnsureError(ef);
|
|
556
|
-
}
|
|
557
|
-
}
|
|
558
|
-
}
|
|
559
|
-
const valueMap = new Map();
|
|
560
|
-
const MALL_VALUE_MODIFIER = 0.9;
|
|
561
|
-
/**
|
|
562
|
-
* Determiens the average value (based on mallprice and autosell) of a collection of items
|
|
563
|
-
*
|
|
564
|
-
* @param items items whose value you care about
|
|
565
|
-
* @returns Average value of items
|
|
566
|
-
*/
|
|
567
|
-
export function getSaleValue(...items) {
|
|
568
|
-
return (items
|
|
569
|
-
.map((item) => {
|
|
570
|
-
if (valueMap.has(item))
|
|
571
|
-
return valueMap.get(item) || 0;
|
|
572
|
-
if (item.discardable) {
|
|
573
|
-
valueMap.set(item, mallPrice(item) > Math.max(2 * autosellPrice(item), 100)
|
|
574
|
-
? MALL_VALUE_MODIFIER * mallPrice(item)
|
|
575
|
-
: autosellPrice(item));
|
|
576
|
-
}
|
|
577
|
-
else {
|
|
578
|
-
valueMap.set(item, mallPrice(item) > 100 ? MALL_VALUE_MODIFIER * mallPrice(item) : 0);
|
|
579
|
-
}
|
|
580
|
-
return valueMap.get(item) || 0;
|
|
581
|
-
})
|
|
582
|
-
.reduce((s, price) => s + price, 0) / items.length);
|
|
583
|
-
}
|
|
584
|
-
export const Environment = {
|
|
585
|
-
Outdoor: "outdoor",
|
|
586
|
-
Indoor: "indoor",
|
|
587
|
-
Underground: "underground",
|
|
588
|
-
Underwater: "underwater",
|
|
589
|
-
};
|
|
590
|
-
/**
|
|
591
|
-
* Determines the weight-coefficient of any leprechaunning that this familiar may find itself doing
|
|
592
|
-
* Assumes the familiar is nude and thus fails for hatrack & pantsrack
|
|
593
|
-
* For the Mutant Cactus Bud, returns the efficacy-multiplier instead
|
|
594
|
-
*
|
|
595
|
-
* @param familiar The familiar whose leprechaun multiplier you're interested in
|
|
596
|
-
* @returns Weight-coefficient
|
|
597
|
-
*/
|
|
598
|
-
export function findLeprechaunMultiplier(familiar) {
|
|
599
|
-
if (familiar === $familiar `Mutant Cactus Bud`) {
|
|
600
|
-
return numericModifier(familiar, "Leprechaun Effectiveness", 1, $item.none);
|
|
601
|
-
}
|
|
602
|
-
if (familiar === $familiar `Reanimated Reanimator`)
|
|
603
|
-
return 0;
|
|
604
|
-
const meatBonus = numericModifier(familiar, "Meat Drop", 1, $item.none);
|
|
605
|
-
if (meatBonus === 0)
|
|
606
|
-
return 0;
|
|
607
|
-
return Math.pow(Math.sqrt(meatBonus / 2 + 55 / 4 + 3) - Math.sqrt(55) / 2, 2);
|
|
608
|
-
}
|
|
609
|
-
/**
|
|
610
|
-
* Determines the weight-coefficient of any baby gravy fairying that this familiar may find itself doing
|
|
611
|
-
* Assumes the familiar is nude and thus fails for hatrack & pantsrack
|
|
612
|
-
* For the Mutant Fire Ant, returns the efficacy-multiplier instead
|
|
613
|
-
*
|
|
614
|
-
* @param familiar The familiar whose fairy multiplier you're interested in
|
|
615
|
-
* @returns Weight-coefficient
|
|
616
|
-
*/
|
|
617
|
-
export function findFairyMultiplier(familiar) {
|
|
618
|
-
if (familiar === $familiar `Mutant Fire Ant`) {
|
|
619
|
-
return numericModifier(familiar, "Fairy Effectiveness", 1, $item.none);
|
|
620
|
-
}
|
|
621
|
-
if (familiar === $familiar `Reanimated Reanimator`)
|
|
622
|
-
return 0;
|
|
623
|
-
const itemBonus = numericModifier(familiar, "Item Drop", 1, $item.none);
|
|
624
|
-
if (itemBonus === 0)
|
|
625
|
-
return 0;
|
|
626
|
-
return Math.pow(Math.sqrt(itemBonus + 55 / 4 + 3) - Math.sqrt(55) / 2, 2);
|
|
627
|
-
}
|
|
628
|
-
export const holidayWanderers = new Map([
|
|
629
|
-
[
|
|
630
|
-
"El Dia De Los Muertos Borrachos",
|
|
631
|
-
$monsters `Novia Cadáver, Novio Cadáver, Padre Cadáver, Persona Inocente Cadáver`,
|
|
632
|
-
],
|
|
633
|
-
[
|
|
634
|
-
"Feast of Boris",
|
|
635
|
-
$monsters `Candied Yam Golem, Malevolent Tofurkey, Possessed Can of Cranberry Sauce, Stuffing Golem`,
|
|
636
|
-
],
|
|
637
|
-
[
|
|
638
|
-
"Talk Like a Pirate Day",
|
|
639
|
-
$monsters `ambulatory pirate, migratory pirate, peripatetic pirate`,
|
|
640
|
-
],
|
|
641
|
-
]);
|
|
642
|
-
/**
|
|
643
|
-
* Get today's holiday wanderers
|
|
644
|
-
*
|
|
645
|
-
* @returns List of holiday wanderer Monsters
|
|
646
|
-
*/
|
|
647
|
-
export function getTodaysHolidayWanderers() {
|
|
648
|
-
return flat(holiday()
|
|
649
|
-
.split("/")
|
|
650
|
-
.map((holiday) => holidayWanderers.get(holiday) ?? []));
|
|
651
|
-
}
|
|
652
|
-
/**
|
|
653
|
-
* Determines whether or not we can safely call visitUrl(), based on whether we're in a fight, multi-fight, choice, etc
|
|
654
|
-
*
|
|
655
|
-
* @returns Whether urls can be safely visited
|
|
656
|
-
*/
|
|
657
|
-
export function canVisitUrl() {
|
|
658
|
-
if (currentRound()) {
|
|
659
|
-
logger.debug(`Current round is ${currentRound()}; you're in combat.`);
|
|
660
|
-
return false;
|
|
661
|
-
}
|
|
662
|
-
if (inMultiFight()) {
|
|
663
|
-
logger.debug("You're in a multifight.");
|
|
664
|
-
return false;
|
|
665
|
-
}
|
|
666
|
-
if (choiceFollowsFight()) {
|
|
667
|
-
logger.debug("A choice follows this fight.");
|
|
668
|
-
return false;
|
|
669
|
-
}
|
|
670
|
-
if (handlingChoice()) {
|
|
671
|
-
logger.debug("You're currently in a choice adventure");
|
|
672
|
-
return false;
|
|
673
|
-
}
|
|
674
|
-
return true;
|
|
675
|
-
}
|
|
676
|
-
/**
|
|
677
|
-
* Calculate damage taken from a specific element after factoring in resistance
|
|
678
|
-
*
|
|
679
|
-
* @param baseDamage Base damage
|
|
680
|
-
* @param element Element
|
|
681
|
-
* @returns damage after factoring in resistances
|
|
682
|
-
*/
|
|
683
|
-
export function damageTakenByElement(baseDamage, element) {
|
|
684
|
-
if (baseDamage < 0)
|
|
685
|
-
return 1;
|
|
686
|
-
const res = elementalResistance(element);
|
|
687
|
-
return Math.max(1, Math.ceil(baseDamage - (baseDamage * res) / 100));
|
|
688
|
-
}
|
|
689
|
-
const telescopeStats = new Map([
|
|
690
|
-
[
|
|
691
|
-
"standing around flexing their muscles and using grip exercisers",
|
|
692
|
-
$stat `Muscle`,
|
|
693
|
-
],
|
|
694
|
-
[
|
|
695
|
-
"sitting around playing chess and solving complicated-looking logic puzzles",
|
|
696
|
-
$stat `Mysticality`,
|
|
697
|
-
],
|
|
698
|
-
["all wearing sunglasses and dancing", $stat `Moxie`],
|
|
699
|
-
]);
|
|
700
|
-
const telescopeElements = new Map([
|
|
701
|
-
["people, all of whom appear to be on fire", $element `hot`],
|
|
702
|
-
["people, surrounded by a cloud of eldritch mist", $element `spooky`],
|
|
703
|
-
["greasy-looking people furtively skulking around", $element `sleaze`],
|
|
704
|
-
["people, surrounded by garbage and clouds of flies", $element `stench`],
|
|
705
|
-
["people, clustered around a group of igloos", $element `cold`],
|
|
706
|
-
]);
|
|
707
|
-
const hedgeTrap1 = new Map([
|
|
708
|
-
["smoldering bushes on the outskirts of a hedge maze", $element `hot`],
|
|
709
|
-
[
|
|
710
|
-
"creepy-looking black bushes on the outskirts of a hedge maze",
|
|
711
|
-
$element `spooky`,
|
|
712
|
-
],
|
|
713
|
-
["purplish, greasy-looking hedges", $element `sleaze`],
|
|
714
|
-
[
|
|
715
|
-
"nasty-looking, dripping green bushes on the outskirts of a hedge maze",
|
|
716
|
-
$element `stench`,
|
|
717
|
-
],
|
|
718
|
-
["frost-rimed bushes on the outskirts of a hedge maze", $element `cold`],
|
|
719
|
-
]);
|
|
720
|
-
const hedgeTrap2 = new Map([
|
|
721
|
-
["smoke rising from deeper within the maze", $element `hot`],
|
|
722
|
-
[
|
|
723
|
-
"a miasma of eldritch vapors rising from deeper within the maze",
|
|
724
|
-
$element `spooky`,
|
|
725
|
-
],
|
|
726
|
-
[
|
|
727
|
-
"a greasy purple cloud hanging over the center of the maze",
|
|
728
|
-
$element `sleaze`,
|
|
729
|
-
],
|
|
730
|
-
["a cloud of green gas hovering over the maze", $element `stench`],
|
|
731
|
-
["wintry mists rising from deeper within the maze", $element `cold`],
|
|
732
|
-
]);
|
|
733
|
-
const hedgeTrap3 = new Map([
|
|
734
|
-
["with lava slowly oozing out of it", $element `hot`],
|
|
735
|
-
["surrounded by creepy black mist", $element `spooky`],
|
|
736
|
-
["that occasionally vomits out a greasy ball of hair", $element `sleaze`],
|
|
737
|
-
["disgorging a really surprising amount of sewage", $element `stench`],
|
|
738
|
-
["occasionally disgorging a bunch of ice cubes", $element `cold`],
|
|
739
|
-
]);
|
|
740
|
-
/**
|
|
741
|
-
* Get information from telescope
|
|
742
|
-
*
|
|
743
|
-
* @returns An object with all information the telescope gives you about the sorceress's contests and maze
|
|
744
|
-
*/
|
|
745
|
-
export function telescope() {
|
|
746
|
-
return {
|
|
747
|
-
statContest: telescopeStats.get(get("telescope1")),
|
|
748
|
-
elementContest: telescopeElements.get(get("telescope2")),
|
|
749
|
-
hedge1: hedgeTrap1.get(get("telescope3")),
|
|
750
|
-
hedge2: hedgeTrap2.get(get("telescope4")),
|
|
751
|
-
hedge3: hedgeTrap3.get(get("telescope5")),
|
|
752
|
-
};
|
|
753
|
-
}
|
|
754
|
-
/**
|
|
755
|
-
* Visit the desc_x.php page for a given thing
|
|
756
|
-
*
|
|
757
|
-
* @param thing Thing to examine
|
|
758
|
-
* @returns Contents of desc_x.php page
|
|
759
|
-
*/
|
|
760
|
-
export function examine(thing) {
|
|
761
|
-
const url = thing instanceof Item
|
|
762
|
-
? `desc_item.php?whichitem=${thing.descid}`
|
|
763
|
-
: thing instanceof Familiar
|
|
764
|
-
? `desc_familiar.php?which=${thing.id}`
|
|
765
|
-
: thing instanceof Effect
|
|
766
|
-
? `desc_effect.php?whicheffect=${thing.descid}`
|
|
767
|
-
: `desc_skill.php?whichskill=${thing.id}`;
|
|
768
|
-
return visitUrl(url);
|
|
769
|
-
}
|
|
770
|
-
/**
|
|
771
|
-
* Picks an option based on your primestat
|
|
772
|
-
*
|
|
773
|
-
* @param options An object keyed by stat; it must either contain all stats, or have a `default` parameter.
|
|
774
|
-
* @returns The option corresponding to your primestat.
|
|
775
|
-
*/
|
|
776
|
-
export const byStat = makeByXFunction(() => myPrimestat().toString());
|
|
777
|
-
/**
|
|
778
|
-
* Picks an option based on your player class
|
|
779
|
-
*
|
|
780
|
-
* @param options An object keyed by player class; it must either contain all classes, or have a `default` parameter.
|
|
781
|
-
* @returns The option corresponding to your player class.
|
|
782
|
-
*/
|
|
783
|
-
export const byClass = makeByXFunction(() => myClass().toString());
|
|
784
|
-
/**
|
|
785
|
-
* Use an item with visitUrl instead of `use`; this is sometimes useful
|
|
786
|
-
*
|
|
787
|
-
* @param item The item you want to use
|
|
788
|
-
* @returns The html of the resulting page
|
|
789
|
-
*/
|
|
790
|
-
export function directlyUse(item) {
|
|
791
|
-
return visitUrl(`inv_use.php?which=3&whichitem=${item.id}&pwd`);
|
|
792
|
-
}
|
|
793
|
-
/**
|
|
794
|
-
* Empty a slot, or unequip all instances of a given equipped item
|
|
795
|
-
*
|
|
796
|
-
* @param thing The slot or item in question
|
|
797
|
-
* @returns Whether we succeeded completely--`false` if we unequip some but not all instances of the item.
|
|
798
|
-
*/
|
|
799
|
-
export function unequip(thing) {
|
|
800
|
-
if (thing instanceof Slot)
|
|
801
|
-
return equip(thing, $item.none);
|
|
802
|
-
const failedSlots = Slot.all().filter((s) => {
|
|
803
|
-
// Filter the slot out if it doesn't contain the relevant item
|
|
804
|
-
if (equippedItem(s) !== thing)
|
|
805
|
-
return false;
|
|
806
|
-
// Filter the slot out if we succeed at unequipping it
|
|
807
|
-
return !unequip(thing);
|
|
808
|
-
// This leaves only slots that do contain the item but that we failed to unequip
|
|
809
|
-
});
|
|
810
|
-
if (failedSlots.length)
|
|
811
|
-
logger.debug(`Failed to unequip ${thing} from slots ${failedSlots.join(", ")}`);
|
|
812
|
-
return failedSlots.length === 0;
|
|
813
|
-
}
|
|
814
|
-
/**
|
|
815
|
-
* @returns a Date object corresponding to the current in-game day, at midnight
|
|
816
|
-
*/
|
|
817
|
-
export function gameDay() {
|
|
818
|
-
const [, year, month, day] = (todayToString().match(/(\d{4})(\d{2})(\d{2})/) ?? []).map(Number);
|
|
819
|
-
return new Date(year, month - 1, day, 0, 0, 0);
|
|
820
|
-
}
|
|
821
|
-
/**
|
|
822
|
-
* @param [type="all"] the type of crafting to check for free crafts
|
|
823
|
-
* @returns the number of free crafts available of that type
|
|
824
|
-
*/
|
|
825
|
-
export function freeCrafts(type = "all") {
|
|
826
|
-
const effectCrafts = (effect) => Math.floor(haveEffect(effect) / 5);
|
|
827
|
-
const all = (have($skill `Rapid Prototyping`) ? 5 - get("_rapidPrototypingUsed") : 0) +
|
|
828
|
-
(have($skill `Expert Corner-Cutter`)
|
|
829
|
-
? 5 - get("_expertCornerCutterUsed")
|
|
830
|
-
: 0) +
|
|
831
|
-
effectCrafts($effect `Inigo's Incantation of Inspiration`) +
|
|
832
|
-
effectCrafts($effect `Craft Tea`) +
|
|
833
|
-
// eslint-disable-next-line libram/verify-constants
|
|
834
|
-
effectCrafts($effect `Cooking Concentrate`);
|
|
835
|
-
const food = type === "food" ? 5 - get("_cookbookbatCrafting") : 0;
|
|
836
|
-
const smith = type === "smith" ? 5 - get("_thorsPliersCrafting") : 0;
|
|
837
|
-
const booze = 0; // currently there is no booze specific free crafting skill
|
|
838
|
-
return all + food + smith + booze;
|
|
839
|
-
}
|
|
840
|
-
export const realmTypes = [
|
|
841
|
-
"spooky",
|
|
842
|
-
"stench",
|
|
843
|
-
"hot",
|
|
844
|
-
"cold",
|
|
845
|
-
"sleaze",
|
|
846
|
-
"fantasy",
|
|
847
|
-
"pirate",
|
|
848
|
-
];
|
|
849
|
-
/**
|
|
850
|
-
* @param identifier which realm to check for
|
|
851
|
-
* @returns if that realm is available
|
|
852
|
-
*/
|
|
853
|
-
export function realmAvailable(identifier) {
|
|
854
|
-
if (identifier === "fantasy") {
|
|
855
|
-
return get(`_frToday`) || get(`frAlways`);
|
|
856
|
-
}
|
|
857
|
-
else if (identifier === "pirate") {
|
|
858
|
-
return get(`_prToday`) || get(`prAlways`);
|
|
859
|
-
}
|
|
860
|
-
return get(`_${identifier}AirportToday`) || get(`${identifier}AirportAlways`);
|
|
861
|
-
}
|
|
862
|
-
/**
|
|
863
|
-
* Compute the currently available Lucky Gold Ring Currencies
|
|
864
|
-
* @param realm the realm type to consider
|
|
865
|
-
* @returns The currency for the given zone
|
|
866
|
-
*/
|
|
867
|
-
export function realmCurrency(realm) {
|
|
868
|
-
switch (realm) {
|
|
869
|
-
case "sleaze":
|
|
870
|
-
return $item `Beach Buck`;
|
|
871
|
-
case "spooky":
|
|
872
|
-
return $item `Coinspiracy`;
|
|
873
|
-
case "stench":
|
|
874
|
-
return $item `FunFunds™`;
|
|
875
|
-
case "cold":
|
|
876
|
-
return $item `Wal-Mart gift certificate`;
|
|
877
|
-
case "hot":
|
|
878
|
-
return $item `Volcoino`;
|
|
879
|
-
case "fantasy":
|
|
880
|
-
return $item `Rubee™`;
|
|
881
|
-
default:
|
|
882
|
-
return null;
|
|
883
|
-
}
|
|
884
|
-
}
|
|
885
|
-
/**
|
|
886
|
-
* Compute which Lucky Gold Ring currencies are currently available
|
|
887
|
-
* @returns a list of currently available currencies
|
|
888
|
-
*/
|
|
889
|
-
export function lgrCurrencies() {
|
|
890
|
-
return realmTypes
|
|
891
|
-
.filter((realm) => realmAvailable(realm) &&
|
|
892
|
-
!(realm === "hot" && get("_luckyGoldRingVolcoino")))
|
|
893
|
-
.map(realmCurrency)
|
|
894
|
-
.filter(notNull);
|
|
895
|
-
}
|
|
896
|
-
const ACCOUNT_COMBAT_FLAGS = [
|
|
897
|
-
"aabosses",
|
|
898
|
-
"wowbar",
|
|
899
|
-
"bothcombatinterf",
|
|
900
|
-
"compactmanuel",
|
|
901
|
-
"eternalmrj",
|
|
902
|
-
"disablelovebugs",
|
|
903
|
-
"boringdarts",
|
|
904
|
-
];
|
|
905
|
-
/**
|
|
906
|
-
* Get the current value of all of your account's combat setting flags
|
|
907
|
-
* @param flags An array of the flags you want to get, defaults to all of them
|
|
908
|
-
* @returns An array of objects that contain the flags and their values as booleans
|
|
909
|
-
*/
|
|
910
|
-
export function getCombatFlags(flags = [...ACCOUNT_COMBAT_FLAGS]) {
|
|
911
|
-
const accountPage = visitUrl("account.php?tab=combat");
|
|
912
|
-
return flags.map((flag) => ({
|
|
913
|
-
flag,
|
|
914
|
-
value: xpath(accountPage, `//*[@id="opt_flag_${flag}"]/label/input[@type='checkbox']@checked`)[0] === "checked",
|
|
915
|
-
}));
|
|
916
|
-
}
|
|
917
|
-
/**
|
|
918
|
-
* Sets the given combat setting flags on your account
|
|
919
|
-
*
|
|
920
|
-
* @param flags A spread array of objects that contain a flag and its desired value; these look like the return value of `getCombatFlags`
|
|
921
|
-
* @returns the result of the associated `visitUrl` call
|
|
922
|
-
*/
|
|
923
|
-
export function setCombatFlags(...flags) {
|
|
924
|
-
return visitUrl(`account.php?${([
|
|
925
|
-
...flat(flags.map(({ flag, value }) => [
|
|
926
|
-
`actions[]=flag_${flag}`,
|
|
927
|
-
`flag_${flag}=${Number(value)}`,
|
|
928
|
-
])),
|
|
929
|
-
"action=Update",
|
|
930
|
-
"am=1",
|
|
931
|
-
"ajax=1",
|
|
932
|
-
].join("&"),
|
|
933
|
-
true)}`);
|
|
934
|
-
}
|
|
935
|
-
/**
|
|
936
|
-
* Perform a given action with certain combat setting flags set, returning them to their initial values if possible
|
|
937
|
-
*
|
|
938
|
-
* @param action The action you want to do with the given combat setting flags
|
|
939
|
-
* @param flags A spread array of objects that contain a combat setting flag and its desired value; these look like the return value of `getCombatFlags`
|
|
940
|
-
* @returns The result of the action
|
|
941
|
-
*/
|
|
942
|
-
export function withCombatFlags(action, ...flags) {
|
|
943
|
-
const initialValues = getCombatFlags(flags.map(({ flag }) => flag));
|
|
944
|
-
try {
|
|
945
|
-
return action();
|
|
946
|
-
}
|
|
947
|
-
finally {
|
|
948
|
-
setCombatFlags(...initialValues);
|
|
949
|
-
}
|
|
950
|
-
}
|
|
951
|
-
/**
|
|
952
|
-
* Determines whether you currently have an effect intrinsically
|
|
953
|
-
* @param effect The effect in question
|
|
954
|
-
* @returns Whether you have that effect as an intrinsic. Alternately you could just have over 2147483647 turns of that effect, but that seems unlikely.
|
|
955
|
-
*/
|
|
956
|
-
export function haveIntrinsic(effect) {
|
|
957
|
-
return haveEffect(effect) >= 2147483647;
|
|
958
|
-
}
|