libram 0.8.28 → 0.8.29

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/dist/Clan.d.ts +128 -0
  2. package/dist/Clan.js +300 -0
  3. package/dist/Copier.d.ts +9 -0
  4. package/dist/Copier.js +15 -0
  5. package/dist/Dungeon.d.ts +45 -0
  6. package/dist/Dungeon.js +115 -0
  7. package/dist/Kmail.d.ts +133 -0
  8. package/dist/Kmail.js +259 -0
  9. package/dist/actions/ActionSource.d.ts +131 -0
  10. package/dist/actions/ActionSource.js +178 -0
  11. package/dist/actions/Banish.d.ts +16 -0
  12. package/dist/actions/Banish.js +121 -0
  13. package/dist/actions/FreeKill.d.ts +16 -0
  14. package/dist/actions/FreeKill.js +94 -0
  15. package/dist/actions/FreeRun.d.ts +16 -0
  16. package/dist/actions/FreeRun.js +81 -0
  17. package/dist/actions/index.d.ts +4 -0
  18. package/dist/actions/index.js +4 -0
  19. package/dist/ascend.d.ts +83 -0
  20. package/dist/ascend.js +268 -0
  21. package/dist/challengePaths/2014/HeavyRains.d.ts +22 -0
  22. package/dist/challengePaths/2014/HeavyRains.js +75 -0
  23. package/dist/challengePaths/2015/CommunityService.d.ts +125 -0
  24. package/dist/challengePaths/2015/CommunityService.js +334 -0
  25. package/dist/challengePaths/2016/NuclearAutumn.d.ts +13 -0
  26. package/dist/challengePaths/2016/NuclearAutumn.js +21 -0
  27. package/dist/challengePaths/index.d.ts +4 -0
  28. package/dist/challengePaths/index.js +4 -0
  29. package/dist/combat.d.ts +414 -0
  30. package/dist/combat.js +711 -0
  31. package/dist/console.d.ts +12 -0
  32. package/dist/console.js +14 -0
  33. package/dist/counter.d.ts +22 -0
  34. package/dist/counter.js +37 -0
  35. package/dist/diet/index.d.ts +80 -0
  36. package/dist/diet/index.js +680 -0
  37. package/dist/diet/knapsack.d.ts +8 -0
  38. package/dist/diet/knapsack.js +128 -0
  39. package/dist/index.d.ts +29 -0
  40. package/dist/index.js +26 -0
  41. package/dist/lib.d.ts +507 -0
  42. package/dist/lib.js +970 -0
  43. package/dist/logger.d.ts +35 -0
  44. package/dist/logger.js +62 -0
  45. package/dist/maximize.d.ts +122 -0
  46. package/dist/maximize.js +531 -0
  47. package/dist/modifier.d.ts +41 -0
  48. package/dist/modifier.js +160 -0
  49. package/dist/modifierTypes.d.ts +16 -0
  50. package/dist/modifierTypes.js +9 -0
  51. package/dist/mood.d.ts +105 -0
  52. package/dist/mood.js +349 -0
  53. package/dist/moonSign.d.ts +13 -0
  54. package/dist/moonSign.js +25 -0
  55. package/dist/overlappingNames.d.ts +3 -0
  56. package/dist/overlappingNames.js +42 -0
  57. package/dist/property.d.ts +222 -0
  58. package/dist/property.js +385 -0
  59. package/dist/propertyTypes.d.ts +19 -0
  60. package/dist/propertyTypes.js +10 -0
  61. package/dist/propertyTyping.d.ts +65 -0
  62. package/dist/propertyTyping.js +91 -0
  63. package/dist/resources/2007/CandyHearts.d.ts +9 -0
  64. package/dist/resources/2007/CandyHearts.js +24 -0
  65. package/dist/resources/2008/DivineFavors.d.ts +9 -0
  66. package/dist/resources/2008/DivineFavors.js +27 -0
  67. package/dist/resources/2008/Stickers.d.ts +49 -0
  68. package/dist/resources/2008/Stickers.js +84 -0
  69. package/dist/resources/2009/Bandersnatch.d.ts +56 -0
  70. package/dist/resources/2009/Bandersnatch.js +93 -0
  71. package/dist/resources/2009/LoveSongs.d.ts +9 -0
  72. package/dist/resources/2009/LoveSongs.js +24 -0
  73. package/dist/resources/2009/SpookyPutty.d.ts +31 -0
  74. package/dist/resources/2009/SpookyPutty.js +49 -0
  75. package/dist/resources/2010/Brickos.d.ts +9 -0
  76. package/dist/resources/2010/Brickos.js +21 -0
  77. package/dist/resources/2010/CrownOfThrones.d.ts +68 -0
  78. package/dist/resources/2010/CrownOfThrones.js +418 -0
  79. package/dist/resources/2010/LookingGlass.d.ts +29 -0
  80. package/dist/resources/2010/LookingGlass.js +89 -0
  81. package/dist/resources/2011/Gygaxian.d.ts +9 -0
  82. package/dist/resources/2011/Gygaxian.js +24 -0
  83. package/dist/resources/2011/ObtuseAngel.d.ts +33 -0
  84. package/dist/resources/2011/ObtuseAngel.js +51 -0
  85. package/dist/resources/2011/StompingBoots.d.ts +37 -0
  86. package/dist/resources/2011/StompingBoots.js +57 -0
  87. package/dist/resources/2012/RainDoh.d.ts +25 -0
  88. package/dist/resources/2012/RainDoh.js +37 -0
  89. package/dist/resources/2012/ReagnimatedGnome.d.ts +31 -0
  90. package/dist/resources/2012/ReagnimatedGnome.js +46 -0
  91. package/dist/resources/2012/Resolutions.d.ts +9 -0
  92. package/dist/resources/2012/Resolutions.js +28 -0
  93. package/dist/resources/2013/Florist.d.ts +81 -0
  94. package/dist/resources/2013/Florist.js +245 -0
  95. package/dist/resources/2013/JungMan.d.ts +33 -0
  96. package/dist/resources/2013/JungMan.js +69 -0
  97. package/dist/resources/2013/PulledTaffy.d.ts +9 -0
  98. package/dist/resources/2013/PulledTaffy.js +33 -0
  99. package/dist/resources/2014/CrimboShrub.d.ts +42 -0
  100. package/dist/resources/2014/CrimboShrub.js +89 -0
  101. package/dist/resources/2014/DNALab.d.ts +56 -0
  102. package/dist/resources/2014/DNALab.js +162 -0
  103. package/dist/resources/2014/WinterGarden.d.ts +23 -0
  104. package/dist/resources/2014/WinterGarden.js +35 -0
  105. package/dist/resources/2015/BarrelShrine.d.ts +8 -0
  106. package/dist/resources/2015/BarrelShrine.js +25 -0
  107. package/dist/resources/2015/ChateauMantegna.d.ts +52 -0
  108. package/dist/resources/2015/ChateauMantegna.js +99 -0
  109. package/dist/resources/2015/DeckOfEveryCard.d.ts +29 -0
  110. package/dist/resources/2015/DeckOfEveryCard.js +122 -0
  111. package/dist/resources/2015/Dinseylandfill.d.ts +89 -0
  112. package/dist/resources/2015/Dinseylandfill.js +205 -0
  113. package/dist/resources/2015/MayoClinic.d.ts +23 -0
  114. package/dist/resources/2015/MayoClinic.js +49 -0
  115. package/dist/resources/2016/GingerBread.d.ts +32 -0
  116. package/dist/resources/2016/GingerBread.js +73 -0
  117. package/dist/resources/2016/SourceTerminal.d.ts +181 -0
  118. package/dist/resources/2016/SourceTerminal.js +275 -0
  119. package/dist/resources/2016/Witchess.d.ts +17 -0
  120. package/dist/resources/2016/Witchess.js +47 -0
  121. package/dist/resources/2017/AsdonMartin.d.ts +59 -0
  122. package/dist/resources/2017/AsdonMartin.js +238 -0
  123. package/dist/resources/2017/Horsery.d.ts +19 -0
  124. package/dist/resources/2017/Horsery.js +42 -0
  125. package/dist/resources/2017/MummingTrunk.d.ts +8 -0
  126. package/dist/resources/2017/MummingTrunk.js +33 -0
  127. package/dist/resources/2017/Pantogram.d.ts +92 -0
  128. package/dist/resources/2017/Pantogram.js +174 -0
  129. package/dist/resources/2017/Robortender.d.ts +30 -0
  130. package/dist/resources/2017/Robortender.js +90 -0
  131. package/dist/resources/2017/Spacegate.d.ts +86 -0
  132. package/dist/resources/2017/Spacegate.js +178 -0
  133. package/dist/resources/2017/TunnelOfLove.d.ts +39 -0
  134. package/dist/resources/2017/TunnelOfLove.js +120 -0
  135. package/dist/resources/2018/LatteLoversMembersMug.d.ts +392 -0
  136. package/dist/resources/2018/LatteLoversMembersMug.js +303 -0
  137. package/dist/resources/2018/SongBoom.d.ts +33 -0
  138. package/dist/resources/2018/SongBoom.js +55 -0
  139. package/dist/resources/2019/BeachComb.d.ts +72 -0
  140. package/dist/resources/2019/BeachComb.js +118 -0
  141. package/dist/resources/2019/CampAway.d.ts +39 -0
  142. package/dist/resources/2019/CampAway.js +72 -0
  143. package/dist/resources/2019/Snapper.d.ts +33 -0
  144. package/dist/resources/2019/Snapper.js +73 -0
  145. package/dist/resources/2020/Cartography.d.ts +16 -0
  146. package/dist/resources/2020/Cartography.js +48 -0
  147. package/dist/resources/2020/Guzzlr.d.ts +160 -0
  148. package/dist/resources/2020/Guzzlr.js +275 -0
  149. package/dist/resources/2020/RetroCape.d.ts +51 -0
  150. package/dist/resources/2020/RetroCape.js +115 -0
  151. package/dist/resources/2021/CrystalBall.d.ts +14 -0
  152. package/dist/resources/2021/CrystalBall.js +41 -0
  153. package/dist/resources/2021/DaylightShavings.d.ts +40 -0
  154. package/dist/resources/2021/DaylightShavings.js +74 -0
  155. package/dist/resources/2022/AutumnAton.d.ts +78 -0
  156. package/dist/resources/2022/AutumnAton.js +182 -0
  157. package/dist/resources/2022/CombatLoversLocket.d.ts +44 -0
  158. package/dist/resources/2022/CombatLoversLocket.js +82 -0
  159. package/dist/resources/2022/GreyGoose.d.ts +59 -0
  160. package/dist/resources/2022/GreyGoose.js +90 -0
  161. package/dist/resources/2022/JuneCleaver.d.ts +47 -0
  162. package/dist/resources/2022/JuneCleaver.js +69 -0
  163. package/dist/resources/2022/TrainSet.d.ts +146 -0
  164. package/dist/resources/2022/TrainSet.js +228 -0
  165. package/dist/resources/2023/AugustScepter.d.ts +25 -0
  166. package/dist/resources/2023/AugustScepter.js +40 -0
  167. package/dist/resources/2023/BurningLeaves.d.ts +25 -0
  168. package/dist/resources/2023/BurningLeaves.js +74 -0
  169. package/dist/resources/2023/CinchoDeMayo.d.ts +25 -0
  170. package/dist/resources/2023/CinchoDeMayo.js +45 -0
  171. package/dist/resources/2023/ClosedCircuitPayphone.d.ts +80 -0
  172. package/dist/resources/2023/ClosedCircuitPayphone.js +129 -0
  173. package/dist/resources/2023/CursedMonkeyPaw.d.ts +46 -0
  174. package/dist/resources/2023/CursedMonkeyPaw.js +113 -0
  175. package/dist/resources/2024/AprilingBandHelmet.d.ts +57 -0
  176. package/dist/resources/2024/AprilingBandHelmet.js +118 -0
  177. package/dist/resources/2024/ChestMimic.d.ts +42 -0
  178. package/dist/resources/2024/ChestMimic.js +125 -0
  179. package/dist/resources/LibramSummon.d.ts +18 -0
  180. package/dist/resources/LibramSummon.js +74 -0
  181. package/dist/resources/index.d.ts +54 -0
  182. package/dist/resources/index.js +54 -0
  183. package/dist/resources/putty-likes.d.ts +21 -0
  184. package/dist/resources/putty-likes.js +33 -0
  185. package/dist/session.d.ts +169 -0
  186. package/dist/session.js +284 -0
  187. package/dist/since.d.ts +51 -0
  188. package/dist/since.js +108 -0
  189. package/dist/template-string.d.ts +324 -0
  190. package/dist/template-string.js +265 -0
  191. package/dist/url.d.ts +35 -0
  192. package/dist/url.js +67 -0
  193. package/dist/utils.d.ts +178 -0
  194. package/dist/utils.js +255 -0
  195. package/package.json +2 -2
