@robsonbittencourt/calc 0.10.0

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 (144) hide show
  1. package/.eslintignore +2 -0
  2. package/.eslintrc +12 -0
  3. package/bundle +107 -0
  4. package/dist/adaptable.d.ts +6 -0
  5. package/dist/adaptable.js +28 -0
  6. package/dist/adaptable.js.map +1 -0
  7. package/dist/calc.d.ts +6 -0
  8. package/dist/calc.js +26 -0
  9. package/dist/calc.js.map +1 -0
  10. package/dist/data/abilities.d.ts +15 -0
  11. package/dist/data/abilities.js +448 -0
  12. package/dist/data/abilities.js.map +1 -0
  13. package/dist/data/index.d.ts +2 -0
  14. package/dist/data/index.js +30 -0
  15. package/dist/data/index.js.map +1 -0
  16. package/dist/data/interface.d.ts +150 -0
  17. package/dist/data/interface.js +3 -0
  18. package/dist/data/interface.js.map +1 -0
  19. package/dist/data/items.d.ts +24 -0
  20. package/dist/data/items.js +708 -0
  21. package/dist/data/items.js.map +1 -0
  22. package/dist/data/moves.d.ts +86 -0
  23. package/dist/data/moves.js +5014 -0
  24. package/dist/data/moves.js.map +1 -0
  25. package/dist/data/natures.d.ts +17 -0
  26. package/dist/data/natures.js +127 -0
  27. package/dist/data/natures.js.map +1 -0
  28. package/dist/data/production.min.js +1 -0
  29. package/dist/data/species.d.ts +48 -0
  30. package/dist/data/species.js +10126 -0
  31. package/dist/data/species.js.map +1 -0
  32. package/dist/data/types.d.ts +23 -0
  33. package/dist/data/types.js +538 -0
  34. package/dist/data/types.js.map +1 -0
  35. package/dist/desc.d.ts +65 -0
  36. package/dist/desc.js +866 -0
  37. package/dist/desc.js.map +1 -0
  38. package/dist/field.d.ts +49 -0
  39. package/dist/field.js +111 -0
  40. package/dist/field.js.map +1 -0
  41. package/dist/index.d.ts +44 -0
  42. package/dist/index.js +99 -0
  43. package/dist/index.js.map +1 -0
  44. package/dist/items.d.ts +13 -0
  45. package/dist/items.js +434 -0
  46. package/dist/items.js.map +1 -0
  47. package/dist/mechanics/gen12.d.ts +6 -0
  48. package/dist/mechanics/gen12.js +271 -0
  49. package/dist/mechanics/gen12.js.map +1 -0
  50. package/dist/mechanics/gen3.d.ts +11 -0
  51. package/dist/mechanics/gen3.js +371 -0
  52. package/dist/mechanics/gen3.js.map +1 -0
  53. package/dist/mechanics/gen4.d.ts +11 -0
  54. package/dist/mechanics/gen4.js +596 -0
  55. package/dist/mechanics/gen4.js.map +1 -0
  56. package/dist/mechanics/gen56.d.ts +13 -0
  57. package/dist/mechanics/gen56.js +836 -0
  58. package/dist/mechanics/gen56.js.map +1 -0
  59. package/dist/mechanics/gen789.d.ts +14 -0
  60. package/dist/mechanics/gen789.js +1325 -0
  61. package/dist/mechanics/gen789.js.map +1 -0
  62. package/dist/mechanics/util.d.ts +39 -0
  63. package/dist/mechanics/util.js +675 -0
  64. package/dist/mechanics/util.js.map +1 -0
  65. package/dist/move.d.ts +50 -0
  66. package/dist/move.js +324 -0
  67. package/dist/move.js.map +1 -0
  68. package/dist/pokemon.d.ts +55 -0
  69. package/dist/pokemon.js +240 -0
  70. package/dist/pokemon.js.map +1 -0
  71. package/dist/production.min.js +1 -0
  72. package/dist/result.d.ts +34 -0
  73. package/dist/result.js +94 -0
  74. package/dist/result.js.map +1 -0
  75. package/dist/state.d.ts +77 -0
  76. package/dist/state.js +3 -0
  77. package/dist/state.js.map +1 -0
  78. package/dist/stats.d.ts +26 -0
  79. package/dist/stats.js +183 -0
  80. package/dist/stats.js.map +1 -0
  81. package/dist/test/calc.test.d.ts +1 -0
  82. package/dist/test/calc.test.js +1297 -0
  83. package/dist/test/calc.test.js.map +1 -0
  84. package/dist/test/data.test.d.ts +1 -0
  85. package/dist/test/data.test.js +368 -0
  86. package/dist/test/data.test.js.map +1 -0
  87. package/dist/test/gen.d.ts +135 -0
  88. package/dist/test/gen.js +636 -0
  89. package/dist/test/gen.js.map +1 -0
  90. package/dist/test/helper.d.ts +55 -0
  91. package/dist/test/helper.js +174 -0
  92. package/dist/test/helper.js.map +1 -0
  93. package/dist/test/move.test.d.ts +1 -0
  94. package/dist/test/move.test.js +14 -0
  95. package/dist/test/move.test.js.map +1 -0
  96. package/dist/test/pokemon.test.d.ts +1 -0
  97. package/dist/test/pokemon.test.js +102 -0
  98. package/dist/test/pokemon.test.js.map +1 -0
  99. package/dist/test/stats.test.d.ts +1 -0
  100. package/dist/test/stats.test.js +64 -0
  101. package/dist/test/stats.test.js.map +1 -0
  102. package/dist/test/utils.test.d.ts +1 -0
  103. package/dist/test/utils.test.js +19 -0
  104. package/dist/test/utils.test.js.map +1 -0
  105. package/dist/util.d.ts +17 -0
  106. package/dist/util.js +115 -0
  107. package/dist/util.js.map +1 -0
  108. package/jest.config.js +11 -0
  109. package/package.json +40 -0
  110. package/src/adaptable.ts +12 -0
  111. package/src/calc.ts +40 -0
  112. package/src/data/abilities.ts +383 -0
  113. package/src/data/index.ts +36 -0
  114. package/src/data/interface.ts +176 -0
  115. package/src/data/items.ts +632 -0
  116. package/src/data/moves.ts +5028 -0
  117. package/src/data/natures.ts +65 -0
  118. package/src/data/species.ts +10098 -0
  119. package/src/data/types.ts +478 -0
  120. package/src/desc.ts +1063 -0
  121. package/src/field.ts +124 -0
  122. package/src/index.ts +156 -0
  123. package/src/items.ts +423 -0
  124. package/src/mechanics/gen12.ts +297 -0
  125. package/src/mechanics/gen3.ts +444 -0
  126. package/src/mechanics/gen4.ts +702 -0
  127. package/src/mechanics/gen56.ts +1134 -0
  128. package/src/mechanics/gen789.ts +1788 -0
  129. package/src/mechanics/util.ts +676 -0
  130. package/src/move.ts +337 -0
  131. package/src/pokemon.ts +244 -0
  132. package/src/result.ts +106 -0
  133. package/src/state.ts +81 -0
  134. package/src/stats.ts +213 -0
  135. package/src/test/calc.test.ts +1588 -0
  136. package/src/test/data.test.ts +129 -0
  137. package/src/test/gen.ts +514 -0
  138. package/src/test/helper.ts +185 -0
  139. package/src/test/move.test.ts +13 -0
  140. package/src/test/pokemon.test.ts +121 -0
  141. package/src/test/stats.test.ts +84 -0
  142. package/src/test/utils.test.ts +18 -0
  143. package/src/util.ts +153 -0
  144. package/tsconfig.json +10 -0
