libram 0.4.1 → 0.4.2

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 (83) hide show
  1. package/dist/Clan.js +268 -485
  2. package/dist/Copier.js +11 -48
  3. package/dist/Dungeon.js +77 -157
  4. package/dist/Kmail.d.ts +3 -1
  5. package/dist/Kmail.js +92 -243
  6. package/dist/Path.js +68 -120
  7. package/dist/ascend.js +153 -172
  8. package/dist/combat.d.ts +84 -0
  9. package/dist/combat.js +294 -387
  10. package/dist/console.js +13 -36
  11. package/dist/diet/index.d.ts +23 -8
  12. package/dist/diet/index.js +320 -426
  13. package/dist/diet/knapsack.d.ts +1 -1
  14. package/dist/diet/knapsack.js +90 -100
  15. package/dist/dungeons/Dreadsylvania.d.ts +4 -0
  16. package/dist/dungeons/Dreadsylvania.js +14 -0
  17. package/dist/dungeons/Dungeon.d.ts +28 -0
  18. package/dist/dungeons/Dungeon.js +99 -0
  19. package/dist/dungeons/Hobopolis.d.ts +4 -0
  20. package/dist/dungeons/Hobopolis.js +14 -0
  21. package/dist/dungeons/SlimeTube.d.ts +4 -0
  22. package/dist/dungeons/SlimeTube.js +14 -0
  23. package/dist/freerun.d.ts +16 -4
  24. package/dist/freerun.js +88 -99
  25. package/dist/index.d.ts +3 -1
  26. package/dist/index.js +21 -300
  27. package/dist/lib.d.ts +2 -0
  28. package/dist/lib.js +264 -515
  29. package/dist/logger.js +23 -63
  30. package/dist/maximize.js +289 -562
  31. package/dist/modifier.js +35 -46
  32. package/dist/modifierTypes.js +8 -22
  33. package/dist/mood.js +220 -531
  34. package/dist/property.d.ts +2 -0
  35. package/dist/property.js +96 -242
  36. package/dist/propertyTypes.d.ts +2 -2
  37. package/dist/propertyTypes.js +1 -0
  38. package/dist/propertyTyping.js +42 -53
  39. package/dist/resources/2007/CandyHearts.d.ts +9 -0
  40. package/dist/resources/2007/CandyHearts.js +24 -0
  41. package/dist/resources/2008/DivineFavors.d.ts +9 -0
  42. package/dist/resources/2008/DivineFavors.js +27 -0
  43. package/dist/resources/2009/Bandersnatch.js +37 -112
  44. package/dist/resources/2009/LoveSongs.d.ts +9 -0
  45. package/dist/resources/2009/LoveSongs.js +24 -0
  46. package/dist/resources/2009/SpookyPutty.js +20 -46
  47. package/dist/resources/2010/Brickos.d.ts +9 -0
  48. package/dist/resources/2010/Brickos.js +21 -0
  49. package/dist/resources/2010/CrownOfThrones.d.ts +9 -0
  50. package/dist/resources/2010/CrownOfThrones.js +550 -374
  51. package/dist/resources/2011/Gygaxian.d.ts +9 -0
  52. package/dist/resources/2011/Gygaxian.js +24 -0
  53. package/dist/resources/2011/ObtuseAngel.js +21 -63
  54. package/dist/resources/2012/RainDoh.js +14 -40
  55. package/dist/resources/2012/Resolutions.d.ts +9 -0
  56. package/dist/resources/2012/Resolutions.js +28 -0
  57. package/dist/resources/2013/Florist.d.ts +1 -0
  58. package/dist/resources/2013/Florist.js +137 -207
  59. package/dist/resources/2013/PulledTaffy.d.ts +9 -0
  60. package/dist/resources/2013/PulledTaffy.js +33 -0
  61. package/dist/resources/2014/WinterGarden.js +15 -43
  62. package/dist/resources/2015/ChateauMantegna.js +52 -86
  63. package/dist/resources/2015/MayoClinic.d.ts +1 -0
  64. package/dist/resources/2015/MayoClinic.js +30 -65
  65. package/dist/resources/2016/SourceTerminal.d.ts +1 -0
  66. package/dist/resources/2016/SourceTerminal.js +114 -237
  67. package/dist/resources/2016/Witchess.js +33 -59
  68. package/dist/resources/2017/TunnelOfLove.js +62 -111
  69. package/dist/resources/2018/SongBoom.js +32 -68
  70. package/dist/resources/2019/BeachComb.js +26 -44
  71. package/dist/resources/2019/Snapper.d.ts +28 -0
  72. package/dist/resources/2019/Snapper.js +70 -0
  73. package/dist/resources/2020/Guzzlr.js +79 -163
  74. package/dist/resources/LibramSummon.d.ts +12 -0
  75. package/dist/resources/LibramSummon.js +66 -0
  76. package/dist/resources/index.d.ts +3 -1
  77. package/dist/resources/index.js +19 -105
  78. package/dist/resources/putty-likes.js +15 -30
  79. package/dist/since.d.ts +1 -0
  80. package/dist/since.js +56 -112
  81. package/dist/template-string.js +40 -132
  82. package/dist/utils.js +36 -134
  83. package/package.json +2 -2
