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.
Files changed (195) hide show
  1. package/package.json +9 -8
  2. package/dist/Clan.d.ts +0 -128
  3. package/dist/Clan.js +0 -300
  4. package/dist/Copier.d.ts +0 -9
  5. package/dist/Copier.js +0 -15
  6. package/dist/Dungeon.d.ts +0 -45
  7. package/dist/Dungeon.js +0 -115
  8. package/dist/Kmail.d.ts +0 -104
  9. package/dist/Kmail.js +0 -182
  10. package/dist/actions/ActionSource.d.ts +0 -131
  11. package/dist/actions/ActionSource.js +0 -177
  12. package/dist/actions/Banish.d.ts +0 -16
  13. package/dist/actions/Banish.js +0 -121
  14. package/dist/actions/FreeKill.d.ts +0 -16
  15. package/dist/actions/FreeKill.js +0 -94
  16. package/dist/actions/FreeRun.d.ts +0 -16
  17. package/dist/actions/FreeRun.js +0 -77
  18. package/dist/actions/index.d.ts +0 -4
  19. package/dist/actions/index.js +0 -4
  20. package/dist/ascend.d.ts +0 -83
  21. package/dist/ascend.js +0 -268
  22. package/dist/challengePaths/2014/HeavyRains.d.ts +0 -22
  23. package/dist/challengePaths/2014/HeavyRains.js +0 -75
  24. package/dist/challengePaths/2015/CommunityService.d.ts +0 -125
  25. package/dist/challengePaths/2015/CommunityService.js +0 -334
  26. package/dist/challengePaths/2016/NuclearAutumn.d.ts +0 -13
  27. package/dist/challengePaths/2016/NuclearAutumn.js +0 -21
  28. package/dist/challengePaths/index.d.ts +0 -4
  29. package/dist/challengePaths/index.js +0 -4
  30. package/dist/combat.d.ts +0 -414
  31. package/dist/combat.js +0 -711
  32. package/dist/console.d.ts +0 -12
  33. package/dist/console.js +0 -14
  34. package/dist/counter.d.ts +0 -22
  35. package/dist/counter.js +0 -37
  36. package/dist/diet/index.d.ts +0 -80
  37. package/dist/diet/index.js +0 -662
  38. package/dist/diet/knapsack.d.ts +0 -8
  39. package/dist/diet/knapsack.js +0 -128
  40. package/dist/index.d.ts +0 -29
  41. package/dist/index.js +0 -26
  42. package/dist/lib.d.ts +0 -497
  43. package/dist/lib.js +0 -958
  44. package/dist/logger.d.ts +0 -35
  45. package/dist/logger.js +0 -62
  46. package/dist/maximize.d.ts +0 -121
  47. package/dist/maximize.js +0 -525
  48. package/dist/modifier.d.ts +0 -41
  49. package/dist/modifier.js +0 -160
  50. package/dist/modifierTypes.d.ts +0 -16
  51. package/dist/modifierTypes.js +0 -9
  52. package/dist/mood.d.ts +0 -105
  53. package/dist/mood.js +0 -349
  54. package/dist/moonSign.d.ts +0 -13
  55. package/dist/moonSign.js +0 -25
  56. package/dist/overlappingNames.d.ts +0 -3
  57. package/dist/overlappingNames.js +0 -42
  58. package/dist/property.d.ts +0 -222
  59. package/dist/property.js +0 -385
  60. package/dist/propertyTypes.d.ts +0 -19
  61. package/dist/propertyTypes.js +0 -10
  62. package/dist/propertyTyping.d.ts +0 -65
  63. package/dist/propertyTyping.js +0 -91
  64. package/dist/resources/2007/CandyHearts.d.ts +0 -9
  65. package/dist/resources/2007/CandyHearts.js +0 -24
  66. package/dist/resources/2008/DivineFavors.d.ts +0 -9
  67. package/dist/resources/2008/DivineFavors.js +0 -27
  68. package/dist/resources/2008/Stickers.d.ts +0 -49
  69. package/dist/resources/2008/Stickers.js +0 -84
  70. package/dist/resources/2009/Bandersnatch.d.ts +0 -56
  71. package/dist/resources/2009/Bandersnatch.js +0 -93
  72. package/dist/resources/2009/LoveSongs.d.ts +0 -9
  73. package/dist/resources/2009/LoveSongs.js +0 -24
  74. package/dist/resources/2009/SpookyPutty.d.ts +0 -31
  75. package/dist/resources/2009/SpookyPutty.js +0 -49
  76. package/dist/resources/2010/Brickos.d.ts +0 -9
  77. package/dist/resources/2010/Brickos.js +0 -21
  78. package/dist/resources/2010/CrownOfThrones.d.ts +0 -68
  79. package/dist/resources/2010/CrownOfThrones.js +0 -418
  80. package/dist/resources/2010/LookingGlass.d.ts +0 -29
  81. package/dist/resources/2010/LookingGlass.js +0 -89
  82. package/dist/resources/2011/Gygaxian.d.ts +0 -9
  83. package/dist/resources/2011/Gygaxian.js +0 -24
  84. package/dist/resources/2011/ObtuseAngel.d.ts +0 -33
  85. package/dist/resources/2011/ObtuseAngel.js +0 -51
  86. package/dist/resources/2011/StompingBoots.d.ts +0 -37
  87. package/dist/resources/2011/StompingBoots.js +0 -57
  88. package/dist/resources/2012/RainDoh.d.ts +0 -25
  89. package/dist/resources/2012/RainDoh.js +0 -37
  90. package/dist/resources/2012/ReagnimatedGnome.d.ts +0 -31
  91. package/dist/resources/2012/ReagnimatedGnome.js +0 -46
  92. package/dist/resources/2012/Resolutions.d.ts +0 -9
  93. package/dist/resources/2012/Resolutions.js +0 -28
  94. package/dist/resources/2013/Florist.d.ts +0 -81
  95. package/dist/resources/2013/Florist.js +0 -245
  96. package/dist/resources/2013/JungMan.d.ts +0 -33
  97. package/dist/resources/2013/JungMan.js +0 -69
  98. package/dist/resources/2013/PulledTaffy.d.ts +0 -9
  99. package/dist/resources/2013/PulledTaffy.js +0 -33
  100. package/dist/resources/2014/CrimboShrub.d.ts +0 -42
  101. package/dist/resources/2014/CrimboShrub.js +0 -89
  102. package/dist/resources/2014/DNALab.d.ts +0 -56
  103. package/dist/resources/2014/DNALab.js +0 -162
  104. package/dist/resources/2014/WinterGarden.d.ts +0 -23
  105. package/dist/resources/2014/WinterGarden.js +0 -35
  106. package/dist/resources/2015/BarrelShrine.d.ts +0 -8
  107. package/dist/resources/2015/BarrelShrine.js +0 -25
  108. package/dist/resources/2015/ChateauMantegna.d.ts +0 -52
  109. package/dist/resources/2015/ChateauMantegna.js +0 -99
  110. package/dist/resources/2015/DeckOfEveryCard.d.ts +0 -29
  111. package/dist/resources/2015/DeckOfEveryCard.js +0 -122
  112. package/dist/resources/2015/Dinseylandfill.d.ts +0 -89
  113. package/dist/resources/2015/Dinseylandfill.js +0 -205
  114. package/dist/resources/2015/MayoClinic.d.ts +0 -23
  115. package/dist/resources/2015/MayoClinic.js +0 -49
  116. package/dist/resources/2016/GingerBread.d.ts +0 -32
  117. package/dist/resources/2016/GingerBread.js +0 -73
  118. package/dist/resources/2016/SourceTerminal.d.ts +0 -181
  119. package/dist/resources/2016/SourceTerminal.js +0 -275
  120. package/dist/resources/2016/Witchess.d.ts +0 -17
  121. package/dist/resources/2016/Witchess.js +0 -47
  122. package/dist/resources/2017/AsdonMartin.d.ts +0 -59
  123. package/dist/resources/2017/AsdonMartin.js +0 -238
  124. package/dist/resources/2017/Horsery.d.ts +0 -19
  125. package/dist/resources/2017/Horsery.js +0 -42
  126. package/dist/resources/2017/MummingTrunk.d.ts +0 -8
  127. package/dist/resources/2017/MummingTrunk.js +0 -33
  128. package/dist/resources/2017/Pantogram.d.ts +0 -92
  129. package/dist/resources/2017/Pantogram.js +0 -174
  130. package/dist/resources/2017/Robortender.d.ts +0 -30
  131. package/dist/resources/2017/Robortender.js +0 -90
  132. package/dist/resources/2017/Spacegate.d.ts +0 -86
  133. package/dist/resources/2017/Spacegate.js +0 -178
  134. package/dist/resources/2017/TunnelOfLove.d.ts +0 -39
  135. package/dist/resources/2017/TunnelOfLove.js +0 -120
  136. package/dist/resources/2018/LatteLoversMembersMug.d.ts +0 -392
  137. package/dist/resources/2018/LatteLoversMembersMug.js +0 -303
  138. package/dist/resources/2018/SongBoom.d.ts +0 -33
  139. package/dist/resources/2018/SongBoom.js +0 -55
  140. package/dist/resources/2019/BeachComb.d.ts +0 -72
  141. package/dist/resources/2019/BeachComb.js +0 -118
  142. package/dist/resources/2019/CampAway.d.ts +0 -39
  143. package/dist/resources/2019/CampAway.js +0 -72
  144. package/dist/resources/2019/Snapper.d.ts +0 -33
  145. package/dist/resources/2019/Snapper.js +0 -73
  146. package/dist/resources/2020/Cartography.d.ts +0 -16
  147. package/dist/resources/2020/Cartography.js +0 -48
  148. package/dist/resources/2020/Guzzlr.d.ts +0 -160
  149. package/dist/resources/2020/Guzzlr.js +0 -275
  150. package/dist/resources/2020/RetroCape.d.ts +0 -51
  151. package/dist/resources/2020/RetroCape.js +0 -115
  152. package/dist/resources/2021/CrystalBall.d.ts +0 -14
  153. package/dist/resources/2021/CrystalBall.js +0 -39
  154. package/dist/resources/2021/DaylightShavings.d.ts +0 -40
  155. package/dist/resources/2021/DaylightShavings.js +0 -74
  156. package/dist/resources/2022/AutumnAton.d.ts +0 -78
  157. package/dist/resources/2022/AutumnAton.js +0 -182
  158. package/dist/resources/2022/CombatLoversLocket.d.ts +0 -44
  159. package/dist/resources/2022/CombatLoversLocket.js +0 -82
  160. package/dist/resources/2022/GreyGoose.d.ts +0 -59
  161. package/dist/resources/2022/GreyGoose.js +0 -90
  162. package/dist/resources/2022/JuneCleaver.d.ts +0 -47
  163. package/dist/resources/2022/JuneCleaver.js +0 -69
  164. package/dist/resources/2022/TrainSet.d.ts +0 -146
  165. package/dist/resources/2022/TrainSet.js +0 -228
  166. package/dist/resources/2023/AugustScepter.d.ts +0 -25
  167. package/dist/resources/2023/AugustScepter.js +0 -40
  168. package/dist/resources/2023/BurningLeaves.d.ts +0 -25
  169. package/dist/resources/2023/BurningLeaves.js +0 -74
  170. package/dist/resources/2023/CinchoDeMayo.d.ts +0 -25
  171. package/dist/resources/2023/CinchoDeMayo.js +0 -45
  172. package/dist/resources/2023/ClosedCircuitPayphone.d.ts +0 -80
  173. package/dist/resources/2023/ClosedCircuitPayphone.js +0 -129
  174. package/dist/resources/2023/CursedMonkeyPaw.d.ts +0 -46
  175. package/dist/resources/2023/CursedMonkeyPaw.js +0 -113
  176. package/dist/resources/2024/AprilingBandHelmet.d.ts +0 -50
  177. package/dist/resources/2024/AprilingBandHelmet.js +0 -103
  178. package/dist/resources/2024/ChestMimic.d.ts +0 -35
  179. package/dist/resources/2024/ChestMimic.js +0 -108
  180. package/dist/resources/LibramSummon.d.ts +0 -18
  181. package/dist/resources/LibramSummon.js +0 -74
  182. package/dist/resources/index.d.ts +0 -54
  183. package/dist/resources/index.js +0 -54
  184. package/dist/resources/putty-likes.d.ts +0 -21
  185. package/dist/resources/putty-likes.js +0 -33
  186. package/dist/session.d.ts +0 -169
  187. package/dist/session.js +0 -284
  188. package/dist/since.d.ts +0 -51
  189. package/dist/since.js +0 -108
  190. package/dist/template-string.d.ts +0 -324
  191. package/dist/template-string.js +0 -265
  192. package/dist/url.d.ts +0 -35
  193. package/dist/url.js +0 -67
  194. package/dist/utils.d.ts +0 -178
  195. 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
- }