@@ -0,0 +1,80 @@
1
+ import { Monster, Item, Location } from "kolmafia";
2
+ /**
3
+ * @returns Whether we currently have the closed-circuit pay phone
4
+ */
5
+ export declare function have(): boolean;
6
+ /**
7
+ * @returns Rufus's currently expected quest target, if he has one
8
+ */
9
+ export declare function rufusTarget(): Monster | Item | string | null;
10
+ declare const INGRESS_RIFTS: {
11
+ readonly desertbeach: Location;
12
+ readonly forestvillage: Location;
13
+ readonly mclargehuge: Location;
14
+ readonly beanstalk: Location;
15
+ readonly manor3: Location;
16
+ readonly "8bit": Location;
17
+ readonly pyramid: Location;
18
+ readonly giantcastle: Location;
19
+ readonly woods: Location;
20
+ readonly hiddencity: Location;
21
+ readonly cemetery: Location;
22
+ readonly plains: Location;
23
+ readonly town_right: Location;
24
+ };
25
+ export declare type Ingress = "" | keyof typeof INGRESS_RIFTS;
26
+ /**
27
+ * @returns Your current `shadowRiftIngress`; `null` if none is set this ascension
28
+ */
29
+ export declare function currentIngress(): Ingress;
30
+ /**
31
+ * @returns The current shadow rift that Mafia thinks KoL thinks you're in.
32
+ */
33
+ export declare function currentRift(): Location | null;
34
+ /**
35
+ * Choose a shadow rift to suit your needs
36
+ *
37
+ * @param options An object of various requirements you might have for the rift you want
38
+ * @param options.canAdventure Set to `true` if you want to only select a rift that you can currently access
39
+ * @param options.monsters Set to an array of Shadow Monsters you want to be available in the rift
40
+ * @param options.drops Set to an array of item drops you want to come from monsters in the rift
41
+ * @param options.otherFilter Set an optional additional filtering function not covered by the above logic
42
+ * @param options.sortBy Set a function used to compare valid rifts between eachother; bigger numbers are better
43
+ * @returns A rift that meets the criteria you specify, if one exists
44
+ */
45
+ export declare function chooseRift(options: {
46
+ canAdventure?: boolean;
47
+ monsters?: Monster[];
48
+ drops?: Item[];
49
+ otherFilter?: (l: Location) => boolean;
50
+ sortBy?: (l: Location) => number;
51
+ }): Location | null;
52
+ /**
53
+ * Choose a quest based on the options available to us
54
+ *
55
+ * @param chooser A function that maps quest-options to a choice
56
+ * @returns Whether we successfully accepted a quest
57
+ */
58
+ export declare function chooseQuest(chooser: ({ entity, artifact, items, }: {
59
+ entity: Monster;
60
+ artifact: Item;
61
+ items: Item;
62
+ }) => 1 | 2 | 3 | 4): boolean;
63
+ /**
64
+ * @returns Array containing all shadow rift locations
65
+ */
66
+ export declare function rifts(): Location[];
67
+ /**
68
+ * Picks an option based on your current shadow rift ingress
69
+ *
70
+ * @param options An object keyed by shadow rift ingress; it must either contain all possible ingresses, or have a `default` parameter.
71
+ * @returns The option corresponding to your current shadow rift ingress.
72
+ */
73
+ export declare const byIngress: <S>(options: import("../../utils").Switch<Ingress, S>) => S;
74
+ /**
75
+ * Submit your Rufus quest
76
+ *
77
+ * @returns Whether we successfully submitted your Rufus quest
78
+ */
79
+ export declare function submitQuest(): boolean;
80
+ export {};
@@ -0,0 +1,129 @@
1
+ import { Monster, Item, getMonsters, itemDrops, canAdventure, runChoice, toItem, use, } from "kolmafia";
2
+ import { directlyUse, have as have_, questStep } from "../../lib";
3
+ import { get, withChoice } from "../../property";
4
+ import { $item, $location, $monster } from "../../template-string";
5
+ import { makeByXFunction, maxBy } from "../../utils";
6
+ const item = $item `closed-circuit pay phone`;
7
+ /**
8
+ * @returns Whether we currently have the closed-circuit pay phone
9
+ */
10
+ export function have() {
11
+ return have_(item);
12
+ }
13
+ /**
14
+ * @returns Rufus's currently expected quest target, if he has one
15
+ */
16
+ export function rufusTarget() {
17
+ const target = get("rufusQuestTarget");
18
+ switch (get("rufusQuestType")) {
19
+ case "entity":
20
+ return Monster.get(target);
21
+ case "artifact":
22
+ case "items":
23
+ return Item.get(target);
24
+ default:
25
+ return null;
26
+ }
27
+ }
28
+ const INGRESS_RIFTS = {
29
+ desertbeach: $location `Shadow Rift (Desert Beach)`,
30
+ forestvillage: $location `Shadow Rift (Forest Village)`,
31
+ mclargehuge: $location `Shadow Rift (Mt. McLargeHuge)`,
32
+ beanstalk: $location `Shadow Rift (Somewhere Over the Beanstalk)`,
33
+ manor3: $location `Shadow Rift (Spookyraven Manor Third Floor)`,
34
+ "8bit": $location `Shadow Rift (The 8-Bit Realm)`,
35
+ pyramid: $location `Shadow Rift (The Ancient Buried Pyramid)`,
36
+ giantcastle: $location `Shadow Rift (The Castle in the Clouds in the Sky)`,
37
+ woods: $location `Shadow Rift (The Distant Woods)`,
38
+ hiddencity: $location `Shadow Rift (The Hidden City)`,
39
+ cemetery: $location `Shadow Rift (The Misspelled Cemetary)`,
40
+ plains: $location `Shadow Rift (The Nearby Plains)`,
41
+ town_right: $location `Shadow Rift (The Right Side of the Tracks)`,
42
+ };
43
+ /**
44
+ * @returns Your current `shadowRiftIngress`; `null` if none is set this ascension
45
+ */
46
+ export function currentIngress() {
47
+ return get("shadowRiftIngress");
48
+ }
49
+ /**
50
+ * @returns The current shadow rift that Mafia thinks KoL thinks you're in.
51
+ */
52
+ export function currentRift() {
53
+ const ingress = currentIngress();
54
+ return ingress ? INGRESS_RIFTS[ingress] : null;
55
+ }
56
+ const RIFTS = Array.from(Object.values(INGRESS_RIFTS));
57
+ /**
58
+ * Choose a shadow rift to suit your needs
59
+ *
60
+ * @param options An object of various requirements you might have for the rift you want
61
+ * @param options.canAdventure Set to `true` if you want to only select a rift that you can currently access
62
+ * @param options.monsters Set to an array of Shadow Monsters you want to be available in the rift
63
+ * @param options.drops Set to an array of item drops you want to come from monsters in the rift
64
+ * @param options.otherFilter Set an optional additional filtering function not covered by the above logic
65
+ * @param options.sortBy Set a function used to compare valid rifts between eachother; bigger numbers are better
66
+ * @returns A rift that meets the criteria you specify, if one exists
67
+ */
68
+ export function chooseRift(options) {
69
+ const filterFunction = (l) => {
70
+ const monsters = getMonsters(l);
71
+ if (options.canAdventure && !canAdventure(l))
72
+ return false;
73
+ if (options.monsters?.some((m) => !monsters.includes(m)))
74
+ return false;
75
+ if (options.drops?.every((i) => !monsters.some((m) => i.name in itemDrops(m))))
76
+ return false;
77
+ return options.otherFilter?.(l) ?? true;
78
+ };
79
+ const validRifts = [...RIFTS].filter(filterFunction);
80
+ if (!validRifts.length)
81
+ return null;
82
+ return options.sortBy ? maxBy(validRifts, options.sortBy) : validRifts[0];
83
+ }
84
+ /**
85
+ * Choose a quest based on the options available to us
86
+ *
87
+ * @param chooser A function that maps quest-options to a choice
88
+ * @returns Whether we successfully accepted a quest
89
+ */
90
+ export function chooseQuest(chooser) {
91
+ if (get("questRufus") !== "unstarted")
92
+ return false;
93
+ if (!have())
94
+ return false;
95
+ withChoice(1497, "", () => {
96
+ directlyUse(item);
97
+ runChoice(chooser({
98
+ artifact: toItem(get("rufusDesiredArtifact")),
99
+ entity: get("rufusDesiredEntity") ?? $monster.none,
100
+ items: toItem(get("rufusDesiredItems")),
101
+ }));
102
+ });
103
+ return get("questRufus") !== "unstarted";
104
+ }
105
+ /**
106
+ * @returns Array containing all shadow rift locations
107
+ */
108
+ export function rifts() {
109
+ return [...RIFTS];
110
+ }
111
+ /**
112
+ * Picks an option based on your current shadow rift ingress
113
+ *
114
+ * @param options An object keyed by shadow rift ingress; it must either contain all possible ingresses, or have a `default` parameter.
115
+ * @returns The option corresponding to your current shadow rift ingress.
116
+ */
117
+ export const byIngress = makeByXFunction(currentIngress);
118
+ /**
119
+ * Submit your Rufus quest
120
+ *
121
+ * @returns Whether we successfully submitted your Rufus quest
122
+ */
123
+ export function submitQuest() {
124
+ if (questStep("questRufus") === 1) {
125
+ withChoice(1498, 1, () => use(item));
126
+ return questStep("questRufus") === -1;
127
+ }
128
+ return false;
129
+ }
@@ -0,0 +1,46 @@
1
+ import { Item, Location, Effect, Monster } from "kolmafia";
2
+ /**
3
+ * @returns Whether or not we currently `have` the cursed monkey's paw
4
+ */
5
+ export declare function have(): boolean;
6
+ /**
7
+ * @returns The number of monkey paw wishes we have remaining
8
+ */
9
+ export declare function wishes(): number;
10
+ export declare type WishableItemsFilters = Partial<{
11
+ location: (location: Location) => boolean;
12
+ monster: (monster: Monster) => boolean;
13
+ drop: (itemDrop: {
14
+ drop: Item;
15
+ rate: number;
16
+ type: string;
17
+ }) => boolean;
18
+ }>;
19
+ /**
20
+ * @param filters An optional object optionally consisting of filtering functions to shrink down the pool of wishable items
21
+ * @param filters.location A filtering function to remove locations from the pool of wishable targets.
22
+ * @param filters.monster A filtering function to remove monsters from the pool of wishable targets.
23
+ * @param filters.drop A filtering function to remove item drops from the pool of wishable targets.
24
+ * @returns A set of all items we expect to be able to wish; this doesn't actually constitute all items
25
+ */
26
+ export declare function wishableItems(filters?: WishableItemsFilters): Set<Item>;
27
+ /**
28
+ * @returns An Array consisting of all genie-wishable Effects that are not Monkey-wishable
29
+ */
30
+ export declare function getUnwishableEffects(): Effect[];
31
+ /**
32
+ * Decides if we expect that a given Item or Effect can be wished for.
33
+ * May be slow for Effects;
34
+ *
35
+ * @param wish The Item or Effect in question
36
+ * @returns Whether we expect it can be wished for
37
+ */
38
+ export declare function isWishable(wish: Effect | Item): boolean;
39
+ /**
40
+ * Wish for a given Item or Effect.
41
+ * If it's an item, will `prepareForAdventure`; if an item is available in multiple locations this will pick the first one.
42
+ *
43
+ * @param wish The Item or Effect to wish for
44
+ * @returns Whether we succeeded in this endeavor
45
+ */
46
+ export declare function wishFor(wish: Effect | Item): boolean;
@@ -0,0 +1,113 @@
1
+ import { Item, Location, canAdventure, getMonsters, itemDropsArray, Effect, toEffect, monkeyPaw, prepareForAdventure, cliExecute, } from "kolmafia";
2
+ import { have as have_ } from "../../lib";
3
+ import logger from "../../logger";
4
+ import { get } from "../../property";
5
+ import { $item } from "../../template-string";
6
+ import { clamp, flat } from "../../utils";
7
+ const item = $item `cursed monkey's paw`;
8
+ /**
9
+ * @returns Whether or not we currently `have` the cursed monkey's paw
10
+ */
11
+ export function have() {
12
+ return have_(item);
13
+ }
14
+ /**
15
+ * @returns The number of monkey paw wishes we have remaining
16
+ */
17
+ export function wishes() {
18
+ return clamp(5 - get("_monkeyPawWishesUsed"), 0, 5);
19
+ }
20
+ /**
21
+ * @param filters An optional object optionally consisting of filtering functions to shrink down the pool of wishable items
22
+ * @param filters.location A filtering function to remove locations from the pool of wishable targets.
23
+ * @param filters.monster A filtering function to remove monsters from the pool of wishable targets.
24
+ * @param filters.drop A filtering function to remove item drops from the pool of wishable targets.
25
+ * @returns A set of all items we expect to be able to wish; this doesn't actually constitute all items
26
+ */
27
+ export function wishableItems(filters = {}) {
28
+ return new Set(flat(Location.all()
29
+ .filter((l) => canAdventure(l) && (filters.location?.(l) ?? true))
30
+ .map((l) => getMonsters(l)
31
+ .filter((m) => m.copyable && (filters.monster?.(m) ?? true))
32
+ .map((m) => itemDropsArray(m)
33
+ .filter(({ type, rate, drop }) => !drop.quest &&
34
+ (type !== "c" || rate >= 1) && // Remove random roll drops
35
+ (filters.drop?.({ type, rate, drop }) ?? true))
36
+ .map(({ drop }) => drop)))));
37
+ }
38
+ const INVALID_CHARACTERS = /[^a-z\d -]/g;
39
+ let _unwishableEffects;
40
+ function unwishableEffects() {
41
+ // This is the set of all names of genie-wishable effects, split into the maximal substrings we can actually submit
42
+ const names = Effect.all()
43
+ .filter((e) => !e.attributes.includes("nohookah"))
44
+ .map((e) => {
45
+ const name = e.name.toLowerCase();
46
+ return { name, splitName: name.split(INVALID_CHARACTERS) };
47
+ });
48
+ return names
49
+ .filter(({ name, splitName }) =>
50
+ // Any effect that doesn't contain an INVALID_CHARACTER is fine
51
+ splitName.length > 1 &&
52
+ // To be unwishable, there can't be any substrings that uniquely match a genie-wishable effect
53
+ splitName.every((s) =>
54
+ // So we check every maximal substring against every one of our genie-wishable effects, excluding the effect we're currently looking at
55
+ // if one of the substrings matches a substring associated with another effect, we're screwed.
56
+ names.some(({ name: n }) => n !== name && n.includes(s))))
57
+ .map(({ name }) => toEffect(name));
58
+ }
59
+ /**
60
+ * @returns An Array consisting of all genie-wishable Effects that are not Monkey-wishable
61
+ */
62
+ export function getUnwishableEffects() {
63
+ return (_unwishableEffects ??= unwishableEffects());
64
+ }
65
+ /**
66
+ * Decides if we expect that a given Item or Effect can be wished for.
67
+ * May be slow for Effects;
68
+ *
69
+ * @param wish The Item or Effect in question
70
+ * @returns Whether we expect it can be wished for
71
+ */
72
+ export function isWishable(wish) {
73
+ if (wish instanceof Item) {
74
+ return wishableItems().has(wish);
75
+ }
76
+ else {
77
+ if (wish.attributes.includes("nohookah"))
78
+ return false;
79
+ if (!wish.name.match(/[.,']/))
80
+ return true;
81
+ return !getUnwishableEffects().includes(wish);
82
+ }
83
+ }
84
+ /**
85
+ * Wish for a given Item or Effect.
86
+ * If it's an item, will `prepareForAdventure`; if an item is available in multiple locations this will pick the first one.
87
+ *
88
+ * @param wish The Item or Effect to wish for
89
+ * @returns Whether we succeeded in this endeavor
90
+ */
91
+ export function wishFor(wish) {
92
+ if (wishes() <= 0)
93
+ return false;
94
+ if (wish instanceof Effect)
95
+ return monkeyPaw(wish);
96
+ const locations = Location.all().filter((l) => canAdventure(l) &&
97
+ getMonsters(l).some((m) => m.copyable && itemDropsArray(m).some(({ drop }) => drop === wish)));
98
+ try {
99
+ if (locations.length) {
100
+ cliExecute("checkpoint");
101
+ prepareForAdventure(locations[0]);
102
+ }
103
+ const result = monkeyPaw(wish);
104
+ if (!result) {
105
+ logger.debug(`Failed to monkeyPaw wish for ${wish}; assumed it was available in locations ${locations.join(", ")}`);
106
+ }
107
+ return result;
108
+ }
109
+ finally {
110
+ if (locations.length)
111
+ cliExecute("outfit checkpoint");
112
+ }
113
+ }
@@ -0,0 +1,57 @@
1
+ import { Effect, Item } from "kolmafia";
2
+ /**
3
+ * @returns whether you `have` the Apriling band helmet
4
+ */
5
+ export declare function have(): boolean;
6
+ export declare const MARCHING_SONGS: readonly ["Apriling Band Patrol Beat", "Apriling Band Battle Cadence", "Apriling Band Celebration Bop"];
7
+ export declare type MarchingSong = typeof MARCHING_SONGS[number];
8
+ export declare const MARCHING_SONG_EFFECTS: readonly Effect[];
9
+ export declare const INSTRUMENTS: readonly ["Apriling band saxophone", "Apriling band quad tom", "Apriling band tuba", "Apriling band staff", "Apriling band piccolo"];
10
+ export declare type Instrument = typeof INSTRUMENTS[number];
11
+ export declare const INSTRUMENT_ITEMS: readonly Item[];
12
+ /**
13
+ * @returns Whether we can currently join a new section of our Apriling band
14
+ */
15
+ export declare function canJoinSection(): boolean;
16
+ /**
17
+ * Joins the given section of your Apriling band, returning whether you successfully obtained its instrument
18
+ *
19
+ * @param section The section of your band to join--either the instrument's name as a string, or the item itself.
20
+ *
21
+ * @returns Whether we have the item, at the end of all things
22
+ */
23
+ export declare const joinSection: (input: Item | "Apriling band saxophone" | "Apriling band quad tom" | "Apriling band tuba" | "Apriling band staff" | "Apriling band piccolo") => boolean;
24
+ /**
25
+ * @returns Whether we can currently change the marching song of our Apriling Band
26
+ */
27
+ export declare function canChangeSong(): boolean;
28
+ /**
29
+ * Instructs your Apriling band to play the given song, returning whether it's successfully playing
30
+ *
31
+ * @param song The song for your band to play--either the effect's name or the effect itself.
32
+ *
33
+ * @returns Whether we have the effect, at the end of all things
34
+ */
35
+ export declare const changeSong: (input: Effect | "Apriling Band Patrol Beat" | "Apriling Band Battle Cadence" | "Apriling Band Celebration Bop") => boolean;
36
+ /**
37
+ * Conduct your Apriling band helmet
38
+ *
39
+ * @param result The instrument (as an item or string) or song (as an effect or string) you want out of this thing
40
+ * @returns Whether we successfully completed the task
41
+ */
42
+ export declare function conduct(result: Item | Instrument | Effect | MarchingSong): boolean;
43
+ /**
44
+ * Plays a given Apriling band instrument
45
+ *
46
+ * @param instrument The instrument to play
47
+ * @param acquire Whether or not we should obtain the instrument if we don't currently have it
48
+ * @returns Whether we successfully played our instrument
49
+ */
50
+ export declare function play(instrument: Instrument | Item, acquire?: boolean): boolean;
51
+ /**
52
+ * Determine whether you can play an instrument
53
+ * @param instrument The instrument you want to play
54
+ * @param acquire Whether you're willing to obtain an instrument you don't already have
55
+ * @returns Whether you can play that instrument
56
+ */
57
+ export declare function canPlay(instrument: Instrument | Item, acquire?: boolean): boolean;
@@ -0,0 +1,118 @@
1
+ import { Effect, Item, myHash, runChoice, toEffect, toItem, totalTurnsPlayed, visitUrl, } from "kolmafia";
2
+ import { have as have_ } from "../../lib";
3
+ import { get } from "../../property";
4
+ import { $item } from "../../template-string";
5
+ import { arrayContains } from "../../utils";
6
+ const helmet = $item `Apriling band helmet`;
7
+ /**
8
+ * @returns whether you `have` the Apriling band helmet
9
+ */
10
+ export function have() {
11
+ return have_(helmet);
12
+ }
13
+ export const MARCHING_SONGS = Object.freeze([
14
+ "Apriling Band Patrol Beat",
15
+ "Apriling Band Battle Cadence",
16
+ "Apriling Band Celebration Bop",
17
+ ]);
18
+ export const MARCHING_SONG_EFFECTS = Object.freeze(MARCHING_SONGS.map((song) => toEffect(song)));
19
+ export const INSTRUMENTS = Object.freeze([
20
+ "Apriling band saxophone",
21
+ "Apriling band quad tom",
22
+ "Apriling band tuba",
23
+ "Apriling band staff",
24
+ "Apriling band piccolo",
25
+ ]);
26
+ export const INSTRUMENT_ITEMS = Object.freeze(INSTRUMENTS.map((instrument) => toItem(instrument)));
27
+ const visitConduct = () => visitUrl("inventory.php?pwd&action=apriling");
28
+ /**
29
+ * @returns Whether we can currently join a new section of our Apriling band
30
+ */
31
+ export function canJoinSection() {
32
+ return have() && get("_aprilBandInstruments") < 2;
33
+ }
34
+ function makeConductFunction(mafiaClass, canDo, set, offset) {
35
+ return (input) => {
36
+ if (!canDo())
37
+ return false;
38
+ const [name, instance] = typeof input === "string"
39
+ ? [input, mafiaClass.get(input)]
40
+ : [input.name, input];
41
+ if (have_(instance))
42
+ return true;
43
+ const key = set.indexOf(name);
44
+ if (key === -1)
45
+ return false;
46
+ visitConduct();
47
+ runChoice(key + offset);
48
+ runChoice(9);
49
+ return have_(instance);
50
+ };
51
+ }
52
+ /**
53
+ * Joins the given section of your Apriling band, returning whether you successfully obtained its instrument
54
+ *
55
+ * @param section The section of your band to join--either the instrument's name as a string, or the item itself.
56
+ *
57
+ * @returns Whether we have the item, at the end of all things
58
+ */
59
+ export const joinSection = makeConductFunction(Item, canJoinSection, INSTRUMENTS, 4);
60
+ /**
61
+ * @returns Whether we can currently change the marching song of our Apriling Band
62
+ */
63
+ export function canChangeSong() {
64
+ return have() && get("nextAprilBandTurn") <= totalTurnsPlayed();
65
+ }
66
+ /**
67
+ * Instructs your Apriling band to play the given song, returning whether it's successfully playing
68
+ *
69
+ * @param song The song for your band to play--either the effect's name or the effect itself.
70
+ *
71
+ * @returns Whether we have the effect, at the end of all things
72
+ */
73
+ export const changeSong = makeConductFunction(Effect, canChangeSong, MARCHING_SONGS, 1);
74
+ /**
75
+ * Conduct your Apriling band helmet
76
+ *
77
+ * @param result The instrument (as an item or string) or song (as an effect or string) you want out of this thing
78
+ * @returns Whether we successfully completed the task
79
+ */
80
+ export function conduct(result) {
81
+ if (result instanceof Item || arrayContains(result, INSTRUMENTS)) {
82
+ return joinSection(result);
83
+ }
84
+ return changeSong(result);
85
+ }
86
+ /**
87
+ * Plays a given Apriling band instrument
88
+ *
89
+ * @param instrument The instrument to play
90
+ * @param acquire Whether or not we should obtain the instrument if we don't currently have it
91
+ * @returns Whether we successfully played our instrument
92
+ */
93
+ export function play(instrument, acquire = false) {
94
+ const item = instrument instanceof Item ? instrument : Item.get(instrument);
95
+ if (!canPlay(instrument, acquire))
96
+ return false;
97
+ if (acquire && !have_(item))
98
+ joinSection(item);
99
+ const currentUsesRemaining = item.dailyusesleft;
100
+ visitUrl(`inventory.php?pwd=${myHash()}&iid=${item.id}&action=aprilplay`, false);
101
+ return item.dailyusesleft !== currentUsesRemaining;
102
+ }
103
+ /**
104
+ * Determine whether you can play an instrument
105
+ * @param instrument The instrument you want to play
106
+ * @param acquire Whether you're willing to obtain an instrument you don't already have
107
+ * @returns Whether you can play that instrument
108
+ */
109
+ export function canPlay(instrument, acquire = false) {
110
+ if (!have())
111
+ return false;
112
+ const item = instrument instanceof Item ? instrument : Item.get(instrument);
113
+ if (!have_(item) && (!acquire || !canJoinSection()))
114
+ return false;
115
+ if (item.dailyusesleft <= 0)
116
+ return false;
117
+ return true;
118
+ }
@@ -0,0 +1,42 @@
1
+ import { Monster, runCombat } from "kolmafia";
2
+ /**
3
+ * @returns Whether you `have` the Chest Mimic familiar.
4
+ */
5
+ export declare function have(): boolean;
6
+ /**
7
+ * @returns List of monsters available for donation at this time
8
+ */
9
+ export declare function getDonableMonsters(): Monster[];
10
+ /**
11
+ * @returns List of monsters available to receive as an egg at this time
12
+ */
13
+ export declare function getReceivableMonsters(): Monster[];
14
+ /**
15
+ * Donate an egg to the DNA bank
16
+ *
17
+ * @param monster The monster whose egg you want to donate
18
+ * @returns Whether we succeeded in our endeavor
19
+ */
20
+ export declare function donate(monster: Monster): boolean;
21
+ /**
22
+ * Receive an egg from the DNA bank
23
+ *
24
+ * @param monster The monster whose egg you want to receive
25
+ * @returns Whether we succeeded in our endeavor
26
+ */
27
+ export declare function receive(monster: Monster): boolean;
28
+ /**
29
+ * Differentiate a Mimic egg into a monster, and fight it!
30
+ *
31
+ * @param monster The monster to differentiate your egg into
32
+ * @param combat Any parameters you'd like to pass to `runCombat`
33
+ * @returns Whether we successfully differentiated our egg
34
+ */
35
+ export declare function differentiate(monster: Monster, ...combat: Parameters<typeof runCombat>): boolean;
36
+ /**
37
+ * Check how many of a monster is available to differentiate into
38
+ *
39
+ * @param monster The monster to differentiate your egg into; may behave weirdly with name collisions
40
+ * @returns How many of a Monster we can differentiate
41
+ */
42
+ export declare function differentiableQuantity(monster: Monster): number;