@@ -1,439 +1,333 @@
1
- "use strict";
2
-
3
- require("core-js/modules/es.symbol.js");
4
-
5
- require("core-js/modules/es.symbol.description.js");
6
-
7
- Object.defineProperty(exports, "__esModule", {
8
- value: true
9
- });
10
- exports.planDiet = planDiet;
11
- exports.MenuItem = void 0;
12
-
13
- require("core-js/modules/es.array.map.js");
14
-
15
- require("core-js/modules/es.regexp.exec.js");
16
-
17
- require("core-js/modules/es.string.split.js");
18
-
19
- require("core-js/modules/es.array.iterator.js");
20
-
21
- require("core-js/modules/es.object.to-string.js");
22
-
23
- require("core-js/modules/es.regexp.to-string.js");
24
-
25
- require("core-js/modules/es.array.filter.js");
26
-
27
- require("core-js/modules/es.array.includes.js");
28
-
29
- require("core-js/modules/es.array.sort.js");
30
-
31
- require("core-js/modules/es.string.includes.js");
32
-
33
- require("core-js/modules/es.array.concat.js");
34
-
35
- require("core-js/modules/es.array.slice.js");
36
-
37
- require("core-js/modules/es.array.find.js");
38
-
39
- var _kolmafia = require("kolmafia");
40
-
41
- var _knapsack3 = require("./knapsack");
42
-
43
- var _lib = require("../lib");
44
-
45
- var _templateString = require("../template-string");
46
-
47
- var _utils = require("../utils");
48
-
49
- var _templateObject, _templateObject2, _templateObject3, _templateObject4, _templateObject5, _templateObject6, _templateObject7, _templateObject8, _templateObject9, _templateObject10, _templateObject11, _templateObject12, _templateObject13, _templateObject14, _templateObject15, _templateObject16, _templateObject17, _templateObject18, _templateObject19, _templateObject20;
50
-
51
- function _taggedTemplateLiteral(strings, raw) { if (!raw) { raw = strings.slice(0); } return Object.freeze(Object.defineProperties(strings, { raw: { value: Object.freeze(raw) } })); }
52
-
53
- function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
54
-
55
- function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
56
-
57
- function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
58
-
59
- function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
60
-
61
- function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e2) { throw _e2; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e3) { didErr = true; err = _e3; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
62
-
63
- function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
64
-
65
- function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
66
-
67
- function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); }
68
-
69
- function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }
70
-
71
- function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
72
-
73
- function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
74
-
75
- function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
76
-
77
- function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
78
-
79
- function _iterableToArrayLimit(arr, i) { var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"]; if (_i == null) return; var _arr = []; var _n = true; var _d = false; var _s, _e; try { for (_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }
80
-
81
- function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
82
-
83
- // TODO: Include other consumption modifiers.
84
- function expectedAdventures(item) {
85
- var forkMug = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
86
- if (item.adventures === "") return 0;
87
-
88
- var _item$adventures$spli = item.adventures.split(/[-–—]/).map(s => parseInt(s)),
89
- _item$adventures$spli2 = _slicedToArray(_item$adventures$spli, 2),
90
- min = _item$adventures$spli2[0],
91
- recordedMax = _item$adventures$spli2[1];
92
-
93
- var max = recordedMax !== null && recordedMax !== void 0 ? recordedMax : min;
94
-
95
- var interpolated = _toConsumableArray(new Array(max - min + 1).keys()).map(n => n + min);
96
-
97
- return (0, _utils.sum)(interpolated, n => Math.floor(n * (forkMug ? 1.3 : 1))) / interpolated.length;
98
- } // Assuming list is already sorted, count adjacent items.
99
- // Effectively run-length encoding.
100
-
101
-
102
- function aggregate(list, isEqual) {
103
- var aggregatedList = [];
104
-
105
- var _iterator = _createForOfIteratorHelper(list),
106
- _step;
107
-
108
- try {
109
- for (_iterator.s(); !(_step = _iterator.n()).done;) {
110
- var item = _step.value;
111
-
112
- if (aggregatedList.length === 0) {
113
- aggregatedList.push([item, 1]);
114
- } else {
115
- var last = aggregatedList[aggregatedList.length - 1];
116
-
117
- var _last = _slicedToArray(last, 1),
118
- lastItem = _last[0];
119
-
120
- if (isEqual(item, lastItem)) {
121
- last[1]++;
122
- } else {
123
- aggregatedList.push([item, 1]);
1
+ import { fullnessLimit, getWorkshed, inebrietyLimit, itemType, mallPrice, mallPrices, myFullness, myPrimestat, mySpleenUse, npcPrice, spleenLimit, } from "kolmafia";
2
+ import { knapsack } from "./knapsack";
3
+ import { have } from "../lib";
4
+ import { $effect, $item, $items, $skill, $stat } from "../template-string";
5
+ import { sum } from "../utils";
6
+ // TODO: Include other consumption modifiers - Salty Mouth?
7
+ // TODO: Include Gar-ish etc.
8
+ function expectedAdventures(item, modifiers) {
9
+ if (item.adventures === "")
10
+ return 0;
11
+ const [min, recordedMax] = item.adventures
12
+ .split(/[-–—]/)
13
+ .map((s) => parseInt(s));
14
+ const max = recordedMax ?? min;
15
+ const interpolated = [...new Array(max - min + 1).keys()].map((n) => n + min);
16
+ const forkMugMultiplier = (itemType(item) === "food" && item.notes?.includes("SALAD")) ||
17
+ (itemType(item) === "booze" && item.notes?.includes("BEER"))
18
+ ? 1.5
19
+ : 1.3;
20
+ const refinedPalate = modifiers.refinedPalate && item.notes?.includes("WINE");
21
+ const pinkyRing = modifiers.pinkyRing && item.notes?.includes("WINE");
22
+ return (sum(interpolated, (baseAdventures) => {
23
+ let adventures = baseAdventures;
24
+ if (modifiers.forkMug) {
25
+ adventures = Math.floor(adventures * forkMugMultiplier);
124
26
  }
125
- }
126
- }
127
- } catch (err) {
128
- _iterator.e(err);
129
- } finally {
130
- _iterator.f();
131
- }
132
-
133
- return aggregatedList;
27
+ if (refinedPalate)
28
+ adventures = Math.floor(adventures * 1.25);
29
+ if (pinkyRing)
30
+ adventures = Math.round(adventures * 1.125);
31
+ if (item.notes?.includes("MARTINI") && modifiers.tuxedoShirt) {
32
+ adventures += 2;
33
+ }
34
+ if (have($skill `Saucemaven`) && item.notes?.includes("SAUCY")) {
35
+ adventures += myPrimestat() === $stat `Mysticality` ? 5 : 3;
36
+ }
37
+ if (itemType(item) === "food" && modifiers.seasoning)
38
+ adventures++;
39
+ if (itemType(item) === "food" && modifiers.mayoflex)
40
+ adventures++;
41
+ return adventures;
42
+ }) / interpolated.length);
134
43
  }
135
-
136
- var MenuItem = /*#__PURE__*/function () {
137
- function MenuItem(item, maximum, additionalValue, size) {
138
- _classCallCheck(this, MenuItem);
139
-
140
- _defineProperty(this, "item", void 0);
141
-
142
- _defineProperty(this, "maximum", void 0);
143
-
144
- _defineProperty(this, "additionalValue", void 0);
145
-
146
- _defineProperty(this, "size", void 0);
147
-
148
- this.item = item;
149
- this.maximum = maximum;
150
- this.additionalValue = additionalValue;
151
- var typ = (0, _kolmafia.itemType)(this.item);
152
- this.size = (size !== null && size !== void 0 ? size : typ === "food") ? this.item.fullness : typ === "booze" ? this.item.inebriety : typ === "spleen item" ? this.item.spleen : 0;
153
- }
154
-
155
- _createClass(MenuItem, [{
156
- key: "toString",
157
- value: function toString() {
158
- return this.item.toString();
44
+ export class MenuItem {
45
+ constructor(item, options = {}) {
46
+ const { size, organ, maximum, additionalValue, wishEffect } = {
47
+ ...options,
48
+ ...(MenuItem.defaultOptions.get(item) ?? {}),
49
+ };
50
+ this.item = item;
51
+ this.maximum = maximum === "auto" ? item.dailyusesleft : maximum;
52
+ this.additionalValue = additionalValue;
53
+ this.wishEffect = wishEffect;
54
+ const typ = itemType(this.item);
55
+ this.organ = organ ?? (isOrgan(typ) ? typ : undefined);
56
+ this.size =
57
+ size ??
58
+ (this.organ === "food"
59
+ ? this.item.fullness
60
+ : this.organ === "booze"
61
+ ? this.item.inebriety
62
+ : this.organ === "spleen item"
63
+ ? this.item.spleen
64
+ : 0);
65
+ }
66
+ equals(other) {
67
+ return this.item === other.item && this.wishEffect === other.wishEffect;
159
68
  }
160
- }, {
161
- key: "price",
162
- value: function price() {
163
- return (0, _kolmafia.npcPrice)(this.item) > 0 ? (0, _kolmafia.npcPrice)(this.item) : (0, _kolmafia.mallPrice)(this.item);
69
+ toString() {
70
+ return this.item.toString();
164
71
  }
165
- }]);
166
-
167
- return MenuItem;
168
- }();
169
-
170
- exports.MenuItem = MenuItem;
171
-
172
- _defineProperty(MenuItem, "seasoning", new MenuItem((0, _templateString.$item)(_templateObject17 || (_templateObject17 = _taggedTemplateLiteral(["Special Seasoning"])))));
173
-
174
- _defineProperty(MenuItem, "mayoflex", new MenuItem((0, _templateString.$item)(_templateObject18 || (_templateObject18 = _taggedTemplateLiteral(["Mayoflex"])))));
175
-
176
- _defineProperty(MenuItem, "fork", new MenuItem((0, _templateString.$item)(_templateObject19 || (_templateObject19 = _taggedTemplateLiteral(["Ol' Scratch's salad fork"])))));
177
-
178
- _defineProperty(MenuItem, "mug", new MenuItem((0, _templateString.$item)(_templateObject20 || (_templateObject20 = _taggedTemplateLiteral(["Frosty's frosty mug"])))));
179
-
180
- var DietPlanner = /*#__PURE__*/function () {
181
- function DietPlanner(mpa, menu) {
182
- _classCallCheck(this, DietPlanner);
183
-
184
- _defineProperty(this, "mpa", void 0);
185
-
186
- _defineProperty(this, "menu", void 0);
187
-
188
- _defineProperty(this, "checkFork", void 0);
189
-
190
- _defineProperty(this, "checkMug", void 0);
191
-
192
- _defineProperty(this, "useSeasoning", void 0);
193
-
194
- _defineProperty(this, "useMayoflex", void 0);
195
-
196
- _defineProperty(this, "spleenValue", 0);
197
-
198
- this.mpa = mpa;
199
- this.checkFork = menu.some(item => item.item === MenuItem.fork.item);
200
- this.checkMug = menu.some(item => item.item === MenuItem.mug.item);
201
- this.useSeasoning = menu.some(item => item.item === (0, _templateString.$item)(_templateObject || (_templateObject = _taggedTemplateLiteral(["Special Seasoning"]))));
202
- this.useMayoflex = (0, _kolmafia.getWorkshed)() === (0, _templateString.$item)(_templateObject2 || (_templateObject2 = _taggedTemplateLiteral(["portable Mayo Clinic"]))) && menu.some(item => item.item === (0, _templateString.$item)(_templateObject3 || (_templateObject3 = _taggedTemplateLiteral(["Mayoflex"]))));
203
- this.menu = menu.filter(item => ["food", "booze", "spleen item"].includes((0, _kolmafia.itemType)(item.item)));
204
-
205
- if (menu.length > 100) {
206
- (0, _kolmafia.mallPrices)("food");
207
- (0, _kolmafia.mallPrices)("booze");
72
+ price() {
73
+ return npcPrice(this.item) > 0 ? npcPrice(this.item) : mallPrice(this.item);
208
74
  }
209
-
210
- var spleenItems = menu.filter(item => (0, _kolmafia.itemType)(item.item) === "spleen item");
211
- spleenItems.sort((x, y) => -(this.consumptionValue(x) / x.item.spleen - this.consumptionValue(y) / y.item.spleen));
212
-
213
- if (spleenItems.length > 0) {
214
- this.spleenValue = this.consumptionValue(spleenItems[0]) / spleenItems[0].item.spleen;
75
+ }
76
+ MenuItem.defaultOptions = new Map([
77
+ [$item `Mr. Burnsger`, { maximum: "auto" }],
78
+ [
79
+ $item `distention pill`,
80
+ {
81
+ organ: "food",
82
+ maximum: "auto",
83
+ size: -1,
84
+ },
85
+ ],
86
+ [
87
+ $item `synthetic dog hair pill`,
88
+ { organ: "booze", maximum: "auto", size: -1 },
89
+ ],
90
+ [$item `cuppa Voraci tea`, { organ: "food", maximum: "auto", size: -1 }],
91
+ [$item `cuppa Sobrie tea`, { organ: "booze", maximum: "auto", size: -1 }],
92
+ [$item `mojo filter`, { organ: "spleen item", maximum: "auto", size: -1 }],
93
+ ]);
94
+ const organs = ["food", "booze", "spleen item"];
95
+ function isOrgan(x) {
96
+ return organs.includes(x);
97
+ }
98
+ class DietPlanner {
99
+ constructor(mpa, menu) {
100
+ this.spleenValue = 0;
101
+ this.mpa = mpa;
102
+ this.fork = menu.find((item) => item.item === $item `Ol' Scratch's salad fork`);
103
+ this.mug = menu.find((item) => item.item === $item `Frosty's frosty mug`);
104
+ this.seasoning = menu.find((item) => item.item === $item `Special Seasoning`);
105
+ this.mayoflex =
106
+ getWorkshed() === $item `portable Mayo Clinic`
107
+ ? menu.find((item) => item.item === $item `Mayoflex`)
108
+ : undefined;
109
+ this.pinkyRing = have($item `mafia pinky ring`);
110
+ this.tuxedoShirt = have($item `tuxedo shirt`);
111
+ this.menu = menu.filter((item) => item.organ);
112
+ if (menu.length > 100) {
113
+ mallPrices("food");
114
+ mallPrices("booze");
115
+ }
116
+ const spleenItems = menu.filter((item) => itemType(item.item) === "spleen item");
117
+ spleenItems.sort((x, y) => -(this.consumptionValue(x) / x.item.spleen -
118
+ this.consumptionValue(y) / y.item.spleen));
119
+ if (spleenItems.length > 0) {
120
+ this.spleenValue =
121
+ this.consumptionValue(spleenItems[0]) / spleenItems[0].item.spleen;
122
+ }
215
123
  }
216
- }
217
-
218
- _createClass(DietPlanner, [{
219
- key: "consumptionValue",
220
- value: function consumptionValue(menuItem) {
221
- return this.consumptionHelpersAndValue(menuItem)[1];
124
+ consumptionValue(menuItem) {
125
+ return this.consumptionHelpersAndValue(menuItem, {})[1];
222
126
  }
223
- }, {
224
- key: "consumptionHelpersAndValue",
225
- value: function consumptionHelpersAndValue(menuItem) {
226
- var _menuItem$additionalV, _menuItem$additionalV2;
227
-
228
- var additionalAdventures = 0;
229
- var helpers = [];
230
-
231
- if (this.useMayoflex && (0, _kolmafia.itemType)(menuItem.item) === "food" && this.mpa > (0, _kolmafia.npcPrice)((0, _templateString.$item)(_templateObject4 || (_templateObject4 = _taggedTemplateLiteral(["Mayoflex"]))))) {
232
- helpers.push(MenuItem.mayoflex);
233
- additionalAdventures++;
234
- }
235
-
236
- if (this.useSeasoning && (0, _kolmafia.itemType)(menuItem.item) === "food" && this.mpa > (0, _kolmafia.mallPrice)((0, _templateString.$item)(_templateObject5 || (_templateObject5 = _taggedTemplateLiteral(["Special Seasoning"]))))) {
237
- helpers.push(MenuItem.seasoning);
238
- additionalAdventures++;
239
- }
240
-
241
- var forkMug = (0, _kolmafia.itemType)(menuItem.item) === "food" ? MenuItem.fork : (0, _kolmafia.itemType)(menuItem.item) === "booze" ? MenuItem.mug : null;
242
- var forkMugPrice = forkMug ? forkMug.price() : Infinity;
243
- var valueRaw = (expectedAdventures(menuItem.item, false) + additionalAdventures) * this.mpa - (0, _kolmafia.mallPrice)(menuItem.item) + ((_menuItem$additionalV = menuItem.additionalValue) !== null && _menuItem$additionalV !== void 0 ? _menuItem$additionalV : 0);
244
- var valueForkMug = (expectedAdventures(menuItem.item, true) + additionalAdventures) * this.mpa - (0, _kolmafia.mallPrice)(menuItem.item) - forkMugPrice + ((_menuItem$additionalV2 = menuItem.additionalValue) !== null && _menuItem$additionalV2 !== void 0 ? _menuItem$additionalV2 : 0);
245
- var valueSpleen = (0, _templateString.$items)(_templateObject6 || (_templateObject6 = _taggedTemplateLiteral(["jar of fermented pickle juice, extra-greasy slider"]))).includes(menuItem.item) ? 5 * this.spleenValue : 0;
246
- return forkMug && valueForkMug > valueRaw ? [[].concat(helpers, [forkMug, menuItem]), valueForkMug + valueSpleen] : [[].concat(helpers, [menuItem]), valueRaw + valueSpleen];
127
+ consumptionHelpersAndValue(menuItem, overrideModifiers) {
128
+ const helpers = [];
129
+ if (this.seasoning &&
130
+ itemType(menuItem.item) === "food" &&
131
+ this.mpa > mallPrice($item `Special Seasoning`)) {
132
+ helpers.push(this.seasoning);
133
+ }
134
+ if (this.mayoflex &&
135
+ itemType(menuItem.item) === "food" &&
136
+ this.mpa > npcPrice($item `Mayoflex`)) {
137
+ helpers.push(this.mayoflex);
138
+ }
139
+ const defaultModifiers = {
140
+ forkMug: false,
141
+ seasoning: this.seasoning ? helpers.includes(this.seasoning) : false,
142
+ mayoflex: this.mayoflex ? helpers.includes(this.mayoflex) : false,
143
+ refinedPalate: false,
144
+ pinkyRing: this.pinkyRing,
145
+ tuxedoShirt: this.tuxedoShirt,
146
+ ...overrideModifiers,
147
+ };
148
+ const forkMug = itemType(menuItem.item) === "food"
149
+ ? this.fork
150
+ : itemType(menuItem.item) === "booze"
151
+ ? this.mug
152
+ : null;
153
+ const forkMugPrice = forkMug ? forkMug.price() : Infinity;
154
+ const baseCost = menuItem.price() + sum(helpers, (item) => item.price());
155
+ const valueRaw = expectedAdventures(menuItem.item, defaultModifiers) * this.mpa -
156
+ baseCost +
157
+ (menuItem.additionalValue ?? 0);
158
+ const valueForkMug = expectedAdventures(menuItem.item, {
159
+ ...defaultModifiers,
160
+ forkMug: true,
161
+ }) *
162
+ this.mpa -
163
+ baseCost -
164
+ forkMugPrice +
165
+ (menuItem.additionalValue ?? 0);
166
+ const valueSpleen = $items `jar of fermented pickle juice, extra-greasy slider`.includes(menuItem.item)
167
+ ? 5 * this.spleenValue
168
+ : 0;
169
+ return forkMug && valueForkMug > valueRaw
170
+ ? [[...helpers, forkMug, menuItem], valueForkMug + valueSpleen]
171
+ : [[...helpers, menuItem], valueRaw + valueSpleen];
247
172
  }
248
- }, {
249
- key: "planOrgan",
250
- value: function planOrgan(organ, capacity) {
251
- // print(`Plan ${organ} < ${capacity}`);
252
- var submenu = this.menu.filter(item => (0, _kolmafia.itemType)(item.item) === organ);
253
- var knapsackValues = submenu.map(menuItem => [].concat(_toConsumableArray(this.consumptionHelpersAndValue(menuItem)), [menuItem.size, menuItem.maximum]));
254
-
255
- var _knapsack = (0, _knapsack3.knapsack)(knapsackValues, capacity),
256
- _knapsack2 = _slicedToArray(_knapsack, 2),
257
- value = _knapsack2[0],
258
- menuItemList = _knapsack2[1];
259
-
260
- var itemList = menuItemList.map(menuItems => menuItems.map(menuItem => menuItem.item)); // print(
261
- // `Items: ${itemList.length} ${([] as Item[])
262
- // .concat(...itemList)
263
- // .map((item) => item.name)
264
- // .join(", ")}`
265
- // );
266
-
267
- return [value, aggregate(itemList, (x, y) => x.every((elem, index) => elem === y[index]))];
173
+ planOrgan(organ, capacity, overrideModifiers = {}) {
174
+ // print(`Plan ${organ} < ${capacity}`);
175
+ const submenu = this.menu.filter((item) => item.organ === organ);
176
+ const knapsackValues = submenu.map((menuItem) => [
177
+ ...this.consumptionHelpersAndValue(menuItem, overrideModifiers),
178
+ menuItem.size,
179
+ menuItem.maximum,
180
+ ]);
181
+ return knapsack(knapsackValues, capacity);
182
+ // print(
183
+ // `Items: ${itemList.length} ${([] as Item[])
184
+ // .concat(...itemList)
185
+ // .map((item) => item.name)
186
+ // .join(", ")}`
187
+ // );
268
188
  }
269
- }, {
270
- key: "planOrgans",
271
- value: function planOrgans(organCapacities) {
272
- var _ref5;
273
-
274
- var valuePlans = organCapacities.map(_ref => {
275
- var _ref2 = _slicedToArray(_ref, 2),
276
- organ = _ref2[0],
277
- capacity = _ref2[1];
278
-
279
- return this.planOrgan(organ, capacity);
280
- });
281
- return [(0, _utils.sum)(valuePlans, _ref3 => {
282
- var _ref4 = _slicedToArray(_ref3, 1),
283
- value = _ref4[0];
284
-
285
- return value;
286
- }), (_ref5 = []).concat.apply(_ref5, _toConsumableArray(valuePlans.map(_ref6 => {
287
- var _ref7 = _slicedToArray(_ref6, 2),
288
- plan = _ref7[1];
289
-
290
- return plan;
291
- })))];
189
+ planOrgans(organCapacities, overrideModifiers = {}) {
190
+ const valuePlans = organCapacities.map(([organ, capacity]) => this.planOrgan(organ, capacity, overrideModifiers));
191
+ return [
192
+ sum(valuePlans, ([value]) => value),
193
+ [].concat(...valuePlans.map(([, plan]) => plan)),
194
+ ];
292
195
  }
293
- }, {
294
- key: "planOrgansWithTrials",
295
- value: function planOrgansWithTrials(organCapacities, trialItems) {
296
- if (trialItems.length === 0) {
297
- return this.planOrgans(organCapacities);
298
- }
299
-
300
- var organCapacitiesWithMap = new Map(organCapacities);
301
-
302
- var _trialItems$ = _slicedToArray(trialItems[0], 2),
303
- trialItem = _trialItems$[0],
304
- organSizes = _trialItems$[1]; // print(`TRYING ${trialItem.item.name}`);
305
-
306
-
307
- var _iterator2 = _createForOfIteratorHelper(organSizes),
308
- _step2;
309
-
310
- try {
311
- for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
312
- var _step2$value = _slicedToArray(_step2.value, 2),
313
- organ = _step2$value[0],
314
- size = _step2$value[1];
315
-
316
- var current = organCapacitiesWithMap.get(organ);
317
-
318
- if (current !== undefined) {
319
- organCapacitiesWithMap.set(organ, current - size);
320
- }
196
+ planOrgansWithTrials(organCapacities, trialItems, overrideModifiers = {}) {
197
+ if (trialItems.length === 0) {
198
+ return this.planOrgans(organCapacities, overrideModifiers);
199
+ }
200
+ const organCapacitiesWithMap = new Map(organCapacities);
201
+ const [trialItem, organSizes] = trialItems[0];
202
+ // print(`TRYING ${trialItem.item.name}`);
203
+ for (const [organ, size] of organSizes) {
204
+ const current = organCapacitiesWithMap.get(organ);
205
+ if (current !== undefined) {
206
+ organCapacitiesWithMap.set(organ, current - size);
207
+ }
321
208
  }
322
- } catch (err) {
323
- _iterator2.e(err);
324
- } finally {
325
- _iterator2.f();
326
- }
327
-
328
- var organCapacitiesWith = _toConsumableArray(organCapacitiesWithMap);
329
-
330
- var _this$planOrgansWithT = this.planOrgansWithTrials(organCapacities, trialItems.slice(1)),
331
- _this$planOrgansWithT2 = _slicedToArray(_this$planOrgansWithT, 2),
332
- valueWithout = _this$planOrgansWithT2[0],
333
- planWithout = _this$planOrgansWithT2[1];
334
-
335
- var _this$planOrgansWithT3 = this.planOrgansWithTrials(organCapacitiesWith, trialItems.slice(1)),
336
- _this$planOrgansWithT4 = _slicedToArray(_this$planOrgansWithT3, 2),
337
- valueWith = _this$planOrgansWithT4[0],
338
- planWith = _this$planOrgansWithT4[1];
339
-
340
- var _this$consumptionHelp = this.consumptionHelpersAndValue(trialItem),
341
- _this$consumptionHelp2 = _slicedToArray(_this$consumptionHelp, 2),
342
- helpers = _this$consumptionHelp2[0],
343
- value = _this$consumptionHelp2[1];
344
-
345
- (0, _kolmafia.print)("".concat(new Array(5 - trialItems.length).join(">"), " ").concat(valueWithout > valueWith + value ? "WITHOUT" : "WITH", " ").concat(trialItem.item, " ").concat(value.toFixed(0), ": ").concat(valueWithout.toFixed(0), " vs. ").concat((valueWith + value).toFixed(0)));
346
- return valueWithout > valueWith + value ? [valueWithout, planWithout] : [valueWith, [].concat(_toConsumableArray(planWith), [[helpers.map(menuItem => menuItem.item), 1]])];
209
+ const organCapacitiesWith = [...organCapacitiesWithMap];
210
+ const isRefinedPalate = trialItem.item === $item `pocket wish` &&
211
+ trialItem.wishEffect === $effect `Refined Palate`;
212
+ const [valueWithout, planWithout] = this.planOrgansWithTrials(organCapacities, trialItems.slice(1), overrideModifiers);
213
+ const [valueWith, planWith] = this.planOrgansWithTrials(organCapacitiesWith, trialItems.slice(1), isRefinedPalate
214
+ ? { ...overrideModifiers, refinedPalate: true }
215
+ : overrideModifiers);
216
+ const [helpersAndItem, value] = this.consumptionHelpersAndValue(trialItem, {});
217
+ // print(
218
+ // `${new Array(trialItems.length).join(">")} ${
219
+ // valueWithout > valueWith + value ? "WITHOUT" : "WITH"
220
+ // } ${trialItem.item} ${trialItem.wishEffect ?? ""} ${value.toFixed(
221
+ // 0
222
+ // )}: ${valueWithout.toFixed(0)} vs. ${(valueWith + value).toFixed(0)}`
223
+ // );
224
+ return valueWithout > valueWith + value
225
+ ? [valueWithout, planWithout]
226
+ : [valueWith, [...planWith, [helpersAndItem, 1]]];
347
227
  }
348
- }]);
349
-
350
- return DietPlanner;
351
- }(); // [item, fullness, inebriety]
352
-
353
-
354
- var interactingItems = [[(0, _templateString.$item)(_templateObject7 || (_templateObject7 = _taggedTemplateLiteral(["spice melange"]))), [["food", -3], ["booze", -3]]], [(0, _templateString.$item)(_templateObject8 || (_templateObject8 = _taggedTemplateLiteral(["Ultra Mega Sour Ball"]))), [["food", -3], ["booze", -3]]], [(0, _templateString.$item)(_templateObject9 || (_templateObject9 = _taggedTemplateLiteral(["The Plumber's mushroom stew"]))), [["food", 3], ["booze", -1]]], [(0, _templateString.$item)(_templateObject10 || (_templateObject10 = _taggedTemplateLiteral(["The Mad Liquor"]))), [["food", -1], ["booze", 3]]], [(0, _templateString.$item)(_templateObject11 || (_templateObject11 = _taggedTemplateLiteral(["Doc Clock's thyme cocktail"]))), [["food", -2], ["booze", 4]]], [(0, _templateString.$item)(_templateObject12 || (_templateObject12 = _taggedTemplateLiteral(["Mr. Burnsger"]))), [["food", 4], ["booze", -2]]]];
355
-
356
- function planDiet(mpa, menu) {
357
- var _resolvedOrganCapacit;
358
-
359
- var organCapacities = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : [["food", null], ["booze", null], ["spleen item", null]];
360
- var dietPlanner = new DietPlanner(mpa, menu);
361
- (0, _kolmafia.print)("MENU:");
362
-
363
- var _iterator3 = _createForOfIteratorHelper(menu),
364
- _step3;
365
-
366
- try {
367
- for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
368
- var menuItem = _step3.value;
369
-
370
- var _dietPlanner$consumpt = dietPlanner.consumptionHelpersAndValue(menuItem),
371
- _dietPlanner$consumpt2 = _slicedToArray(_dietPlanner$consumpt, 2),
372
- helpers = _dietPlanner$consumpt2[0],
373
- value = _dietPlanner$consumpt2[1];
374
-
375
- (0, _kolmafia.print)("".concat(menuItem.item.name, ": ").concat(helpers.join(", "), " ").concat(value));
228
+ }
229
+ /**
230
+ * Because the knapsack solver is one-dimensional only, any items that touch
231
+ * multiple organs have to be treated specially. What we do is run the knapsack
232
+ * solver multiple times, trying with + without each interacting item.
233
+ */
234
+ const interactingItems = [
235
+ [
236
+ $item `spice melange`,
237
+ [
238
+ ["food", -3],
239
+ ["booze", -3],
240
+ ],
241
+ ],
242
+ [
243
+ $item `Ultra Mega Sour Ball`,
244
+ [
245
+ ["food", -3],
246
+ ["booze", -3],
247
+ ],
248
+ ],
249
+ [
250
+ $item `The Plumber's mushroom stew`,
251
+ [
252
+ ["food", 3],
253
+ ["booze", -1],
254
+ ],
255
+ ],
256
+ [
257
+ $item `The Mad Liquor`,
258
+ [
259
+ ["food", -1],
260
+ ["booze", 3],
261
+ ],
262
+ ],
263
+ [
264
+ $item `Doc Clock's thyme cocktail`,
265
+ [
266
+ ["food", -2],
267
+ ["booze", 4],
268
+ ],
269
+ ],
270
+ [
271
+ $item `Mr. Burnsger`,
272
+ [
273
+ ["food", 4],
274
+ ["booze", -2],
275
+ ],
276
+ ],
277
+ ];
278
+ /**
279
+ * Plan out an optimal diet using a knapsack algorithm.
280
+ * @param mpa Meat per adventure value.
281
+ * @param menu Array of MenuItems to consider for diet purposes.
282
+ * @param organCapacities Optional override of each organ's capacity.
283
+ * @returns Array of [menu item and helpers, count].
284
+ */
285
+ export function planDiet(mpa, menu, organCapacities = [
286
+ ["food", null],
287
+ ["booze", null],
288
+ ["spleen item", null],
289
+ ]) {
290
+ const dietPlanner = new DietPlanner(mpa, menu);
291
+ // print("MENU:");
292
+ for (const menuItem of menu) {
293
+ const [helpers, value] = dietPlanner.consumptionHelpersAndValue(menuItem, {});
294
+ // print(`${menuItem.item.name}: ${helpers.join(", ")} ${value}`);
295
+ }
296
+ const resolvedOrganCapacities = organCapacities.map(([organ, size]) => [
297
+ organ,
298
+ size ??
299
+ (organ === "food"
300
+ ? fullnessLimit() -
301
+ myFullness() +
302
+ (have($item `distention pill`) ? 1 : 0)
303
+ : organ === "booze"
304
+ ? inebrietyLimit() + (have($item `synthetic dog hair pill`) ? 1 : 0)
305
+ : organ === "spleen item"
306
+ ? spleenLimit() - mySpleenUse()
307
+ : 0),
308
+ ]);
309
+ const allItems = new Map(menu.map((menuItem) => [menuItem.item, menuItem]));
310
+ const includedInteractingItems = interactingItems
311
+ .map(([item, sizes]) => [allItems.get(item), sizes])
312
+ .filter(([menuItem]) => menuItem);
313
+ // print(
314
+ // `included interacting: ${includedInteractingItems
315
+ // .map(([menuItem]) => menuItem.item.name)
316
+ // .join(", ")}`
317
+ // );
318
+ // TODO: support toasted brie.
319
+ // Refined Palate must also be treated as an interacting item, as it's a one-time cost.
320
+ const palateWish = menu.find((menuItem) => menuItem.item === $item `pocket wish` &&
321
+ menuItem.wishEffect === $effect `Refined Palate`);
322
+ if (palateWish) {
323
+ includedInteractingItems.push([palateWish, []]);
376
324
  }
377
- } catch (err) {
378
- _iterator3.e(err);
379
- } finally {
380
- _iterator3.f();
381
- }
382
-
383
- var resolvedOrganCapacities = organCapacities.map(_ref8 => {
384
- var _ref9 = _slicedToArray(_ref8, 2),
385
- organ = _ref9[0],
386
- size = _ref9[1];
387
-
388
- return [organ, size !== null && size !== void 0 ? size : organ === "food" ? (0, _kolmafia.fullnessLimit)() - (0, _kolmafia.myFullness)() + ((0, _lib.have)((0, _templateString.$item)(_templateObject13 || (_templateObject13 = _taggedTemplateLiteral(["distention pill"])))) ? 1 : 0) : organ === "booze" ? (0, _kolmafia.inebrietyLimit)() + ((0, _lib.have)((0, _templateString.$item)(_templateObject14 || (_templateObject14 = _taggedTemplateLiteral(["synthetic dog hair pill"])))) ? 1 : 0) : organ === "spleen item" ? (0, _kolmafia.spleenLimit)() - (0, _kolmafia.mySpleenUse)() : 0];
389
- });
390
- var allItems = new Map(menu.map(menuItem => [menuItem.item, menuItem]));
391
- var includedInteractingItems = interactingItems.map(_ref10 => {
392
- var _ref11 = _slicedToArray(_ref10, 2),
393
- item = _ref11[0],
394
- sizes = _ref11[1];
395
-
396
- return [allItems.get(item), sizes];
397
- }).filter(_ref12 => {
398
- var _ref13 = _slicedToArray(_ref12, 1),
399
- menuItem = _ref13[0];
400
-
401
- return menuItem;
402
- }); // print(
403
- // `included interacting: ${includedInteractingItems
404
- // .map(([menuItem]) => menuItem.item.name)
405
- // .join(", ")}`
406
- // );
407
-
408
- var _dietPlanner$planOrga = dietPlanner.planOrgansWithTrials(resolvedOrganCapacities.filter(_ref14 => {
409
- var _ref15 = _slicedToArray(_ref14, 1),
410
- organ = _ref15[0];
411
-
412
- return ["food", "booze"].includes(organ);
413
- }), includedInteractingItems),
414
- _dietPlanner$planOrga2 = _slicedToArray(_dietPlanner$planOrga, 2),
415
- planFoodBooze = _dietPlanner$planOrga2[1];
416
-
417
- var additionalSpleen = (0, _utils.sum)(planFoodBooze, _ref16 => {
418
- var _ref17 = _slicedToArray(_ref16, 2),
419
- items = _ref17[0],
420
- number = _ref17[1];
421
-
422
- return items.includes((0, _templateString.$item)(_templateObject15 || (_templateObject15 = _taggedTemplateLiteral(["jar of fermented pickle juice"])))) || items.includes((0, _templateString.$item)(_templateObject16 || (_templateObject16 = _taggedTemplateLiteral(["extra-greasy slider"])))) ? 5 * number : 0;
423
- });
424
-
425
- var _ref18 = (_resolvedOrganCapacit = resolvedOrganCapacities.find(_ref20 => {
426
- var _ref21 = _slicedToArray(_ref20, 1),
427
- organ = _ref21[0];
428
-
429
- return organ === "spleen item";
430
- })) !== null && _resolvedOrganCapacit !== void 0 ? _resolvedOrganCapacit : ["spleen item", 0],
431
- _ref19 = _slicedToArray(_ref18, 2),
432
- availableSpleen = _ref19[1];
433
-
434
- var _dietPlanner$planOrga3 = dietPlanner.planOrgan("spleen item", availableSpleen + additionalSpleen),
435
- _dietPlanner$planOrga4 = _slicedToArray(_dietPlanner$planOrga3, 2),
436
- planSpleen = _dietPlanner$planOrga4[1];
437
-
438
- return [].concat(_toConsumableArray(planFoodBooze), _toConsumableArray(planSpleen));
439
- }
325
+ const [, planFoodBooze] = dietPlanner.planOrgansWithTrials(resolvedOrganCapacities.filter(([organ]) => ["food", "booze"].includes(organ)), includedInteractingItems);
326
+ // Count sliders and pickle juice, figure out how much extra spleen we got.
327
+ const additionalSpleen = sum(planFoodBooze, ([items, number]) => items.some((menuItem) => $items `jar of fermented pickle juice, extra-greasy slider`.includes(menuItem.item))
328
+ ? 5 * number
329
+ : 0);
330
+ const [, availableSpleen] = resolvedOrganCapacities.find(([organ]) => organ === "spleen item") ?? ["spleen item", 0];
331
+ const [, planSpleen] = dietPlanner.planOrgan("spleen item", availableSpleen + additionalSpleen);
332
+ return [...planFoodBooze, ...planSpleen];
333
+ }