package/dist/desc.js ADDED
@@ -0,0 +1,866 @@
1
+ "use strict";
2
+ var __read = (this && this.__read) || function (o, n) {
3
+ var m = typeof Symbol === "function" && o[Symbol.iterator];
4
+ if (!m) return o;
5
+ var i = m.call(o), r, ar = [], e;
6
+ try {
7
+ while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
8
+ }
9
+ catch (error) { e = { error: error }; }
10
+ finally {
11
+ try {
12
+ if (r && !r.done && (m = i["return"])) m.call(i);
13
+ }
14
+ finally { if (e) throw e.error; }
15
+ }
16
+ return ar;
17
+ };
18
+ exports.__esModule = true;
19
+ exports.getKOChance = exports.getRecoil = exports.getRecovery = exports.displayMove = exports.display = void 0;
20
+ var result_1 = require("./result");
21
+ var util_1 = require("./util");
22
+ var util_2 = require("./mechanics/util");
23
+ function display(gen, attacker, defender, move, field, damage, rawDesc, notation, err) {
24
+ if (notation === void 0) { notation = '%'; }
25
+ if (err === void 0) { err = true; }
26
+ var _a = __read((0, result_1.damageRange)(damage), 2), minDamage = _a[0], maxDamage = _a[1];
27
+ var min = (typeof minDamage === 'number' ? minDamage : minDamage[0] + minDamage[1]);
28
+ var max = (typeof maxDamage === 'number' ? maxDamage : maxDamage[0] + maxDamage[1]);
29
+ var minDisplay = toDisplay(notation, min, defender.maxHP());
30
+ var maxDisplay = toDisplay(notation, max, defender.maxHP());
31
+ var desc = buildDescription(rawDesc, attacker, defender);
32
+ var damageText = "".concat(min, "-").concat(max, " (").concat(minDisplay, " - ").concat(maxDisplay).concat(notation, ")");
33
+ if (move.category === 'Status' && !move.named('Nature Power'))
34
+ return "".concat(desc, ": ").concat(damageText);
35
+ var koChanceText = getKOChance(gen, attacker, defender, move, field, damage, err).text;
36
+ return koChanceText ? "".concat(desc, ": ").concat(damageText, " -- ").concat(koChanceText) : "".concat(desc, ": ").concat(damageText);
37
+ }
38
+ exports.display = display;
39
+ function displayMove(gen, attacker, defender, move, damage, notation) {
40
+ if (notation === void 0) { notation = '%'; }
41
+ var _a = __read((0, result_1.damageRange)(damage), 2), minDamage = _a[0], maxDamage = _a[1];
42
+ var min = (typeof minDamage === 'number' ? minDamage : minDamage[0] + minDamage[1]);
43
+ var max = (typeof maxDamage === 'number' ? maxDamage : maxDamage[0] + maxDamage[1]);
44
+ var minDisplay = toDisplay(notation, min, defender.maxHP());
45
+ var maxDisplay = toDisplay(notation, max, defender.maxHP());
46
+ var recoveryText = getRecovery(gen, attacker, defender, move, damage, notation).text;
47
+ var recoilText = getRecoil(gen, attacker, defender, move, damage, notation).text;
48
+ return "".concat(minDisplay, " - ").concat(maxDisplay).concat(notation).concat(recoveryText &&
49
+ " (".concat(recoveryText, ")")).concat(recoilText && " (".concat(recoilText, ")"));
50
+ }
51
+ exports.displayMove = displayMove;
52
+ function getRecovery(gen, attacker, defender, move, damage, notation) {
53
+ if (notation === void 0) { notation = '%'; }
54
+ var _a = __read((0, result_1.damageRange)(damage), 2), minDamage = _a[0], maxDamage = _a[1];
55
+ var minD = typeof minDamage === 'number' ? [minDamage] : minDamage;
56
+ var maxD = typeof maxDamage === 'number' ? [maxDamage] : maxDamage;
57
+ var recovery = [0, 0];
58
+ var text = '';
59
+ var ignoresShellBell = gen.num === 3 && move.named('Doom Desire', 'Future Sight');
60
+ if (attacker.hasItem('Shell Bell') && !ignoresShellBell) {
61
+ var max = Math.round(defender.maxHP() / 8);
62
+ for (var i = 0; i < minD.length; i++) {
63
+ recovery[0] += Math.min(Math.round(minD[i] * move.hits / 8), max);
64
+ recovery[1] += Math.min(Math.round(maxD[i] * move.hits / 8), max);
65
+ }
66
+ }
67
+ if (move.named('G-Max Finale')) {
68
+ recovery[0] = recovery[1] = Math.round(attacker.maxHP() / 6);
69
+ }
70
+ if (move.named('Pain Split')) {
71
+ var average = Math.floor((attacker.curHP() + defender.curHP()) / 2);
72
+ recovery[0] = recovery[1] = average - attacker.curHP();
73
+ }
74
+ if (move.drain) {
75
+ var percentHealed = move.drain[0] / move.drain[1];
76
+ var max = Math.round(defender.maxHP() * percentHealed);
77
+ for (var i = 0; i < minD.length; i++) {
78
+ var range = [minD[i], maxD[i]];
79
+ for (var j in recovery) {
80
+ var drained = Math.round(range[j] * percentHealed);
81
+ if (attacker.hasItem('Big Root'))
82
+ drained = Math.trunc(drained * 5324 / 4096);
83
+ recovery[j] += Math.min(drained * move.hits, max);
84
+ }
85
+ }
86
+ }
87
+ if (recovery[1] === 0)
88
+ return { recovery: recovery, text: text };
89
+ var minHealthRecovered = toDisplay(notation, recovery[0], attacker.maxHP());
90
+ var maxHealthRecovered = toDisplay(notation, recovery[1], attacker.maxHP());
91
+ var change = recovery[0] > 0 ? 'recovered' : 'lost';
92
+ text = "".concat(minHealthRecovered, " - ").concat(maxHealthRecovered).concat(notation, " ").concat(change);
93
+ return { recovery: recovery, text: text };
94
+ }
95
+ exports.getRecovery = getRecovery;
96
+ function getRecoil(gen, attacker, defender, move, damage, notation) {
97
+ if (notation === void 0) { notation = '%'; }
98
+ var _a = __read((0, result_1.damageRange)(damage), 2), minDamage = _a[0], maxDamage = _a[1];
99
+ var min = (typeof minDamage === 'number' ? minDamage : minDamage[0] + minDamage[1]) * move.hits;
100
+ var max = (typeof maxDamage === 'number' ? maxDamage : maxDamage[0] + maxDamage[1]) * move.hits;
101
+ var recoil = [0, 0];
102
+ var text = '';
103
+ var damageOverflow = minDamage > defender.curHP() || maxDamage > defender.curHP();
104
+ if (move.recoil) {
105
+ var mod = (move.recoil[0] / move.recoil[1]) * 100;
106
+ var minRecoilDamage = void 0, maxRecoilDamage = void 0;
107
+ if (damageOverflow) {
108
+ minRecoilDamage =
109
+ toDisplay(notation, defender.curHP() * mod, attacker.maxHP(), 100);
110
+ maxRecoilDamage =
111
+ toDisplay(notation, defender.curHP() * mod, attacker.maxHP(), 100);
112
+ }
113
+ else {
114
+ minRecoilDamage = toDisplay(notation, Math.min(min, defender.curHP()) * mod, attacker.maxHP(), 100);
115
+ maxRecoilDamage = toDisplay(notation, Math.min(max, defender.curHP()) * mod, attacker.maxHP(), 100);
116
+ }
117
+ if (!attacker.hasAbility('Rock Head')) {
118
+ recoil = [minRecoilDamage, maxRecoilDamage];
119
+ text = "".concat(minRecoilDamage, " - ").concat(maxRecoilDamage).concat(notation, " recoil damage");
120
+ }
121
+ }
122
+ else if (move.hasCrashDamage) {
123
+ var genMultiplier = gen.num === 2 ? 12.5 : gen.num >= 3 ? 50 : 1;
124
+ var minRecoilDamage = void 0, maxRecoilDamage = void 0;
125
+ if (damageOverflow && gen.num !== 2) {
126
+ minRecoilDamage =
127
+ toDisplay(notation, defender.curHP() * genMultiplier, attacker.maxHP(), 100);
128
+ maxRecoilDamage =
129
+ toDisplay(notation, defender.curHP() * genMultiplier, attacker.maxHP(), 100);
130
+ }
131
+ else {
132
+ minRecoilDamage = toDisplay(notation, Math.min(min, defender.maxHP()) * genMultiplier, attacker.maxHP(), 100);
133
+ maxRecoilDamage = toDisplay(notation, Math.min(max, defender.maxHP()) * genMultiplier, attacker.maxHP(), 100);
134
+ }
135
+ recoil = [minRecoilDamage, maxRecoilDamage];
136
+ switch (gen.num) {
137
+ case 1:
138
+ recoil = toDisplay(notation, 1, attacker.maxHP());
139
+ text = '1hp damage on miss';
140
+ break;
141
+ case 2:
142
+ case 3:
143
+ case 4:
144
+ if (defender.hasType('Ghost')) {
145
+ if (gen.num === 4) {
146
+ var gen4CrashDamage = Math.floor(((defender.maxHP() * 0.5) / attacker.maxHP()) * 100);
147
+ recoil = notation === '%' ? gen4CrashDamage : Math.floor((gen4CrashDamage / 100) * 48);
148
+ text = "".concat(gen4CrashDamage, "% crash damage");
149
+ }
150
+ else {
151
+ recoil = 0;
152
+ text = 'no crash damage on Ghost types';
153
+ }
154
+ }
155
+ else {
156
+ text = "".concat(minRecoilDamage, " - ").concat(maxRecoilDamage).concat(notation, " crash damage on miss");
157
+ }
158
+ break;
159
+ default:
160
+ recoil = notation === '%' ? 24 : 50;
161
+ text = '50% crash damage';
162
+ }
163
+ }
164
+ else if (move.struggleRecoil) {
165
+ recoil = notation === '%' ? 12 : 25;
166
+ text = '25% struggle damage';
167
+ if (gen.num === 4)
168
+ text += ' (rounded down)';
169
+ }
170
+ else if (move.mindBlownRecoil) {
171
+ recoil = notation === '%' ? 24 : 50;
172
+ text = '50% recoil damage';
173
+ }
174
+ return { recoil: recoil, text: text };
175
+ }
176
+ exports.getRecoil = getRecoil;
177
+ function getKOChance(gen, attacker, defender, move, field, damage, err) {
178
+ if (err === void 0) { err = true; }
179
+ damage = combine(damage);
180
+ if (isNaN(damage[0])) {
181
+ (0, util_1.error)(err, 'damage[0] must be a number.');
182
+ return { chance: 0, n: 0, text: '' };
183
+ }
184
+ if (damage[damage.length - 1] === 0) {
185
+ (0, util_1.error)(err, 'damage[damage.length - 1] === 0.');
186
+ return { chance: 0, n: 0, text: '' };
187
+ }
188
+ if (move.timesUsed === undefined)
189
+ move.timesUsed = 1;
190
+ if (move.timesUsedWithMetronome === undefined)
191
+ move.timesUsedWithMetronome = 1;
192
+ if (damage[0] >= defender.maxHP() && move.timesUsed === 1 && move.timesUsedWithMetronome === 1) {
193
+ return { chance: 1, n: 1, text: 'guaranteed OHKO' };
194
+ }
195
+ var hazards = getHazards(gen, defender, field.defenderSide);
196
+ var eot = getEndOfTurn(gen, attacker, defender, move, field);
197
+ var toxicCounter = defender.hasStatus('tox') && !defender.hasAbility('Magic Guard', 'Poison Heal')
198
+ ? defender.toxicCounter : 0;
199
+ var qualifier = move.hits > 1 ? 'approx. ' : '';
200
+ var hazardsText = hazards.texts.length > 0
201
+ ? ' after ' + serializeText(hazards.texts)
202
+ : '';
203
+ var afterText = hazards.texts.length > 0 || eot.texts.length > 0
204
+ ? ' after ' + serializeText(hazards.texts.concat(eot.texts))
205
+ : '';
206
+ var afterTextNoHazards = eot.texts.length > 0 ? ' after ' + serializeText(eot.texts) : '';
207
+ function roundChance(chance) {
208
+ return Math.max(Math.min(Math.round(chance * 1000), 999), 1) / 10;
209
+ }
210
+ function KOChance(chanceWithoutEot, chanceWithEot, n, multipleTurns) {
211
+ if (multipleTurns === void 0) { multipleTurns = false; }
212
+ var KOTurnText = n === 1 ? 'OHKO'
213
+ : (multipleTurns ? "KO in ".concat(n, " turns") : "".concat(n, "HKO"));
214
+ var text = qualifier;
215
+ var chance = undefined;
216
+ if (chanceWithoutEot === undefined || chanceWithEot === undefined) {
217
+ text += "possible ".concat(KOTurnText);
218
+ }
219
+ else if (chanceWithoutEot + chanceWithEot === 0) {
220
+ chance = 0;
221
+ text += 'not a KO';
222
+ }
223
+ else if (chanceWithoutEot === 1) {
224
+ chance = chanceWithoutEot;
225
+ if (qualifier === '')
226
+ text += 'guaranteed ';
227
+ text += "OHKO".concat(hazardsText);
228
+ }
229
+ else if (chanceWithoutEot > 0) {
230
+ chance = chanceWithEot;
231
+ if (chanceWithEot === 1) {
232
+ text += "".concat(roundChance(chanceWithoutEot), "% chance to ").concat(KOTurnText).concat(hazardsText, " ") +
233
+ "(guaranteed ".concat(KOTurnText).concat(afterTextNoHazards, ")");
234
+ }
235
+ else if (chanceWithEot > chanceWithoutEot) {
236
+ text += "".concat(roundChance(chanceWithoutEot), "% chance to ").concat(KOTurnText).concat(hazardsText, " ") +
237
+ "(".concat(qualifier).concat(roundChance(chanceWithEot), "% chance to ") +
238
+ "".concat(KOTurnText).concat(afterTextNoHazards, ")");
239
+ }
240
+ else if (chanceWithoutEot > 0) {
241
+ text += "".concat(roundChance(chanceWithoutEot), "% chance to ").concat(KOTurnText).concat(hazardsText);
242
+ }
243
+ }
244
+ else if (chanceWithoutEot === 0) {
245
+ chance = chanceWithEot;
246
+ if (chanceWithEot === 1) {
247
+ if (qualifier === '')
248
+ text += 'guaranteed ';
249
+ text += "".concat(KOTurnText).concat(afterText);
250
+ }
251
+ else if (chanceWithEot > 0) {
252
+ text += "".concat(roundChance(chanceWithEot), "% chance to ").concat(KOTurnText).concat(afterText);
253
+ }
254
+ }
255
+ return { chance: chance, n: n, text: text };
256
+ }
257
+ if ((move.timesUsed === 1 && move.timesUsedWithMetronome === 1) || move.isZ) {
258
+ var chance = computeKOChance(damage, defender.curHP() - hazards.damage, 0, 1, 1, defender.maxHP(), 0);
259
+ var chanceWithEot = computeKOChance(damage, defender.curHP() - hazards.damage, eot.damage, 1, 1, defender.maxHP(), toxicCounter);
260
+ if (chance + chanceWithEot > 0)
261
+ return KOChance(chance, chanceWithEot, 1);
262
+ if (damage.length === 256) {
263
+ qualifier = 'approx. ';
264
+ }
265
+ for (var i = 2; i <= 4; i++) {
266
+ var chance_1 = computeKOChance(damage, defender.curHP() - hazards.damage, eot.damage, i, 1, defender.maxHP(), toxicCounter);
267
+ if (chance_1 > 0)
268
+ return KOChance(0, chance_1, i);
269
+ }
270
+ for (var i = 5; i <= 9; i++) {
271
+ if (predictTotal(damage[0], eot.damage, i, 1, toxicCounter, defender.maxHP()) >=
272
+ defender.curHP() - hazards.damage) {
273
+ return KOChance(0, 1, i);
274
+ }
275
+ else if (predictTotal(damage[damage.length - 1], eot.damage, i, 1, toxicCounter, defender.maxHP()) >=
276
+ defender.curHP() - hazards.damage) {
277
+ return KOChance(undefined, undefined, i);
278
+ }
279
+ }
280
+ }
281
+ else {
282
+ var chance = computeKOChance(damage, defender.maxHP() - hazards.damage, eot.damage, move.hits || 1, move.timesUsed || 1, defender.maxHP(), toxicCounter);
283
+ if (chance > 0)
284
+ return KOChance(0, chance, move.timesUsed, chance === 1);
285
+ if (predictTotal(damage[0], eot.damage, 1, move.timesUsed, toxicCounter, defender.maxHP()) >=
286
+ defender.curHP() - hazards.damage) {
287
+ return KOChance(0, 1, move.timesUsed, true);
288
+ }
289
+ else if (predictTotal(damage[damage.length - 1], eot.damage, 1, move.timesUsed, toxicCounter, defender.maxHP()) >=
290
+ defender.curHP() - hazards.damage) {
291
+ return KOChance(undefined, undefined, move.timesUsed, true);
292
+ }
293
+ return KOChance(0, 0, move.timesUsed);
294
+ }
295
+ return { chance: 0, n: 0, text: '' };
296
+ }
297
+ exports.getKOChance = getKOChance;
298
+ function combine(damage) {
299
+ if (typeof damage === 'number')
300
+ return [damage];
301
+ if (damage.length > 2) {
302
+ if (damage[0] > damage[damage.length - 1])
303
+ damage = damage.slice().sort();
304
+ return damage;
305
+ }
306
+ if (typeof damage[0] === 'number' && typeof damage[1] === 'number') {
307
+ return [damage[0] + damage[1]];
308
+ }
309
+ var d = damage;
310
+ var combined = [];
311
+ for (var i = 0; i < d[0].length; i++) {
312
+ for (var j = 0; j < d[1].length; j++) {
313
+ combined.push(d[0][i] + d[1][j]);
314
+ }
315
+ }
316
+ return combined.sort();
317
+ }
318
+ var TRAPPING = [
319
+ 'Bind', 'Clamp', 'Fire Spin', 'Infestation', 'Magma Storm', 'Sand Tomb',
320
+ 'Thunder Cage', 'Whirlpool', 'Wrap', 'G-Max Sandblast', 'G-Max Centiferno',
321
+ ];
322
+ function getHazards(gen, defender, defenderSide) {
323
+ var damage = 0;
324
+ var texts = [];
325
+ if (defender.hasItem('Heavy-Duty Boots')) {
326
+ return { damage: damage, texts: texts };
327
+ }
328
+ if (defenderSide.isSR && !defender.hasAbility('Magic Guard', 'Mountaineer')) {
329
+ var rockType = gen.types.get('rock');
330
+ var effectiveness = rockType.effectiveness[defender.types[0]] *
331
+ (defender.types[1] ? rockType.effectiveness[defender.types[1]] : 1);
332
+ damage += Math.floor((effectiveness * defender.maxHP()) / 8);
333
+ texts.push('Stealth Rock');
334
+ }
335
+ if (defenderSide.steelsurge && !defender.hasAbility('Magic Guard', 'Mountaineer')) {
336
+ var steelType = gen.types.get('steel');
337
+ var effectiveness = steelType.effectiveness[defender.types[0]] *
338
+ (defender.types[1] ? steelType.effectiveness[defender.types[1]] : 1);
339
+ damage += Math.floor((effectiveness * defender.maxHP()) / 8);
340
+ texts.push('Steelsurge');
341
+ }
342
+ if (!defender.hasType('Flying') &&
343
+ !defender.hasAbility('Magic Guard', 'Levitate') &&
344
+ !defender.hasItem('Air Balloon')) {
345
+ if (defenderSide.spikes === 1) {
346
+ damage += Math.floor(defender.maxHP() / 8);
347
+ if (gen.num === 2) {
348
+ texts.push('Spikes');
349
+ }
350
+ else {
351
+ texts.push('1 layer of Spikes');
352
+ }
353
+ }
354
+ else if (defenderSide.spikes === 2) {
355
+ damage += Math.floor(defender.maxHP() / 6);
356
+ texts.push('2 layers of Spikes');
357
+ }
358
+ else if (defenderSide.spikes === 3) {
359
+ damage += Math.floor(defender.maxHP() / 4);
360
+ texts.push('3 layers of Spikes');
361
+ }
362
+ }
363
+ if (isNaN(damage)) {
364
+ damage = 0;
365
+ }
366
+ return { damage: damage, texts: texts };
367
+ }
368
+ function getEndOfTurn(gen, attacker, defender, move, field) {
369
+ var damage = 0;
370
+ var texts = [];
371
+ if (field.hasWeather('Sun', 'Harsh Sunshine')) {
372
+ if (defender.hasAbility('Dry Skin', 'Solar Power')) {
373
+ damage -= Math.floor(defender.maxHP() / 8);
374
+ texts.push(defender.ability + ' damage');
375
+ }
376
+ }
377
+ else if (field.hasWeather('Rain', 'Heavy Rain')) {
378
+ if (defender.hasAbility('Dry Skin')) {
379
+ damage += Math.floor(defender.maxHP() / 8);
380
+ texts.push('Dry Skin recovery');
381
+ }
382
+ else if (defender.hasAbility('Rain Dish')) {
383
+ damage += Math.floor(defender.maxHP() / 16);
384
+ texts.push('Rain Dish recovery');
385
+ }
386
+ }
387
+ else if (field.hasWeather('Sand')) {
388
+ if (!defender.hasType('Rock', 'Ground', 'Steel') &&
389
+ !defender.hasAbility('Magic Guard', 'Overcoat', 'Sand Force', 'Sand Rush', 'Sand Veil') &&
390
+ !defender.hasItem('Safety Goggles')) {
391
+ damage -= Math.floor(defender.maxHP() / (gen.num === 2 ? 8 : 16));
392
+ texts.push('sandstorm damage');
393
+ }
394
+ }
395
+ else if (field.hasWeather('Hail', 'Snow')) {
396
+ if (defender.hasAbility('Ice Body')) {
397
+ damage += Math.floor(defender.maxHP() / 16);
398
+ texts.push('Ice Body recovery');
399
+ }
400
+ else if (!defender.hasType('Ice') &&
401
+ !defender.hasAbility('Magic Guard', 'Overcoat', 'Snow Cloak') &&
402
+ !defender.hasItem('Safety Goggles') &&
403
+ field.hasWeather('Hail')) {
404
+ damage -= Math.floor(defender.maxHP() / 16);
405
+ texts.push('hail damage');
406
+ }
407
+ }
408
+ var loseItem = move.named('Knock Off') && !defender.hasAbility('Sticky Hold');
409
+ if (defender.hasItem('Leftovers') && !loseItem) {
410
+ damage += Math.floor(defender.maxHP() / 16);
411
+ texts.push('Leftovers recovery');
412
+ }
413
+ else if (defender.hasItem('Black Sludge') && !loseItem) {
414
+ if (defender.hasType('Poison')) {
415
+ damage += Math.floor(defender.maxHP() / 16);
416
+ texts.push('Black Sludge recovery');
417
+ }
418
+ else if (!defender.hasAbility('Magic Guard', 'Klutz')) {
419
+ damage -= Math.floor(defender.maxHP() / 8);
420
+ texts.push('Black Sludge damage');
421
+ }
422
+ }
423
+ else if (defender.hasItem('Sticky Barb')) {
424
+ damage -= Math.floor(defender.maxHP() / 8);
425
+ texts.push('Sticky Barb damage');
426
+ }
427
+ if (field.defenderSide.isSeeded) {
428
+ if (!defender.hasAbility('Magic Guard')) {
429
+ damage -= Math.floor(defender.maxHP() / (gen.num >= 2 ? 8 : 16));
430
+ texts.push('Leech Seed damage');
431
+ }
432
+ }
433
+ if (field.attackerSide.isSeeded && !attacker.hasAbility('Magic Guard')) {
434
+ var recovery = Math.floor(attacker.maxHP() / (gen.num >= 2 ? 8 : 16));
435
+ if (defender.hasItem('Big Root'))
436
+ recovery = Math.trunc(recovery * 5324 / 4096);
437
+ if (attacker.hasAbility('Liquid Ooze')) {
438
+ damage -= recovery;
439
+ texts.push('Liquid Ooze damage');
440
+ }
441
+ else {
442
+ damage += recovery;
443
+ texts.push('Leech Seed recovery');
444
+ }
445
+ }
446
+ if (field.hasTerrain('Grassy')) {
447
+ if ((0, util_2.isGrounded)(defender, field)) {
448
+ damage += Math.floor(defender.maxHP() / 16);
449
+ texts.push('Grassy Terrain recovery');
450
+ }
451
+ }
452
+ if (defender.hasStatus('psn')) {
453
+ if (defender.hasAbility('Poison Heal')) {
454
+ damage += Math.floor(defender.maxHP() / 8);
455
+ texts.push('Poison Heal');
456
+ }
457
+ else if (!defender.hasAbility('Magic Guard')) {
458
+ damage -= Math.floor(defender.maxHP() / (gen.num === 1 ? 16 : 8));
459
+ texts.push('poison damage');
460
+ }
461
+ }
462
+ else if (defender.hasStatus('tox')) {
463
+ if (defender.hasAbility('Poison Heal')) {
464
+ damage += Math.floor(defender.maxHP() / 8);
465
+ texts.push('Poison Heal');
466
+ }
467
+ else if (!defender.hasAbility('Magic Guard')) {
468
+ texts.push('toxic damage');
469
+ }
470
+ }
471
+ else if (defender.hasStatus('brn')) {
472
+ if (defender.hasAbility('Heatproof')) {
473
+ damage -= Math.floor(defender.maxHP() / (gen.num > 6 ? 32 : 16));
474
+ texts.push('reduced burn damage');
475
+ }
476
+ else if (!defender.hasAbility('Magic Guard')) {
477
+ damage -= Math.floor(defender.maxHP() / (gen.num === 1 || gen.num > 6 ? 16 : 8));
478
+ texts.push('burn damage');
479
+ }
480
+ }
481
+ else if ((defender.hasStatus('slp') || defender.hasAbility('Comatose')) &&
482
+ attacker.hasAbility('isBadDreams') &&
483
+ !defender.hasAbility('Magic Guard')) {
484
+ damage -= Math.floor(defender.maxHP() / 8);
485
+ texts.push('Bad Dreams');
486
+ }
487
+ if (!defender.hasAbility('Magic Guard') && TRAPPING.includes(move.name)) {
488
+ if (attacker.hasItem('Binding Band')) {
489
+ damage -= gen.num > 5 ? Math.floor(defender.maxHP() / 6) : Math.floor(defender.maxHP() / 8);
490
+ texts.push('trapping damage');
491
+ }
492
+ else {
493
+ damage -= gen.num > 5 ? Math.floor(defender.maxHP() / 8) : Math.floor(defender.maxHP() / 16);
494
+ texts.push('trapping damage');
495
+ }
496
+ }
497
+ if (defender.isSaltCure && !defender.hasAbility('Magic Guard')) {
498
+ var isWaterOrSteel = defender.hasType('Water', 'Steel') ||
499
+ (defender.teraType && ['Water', 'Steel'].includes(defender.teraType));
500
+ damage -= Math.floor(defender.maxHP() / (isWaterOrSteel ? 4 : 8));
501
+ texts.push('Salt Cure');
502
+ }
503
+ if (!defender.hasType('Fire') && !defender.hasAbility('Magic Guard') &&
504
+ (move.named('Fire Pledge (Grass Pledge Boosted)', 'Grass Pledge (Fire Pledge Boosted)'))) {
505
+ damage -= Math.floor(defender.maxHP() / 8);
506
+ texts.push('Sea of Fire damage');
507
+ }
508
+ if (!defender.hasAbility('Magic Guard') && !defender.hasType('Grass') &&
509
+ (field.defenderSide.vinelash || move.named('G-Max Vine Lash'))) {
510
+ damage -= Math.floor(defender.maxHP() / 6);
511
+ texts.push('Vine Lash damage');
512
+ }
513
+ if (!defender.hasAbility('Magic Guard') && !defender.hasType('Fire') &&
514
+ (field.defenderSide.wildfire || move.named('G-Max Wildfire'))) {
515
+ damage -= Math.floor(defender.maxHP() / 6);
516
+ texts.push('Wildfire damage');
517
+ }
518
+ if (!defender.hasAbility('Magic Guard') && !defender.hasType('Water') &&
519
+ (field.defenderSide.cannonade || move.named('G-Max Cannonade'))) {
520
+ damage -= Math.floor(defender.maxHP() / 6);
521
+ texts.push('Cannonade damage');
522
+ }
523
+ if (!defender.hasAbility('Magic Guard') && !defender.hasType('Rock') &&
524
+ (field.defenderSide.volcalith || move.named('G-Max Volcalith'))) {
525
+ damage -= Math.floor(defender.maxHP() / 6);
526
+ texts.push('Volcalith damage');
527
+ }
528
+ return { damage: damage, texts: texts };
529
+ }
530
+ function computeKOChance(damage, hp, eot, hits, timesUsed, maxHP, toxicCounter) {
531
+ var toxicDamage = 0;
532
+ if (toxicCounter > 0) {
533
+ toxicDamage = Math.floor((toxicCounter * maxHP) / 16);
534
+ toxicCounter++;
535
+ }
536
+ var n = damage.length;
537
+ if (hits === 1) {
538
+ if (eot - toxicDamage > 0) {
539
+ eot = 0;
540
+ toxicDamage = 0;
541
+ }
542
+ for (var i = 0; i < n; i++) {
543
+ if (damage[n - 1] - eot + toxicDamage < hp)
544
+ return 0;
545
+ if (damage[i] - eot + toxicDamage >= hp) {
546
+ return (n - i) / n;
547
+ }
548
+ }
549
+ }
550
+ var sum = 0;
551
+ var lastc = 0;
552
+ for (var i = 0; i < n; i++) {
553
+ var c = void 0;
554
+ if (i === 0 || damage[i] !== damage[i - 1]) {
555
+ c = computeKOChance(damage, hp - damage[i] + eot - toxicDamage, eot, hits - 1, timesUsed, maxHP, toxicCounter);
556
+ }
557
+ else {
558
+ c = lastc;
559
+ }
560
+ if (c === 1) {
561
+ sum += n - i;
562
+ break;
563
+ }
564
+ else {
565
+ sum += c;
566
+ }
567
+ lastc = c;
568
+ }
569
+ return sum / n;
570
+ }
571
+ function predictTotal(damage, eot, hits, timesUsed, toxicCounter, maxHP) {
572
+ var toxicDamage = 0;
573
+ var lastTurnEot = eot;
574
+ if (toxicCounter > 0) {
575
+ for (var i = 0; i < hits - 1; i++) {
576
+ toxicDamage += Math.floor(((toxicCounter + i) * maxHP) / 16);
577
+ }
578
+ lastTurnEot -= Math.floor(((toxicCounter + (hits - 1)) * maxHP) / 16);
579
+ }
580
+ var total = 0;
581
+ if (hits > 1 && timesUsed === 1) {
582
+ total = damage * hits - eot * (hits - 1) + toxicDamage;
583
+ }
584
+ else {
585
+ total = damage - eot * (hits - 1) + toxicDamage;
586
+ }
587
+ if (lastTurnEot < 0)
588
+ total -= lastTurnEot;
589
+ return total;
590
+ }
591
+ function squashMultihit(gen, d, hits, err) {
592
+ if (err === void 0) { err = true; }
593
+ if (d.length === 1) {
594
+ return [d[0] * hits];
595
+ }
596
+ else if (gen.num === 1) {
597
+ var r = [];
598
+ for (var i = 0; i < d.length; i++) {
599
+ r[i] = d[i] * hits;
600
+ }
601
+ return r;
602
+ }
603
+ else if (d.length === 16) {
604
+ switch (hits) {
605
+ case 2:
606
+ return [
607
+ 2 * d[0], d[2] + d[3], d[4] + d[4], d[4] + d[5], d[5] + d[6], d[6] + d[6],
608
+ d[6] + d[7], d[7] + d[7], d[8] + d[8], d[8] + d[9], d[9] + d[9], d[9] + d[10],
609
+ d[10] + d[11], d[11] + d[11], d[12] + d[13], 2 * d[15],
610
+ ];
611
+ case 3:
612
+ return [
613
+ 3 * d[0], d[3] + d[3] + d[4], d[4] + d[4] + d[5], d[5] + d[5] + d[6],
614
+ d[5] + d[6] + d[6], d[6] + d[6] + d[7], d[6] + d[7] + d[7], d[7] + d[7] + d[8],
615
+ d[7] + d[8] + d[8], d[8] + d[8] + d[9], d[8] + d[9] + d[9], d[9] + d[9] + d[10],
616
+ d[9] + d[10] + d[10], d[10] + d[11] + d[11], d[11] + d[12] + d[12], 3 * d[15],
617
+ ];
618
+ case 4:
619
+ return [
620
+ 4 * d[0], 4 * d[4], d[4] + d[5] + d[5] + d[5], d[5] + d[5] + d[6] + d[6],
621
+ 4 * d[6], d[6] + d[6] + d[7] + d[7], 4 * d[7], d[7] + d[7] + d[7] + d[8],
622
+ d[7] + d[8] + d[8] + d[8], 4 * d[8], d[8] + d[8] + d[9] + d[9], 4 * d[9],
623
+ d[9] + d[9] + d[10] + d[10], d[10] + d[10] + d[10] + d[11], 4 * d[11], 4 * d[15],
624
+ ];
625
+ case 5:
626
+ return [
627
+ 5 * d[0], d[4] + d[4] + d[4] + d[5] + d[5], d[5] + d[5] + d[5] + d[5] + d[6],
628
+ d[5] + d[6] + d[6] + d[6] + d[6], d[6] + d[6] + d[6] + d[6] + d[7],
629
+ d[6] + d[6] + d[7] + d[7] + d[7], 5 * d[7], d[7] + d[7] + d[7] + d[8] + d[8],
630
+ d[7] + d[7] + d[8] + d[8] + d[8], 5 * d[8], d[8] + d[8] + d[8] + d[9] + d[9],
631
+ d[8] + d[9] + d[9] + d[9] + d[9], d[9] + d[9] + d[9] + d[9] + d[10],
632
+ d[9] + d[10] + d[10] + d[10] + d[10], d[10] + d[10] + d[11] + d[11] + d[11], 5 * d[15],
633
+ ];
634
+ case 10:
635
+ return [
636
+ 10 * d[0], 10 * d[4], 3 * d[4] + 7 * d[5], 5 * d[5] + 5 * d[6], 10 * d[6],
637
+ 5 * d[6] + 5 * d[7], 10 * d[7], 7 * d[7] + 3 * d[8], 3 * d[7] + 7 * d[8], 10 * d[8],
638
+ 5 * d[8] + 5 * d[9], 4 * d[9], 5 * d[9] + 5 * d[10], 7 * d[10] + 3 * d[11], 10 * d[11],
639
+ 10 * d[15],
640
+ ];
641
+ default:
642
+ (0, util_1.error)(err, "Unexpected # of hits: ".concat(hits));
643
+ return d;
644
+ }
645
+ }
646
+ else if (d.length === 39) {
647
+ switch (hits) {
648
+ case 2:
649
+ return [
650
+ 2 * d[0], 2 * d[7], 2 * d[10], 2 * d[12], 2 * d[14], d[15] + d[16],
651
+ 2 * d[17], d[18] + d[19], d[19] + d[20], 2 * d[21], d[22] + d[23],
652
+ 2 * d[24], 2 * d[26], 2 * d[28], 2 * d[31], 2 * d[38],
653
+ ];
654
+ case 3:
655
+ return [
656
+ 3 * d[0], 3 * d[9], 3 * d[12], 3 * d[13], 3 * d[15], 3 * d[16],
657
+ 3 * d[17], 3 * d[18], 3 * d[20], 3 * d[21], 3 * d[22], 3 * d[23],
658
+ 3 * d[25], 3 * d[26], 3 * d[29], 3 * d[38],
659
+ ];
660
+ case 4:
661
+ return [
662
+ 4 * d[0], 2 * d[10] + 2 * d[11], 4 * d[13], 4 * d[14], 2 * d[15] + 2 * d[16],
663
+ 2 * d[16] + 2 * d[17], 2 * d[17] + 2 * d[18], 2 * d[18] + 2 * d[19],
664
+ 2 * d[19] + 2 * d[20], 2 * d[20] + 2 * d[21], 2 * d[21] + 2 * d[22],
665
+ 2 * d[22] + 2 * d[23], 4 * d[24], 4 * d[25], 2 * d[27] + 2 * d[28], 4 * d[38],
666
+ ];
667
+ case 5:
668
+ return [
669
+ 5 * d[0], 5 * d[11], 5 * d[13], 5 * d[15], 5 * d[16], 5 * d[17],
670
+ 5 * d[18], 5 * d[19], 5 * d[19], 5 * d[20], 5 * d[21], 5 * d[22],
671
+ 5 * d[23], 5 * d[25], 5 * d[27], 5 * d[38],
672
+ ];
673
+ case 10:
674
+ return [
675
+ 10 * d[0], 10 * d[11], 10 * d[13], 10 * d[15], 10 * d[16], 10 * d[17],
676
+ 10 * d[18], 10 * d[19], 10 * d[19], 10 * d[20], 10 * d[21], 10 * d[22],
677
+ 10 * d[23], 10 * d[25], 10 * d[27], 10 * d[38],
678
+ ];
679
+ default:
680
+ (0, util_1.error)(err, "Unexpected # of hits: ".concat(hits));
681
+ return d;
682
+ }
683
+ }
684
+ else if (d.length === 256) {
685
+ if (hits > 1) {
686
+ (0, util_1.error)(err, "Unexpected # of hits for Parental Bond: ".concat(hits));
687
+ }
688
+ var r = [];
689
+ for (var i = 0; i < 16; i++) {
690
+ var val = 0;
691
+ for (var j = 0; j < 16; j++) {
692
+ val += d[i + j];
693
+ }
694
+ r[i] = Math.round(val / 16);
695
+ }
696
+ return r;
697
+ }
698
+ else {
699
+ (0, util_1.error)(err, "Unexpected # of possible damage values: ".concat(d.length));
700
+ return d;
701
+ }
702
+ }
703
+ function buildDescription(description, attacker, defender) {
704
+ var _a = __read(getDescriptionLevels(attacker, defender), 2), attackerLevel = _a[0], defenderLevel = _a[1];
705
+ var output = '';
706
+ if (description.attackBoost) {
707
+ if (description.attackBoost > 0) {
708
+ output += '+';
709
+ }
710
+ output += description.attackBoost + ' ';
711
+ }
712
+ output = appendIfSet(output, attackerLevel);
713
+ output = appendIfSet(output, description.attackEVs);
714
+ output = appendIfSet(output, description.attackerItem);
715
+ output = appendIfSet(output, description.attackerAbility);
716
+ output = appendIfSet(output, description.rivalry);
717
+ if (description.isBurned) {
718
+ output += 'burned ';
719
+ }
720
+ if (description.alliesFainted) {
721
+ output += Math.min(5, description.alliesFainted) +
722
+ " ".concat(description.alliesFainted === 1 ? 'ally' : 'allies', " fainted ");
723
+ }
724
+ if (description.attackerTera) {
725
+ output += "Tera ".concat(description.attackerTera, " ");
726
+ }
727
+ if (description.isStellarFirstUse) {
728
+ output += '(First Use) ';
729
+ }
730
+ if (description.isBeadsOfRuin) {
731
+ output += 'Beads of Ruin ';
732
+ }
733
+ if (description.isSwordOfRuin) {
734
+ output += 'Sword of Ruin ';
735
+ }
736
+ output += description.attackerName + ' ';
737
+ if (description.isHelpingHand) {
738
+ output += 'Helping Hand ';
739
+ }
740
+ if (description.isFlowerGiftAttacker) {
741
+ output += 'with an ally\'s Flower Gift ';
742
+ }
743
+ if (description.isSteelySpiritAttacker) {
744
+ output += 'with an ally\'s Steely Spirit ';
745
+ }
746
+ if (description.isBattery) {
747
+ output += 'Battery boosted ';
748
+ }
749
+ if (description.isPowerSpot) {
750
+ output += 'Power Spot boosted ';
751
+ }
752
+ if (description.isSwitching) {
753
+ output += 'switching boosted ';
754
+ }
755
+ output += description.moveName + ' ';
756
+ if (description.moveBP && description.moveType) {
757
+ output += '(' + description.moveBP + ' BP ' + description.moveType + ') ';
758
+ }
759
+ else if (description.moveBP) {
760
+ output += '(' + description.moveBP + ' BP) ';
761
+ }
762
+ else if (description.moveType) {
763
+ output += '(' + description.moveType + ') ';
764
+ }
765
+ if (description.hits) {
766
+ output += '(' + description.hits + ' hits) ';
767
+ }
768
+ output = appendIfSet(output, description.moveTurns);
769
+ output += 'vs. ';
770
+ if (description.defenseBoost) {
771
+ if (description.defenseBoost > 0) {
772
+ output += '+';
773
+ }
774
+ output += description.defenseBoost + ' ';
775
+ }
776
+ output = appendIfSet(output, defenderLevel);
777
+ output = appendIfSet(output, description.HPEVs);
778
+ if (description.defenseEVs) {
779
+ output += '/ ' + description.defenseEVs + ' ';
780
+ }
781
+ output = appendIfSet(output, description.defenderItem);
782
+ output = appendIfSet(output, description.defenderAbility);
783
+ if (description.isTabletsOfRuin) {
784
+ output += 'Tablets of Ruin ';
785
+ }
786
+ if (description.isVesselOfRuin) {
787
+ output += 'Vessel of Ruin ';
788
+ }
789
+ if (description.isProtected) {
790
+ output += 'protected ';
791
+ }
792
+ if (description.isDefenderDynamaxed) {
793
+ output += 'Dynamax ';
794
+ }
795
+ if (description.defenderTera) {
796
+ output += "Tera ".concat(description.defenderTera, " ");
797
+ }
798
+ output += description.defenderName;
799
+ if (description.weather && description.terrain) {
800
+ }
801
+ else if (description.weather) {
802
+ output += ' in ' + description.weather;
803
+ }
804
+ else if (description.terrain) {
805
+ output += ' in ' + description.terrain + ' Terrain';
806
+ }
807
+ if (description.isReflect) {
808
+ output += ' through Reflect';
809
+ }
810
+ else if (description.isLightScreen) {
811
+ output += ' through Light Screen';
812
+ }
813
+ if (description.isFlowerGiftDefender) {
814
+ output += ' with an ally\'s Flower Gift';
815
+ }
816
+ if (description.isFriendGuard) {
817
+ output += ' with an ally\'s Friend Guard';
818
+ }
819
+ if (description.isAuroraVeil) {
820
+ output += ' with an ally\'s Aurora Veil';
821
+ }
822
+ if (description.isCritical) {
823
+ output += ' on a critical hit';
824
+ }
825
+ if (description.isWonderRoom) {
826
+ output += ' in Wonder Room';
827
+ }
828
+ return output;
829
+ }
830
+ function getDescriptionLevels(attacker, defender) {
831
+ if (attacker.level !== defender.level) {
832
+ return [
833
+ attacker.level === 100 ? '' : "Lvl ".concat(attacker.level),
834
+ defender.level === 100 ? '' : "Lvl ".concat(defender.level),
835
+ ];
836
+ }
837
+ var elide = [100, 50, 5].includes(attacker.level);
838
+ var level = elide ? '' : "Lvl ".concat(attacker.level);
839
+ return [level, level];
840
+ }
841
+ function serializeText(arr) {
842
+ if (arr.length === 0) {
843
+ return '';
844
+ }
845
+ else if (arr.length === 1) {
846
+ return arr[0];
847
+ }
848
+ else if (arr.length === 2) {
849
+ return arr[0] + ' and ' + arr[1];
850
+ }
851
+ else {
852
+ var text = '';
853
+ for (var i = 0; i < arr.length - 1; i++) {
854
+ text += arr[i] + ', ';
855
+ }
856
+ return text + 'and ' + arr[arr.length - 1];
857
+ }
858
+ }
859
+ function appendIfSet(str, toAppend) {
860
+ return toAppend ? "".concat(str).concat(toAppend, " ") : str;
861
+ }
862
+ function toDisplay(notation, a, b, f) {
863
+ if (f === void 0) { f = 1; }
864
+ return notation === '%' ? Math.floor((a * (1000 / f)) / b) / 10 : Math.floor((a * (48 / f)) / b);
865
+ }
866
+ //# sourceMappingURL=desc.js.map