@firestone-hs/simulate-bgs-battle 1.1.726 → 1.1.727

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 (109) hide show
  1. package/dist/bgs-battle-info.d.ts +1 -0
  2. package/dist/bgs-battle-info.js.map +1 -1
  3. package/dist/bgs-battle-options.d.ts +1 -0
  4. package/dist/bgs-battle-options.js.map +1 -1
  5. package/dist/cards/impl/_card-mappings.js +36 -0
  6. package/dist/cards/impl/_card-mappings.js.map +1 -1
  7. package/dist/cards/impl/hero-power/die-insects.d.ts +2 -0
  8. package/dist/cards/impl/hero-power/die-insects.js +21 -0
  9. package/dist/cards/impl/hero-power/die-insects.js.map +1 -0
  10. package/dist/cards/impl/hero-power/fire-the-cannons.d.ts +2 -0
  11. package/dist/cards/impl/hero-power/fire-the-cannons.js +21 -0
  12. package/dist/cards/impl/hero-power/fire-the-cannons.js.map +1 -0
  13. package/dist/cards/impl/hero-power/murloc-king-enchantment.d.ts +2 -0
  14. package/dist/cards/impl/hero-power/murloc-king-enchantment.js +9 -0
  15. package/dist/cards/impl/hero-power/murloc-king-enchantment.js.map +1 -0
  16. package/dist/cards/impl/hero-power/murloc-king.d.ts +2 -0
  17. package/dist/cards/impl/hero-power/murloc-king.js +24 -0
  18. package/dist/cards/impl/hero-power/murloc-king.js.map +1 -0
  19. package/dist/cards/impl/hero-power/nefarious-fire.d.ts +2 -0
  20. package/dist/cards/impl/hero-power/nefarious-fire.js +19 -0
  21. package/dist/cards/impl/hero-power/nefarious-fire.js.map +1 -0
  22. package/dist/cards/impl/hero-power/wax-warband.js +5 -1
  23. package/dist/cards/impl/hero-power/wax-warband.js.map +1 -1
  24. package/dist/cards/impl/minion/arfus.d.ts +2 -0
  25. package/dist/cards/impl/minion/arfus.js +17 -0
  26. package/dist/cards/impl/minion/arfus.js.map +1 -0
  27. package/dist/cards/impl/minion/branns-epic-egg.d.ts +2 -0
  28. package/dist/cards/impl/minion/branns-epic-egg.js +23 -0
  29. package/dist/cards/impl/minion/branns-epic-egg.js.map +1 -0
  30. package/dist/cards/impl/minion/choral-mrrrglr.js +15 -5
  31. package/dist/cards/impl/minion/choral-mrrrglr.js.map +1 -1
  32. package/dist/cards/impl/minion/elder-taggawag.d.ts +2 -5
  33. package/dist/cards/impl/minion/elder-taggawag.js +1 -0
  34. package/dist/cards/impl/minion/elder-taggawag.js.map +1 -1
  35. package/dist/cards/impl/minion/elementium-squirrel-bomb.d.ts +2 -0
  36. package/dist/cards/impl/minion/elementium-squirrel-bomb.js +22 -0
  37. package/dist/cards/impl/minion/elementium-squirrel-bomb.js.map +1 -0
  38. package/dist/cards/impl/minion/kilrek.d.ts +2 -0
  39. package/dist/cards/impl/minion/kilrek.js +18 -0
  40. package/dist/cards/impl/minion/kilrek.js.map +1 -0
  41. package/dist/cards/impl/minion/lady-sinestra.d.ts +2 -0
  42. package/dist/cards/impl/minion/lady-sinestra.js +14 -0
  43. package/dist/cards/impl/minion/lady-sinestra.js.map +1 -0
  44. package/dist/cards/impl/minion/loyal-henchman.d.ts +2 -0
  45. package/dist/cards/impl/minion/loyal-henchman.js +21 -0
  46. package/dist/cards/impl/minion/loyal-henchman.js.map +1 -0
  47. package/dist/cards/impl/minion/mawsworn-soulkeeper.d.ts +2 -0
  48. package/dist/cards/impl/minion/mawsworn-soulkeeper.js +21 -0
  49. package/dist/cards/impl/minion/mawsworn-soulkeeper.js.map +1 -0
  50. package/dist/cards/impl/minion/probius.d.ts +2 -0
  51. package/dist/cards/impl/minion/probius.js +16 -0
  52. package/dist/cards/impl/minion/probius.js.map +1 -0
  53. package/dist/cards/impl/minion/sr-tomb-diver.d.ts +2 -0
  54. package/dist/cards/impl/minion/sr-tomb-diver.js +18 -0
  55. package/dist/cards/impl/minion/sr-tomb-diver.js.map +1 -0
  56. package/dist/cards/impl/minion/stalwart-kodo.js +3 -1
  57. package/dist/cards/impl/minion/stalwart-kodo.js.map +1 -1
  58. package/dist/cards/impl/minion/timewarped-mrrrglr.js +11 -5
  59. package/dist/cards/impl/minion/timewarped-mrrrglr.js.map +1 -1
  60. package/dist/cards/impl/minion/tuskarr-raider.d.ts +2 -0
  61. package/dist/cards/impl/minion/tuskarr-raider.js +36 -0
  62. package/dist/cards/impl/minion/tuskarr-raider.js.map +1 -0
  63. package/dist/cards/impl/minion/twilight-hatchling.js +1 -4
  64. package/dist/cards/impl/minion/twilight-hatchling.js.map +1 -1
  65. package/dist/cards/impl/minion/unearthed-underling.d.ts +2 -0
  66. package/dist/cards/impl/minion/unearthed-underling.js +14 -0
  67. package/dist/cards/impl/minion/unearthed-underling.js.map +1 -0
  68. package/dist/cards/impl/spell/fleeting-vigor.js +6 -1
  69. package/dist/cards/impl/spell/fleeting-vigor.js.map +1 -1
  70. package/dist/input-clone.js +5 -1
  71. package/dist/input-clone.js.map +1 -1
  72. package/dist/input-sanitation.js +3 -0
  73. package/dist/input-sanitation.js.map +1 -1
  74. package/dist/services/rng.d.ts +8 -0
  75. package/dist/services/rng.js +40 -0
  76. package/dist/services/rng.js.map +1 -0
  77. package/dist/services/utils.js +3 -2
  78. package/dist/services/utils.js.map +1 -1
  79. package/dist/simulate-bgs-battle.d.ts +10 -0
  80. package/dist/simulate-bgs-battle.js +119 -77
  81. package/dist/simulate-bgs-battle.js.map +1 -1
  82. package/dist/simulation/add-minion-to-board.js +8 -6
  83. package/dist/simulation/add-minion-to-board.js.map +1 -1
  84. package/dist/simulation/auras.js +42 -41
  85. package/dist/simulation/auras.js.map +1 -1
  86. package/dist/simulation/damage-cap.d.ts +2 -0
  87. package/dist/simulation/damage-cap.js +28 -0
  88. package/dist/simulation/damage-cap.js.map +1 -0
  89. package/dist/simulation/deathrattle-spawns.js +0 -57
  90. package/dist/simulation/deathrattle-spawns.js.map +1 -1
  91. package/dist/simulation/internal-game-state.d.ts +2 -0
  92. package/dist/simulation/internal-game-state.js.map +1 -1
  93. package/dist/simulation/reborn.js +0 -13
  94. package/dist/simulation/reborn.js.map +1 -1
  95. package/dist/simulation/shared-state.d.ts +3 -1
  96. package/dist/simulation/shared-state.js +4 -1
  97. package/dist/simulation/shared-state.js.map +1 -1
  98. package/dist/simulation/simulator.d.ts +1 -0
  99. package/dist/simulation/simulator.js +13 -4
  100. package/dist/simulation/simulator.js.map +1 -1
  101. package/dist/simulation/spawns.js +1 -1
  102. package/dist/simulation/spawns.js.map +1 -1
  103. package/dist/simulation/start-of-combat/soc-action-processor.js +12 -0
  104. package/dist/simulation/start-of-combat/soc-action-processor.js.map +1 -1
  105. package/dist/simulation/stats.js +41 -24
  106. package/dist/simulation/stats.js.map +1 -1
  107. package/dist/utils.js +4 -4
  108. package/dist/utils.js.map +1 -1
  109. package/package.json +2 -2
@@ -1,22 +1,52 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.simulateBattle = exports.assignCards = exports.isValidDeathrattleEnchantment = void 0;
3
+ exports.simulateBattle = exports.simulateSingleCombat = exports.assignCards = exports.withRng = exports.random = exports.getActiveRng = exports.defaultRng = exports.createSeededRng = exports.isValidDeathrattleEnchantment = void 0;
4
4
  const reference_data_1 = require("@firestone-hs/reference-data");
5
5
  const cards_data_1 = require("./cards/cards-data");
6
6
  const debug_state_1 = require("./debug-state");
7
7
  const input_clone_1 = require("./input-clone");
8
8
  const input_sanitation_1 = require("./input-sanitation");
9
+ const rng_1 = require("./services/rng");
9
10
  const shared_state_1 = require("./simulation/shared-state");
10
11
  const simulator_1 = require("./simulation/simulator");
11
12
  const spectator_1 = require("./simulation/spectator/spectator");
12
13
  var deathrattle_utils_1 = require("./simulation/deathrattle-utils");
13
14
  Object.defineProperty(exports, "isValidDeathrattleEnchantment", { enumerable: true, get: function () { return deathrattle_utils_1.isValidDeathrattleEnchantment; } });
15
+ var rng_2 = require("./services/rng");
16
+ Object.defineProperty(exports, "createSeededRng", { enumerable: true, get: function () { return rng_2.createSeededRng; } });
17
+ Object.defineProperty(exports, "defaultRng", { enumerable: true, get: function () { return rng_2.defaultRng; } });
18
+ Object.defineProperty(exports, "getActiveRng", { enumerable: true, get: function () { return rng_2.getActiveRng; } });
19
+ Object.defineProperty(exports, "random", { enumerable: true, get: function () { return rng_2.random; } });
20
+ Object.defineProperty(exports, "withRng", { enumerable: true, get: function () { return rng_2.withRng; } });
14
21
  const MAX_SAMPLE_RESIMS = 500;
15
22
  let globalCards = new reference_data_1.AllCardsService();
16
23
  const assignCards = (cards) => {
17
24
  globalCards = cards;
18
25
  };
19
26
  exports.assignCards = assignCards;
27
+ const simulateSingleCombat = (battleInput, cards, cardsData, options = {}) => {
28
+ var _a, _b, _c;
29
+ if (!((_a = cards === null || cards === void 0 ? void 0 : cards.getCards()) === null || _a === void 0 ? void 0 : _a.length)) {
30
+ console.error('[simulate-bgs-battle] reference cards are empty, cannot simulate combat', cards);
31
+ return null;
32
+ }
33
+ const rng = (_b = options.rng) !== null && _b !== void 0 ? _b : (options.seed !== undefined ? (0, rng_1.createSeededRng)(options.seed) : rng_1.defaultRng);
34
+ const includeSpectator = (_c = options.includeSpectator) !== null && _c !== void 0 ? _c : false;
35
+ applyDebugStateFromInput(battleInput);
36
+ try {
37
+ const inputReady = (0, input_sanitation_1.buildFinalInput)(battleInput, cards, cardsData);
38
+ const cloneTemplate = (0, input_clone_1.buildTemplateCloner)((0, input_clone_1.cloneInput3)(inputReady));
39
+ const spectator = new spectator_1.Spectator(includeSpectator);
40
+ if (includeSpectator) {
41
+ spectator.startRecording();
42
+ }
43
+ return (0, rng_1.withRng)(rng, () => runSingleBattle(cloneTemplate, cards, cardsData, spectator, rng));
44
+ }
45
+ finally {
46
+ clearDebugStateFromInput(battleInput);
47
+ }
48
+ };
49
+ exports.simulateSingleCombat = simulateSingleCombat;
20
50
  exports.default = async (event) => {
21
51
  var _a, _b, _c, _d, _e, _f;
22
52
  if (!((_a = event.body) === null || _a === void 0 ? void 0 : _a.length)) {
@@ -42,7 +72,7 @@ exports.default = async (event) => {
42
72
  return response;
43
73
  };
44
74
  const simulateBattle = function* (battleInput, cards, cardsData) {
45
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q;
75
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p;
46
76
  if (!((_a = cards === null || cards === void 0 ? void 0 : cards.getCards()) === null || _a === void 0 ? void 0 : _a.length)) {
47
77
  console.error('[simulate-bgs-battle] reference cards are empty, cannot simulate battle', cards);
48
78
  return null;
@@ -76,79 +106,14 @@ const simulateBattle = function* (battleInput, cards, cardsData) {
76
106
  };
77
107
  const spectator = new spectator_1.Spectator(includeOutcomeSamples);
78
108
  const inputReady = (0, input_sanitation_1.buildFinalInput)(battleInput, cards, cardsData);
79
- if (battleInput.debugState) {
80
- debug_state_1.debugState.active = true;
81
- debug_state_1.debugState.forcedCurrentAttacker = battleInput.debugState.forcedCurrentAttacker;
82
- debug_state_1.debugState.forcedFaceOffBase = battleInput.debugState.forcedFaceOffBase.map((f) => ({
83
- attacker: { ...f.attacker },
84
- defender: { ...f.defender },
85
- }));
86
- const rawPicks = (_m = battleInput.debugState.forcedRandomPicks) !== null && _m !== void 0 ? _m : [];
87
- debug_state_1.debugState.forcedRandomPicksBase = rawPicks.map((p) => ({
88
- source: { ...p.source },
89
- target: { ...p.target },
90
- ...(p.chosenCardId && { chosenCardId: p.chosenCardId }),
91
- }));
92
- }
109
+ applyDebugStateFromInput(battleInput);
93
110
  const cloneTemplate = (0, input_clone_1.buildTemplateCloner)((0, input_clone_1.cloneInput3)(inputReady));
94
- const runSingleBattle = () => {
95
- const input = cloneTemplate();
96
- let playerInitialState = null;
97
- let opponentInitialState = null;
98
- const buildInitialStates = () => {
99
- const inputClone = cloneTemplate();
100
- playerInitialState = {
101
- player: inputClone.playerBoard.player,
102
- board: inputClone.playerBoard.board,
103
- teammate: inputClone.playerTeammateBoard,
104
- };
105
- opponentInitialState = {
106
- player: inputClone.opponentBoard.player,
107
- board: inputClone.opponentBoard.board,
108
- teammate: inputClone.opponentTeammateBoard,
109
- };
110
- };
111
- const gameState = {
112
- allCards: cards,
113
- cardsData: cardsData,
114
- spectator: spectator,
115
- sharedState: new shared_state_1.SharedState(),
116
- currentTurn: input.gameState.currentTurn,
117
- validTribes: input.gameState.validTribes,
118
- anomalies: input.gameState.anomalies,
119
- gameState: {
120
- player: {
121
- player: input.playerBoard.player,
122
- board: input.playerBoard.board,
123
- teammate: input.playerTeammateBoard,
124
- },
125
- opponent: {
126
- player: input.opponentBoard.player,
127
- board: input.opponentBoard.board,
128
- teammate: input.opponentTeammateBoard,
129
- },
130
- get playerInitial() {
131
- if (!playerInitialState) {
132
- buildInitialStates();
133
- }
134
- return playerInitialState;
135
- },
136
- get opponentInitial() {
137
- if (!opponentInitialState) {
138
- buildInitialStates();
139
- }
140
- return opponentInitialState;
141
- },
142
- },
143
- };
144
- const simulator = new simulator_1.Simulator(gameState);
145
- return simulator.simulateSingleBattle(gameState.gameState.player, gameState.gameState.opponent);
146
- };
111
+ const runOne = () => runSingleBattle(cloneTemplate, cards, cardsData, spectator, rng_1.defaultRng);
147
112
  try {
148
- !((_o = battleInput.options) === null || _o === void 0 ? void 0 : _o.skipInfoLogs) && console.time('simulation');
113
+ !((_m = battleInput.options) === null || _m === void 0 ? void 0 : _m.skipInfoLogs) && console.time('simulation');
149
114
  const outcomes = {};
150
115
  for (let i = 0; i < numberOfSimulations; i++) {
151
- const battleResult = runSingleBattle();
116
+ const battleResult = runOne();
152
117
  if (!battleResult) {
153
118
  continue;
154
119
  }
@@ -164,7 +129,7 @@ const simulateBattle = function* (battleInput, cards, cardsData) {
164
129
  simulationResult.lost++;
165
130
  simulationResult.damageLost += battleResult.damageDealt;
166
131
  simulationResult.damageLosts.push(battleResult.damageDealt);
167
- outcomes[battleResult.damageDealt] = ((_p = outcomes[battleResult.damageDealt]) !== null && _p !== void 0 ? _p : 0) + 1;
132
+ outcomes[battleResult.damageDealt] = ((_o = outcomes[battleResult.damageDealt]) !== null && _o !== void 0 ? _o : 0) + 1;
168
133
  if (battleInput.playerBoard.player.hpLeft &&
169
134
  battleResult.damageDealt >= battleInput.playerBoard.player.hpLeft) {
170
135
  simulationResult.lostLethal++;
@@ -183,7 +148,7 @@ const simulateBattle = function* (battleInput, cards, cardsData) {
183
148
  }
184
149
  }
185
150
  updateSimulationResult(simulationResult, inputReady, damageConfidence);
186
- !((_q = battleInput.options) === null || _q === void 0 ? void 0 : _q.skipInfoLogs) && console.timeEnd('simulation');
151
+ !((_p = battleInput.options) === null || _p === void 0 ? void 0 : _p.skipInfoLogs) && console.timeEnd('simulation');
187
152
  if (includeOutcomeSamples) {
188
153
  const neededOutcomes = [];
189
154
  simulationResult.won > 0 && neededOutcomes.push('won');
@@ -193,7 +158,7 @@ const simulateBattle = function* (battleInput, cards, cardsData) {
193
158
  if (missingOutcomes.size > 0) {
194
159
  spectator.startRecording();
195
160
  for (let i = 0; i < MAX_SAMPLE_RESIMS && missingOutcomes.size > 0; i++) {
196
- const battleResult = runSingleBattle();
161
+ const battleResult = runOne();
197
162
  if (!(battleResult === null || battleResult === void 0 ? void 0 : battleResult.result)) {
198
163
  continue;
199
164
  }
@@ -212,12 +177,89 @@ const simulateBattle = function* (battleInput, cards, cardsData) {
212
177
  return simulationResult;
213
178
  }
214
179
  finally {
215
- if (battleInput.debugState) {
216
- debug_state_1.debugState.active = false;
217
- }
180
+ clearDebugStateFromInput(battleInput);
218
181
  }
219
182
  };
220
183
  exports.simulateBattle = simulateBattle;
184
+ const runSingleBattle = (cloneTemplate, cards, cardsData, spectator, rng) => {
185
+ var _a;
186
+ const input = cloneTemplate();
187
+ let playerInitialState = null;
188
+ let opponentInitialState = null;
189
+ const buildInitialStates = () => {
190
+ const inputClone = cloneTemplate();
191
+ playerInitialState = {
192
+ player: inputClone.playerBoard.player,
193
+ board: inputClone.playerBoard.board,
194
+ teammate: inputClone.playerTeammateBoard,
195
+ };
196
+ opponentInitialState = {
197
+ player: inputClone.opponentBoard.player,
198
+ board: inputClone.opponentBoard.board,
199
+ teammate: inputClone.opponentTeammateBoard,
200
+ };
201
+ };
202
+ const gameState = {
203
+ allCards: cards,
204
+ cardsData: cardsData,
205
+ spectator: spectator,
206
+ sharedState: new shared_state_1.SharedState(rng),
207
+ currentTurn: input.gameState.currentTurn,
208
+ numberOfPlayersAlive: input.gameState.numberOfPlayersAlive,
209
+ applyDamageCap: ((_a = input.options) === null || _a === void 0 ? void 0 : _a.applyDamageCap) === true,
210
+ validTribes: input.gameState.validTribes,
211
+ anomalies: input.gameState.anomalies,
212
+ gameState: {
213
+ player: {
214
+ player: input.playerBoard.player,
215
+ board: input.playerBoard.board,
216
+ teammate: input.playerTeammateBoard,
217
+ },
218
+ opponent: {
219
+ player: input.opponentBoard.player,
220
+ board: input.opponentBoard.board,
221
+ teammate: input.opponentTeammateBoard,
222
+ },
223
+ get playerInitial() {
224
+ if (!playerInitialState) {
225
+ buildInitialStates();
226
+ }
227
+ return playerInitialState;
228
+ },
229
+ get opponentInitial() {
230
+ if (!opponentInitialState) {
231
+ buildInitialStates();
232
+ }
233
+ return opponentInitialState;
234
+ },
235
+ },
236
+ };
237
+ const simulator = new simulator_1.Simulator(gameState);
238
+ return simulator.simulateSingleBattle(gameState.gameState.player, gameState.gameState.opponent);
239
+ };
240
+ const applyDebugStateFromInput = (battleInput) => {
241
+ var _a;
242
+ if (!battleInput.debugState) {
243
+ return;
244
+ }
245
+ debug_state_1.debugState.active = true;
246
+ debug_state_1.debugState.forcedCurrentAttacker = battleInput.debugState.forcedCurrentAttacker;
247
+ debug_state_1.debugState.forcedFaceOffBase = battleInput.debugState.forcedFaceOffBase.map((f) => ({
248
+ attacker: { ...f.attacker },
249
+ defender: { ...f.defender },
250
+ }));
251
+ const rawPicks = (_a = battleInput.debugState.forcedRandomPicks) !== null && _a !== void 0 ? _a : [];
252
+ debug_state_1.debugState.forcedRandomPicksBase = rawPicks.map((p) => ({
253
+ source: { ...p.source },
254
+ target: { ...p.target },
255
+ ...(p.chosenCardId && { chosenCardId: p.chosenCardId }),
256
+ }));
257
+ };
258
+ const clearDebugStateFromInput = (battleInput) => {
259
+ if (battleInput.debugState) {
260
+ debug_state_1.debugState.active = false;
261
+ }
262
+ };
221
263
  const updateSimulationResult = (simulationResult, input, damageConfidence) => {
222
264
  const totalMatches = simulationResult.won + simulationResult.tied + simulationResult.lost;
223
265
  simulationResult.wonPercent = checkRounding(Math.round((10 * (100 * simulationResult.won)) / totalMatches) / 10, simulationResult.won, totalMatches);
@@ -1 +1 @@
1
- {"version":3,"file":"simulate-bgs-battle.js","sourceRoot":"","sources":["../src/simulate-bgs-battle.ts"],"names":[],"mappings":";;;AACA,iEAA+D;AAE/D,mDAA+C;AAC/C,+CAA2C;AAC3C,+CAAiE;AACjE,yDAAqD;AAGrD,4DAAwD;AACxD,sDAAmD;AACnD,gEAA6D;AAE7D,oEAA+E;AAAtE,kIAAA,6BAA6B,OAAA;AAKtC,MAAM,iBAAiB,GAAG,GAAG,CAAC;AAE9B,IAAI,WAAW,GAAG,IAAI,gCAAe,EAAE,CAAC;AAEjC,MAAM,WAAW,GAAG,CAAC,KAAsB,EAAE,EAAE;IACrD,WAAW,GAAG,KAAK,CAAC;AACrB,CAAC,CAAC;AAFW,QAAA,WAAW,eAEtB;AAKF,kBAAe,KAAK,EAAE,KAAK,EAAgB,EAAE;;IAC5C,IAAI,CAAC,CAAA,MAAA,KAAK,CAAC,IAAI,0CAAE,MAAM,CAAA,EAAE;QACxB,OAAO,CAAC,IAAI,CAAC,oBAAoB,EAAE,KAAK,CAAC,CAAC;QAC1C,OAAO;KACP;IAED,MAAM,WAAW,GAAkB,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC1D,MAAM,KAAK,GAAG,WAAW,CAAC;IAC1B,MAAM,KAAK,CAAC,iBAAiB,EAAE,CAAC;IAChC,MAAM,SAAS,GAAG,IAAI,sBAAS,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;IAC9C,SAAS,CAAC,YAAY,CACrB,MAAA,MAAA,WAAW,CAAC,SAAS,0CAAE,WAAW,mCAAI,MAAA,WAAW,CAAC,OAAO,0CAAE,WAAW,EACtE,MAAA,MAAA,WAAW,CAAC,SAAS,0CAAE,SAAS,mCAAI,EAAE,CACtC,CAAC;IACF,MAAM,cAAc,GAAG,IAAA,sBAAc,EAAC,WAAW,EAAE,KAAK,EAAE,SAAS,CAAC,CAAC;IAGrE,IAAI,MAAM,GAAG,cAAc,CAAC,IAAI,EAAE,CAAC;IACnC,OAAO,CAAC,MAAM,CAAC,IAAI,EAAE;QACpB,MAAM,GAAG,cAAc,CAAC,IAAI,EAAE,CAAC;KAC/B;IAED,MAAM,gBAAgB,GAAG,MAAM,CAAC,KAAK,CAAC;IAGtC,MAAM,QAAQ,GAAG;QAChB,UAAU,EAAE,GAAG;QACf,eAAe,EAAE,KAAK;QACtB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,gBAAgB,CAAC;KACtC,CAAC;IACF,OAAO,QAAQ,CAAC;AACjB,CAAC,CAAC;AAEK,MAAM,cAAc,GAAG,QAAQ,CAAC,EACtC,WAA0B,EAC1B,KAAsB,EACtB,SAAoB;;IAEpB,IAAI,CAAC,CAAA,MAAA,KAAK,aAAL,KAAK,uBAAL,KAAK,CAAE,QAAQ,EAAE,0CAAE,MAAM,CAAA,EAAE;QAC/B,OAAO,CAAC,KAAK,CAAC,yEAAyE,EAAE,KAAK,CAAC,CAAC;QAChG,OAAO,IAAI,CAAC;KACZ;IAED,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACzB,MAAM,qBAAqB,GAAG,CAAA,MAAA,WAAW,CAAC,OAAO,0CAAE,qBAAqB,KAAI,IAAI,CAAC;IACjF,MAAM,gCAAgC,GAAG,MAAA,MAAA,WAAW,CAAC,OAAO,0CAAE,gCAAgC,mCAAI,KAAK,CAAC;IACxG,MAAM,mBAAmB,GAAG,CAAA,MAAA,WAAW,CAAC,OAAO,0CAAE,mBAAmB,KAAI,IAAI,CAAC;IAC7E,MAAM,iBAAiB,GAAG,MAAA,MAAA,WAAW,CAAC,OAAO,0CAAE,mBAAmB,mCAAI,GAAG,CAAC;IAC1E,MAAM,gBAAgB,GAAG,MAAA,MAAA,WAAW,CAAC,OAAO,0CAAE,gBAAgB,mCAAI,GAAG,CAAC;IACtE,MAAM,qBAAqB,GAAG,MAAA,MAAA,WAAW,CAAC,OAAO,0CAAE,qBAAqB,mCAAI,IAAI,CAAC;IACjF,MAAM,gBAAgB,GAAqB;QAC1C,SAAS,EAAE,CAAC;QACZ,GAAG,EAAE,CAAC;QACN,IAAI,EAAE,CAAC;QACP,IAAI,EAAE,CAAC;QACP,UAAU,EAAE,CAAC;QACb,UAAU,EAAE,EAAE;QACd,SAAS,EAAE,CAAC;QACZ,cAAc,EAAE,IAAI;QACpB,WAAW,EAAE,EAAE;QACf,UAAU,EAAE,CAAC;QACb,eAAe,EAAE,IAAI;QACrB,gBAAgB,EAAE,SAAS;QAC3B,UAAU,EAAE,SAAS;QACrB,WAAW,EAAE,SAAS;QACtB,WAAW,EAAE,SAAS;QACtB,iBAAiB,EAAE,SAAS;QAC5B,gBAAgB,EAAE,SAAS;QAC3B,iBAAiB,EAAE,SAAS;KAC5B,CAAC;IAEF,MAAM,SAAS,GAAG,IAAI,qBAAS,CAAC,qBAAqB,CAAC,CAAC;IACvD,MAAM,UAAU,GAAG,IAAA,kCAAe,EAAC,WAAW,EAAE,KAAK,EAAE,SAAS,CAAC,CAAC;IAGlE,IAAI,WAAW,CAAC,UAAU,EAAE;QAC3B,wBAAU,CAAC,MAAM,GAAG,IAAI,CAAC;QACzB,wBAAU,CAAC,qBAAqB,GAAG,WAAW,CAAC,UAAU,CAAC,qBAAqB,CAAC;QAChF,wBAAU,CAAC,iBAAiB,GAAG,WAAW,CAAC,UAAU,CAAC,iBAAiB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACnF,QAAQ,EAAE,EAAE,GAAG,CAAC,CAAC,QAAQ,EAAE;YAC3B,QAAQ,EAAE,EAAE,GAAG,CAAC,CAAC,QAAQ,EAAE;SAC3B,CAAC,CAAC,CAAC;QACJ,MAAM,QAAQ,GAAG,MAAA,WAAW,CAAC,UAAU,CAAC,iBAAiB,mCAAI,EAAE,CAAC;QAChE,wBAAU,CAAC,qBAAqB,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACvD,MAAM,EAAE,EAAE,GAAG,CAAC,CAAC,MAAM,EAAE;YACvB,MAAM,EAAE,EAAE,GAAG,CAAC,CAAC,MAAM,EAAE;YACvB,GAAG,CAAC,CAAC,CAAC,YAAY,IAAI,EAAE,YAAY,EAAE,CAAC,CAAC,YAAY,EAAE,CAAC;SACvD,CAAC,CAAC,CAAC;KACJ;IAOD,MAAM,aAAa,GAAG,IAAA,iCAAmB,EAAC,IAAA,yBAAW,EAAC,UAAU,CAAC,CAAC,CAAC;IAEnE,MAAM,eAAe,GAAG,GAAG,EAAE;QAC5B,MAAM,KAAK,GAAkB,aAAa,EAAE,CAAC;QAG7C,IAAI,kBAAkB,GAAG,IAAI,CAAC;QAC9B,IAAI,oBAAoB,GAAG,IAAI,CAAC;QAChC,MAAM,kBAAkB,GAAG,GAAG,EAAE;YAC/B,MAAM,UAAU,GAAkB,aAAa,EAAE,CAAC;YAClD,kBAAkB,GAAG;gBACpB,MAAM,EAAE,UAAU,CAAC,WAAW,CAAC,MAAM;gBACrC,KAAK,EAAE,UAAU,CAAC,WAAW,CAAC,KAAK;gBACnC,QAAQ,EAAE,UAAU,CAAC,mBAAmB;aACxC,CAAC;YACF,oBAAoB,GAAG;gBACtB,MAAM,EAAE,UAAU,CAAC,aAAa,CAAC,MAAM;gBACvC,KAAK,EAAE,UAAU,CAAC,aAAa,CAAC,KAAK;gBACrC,QAAQ,EAAE,UAAU,CAAC,qBAAqB;aAC1C,CAAC;QACH,CAAC,CAAC;QACF,MAAM,SAAS,GAAkB;YAChC,QAAQ,EAAE,KAAK;YACf,SAAS,EAAE,SAAS;YACpB,SAAS,EAAE,SAAS;YACpB,WAAW,EAAE,IAAI,0BAAW,EAAE;YAC9B,WAAW,EAAE,KAAK,CAAC,SAAS,CAAC,WAAW;YACxC,WAAW,EAAE,KAAK,CAAC,SAAS,CAAC,WAAW;YACxC,SAAS,EAAE,KAAK,CAAC,SAAS,CAAC,SAAS;YACpC,SAAS,EAAE;gBACV,MAAM,EAAE;oBACP,MAAM,EAAE,KAAK,CAAC,WAAW,CAAC,MAAM;oBAChC,KAAK,EAAE,KAAK,CAAC,WAAW,CAAC,KAAK;oBAC9B,QAAQ,EAAE,KAAK,CAAC,mBAAmB;iBACnC;gBACD,QAAQ,EAAE;oBACT,MAAM,EAAE,KAAK,CAAC,aAAa,CAAC,MAAM;oBAClC,KAAK,EAAE,KAAK,CAAC,aAAa,CAAC,KAAK;oBAChC,QAAQ,EAAE,KAAK,CAAC,qBAAqB;iBACrC;gBACD,IAAI,aAAa;oBAChB,IAAI,CAAC,kBAAkB,EAAE;wBACxB,kBAAkB,EAAE,CAAC;qBACrB;oBACD,OAAO,kBAAkB,CAAC;gBAC3B,CAAC;gBACD,IAAI,eAAe;oBAClB,IAAI,CAAC,oBAAoB,EAAE;wBAC1B,kBAAkB,EAAE,CAAC;qBACrB;oBACD,OAAO,oBAAoB,CAAC;gBAC7B,CAAC;aACD;SACD,CAAC;QACF,MAAM,SAAS,GAAG,IAAI,qBAAS,CAAC,SAAS,CAAC,CAAC;QAC3C,OAAO,SAAS,CAAC,oBAAoB,CAAC,SAAS,CAAC,SAAS,CAAC,MAAM,EAAE,SAAS,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;IACjG,CAAC,CAAC;IAEF,IAAI;QACH,CAAC,CAAA,MAAA,WAAW,CAAC,OAAO,0CAAE,YAAY,CAAA,IAAI,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QACjE,MAAM,QAAQ,GAAG,EAAE,CAAC;QACpB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,mBAAmB,EAAE,CAAC,EAAE,EAAE;YAC7C,MAAM,YAAY,GAAG,eAAe,EAAE,CAAC;YACvC,IAAI,CAAC,YAAY,EAAE;gBAClB,SAAS;aACT;YACD,IAAI,YAAY,CAAC,MAAM,KAAK,KAAK,EAAE;gBAClC,gBAAgB,CAAC,GAAG,EAAE,CAAC;gBACvB,gBAAgB,CAAC,SAAS,IAAI,YAAY,CAAC,WAAW,CAAC;gBACvD,gBAAgB,CAAC,UAAU,CAAC,IAAI,CAAC,YAAY,CAAC,WAAW,CAAC,CAAC;gBAC3D,IAAI,YAAY,CAAC,WAAW,IAAI,WAAW,CAAC,aAAa,CAAC,MAAM,CAAC,MAAM,EAAE;oBACxE,gBAAgB,CAAC,SAAS,EAAE,CAAC;iBAC7B;aACD;iBAAM,IAAI,YAAY,CAAC,MAAM,KAAK,MAAM,EAAE;gBAC1C,gBAAgB,CAAC,IAAI,EAAE,CAAC;gBACxB,gBAAgB,CAAC,UAAU,IAAI,YAAY,CAAC,WAAW,CAAC;gBACxD,gBAAgB,CAAC,WAAW,CAAC,IAAI,CAAC,YAAY,CAAC,WAAW,CAAC,CAAC;gBAC5D,QAAQ,CAAC,YAAY,CAAC,WAAW,CAAC,GAAG,CAAC,MAAA,QAAQ,CAAC,YAAY,CAAC,WAAW,CAAC,mCAAI,CAAC,CAAC,GAAG,CAAC,CAAC;gBACnF,IACC,WAAW,CAAC,WAAW,CAAC,MAAM,CAAC,MAAM;oBACrC,YAAY,CAAC,WAAW,IAAI,WAAW,CAAC,WAAW,CAAC,MAAM,CAAC,MAAM,EAChE;oBACD,gBAAgB,CAAC,UAAU,EAAE,CAAC;iBAC9B;aACD;iBAAM,IAAI,YAAY,CAAC,MAAM,KAAK,MAAM,EAAE;gBAC1C,gBAAgB,CAAC,IAAI,EAAE,CAAC;aACxB;YAED,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,GAAG,qBAAqB,IAAI,CAAC,gCAAgC,EAAE;gBAEpF,OAAO,CAAC,IAAI,CAAC,2BAA2B,EAAE,CAAC,EAAE,iBAAiB,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,EAAE,IAAI,CAAC,CAAC;gBAC1F,MAAM;aACN;YAGD,IAAI,CAAC,CAAC,iBAAiB,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,iBAAiB,KAAK,CAAC,EAAE;gBAChE,sBAAsB,CAAC,gBAAgB,EAAE,UAAU,EAAE,gBAAgB,CAAC,CAAC;gBACvE,MAAM,gBAAgB,CAAC;aACvB;SACD;QACD,sBAAsB,CAAC,gBAAgB,EAAE,UAAU,EAAE,gBAAgB,CAAC,CAAC;QACvE,CAAC,CAAA,MAAA,WAAW,CAAC,OAAO,0CAAE,YAAY,CAAA,IAAI,OAAO,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;QAOpE,IAAI,qBAAqB,EAAE;YAC1B,MAAM,cAAc,GAAgC,EAAE,CAAC;YACvD,gBAAgB,CAAC,GAAG,GAAG,CAAC,IAAI,cAAc,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACvD,gBAAgB,CAAC,IAAI,GAAG,CAAC,IAAI,cAAc,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACzD,gBAAgB,CAAC,IAAI,GAAG,CAAC,IAAI,cAAc,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACzD,MAAM,eAAe,GAAG,IAAI,GAAG,CAAC,cAAc,CAAC,CAAC;YAChD,IAAI,eAAe,CAAC,IAAI,GAAG,CAAC,EAAE;gBAC7B,SAAS,CAAC,cAAc,EAAE,CAAC;gBAC3B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,iBAAiB,IAAI,eAAe,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE;oBACvE,MAAM,YAAY,GAAG,eAAe,EAAE,CAAC;oBACvC,IAAI,CAAC,CAAA,YAAY,aAAZ,YAAY,uBAAZ,YAAY,CAAE,MAAM,CAAA,EAAE;wBAC1B,SAAS;qBACT;oBACD,SAAS,CAAC,kBAAkB,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;oBAClD,IAAI,SAAS,CAAC,YAAY,CAAC,YAAY,CAAC,MAAM,CAAC,EAAE;wBAChD,eAAe,CAAC,MAAM,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;qBAC5C;iBACD;gBACD,SAAS,CAAC,aAAa,EAAE,CAAC;aAC1B;SACD;QAED,SAAS,CAAC,KAAK,EAAE,CAAC;QAClB,gBAAgB,CAAC,cAAc,GAAG,SAAS,CAAC,mBAAmB,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC;QAGvF,gBAAgB,CAAC,UAAU,GAAG,EAAE,CAAC;QACjC,gBAAgB,CAAC,WAAW,GAAG,EAAE,CAAC;QAElC,OAAO,gBAAgB,CAAC;KACxB;YAAS;QACT,IAAI,WAAW,CAAC,UAAU,EAAE;YAC3B,wBAAU,CAAC,MAAM,GAAG,KAAK,CAAC;SAC1B;KACD;AACF,CAAC,CAAC;AA7MW,QAAA,cAAc,kBA6MzB;AAEF,MAAM,sBAAsB,GAAG,CAAC,gBAAkC,EAAE,KAAoB,EAAE,gBAAwB,EAAE,EAAE;IACrH,MAAM,YAAY,GAAG,gBAAgB,CAAC,GAAG,GAAG,gBAAgB,CAAC,IAAI,GAAG,gBAAgB,CAAC,IAAI,CAAC;IAC1F,gBAAgB,CAAC,UAAU,GAAG,aAAa,CAC1C,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,GAAG,GAAG,gBAAgB,CAAC,GAAG,CAAC,CAAC,GAAG,YAAY,CAAC,GAAG,EAAE,EACnE,gBAAgB,CAAC,GAAG,EACpB,YAAY,CACZ,CAAC;IACF,gBAAgB,CAAC,gBAAgB,GAAG,aAAa,CAChD,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,GAAG,GAAG,gBAAgB,CAAC,SAAS,CAAC,CAAC,GAAG,YAAY,CAAC,GAAG,EAAE,EACzE,gBAAgB,CAAC,SAAS,EAC1B,YAAY,CACZ,CAAC;IACF,gBAAgB,CAAC,WAAW,GAAG,aAAa,CAC3C,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,GAAG,GAAG,gBAAgB,CAAC,IAAI,CAAC,CAAC,GAAG,YAAY,CAAC,GAAG,EAAE,EACpE,gBAAgB,CAAC,IAAI,EACrB,YAAY,CACZ,CAAC;IACF,gBAAgB,CAAC,iBAAiB,GAAG,aAAa,CACjD,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,GAAG,GAAG,gBAAgB,CAAC,UAAU,CAAC,CAAC,GAAG,YAAY,CAAC,GAAG,EAAE,EAC1E,gBAAgB,CAAC,UAAU,EAC3B,YAAY,CACZ,CAAC;IACF,gBAAgB,CAAC,WAAW,GAAG,aAAa,CAC3C,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,GAAG,gBAAgB,CAAC,WAAW,GAAG,gBAAgB,CAAC,UAAU,CAAC,EAC7E,gBAAgB,CAAC,IAAI,EACrB,YAAY,CACZ,CAAC;IAIF,MAAM,cAAc,GAAG,gBAAgB,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;IAC9E,MAAM,eAAe,GAAG,gBAAgB,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;IAChF,MAAM,cAAc,GAAG,oBAAoB,CAAC,gBAAgB,CAAC,UAAU,EAAE,gBAAgB,CAAC,CAAC;IAC3F,MAAM,eAAe,GAAG,oBAAoB,CAAC,gBAAgB,CAAC,WAAW,EAAE,gBAAgB,CAAC,CAAC;IAC7F,gBAAgB,CAAC,gBAAgB,GAAG,gBAAgB,CAAC,GAAG,CAAC,CAAC,CAAC,cAAc,GAAG,gBAAgB,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IACrG,gBAAgB,CAAC,iBAAiB,GAAG,gBAAgB,CAAC,IAAI,CAAC,CAAC,CAAC,eAAe,GAAG,gBAAgB,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;IACzG,gBAAgB,CAAC,cAAc,GAAG,gBAAgB,CAAC,GAAG,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,IAAI,CAAC;IAC/E,gBAAgB,CAAC,eAAe,GAAG,gBAAgB,CAAC,IAAI,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,IAAI,CAAC;IAElF,IACC,gBAAgB,CAAC,gBAAgB,GAAG,CAAC;QACrC,gBAAgB,CAAC,gBAAgB,GAAG,KAAK,CAAC,WAAW,CAAC,MAAM,CAAC,UAAU,EACtE;QACD,OAAO,CAAC,IAAI,CAAC,0BAA0B,CAAC,CAAC;KACzC;IACD,IACC,gBAAgB,CAAC,iBAAiB,GAAG,CAAC;QACtC,gBAAgB,CAAC,iBAAiB,GAAG,KAAK,CAAC,aAAa,CAAC,MAAM,CAAC,UAAU,EACzE;QACD,OAAO,CAAC,IAAI,CAAC,2BAA2B,CAAC,CAAC;KAC1C;AACF,CAAC,CAAC;AAEF,MAAM,oBAAoB,GAAG,CAAC,WAAqB,EAAE,gBAAwB,EAAgC,EAAE;IAC9G,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC,EAAE;QAC7B,OAAO,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC;KAC1B;IAGD,MAAM,YAAY,GAAG,CAAC,GAAG,WAAW,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IAG5D,MAAM,UAAU,GAAG,CAAC,GAAa,EAAE,CAAS,EAAE,EAAE;QAC/C,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC;QACzC,OAAO,GAAG,CAAC,KAAK,CAAC,CAAC;IACnB,CAAC,CAAC;IAEF,MAAM,SAAS,GAAG,UAAU,CAAC,YAAY,EAAE,CAAC,GAAG,gBAAgB,CAAC,CAAC;IACjE,MAAM,SAAS,GAAG,UAAU,CAAC,YAAY,EAAE,gBAAgB,CAAC,CAAC;IAE7D,OAAO,EAAE,GAAG,EAAE,SAAS,EAAE,GAAG,EAAE,SAAS,EAAE,CAAC;AAC3C,CAAC,CAAC;AAEF,MAAM,aAAa,GAAG,CAAC,YAAoB,EAAE,YAAoB,EAAE,UAAkB,EAAU,EAAE;IAChG,IAAI,YAAY,KAAK,CAAC,IAAI,YAAY,KAAK,CAAC,EAAE;QAC7C,OAAO,IAAI,CAAC;KACZ;IACD,IAAI,YAAY,KAAK,GAAG,IAAI,YAAY,KAAK,UAAU,EAAE;QACxD,OAAO,IAAI,CAAC;KACZ;IACD,OAAO,YAAY,CAAC;AACrB,CAAC,CAAC","sourcesContent":["/* eslint-disable @typescript-eslint/no-use-before-define */\r\nimport { AllCardsService } from '@firestone-hs/reference-data';\r\nimport { BgsBattleInfo } from './bgs-battle-info';\r\nimport { CardsData } from './cards/cards-data';\r\nimport { debugState } from './debug-state';\r\nimport { buildTemplateCloner, cloneInput3 } from './input-clone';\r\nimport { buildFinalInput } from './input-sanitation';\r\nimport { SimulationResult } from './simulation-result';\r\nimport { FullGameState } from './simulation/internal-game-state';\r\nimport { SharedState } from './simulation/shared-state';\r\nimport { Simulator } from './simulation/simulator';\r\nimport { Spectator } from './simulation/spectator/spectator';\r\n\r\nexport { isValidDeathrattleEnchantment } from './simulation/deathrattle-utils';\r\n\r\n// Cap for the post-hoc outcome sample capture phase: rare outcomes (e.g. a 0.1% tie\r\n// chance) might never show up again when re-simulating, so we stop hunting after this\r\n// many extra battles\r\nconst MAX_SAMPLE_RESIMS = 500;\r\n\r\nlet globalCards = new AllCardsService();\r\n\r\nexport const assignCards = (cards: AllCardsService) => {\r\n\tglobalCards = cards;\r\n};\r\n\r\n// This example demonstrates a NodeJS 8.10 async handler[1], however of course you could use\r\n// the more traditional callback-style handler.\r\n// [1]: https://aws.amazon.com/blogs/compute/node-js-8-10-runtime-now-available-in-aws-lambda/\r\nexport default async (event): Promise<any> => {\r\n\tif (!event.body?.length) {\r\n\t\tconsole.warn('missing event body', event);\r\n\t\treturn;\r\n\t}\r\n\r\n\tconst battleInput: BgsBattleInfo = JSON.parse(event.body);\r\n\tconst cards = globalCards;\r\n\tawait cards.initializeCardsDb();\r\n\tconst cardsData = new CardsData(cards, false);\r\n\tcardsData.inititialize(\r\n\t\tbattleInput.gameState?.validTribes ?? battleInput.options?.validTribes,\r\n\t\tbattleInput.gameState?.anomalies ?? [],\r\n\t);\r\n\tconst battleIterator = simulateBattle(battleInput, cards, cardsData);\r\n\r\n\t// Iterate through all intermediate results to reach the final result\r\n\tlet result = battleIterator.next();\r\n\twhile (!result.done) {\r\n\t\tresult = battleIterator.next();\r\n\t}\r\n\r\n\tconst simulationResult = result.value;\r\n\t// console.debug('simulationResult', simulationResult);\r\n\r\n\tconst response = {\r\n\t\tstatusCode: 200,\r\n\t\tisBase64Encoded: false,\r\n\t\tbody: JSON.stringify(simulationResult),\r\n\t};\r\n\treturn response;\r\n};\r\n\r\nexport const simulateBattle = function* (\r\n\tbattleInput: BgsBattleInfo,\r\n\tcards: AllCardsService,\r\n\tcardsData: CardsData,\r\n): Generator<SimulationResult, SimulationResult, void> {\r\n\tif (!cards?.getCards()?.length) {\r\n\t\tconsole.error('[simulate-bgs-battle] reference cards are empty, cannot simulate battle', cards);\r\n\t\treturn null;\r\n\t}\r\n\t// !battleInput.options?.skipInfoLogs && console.time('full-sim');\r\n\tconst start = Date.now();\r\n\tconst maxAcceptableDuration = battleInput.options?.maxAcceptableDuration || 8000;\r\n\tconst hideMaxSimulationDurationWarning = battleInput.options?.hideMaxSimulationDurationWarning ?? false;\r\n\tconst numberOfSimulations = battleInput.options?.numberOfSimulations || 8000;\r\n\tconst intermediateSteps = battleInput.options?.intermediateResults ?? 200;\r\n\tconst damageConfidence = battleInput.options?.damageConfidence ?? 0.9;\r\n\tconst includeOutcomeSamples = battleInput.options?.includeOutcomeSamples ?? true;\r\n\tconst simulationResult: SimulationResult = {\r\n\t\twonLethal: 0,\r\n\t\twon: 0,\r\n\t\ttied: 0,\r\n\t\tlost: 0,\r\n\t\tlostLethal: 0,\r\n\t\tdamageWons: [],\r\n\t\tdamageWon: 0,\r\n\t\tdamageWonRange: null,\r\n\t\tdamageLosts: [],\r\n\t\tdamageLost: 0,\r\n\t\tdamageLostRange: null,\r\n\t\twonLethalPercent: undefined,\r\n\t\twonPercent: undefined,\r\n\t\ttiedPercent: undefined,\r\n\t\tlostPercent: undefined,\r\n\t\tlostLethalPercent: undefined,\r\n\t\taverageDamageWon: undefined,\r\n\t\taverageDamageLost: undefined,\r\n\t};\r\n\r\n\tconst spectator = new Spectator(includeOutcomeSamples);\r\n\tconst inputReady = buildFinalInput(battleInput, cards, cardsData);\r\n\r\n\t// Apply debug state from input when present (e.g. from bug report)\r\n\tif (battleInput.debugState) {\r\n\t\tdebugState.active = true;\r\n\t\tdebugState.forcedCurrentAttacker = battleInput.debugState.forcedCurrentAttacker;\r\n\t\tdebugState.forcedFaceOffBase = battleInput.debugState.forcedFaceOffBase.map((f) => ({\r\n\t\t\tattacker: { ...f.attacker },\r\n\t\t\tdefender: { ...f.defender },\r\n\t\t}));\r\n\t\tconst rawPicks = battleInput.debugState.forcedRandomPicks ?? [];\r\n\t\tdebugState.forcedRandomPicksBase = rawPicks.map((p) => ({\r\n\t\t\tsource: { ...p.source },\r\n\t\t\ttarget: { ...p.target },\r\n\t\t\t...(p.chosenCardId && { chosenCardId: p.chosenCardId }),\r\n\t\t}));\r\n\t}\r\n\r\n\t// cloneInput3 normalizes the input (sorted secrets, reset pendingAttackBuffs, etc.).\r\n\t// The compiled cloner re-materializes that normalized shape as an object literal, which is\r\n\t// faster than JSON.parse of a template string (~0.02ms vs ~0.12ms per clone on a 7v7\r\n\t// board), which was itself faster than generic recursive cloners (~0.19-0.23ms) and\r\n\t// structuredClone (~0.46ms)\r\n\tconst cloneTemplate = buildTemplateCloner(cloneInput3(inputReady));\r\n\r\n\tconst runSingleBattle = () => {\r\n\t\tconst input: BgsBattleInfo = cloneTemplate();\r\n\t\t// The \"initial\" states are only read by a handful of cards (and mutated by some, like\r\n\t\t// San'layn Scribe), so we only pay for the second clone when they are actually accessed\r\n\t\tlet playerInitialState = null;\r\n\t\tlet opponentInitialState = null;\r\n\t\tconst buildInitialStates = () => {\r\n\t\t\tconst inputClone: BgsBattleInfo = cloneTemplate();\r\n\t\t\tplayerInitialState = {\r\n\t\t\t\tplayer: inputClone.playerBoard.player,\r\n\t\t\t\tboard: inputClone.playerBoard.board,\r\n\t\t\t\tteammate: inputClone.playerTeammateBoard,\r\n\t\t\t};\r\n\t\t\topponentInitialState = {\r\n\t\t\t\tplayer: inputClone.opponentBoard.player,\r\n\t\t\t\tboard: inputClone.opponentBoard.board,\r\n\t\t\t\tteammate: inputClone.opponentTeammateBoard,\r\n\t\t\t};\r\n\t\t};\r\n\t\tconst gameState: FullGameState = {\r\n\t\t\tallCards: cards,\r\n\t\t\tcardsData: cardsData,\r\n\t\t\tspectator: spectator,\r\n\t\t\tsharedState: new SharedState(),\r\n\t\t\tcurrentTurn: input.gameState.currentTurn,\r\n\t\t\tvalidTribes: input.gameState.validTribes,\r\n\t\t\tanomalies: input.gameState.anomalies,\r\n\t\t\tgameState: {\r\n\t\t\t\tplayer: {\r\n\t\t\t\t\tplayer: input.playerBoard.player,\r\n\t\t\t\t\tboard: input.playerBoard.board,\r\n\t\t\t\t\tteammate: input.playerTeammateBoard,\r\n\t\t\t\t},\r\n\t\t\t\topponent: {\r\n\t\t\t\t\tplayer: input.opponentBoard.player,\r\n\t\t\t\t\tboard: input.opponentBoard.board,\r\n\t\t\t\t\tteammate: input.opponentTeammateBoard,\r\n\t\t\t\t},\r\n\t\t\t\tget playerInitial() {\r\n\t\t\t\t\tif (!playerInitialState) {\r\n\t\t\t\t\t\tbuildInitialStates();\r\n\t\t\t\t\t}\r\n\t\t\t\t\treturn playerInitialState;\r\n\t\t\t\t},\r\n\t\t\t\tget opponentInitial() {\r\n\t\t\t\t\tif (!opponentInitialState) {\r\n\t\t\t\t\t\tbuildInitialStates();\r\n\t\t\t\t\t}\r\n\t\t\t\t\treturn opponentInitialState;\r\n\t\t\t\t},\r\n\t\t\t},\r\n\t\t};\r\n\t\tconst simulator = new Simulator(gameState);\r\n\t\treturn simulator.simulateSingleBattle(gameState.gameState.player, gameState.gameState.opponent);\r\n\t};\r\n\r\n\ttry {\r\n\t\t!battleInput.options?.skipInfoLogs && console.time('simulation');\r\n\t\tconst outcomes = {};\r\n\t\tfor (let i = 0; i < numberOfSimulations; i++) {\r\n\t\t\tconst battleResult = runSingleBattle();\r\n\t\t\tif (!battleResult) {\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\t\t\tif (battleResult.result === 'won') {\r\n\t\t\t\tsimulationResult.won++;\r\n\t\t\t\tsimulationResult.damageWon += battleResult.damageDealt;\r\n\t\t\t\tsimulationResult.damageWons.push(battleResult.damageDealt);\r\n\t\t\t\tif (battleResult.damageDealt >= battleInput.opponentBoard.player.hpLeft) {\r\n\t\t\t\t\tsimulationResult.wonLethal++;\r\n\t\t\t\t}\r\n\t\t\t} else if (battleResult.result === 'lost') {\r\n\t\t\t\tsimulationResult.lost++;\r\n\t\t\t\tsimulationResult.damageLost += battleResult.damageDealt;\r\n\t\t\t\tsimulationResult.damageLosts.push(battleResult.damageDealt);\r\n\t\t\t\toutcomes[battleResult.damageDealt] = (outcomes[battleResult.damageDealt] ?? 0) + 1;\r\n\t\t\t\tif (\r\n\t\t\t\t\tbattleInput.playerBoard.player.hpLeft &&\r\n\t\t\t\t\tbattleResult.damageDealt >= battleInput.playerBoard.player.hpLeft\r\n\t\t\t\t) {\r\n\t\t\t\t\tsimulationResult.lostLethal++;\r\n\t\t\t\t}\r\n\t\t\t} else if (battleResult.result === 'tied') {\r\n\t\t\t\tsimulationResult.tied++;\r\n\t\t\t}\r\n\r\n\t\t\tif (Date.now() - start > maxAcceptableDuration && !hideMaxSimulationDurationWarning) {\r\n\t\t\t\t// Can happen in case of inifinite boards, or a bug. Don't hog the user's computer in that case\r\n\t\t\t\tconsole.warn('Stopping simulation after', i, 'iterations and ', Date.now() - start, 'ms');\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\r\n\t\t\t// Yield intermediate result every 200 iterations\r\n\t\t\tif (!!intermediateSteps && i > 0 && i % intermediateSteps === 0) {\r\n\t\t\t\tupdateSimulationResult(simulationResult, inputReady, damageConfidence);\r\n\t\t\t\tyield simulationResult;\r\n\t\t\t}\r\n\t\t}\r\n\t\tupdateSimulationResult(simulationResult, inputReady, damageConfidence);\r\n\t\t!battleInput.options?.skipInfoLogs && console.timeEnd('simulation');\r\n\r\n\t\t// Capture outcome samples post-hoc: re-run a few battles with action recording turned\r\n\t\t// on, until each outcome that actually occurred has a sample. This is much cheaper\r\n\t\t// than recording during the main loop, where almost all recorded actions get discarded.\r\n\t\t// This phase intentionally ignores maxAcceptableDuration: when the main loop was cut\r\n\t\t// short by the time budget, we would otherwise end up with no samples at all.\r\n\t\tif (includeOutcomeSamples) {\r\n\t\t\tconst neededOutcomes: ('won' | 'lost' | 'tied')[] = [];\r\n\t\t\tsimulationResult.won > 0 && neededOutcomes.push('won');\r\n\t\t\tsimulationResult.lost > 0 && neededOutcomes.push('lost');\r\n\t\t\tsimulationResult.tied > 0 && neededOutcomes.push('tied');\r\n\t\t\tconst missingOutcomes = new Set(neededOutcomes);\r\n\t\t\tif (missingOutcomes.size > 0) {\r\n\t\t\t\tspectator.startRecording();\r\n\t\t\t\tfor (let i = 0; i < MAX_SAMPLE_RESIMS && missingOutcomes.size > 0; i++) {\r\n\t\t\t\t\tconst battleResult = runSingleBattle();\r\n\t\t\t\t\tif (!battleResult?.result) {\r\n\t\t\t\t\t\tcontinue;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tspectator.commitBattleResult(battleResult.result);\r\n\t\t\t\t\tif (spectator.hasSampleFor(battleResult.result)) {\r\n\t\t\t\t\t\tmissingOutcomes.delete(battleResult.result);\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\tspectator.stopRecording();\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tspectator.prune();\r\n\t\tsimulationResult.outcomeSamples = spectator.buildOutcomeSamples(battleInput.gameState);\r\n\t\t// Avoid sending this verbose data\r\n\r\n\t\tsimulationResult.damageWons = [];\r\n\t\tsimulationResult.damageLosts = [];\r\n\t\t// !battleInput.options?.skipInfoLogs && console.timeEnd('full-sim');\r\n\t\treturn simulationResult;\r\n\t} finally {\r\n\t\tif (battleInput.debugState) {\r\n\t\t\tdebugState.active = false;\r\n\t\t}\r\n\t}\r\n};\r\n\r\nconst updateSimulationResult = (simulationResult: SimulationResult, input: BgsBattleInfo, damageConfidence: number) => {\r\n\tconst totalMatches = simulationResult.won + simulationResult.tied + simulationResult.lost;\r\n\tsimulationResult.wonPercent = checkRounding(\r\n\t\tMath.round((10 * (100 * simulationResult.won)) / totalMatches) / 10,\r\n\t\tsimulationResult.won,\r\n\t\ttotalMatches,\r\n\t);\r\n\tsimulationResult.wonLethalPercent = checkRounding(\r\n\t\tMath.round((10 * (100 * simulationResult.wonLethal)) / totalMatches) / 10,\r\n\t\tsimulationResult.wonLethal,\r\n\t\ttotalMatches,\r\n\t);\r\n\tsimulationResult.lostPercent = checkRounding(\r\n\t\tMath.round((10 * (100 * simulationResult.lost)) / totalMatches) / 10,\r\n\t\tsimulationResult.lost,\r\n\t\ttotalMatches,\r\n\t);\r\n\tsimulationResult.lostLethalPercent = checkRounding(\r\n\t\tMath.round((10 * (100 * simulationResult.lostLethal)) / totalMatches) / 10,\r\n\t\tsimulationResult.lostLethal,\r\n\t\ttotalMatches,\r\n\t);\r\n\tsimulationResult.tiedPercent = checkRounding(\r\n\t\tMath.max(0, 100 - simulationResult.lostPercent - simulationResult.wonPercent),\r\n\t\tsimulationResult.tied,\r\n\t\ttotalMatches,\r\n\t);\r\n\r\n\t// simulationResult.wonLethalPercent = Math.round((10 * (100 * simulationResult.wonLethal)) / totalMatches) / 10;\r\n\t// simulationResult.lostLethalPercent = Math.round((10 * (100 * simulationResult.lostLethal)) / totalMatches) / 10;\r\n\tconst totalDamageWon = simulationResult.damageWons.reduce((a, b) => a + b, 0);\r\n\tconst totalDamageLost = simulationResult.damageLosts.reduce((a, b) => a + b, 0);\r\n\tconst damageWonRange = calculateDamageRange(simulationResult.damageWons, damageConfidence);\r\n\tconst damageLostRange = calculateDamageRange(simulationResult.damageLosts, damageConfidence);\r\n\tsimulationResult.averageDamageWon = simulationResult.won ? totalDamageWon / simulationResult.won : 0;\r\n\tsimulationResult.averageDamageLost = simulationResult.lost ? totalDamageLost / simulationResult.lost : 0;\r\n\tsimulationResult.damageWonRange = simulationResult.won ? damageWonRange : null;\r\n\tsimulationResult.damageLostRange = simulationResult.lost ? damageLostRange : null;\r\n\r\n\tif (\r\n\t\tsimulationResult.averageDamageWon > 0 &&\r\n\t\tsimulationResult.averageDamageWon < input.playerBoard.player.tavernTier\r\n\t) {\r\n\t\tconsole.warn('average damage won issue');\r\n\t}\r\n\tif (\r\n\t\tsimulationResult.averageDamageLost > 0 &&\r\n\t\tsimulationResult.averageDamageLost < input.opponentBoard.player.tavernTier\r\n\t) {\r\n\t\tconsole.warn('average damage lost issue');\r\n\t}\r\n};\r\n\r\nconst calculateDamageRange = (damageArray: number[], damageConfidence: number): { min: number; max: number } => {\r\n\tif (damageArray.length === 0) {\r\n\t\treturn { min: 0, max: 0 };\r\n\t}\r\n\r\n\t// Sort the array\r\n\tconst sortedDamage = [...damageArray].sort((a, b) => a - b);\r\n\r\n\t// Calculate the 10th and 90th percentiles\r\n\tconst percentile = (arr: number[], p: number) => {\r\n\t\tconst index = Math.floor(p * arr.length);\r\n\t\treturn arr[index];\r\n\t};\r\n\r\n\tconst minDamage = percentile(sortedDamage, 1 - damageConfidence);\r\n\tconst maxDamage = percentile(sortedDamage, damageConfidence);\r\n\r\n\treturn { min: minDamage, max: maxDamage };\r\n};\r\n\r\nconst checkRounding = (roundedValue: number, initialValue: number, totalValue: number): number => {\r\n\tif (roundedValue === 0 && initialValue !== 0) {\r\n\t\treturn 0.01;\r\n\t}\r\n\tif (roundedValue === 100 && initialValue !== totalValue) {\r\n\t\treturn 99.9;\r\n\t}\r\n\treturn roundedValue;\r\n};\r\n\r\n// const cleanEnchantmentsForEntity = (\r\n// \tenchantments: { cardId: string; originEntityId?: number; timing: number }[],\r\n// \tentityIds: readonly number[],\r\n// ): { cardId: string; originEntityId?: number; timing: number }[] => {\r\n// \treturn enchantments.filter(\r\n// \t\t(enchant) =>\r\n// \t\t\tentityIds.indexOf(enchant.originEntityId) !== -1 ||\r\n// \t\t\tvalidEnchantments.indexOf(enchant.cardId as CardIds) !== -1,\r\n// \t);\r\n// };\r\n"]}
1
+ {"version":3,"file":"simulate-bgs-battle.js","sourceRoot":"","sources":["../src/simulate-bgs-battle.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable @typescript-eslint/no-use-before-define */\r\nimport { AllCardsService } from '@firestone-hs/reference-data';\r\nimport { BgsBattleInfo } from './bgs-battle-info';\r\nimport { CardsData } from './cards/cards-data';\r\nimport { debugState } from './debug-state';\r\nimport { buildTemplateCloner, cloneInput3 } from './input-clone';\r\nimport { buildFinalInput } from './input-sanitation';\r\nimport { createSeededRng, defaultRng, Rng, withRng } from './services/rng';\r\nimport { SimulationResult } from './simulation-result';\r\nimport { SingleSimulationResult } from './single-simulation-result';\r\nimport { FullGameState } from './simulation/internal-game-state';\r\nimport { SharedState } from './simulation/shared-state';\r\nimport { Simulator } from './simulation/simulator';\r\nimport { Spectator } from './simulation/spectator/spectator';\r\n\r\nexport { isValidDeathrattleEnchantment } from './simulation/deathrattle-utils';\r\nexport { createSeededRng, defaultRng, getActiveRng, random, withRng } from './services/rng';\r\nexport type { Rng } from './services/rng';\r\n\r\n// Cap for the post-hoc outcome sample capture phase: rare outcomes (e.g. a 0.1% tie\r\n// chance) might never show up again when re-simulating, so we stop hunting after this\r\n// many extra battles\r\nconst MAX_SAMPLE_RESIMS = 500;\r\n\r\nlet globalCards = new AllCardsService();\r\n\r\nexport const assignCards = (cards: AllCardsService) => {\r\n\tglobalCards = cards;\r\n};\r\n\r\nexport interface SimulateSingleCombatOptions {\r\n\t/** If set, creates a Mulberry32 RNG from this seed. Ignored when `rng` is provided. */\r\n\treadonly seed?: number;\r\n\t/** Explicit RNG instance. Takes precedence over `seed`. */\r\n\treadonly rng?: Rng;\r\n\t/** When true, records spectator actions (slower). Default false. */\r\n\treadonly includeSpectator?: boolean;\r\n}\r\n\r\n/**\r\n * Run exactly one combat with a deterministic (or default) RNG.\r\n * Intended for the full-game / self-play env — not for Firestone win% Monte Carlo.\r\n */\r\nexport const simulateSingleCombat = (\r\n\tbattleInput: BgsBattleInfo,\r\n\tcards: AllCardsService,\r\n\tcardsData: CardsData,\r\n\toptions: SimulateSingleCombatOptions = {},\r\n): SingleSimulationResult => {\r\n\tif (!cards?.getCards()?.length) {\r\n\t\tconsole.error('[simulate-bgs-battle] reference cards are empty, cannot simulate combat', cards);\r\n\t\treturn null;\r\n\t}\r\n\r\n\tconst rng = options.rng ?? (options.seed !== undefined ? createSeededRng(options.seed) : defaultRng);\r\n\tconst includeSpectator = options.includeSpectator ?? false;\r\n\r\n\tapplyDebugStateFromInput(battleInput);\r\n\ttry {\r\n\t\tconst inputReady = buildFinalInput(battleInput, cards, cardsData);\r\n\t\tconst cloneTemplate = buildTemplateCloner(cloneInput3(inputReady));\r\n\t\tconst spectator = new Spectator(includeSpectator);\r\n\t\tif (includeSpectator) {\r\n\t\t\tspectator.startRecording();\r\n\t\t}\r\n\t\treturn withRng(rng, () => runSingleBattle(cloneTemplate, cards, cardsData, spectator, rng));\r\n\t} finally {\r\n\t\tclearDebugStateFromInput(battleInput);\r\n\t}\r\n};\r\n\r\n// This example demonstrates a NodeJS 8.10 async handler[1], however of course you could use\r\n// the more traditional callback-style handler.\r\n// [1]: https://aws.amazon.com/blogs/compute/node-js-8-10-runtime-now-available-in-aws-lambda/\r\nexport default async (event): Promise<any> => {\r\n\tif (!event.body?.length) {\r\n\t\tconsole.warn('missing event body', event);\r\n\t\treturn;\r\n\t}\r\n\r\n\tconst battleInput: BgsBattleInfo = JSON.parse(event.body);\r\n\tconst cards = globalCards;\r\n\tawait cards.initializeCardsDb();\r\n\tconst cardsData = new CardsData(cards, false);\r\n\tcardsData.inititialize(\r\n\t\tbattleInput.gameState?.validTribes ?? battleInput.options?.validTribes,\r\n\t\tbattleInput.gameState?.anomalies ?? [],\r\n\t);\r\n\tconst battleIterator = simulateBattle(battleInput, cards, cardsData);\r\n\r\n\t// Iterate through all intermediate results to reach the final result\r\n\tlet result = battleIterator.next();\r\n\twhile (!result.done) {\r\n\t\tresult = battleIterator.next();\r\n\t}\r\n\r\n\tconst simulationResult = result.value;\r\n\t// console.debug('simulationResult', simulationResult);\r\n\r\n\tconst response = {\r\n\t\tstatusCode: 200,\r\n\t\tisBase64Encoded: false,\r\n\t\tbody: JSON.stringify(simulationResult),\r\n\t};\r\n\treturn response;\r\n};\r\n\r\nexport const simulateBattle = function* (\r\n\tbattleInput: BgsBattleInfo,\r\n\tcards: AllCardsService,\r\n\tcardsData: CardsData,\r\n): Generator<SimulationResult, SimulationResult, void> {\r\n\tif (!cards?.getCards()?.length) {\r\n\t\tconsole.error('[simulate-bgs-battle] reference cards are empty, cannot simulate battle', cards);\r\n\t\treturn null;\r\n\t}\r\n\t// !battleInput.options?.skipInfoLogs && console.time('full-sim');\r\n\tconst start = Date.now();\r\n\tconst maxAcceptableDuration = battleInput.options?.maxAcceptableDuration || 8000;\r\n\tconst hideMaxSimulationDurationWarning = battleInput.options?.hideMaxSimulationDurationWarning ?? false;\r\n\tconst numberOfSimulations = battleInput.options?.numberOfSimulations || 8000;\r\n\tconst intermediateSteps = battleInput.options?.intermediateResults ?? 200;\r\n\tconst damageConfidence = battleInput.options?.damageConfidence ?? 0.9;\r\n\tconst includeOutcomeSamples = battleInput.options?.includeOutcomeSamples ?? true;\r\n\tconst simulationResult: SimulationResult = {\r\n\t\twonLethal: 0,\r\n\t\twon: 0,\r\n\t\ttied: 0,\r\n\t\tlost: 0,\r\n\t\tlostLethal: 0,\r\n\t\tdamageWons: [],\r\n\t\tdamageWon: 0,\r\n\t\tdamageWonRange: null,\r\n\t\tdamageLosts: [],\r\n\t\tdamageLost: 0,\r\n\t\tdamageLostRange: null,\r\n\t\twonLethalPercent: undefined,\r\n\t\twonPercent: undefined,\r\n\t\ttiedPercent: undefined,\r\n\t\tlostPercent: undefined,\r\n\t\tlostLethalPercent: undefined,\r\n\t\taverageDamageWon: undefined,\r\n\t\taverageDamageLost: undefined,\r\n\t};\r\n\r\n\tconst spectator = new Spectator(includeOutcomeSamples);\r\n\tconst inputReady = buildFinalInput(battleInput, cards, cardsData);\r\n\r\n\tapplyDebugStateFromInput(battleInput);\r\n\r\n\t// cloneInput3 normalizes the input (sorted secrets, reset pendingAttackBuffs, etc.).\r\n\t// The compiled cloner re-materializes that normalized shape as an object literal, which is\r\n\t// faster than JSON.parse of a template string (~0.02ms vs ~0.12ms per clone on a 7v7\r\n\t// board), which was itself faster than generic recursive cloners (~0.19-0.23ms) and\r\n\t// structuredClone (~0.46ms)\r\n\tconst cloneTemplate = buildTemplateCloner(cloneInput3(inputReady));\r\n\r\n\tconst runOne = () => runSingleBattle(cloneTemplate, cards, cardsData, spectator, defaultRng);\r\n\r\n\ttry {\r\n\t\t!battleInput.options?.skipInfoLogs && console.time('simulation');\r\n\t\tconst outcomes = {};\r\n\t\tfor (let i = 0; i < numberOfSimulations; i++) {\r\n\t\t\tconst battleResult = runOne();\r\n\t\t\tif (!battleResult) {\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\t\t\tif (battleResult.result === 'won') {\r\n\t\t\t\tsimulationResult.won++;\r\n\t\t\t\tsimulationResult.damageWon += battleResult.damageDealt;\r\n\t\t\t\tsimulationResult.damageWons.push(battleResult.damageDealt);\r\n\t\t\t\tif (battleResult.damageDealt >= battleInput.opponentBoard.player.hpLeft) {\r\n\t\t\t\t\tsimulationResult.wonLethal++;\r\n\t\t\t\t}\r\n\t\t\t} else if (battleResult.result === 'lost') {\r\n\t\t\t\tsimulationResult.lost++;\r\n\t\t\t\tsimulationResult.damageLost += battleResult.damageDealt;\r\n\t\t\t\tsimulationResult.damageLosts.push(battleResult.damageDealt);\r\n\t\t\t\toutcomes[battleResult.damageDealt] = (outcomes[battleResult.damageDealt] ?? 0) + 1;\r\n\t\t\t\tif (\r\n\t\t\t\t\tbattleInput.playerBoard.player.hpLeft &&\r\n\t\t\t\t\tbattleResult.damageDealt >= battleInput.playerBoard.player.hpLeft\r\n\t\t\t\t) {\r\n\t\t\t\t\tsimulationResult.lostLethal++;\r\n\t\t\t\t}\r\n\t\t\t} else if (battleResult.result === 'tied') {\r\n\t\t\t\tsimulationResult.tied++;\r\n\t\t\t}\r\n\r\n\t\t\tif (Date.now() - start > maxAcceptableDuration && !hideMaxSimulationDurationWarning) {\r\n\t\t\t\t// Can happen in case of inifinite boards, or a bug. Don't hog the user's computer in that case\r\n\t\t\t\tconsole.warn('Stopping simulation after', i, 'iterations and ', Date.now() - start, 'ms');\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\r\n\t\t\t// Yield intermediate result every 200 iterations\r\n\t\t\tif (!!intermediateSteps && i > 0 && i % intermediateSteps === 0) {\r\n\t\t\t\tupdateSimulationResult(simulationResult, inputReady, damageConfidence);\r\n\t\t\t\tyield simulationResult;\r\n\t\t\t}\r\n\t\t}\r\n\t\tupdateSimulationResult(simulationResult, inputReady, damageConfidence);\r\n\t\t!battleInput.options?.skipInfoLogs && console.timeEnd('simulation');\r\n\r\n\t\t// Capture outcome samples post-hoc: re-run a few battles with action recording turned\r\n\t\t// on, until each outcome that actually occurred has a sample. This is much cheaper\r\n\t\t// than recording during the main loop, where almost all recorded actions get discarded.\r\n\t\t// This phase intentionally ignores maxAcceptableDuration: when the main loop was cut\r\n\t\t// short by the time budget, we would otherwise end up with no samples at all.\r\n\t\tif (includeOutcomeSamples) {\r\n\t\t\tconst neededOutcomes: ('won' | 'lost' | 'tied')[] = [];\r\n\t\t\tsimulationResult.won > 0 && neededOutcomes.push('won');\r\n\t\t\tsimulationResult.lost > 0 && neededOutcomes.push('lost');\r\n\t\t\tsimulationResult.tied > 0 && neededOutcomes.push('tied');\r\n\t\t\tconst missingOutcomes = new Set(neededOutcomes);\r\n\t\t\tif (missingOutcomes.size > 0) {\r\n\t\t\t\tspectator.startRecording();\r\n\t\t\t\tfor (let i = 0; i < MAX_SAMPLE_RESIMS && missingOutcomes.size > 0; i++) {\r\n\t\t\t\t\tconst battleResult = runOne();\r\n\t\t\t\t\tif (!battleResult?.result) {\r\n\t\t\t\t\t\tcontinue;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tspectator.commitBattleResult(battleResult.result);\r\n\t\t\t\t\tif (spectator.hasSampleFor(battleResult.result)) {\r\n\t\t\t\t\t\tmissingOutcomes.delete(battleResult.result);\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\tspectator.stopRecording();\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tspectator.prune();\r\n\t\tsimulationResult.outcomeSamples = spectator.buildOutcomeSamples(battleInput.gameState);\r\n\t\t// Avoid sending this verbose data\r\n\r\n\t\tsimulationResult.damageWons = [];\r\n\t\tsimulationResult.damageLosts = [];\r\n\t\t// !battleInput.options?.skipInfoLogs && console.timeEnd('full-sim');\r\n\t\treturn simulationResult;\r\n\t} finally {\r\n\t\tclearDebugStateFromInput(battleInput);\r\n\t}\r\n};\r\n\r\ntype CloneTemplate = () => BgsBattleInfo;\r\n\r\nconst runSingleBattle = (\r\n\tcloneTemplate: CloneTemplate,\r\n\tcards: AllCardsService,\r\n\tcardsData: CardsData,\r\n\tspectator: Spectator,\r\n\trng: Rng,\r\n): SingleSimulationResult => {\r\n\tconst input: BgsBattleInfo = cloneTemplate();\r\n\t// The \"initial\" states are only read by a handful of cards (and mutated by some, like\r\n\t// San'layn Scribe), so we only pay for the second clone when they are actually accessed\r\n\tlet playerInitialState = null;\r\n\tlet opponentInitialState = null;\r\n\tconst buildInitialStates = () => {\r\n\t\tconst inputClone: BgsBattleInfo = cloneTemplate();\r\n\t\tplayerInitialState = {\r\n\t\t\tplayer: inputClone.playerBoard.player,\r\n\t\t\tboard: inputClone.playerBoard.board,\r\n\t\t\tteammate: inputClone.playerTeammateBoard,\r\n\t\t};\r\n\t\topponentInitialState = {\r\n\t\t\tplayer: inputClone.opponentBoard.player,\r\n\t\t\tboard: inputClone.opponentBoard.board,\r\n\t\t\tteammate: inputClone.opponentTeammateBoard,\r\n\t\t};\r\n\t};\r\n\tconst gameState: FullGameState = {\r\n\t\tallCards: cards,\r\n\t\tcardsData: cardsData,\r\n\t\tspectator: spectator,\r\n\t\tsharedState: new SharedState(rng),\r\n\t\tcurrentTurn: input.gameState.currentTurn,\r\n\t\tnumberOfPlayersAlive: input.gameState.numberOfPlayersAlive,\r\n\t\tapplyDamageCap: input.options?.applyDamageCap === true,\r\n\t\tvalidTribes: input.gameState.validTribes,\r\n\t\tanomalies: input.gameState.anomalies,\r\n\t\tgameState: {\r\n\t\t\tplayer: {\r\n\t\t\t\tplayer: input.playerBoard.player,\r\n\t\t\t\tboard: input.playerBoard.board,\r\n\t\t\t\tteammate: input.playerTeammateBoard,\r\n\t\t\t},\r\n\t\t\topponent: {\r\n\t\t\t\tplayer: input.opponentBoard.player,\r\n\t\t\t\tboard: input.opponentBoard.board,\r\n\t\t\t\tteammate: input.opponentTeammateBoard,\r\n\t\t\t},\r\n\t\t\tget playerInitial() {\r\n\t\t\t\tif (!playerInitialState) {\r\n\t\t\t\t\tbuildInitialStates();\r\n\t\t\t\t}\r\n\t\t\t\treturn playerInitialState;\r\n\t\t\t},\r\n\t\t\tget opponentInitial() {\r\n\t\t\t\tif (!opponentInitialState) {\r\n\t\t\t\t\tbuildInitialStates();\r\n\t\t\t\t}\r\n\t\t\t\treturn opponentInitialState;\r\n\t\t\t},\r\n\t\t},\r\n\t};\r\n\tconst simulator = new Simulator(gameState);\r\n\treturn simulator.simulateSingleBattle(gameState.gameState.player, gameState.gameState.opponent);\r\n};\r\n\r\nconst applyDebugStateFromInput = (battleInput: BgsBattleInfo) => {\r\n\tif (!battleInput.debugState) {\r\n\t\treturn;\r\n\t}\r\n\tdebugState.active = true;\r\n\tdebugState.forcedCurrentAttacker = battleInput.debugState.forcedCurrentAttacker;\r\n\tdebugState.forcedFaceOffBase = battleInput.debugState.forcedFaceOffBase.map((f) => ({\r\n\t\tattacker: { ...f.attacker },\r\n\t\tdefender: { ...f.defender },\r\n\t}));\r\n\tconst rawPicks = battleInput.debugState.forcedRandomPicks ?? [];\r\n\tdebugState.forcedRandomPicksBase = rawPicks.map((p) => ({\r\n\t\tsource: { ...p.source },\r\n\t\ttarget: { ...p.target },\r\n\t\t...(p.chosenCardId && { chosenCardId: p.chosenCardId }),\r\n\t}));\r\n};\r\n\r\nconst clearDebugStateFromInput = (battleInput: BgsBattleInfo) => {\r\n\tif (battleInput.debugState) {\r\n\t\tdebugState.active = false;\r\n\t}\r\n};\r\n\r\nconst updateSimulationResult = (simulationResult: SimulationResult, input: BgsBattleInfo, damageConfidence: number) => {\r\n\tconst totalMatches = simulationResult.won + simulationResult.tied + simulationResult.lost;\r\n\tsimulationResult.wonPercent = checkRounding(\r\n\t\tMath.round((10 * (100 * simulationResult.won)) / totalMatches) / 10,\r\n\t\tsimulationResult.won,\r\n\t\ttotalMatches,\r\n\t);\r\n\tsimulationResult.wonLethalPercent = checkRounding(\r\n\t\tMath.round((10 * (100 * simulationResult.wonLethal)) / totalMatches) / 10,\r\n\t\tsimulationResult.wonLethal,\r\n\t\ttotalMatches,\r\n\t);\r\n\tsimulationResult.lostPercent = checkRounding(\r\n\t\tMath.round((10 * (100 * simulationResult.lost)) / totalMatches) / 10,\r\n\t\tsimulationResult.lost,\r\n\t\ttotalMatches,\r\n\t);\r\n\tsimulationResult.lostLethalPercent = checkRounding(\r\n\t\tMath.round((10 * (100 * simulationResult.lostLethal)) / totalMatches) / 10,\r\n\t\tsimulationResult.lostLethal,\r\n\t\ttotalMatches,\r\n\t);\r\n\tsimulationResult.tiedPercent = checkRounding(\r\n\t\tMath.max(0, 100 - simulationResult.lostPercent - simulationResult.wonPercent),\r\n\t\tsimulationResult.tied,\r\n\t\ttotalMatches,\r\n\t);\r\n\r\n\t// simulationResult.wonLethalPercent = Math.round((10 * (100 * simulationResult.wonLethal)) / totalMatches) / 10;\r\n\t// simulationResult.lostLethalPercent = Math.round((10 * (100 * simulationResult.lostLethal)) / totalMatches) / 10;\r\n\tconst totalDamageWon = simulationResult.damageWons.reduce((a, b) => a + b, 0);\r\n\tconst totalDamageLost = simulationResult.damageLosts.reduce((a, b) => a + b, 0);\r\n\tconst damageWonRange = calculateDamageRange(simulationResult.damageWons, damageConfidence);\r\n\tconst damageLostRange = calculateDamageRange(simulationResult.damageLosts, damageConfidence);\r\n\tsimulationResult.averageDamageWon = simulationResult.won ? totalDamageWon / simulationResult.won : 0;\r\n\tsimulationResult.averageDamageLost = simulationResult.lost ? totalDamageLost / simulationResult.lost : 0;\r\n\tsimulationResult.damageWonRange = simulationResult.won ? damageWonRange : null;\r\n\tsimulationResult.damageLostRange = simulationResult.lost ? damageLostRange : null;\r\n\r\n\tif (\r\n\t\tsimulationResult.averageDamageWon > 0 &&\r\n\t\tsimulationResult.averageDamageWon < input.playerBoard.player.tavernTier\r\n\t) {\r\n\t\tconsole.warn('average damage won issue');\r\n\t}\r\n\tif (\r\n\t\tsimulationResult.averageDamageLost > 0 &&\r\n\t\tsimulationResult.averageDamageLost < input.opponentBoard.player.tavernTier\r\n\t) {\r\n\t\tconsole.warn('average damage lost issue');\r\n\t}\r\n};\r\n\r\nconst calculateDamageRange = (damageArray: number[], damageConfidence: number): { min: number; max: number } => {\r\n\tif (damageArray.length === 0) {\r\n\t\treturn { min: 0, max: 0 };\r\n\t}\r\n\r\n\t// Sort the array\r\n\tconst sortedDamage = [...damageArray].sort((a, b) => a - b);\r\n\r\n\t// Calculate the 10th and 90th percentiles\r\n\tconst percentile = (arr: number[], p: number) => {\r\n\t\tconst index = Math.floor(p * arr.length);\r\n\t\treturn arr[index];\r\n\t};\r\n\r\n\tconst minDamage = percentile(sortedDamage, 1 - damageConfidence);\r\n\tconst maxDamage = percentile(sortedDamage, damageConfidence);\r\n\r\n\treturn { min: minDamage, max: maxDamage };\r\n};\r\n\r\nconst checkRounding = (roundedValue: number, initialValue: number, totalValue: number): number => {\r\n\tif (roundedValue === 0 && initialValue !== 0) {\r\n\t\treturn 0.01;\r\n\t}\r\n\tif (roundedValue === 100 && initialValue !== totalValue) {\r\n\t\treturn 99.9;\r\n\t}\r\n\treturn roundedValue;\r\n};\r\n\r\n// const cleanEnchantmentsForEntity = (\r\n// \tenchantments: { cardId: string; originEntityId?: number; timing: number }[],\r\n// \tentityIds: readonly number[],\r\n// ): { cardId: string; originEntityId?: number; timing: number }[] => {\r\n// \treturn enchantments.filter(\r\n// \t\t(enchant) =>\r\n// \t\t\tentityIds.indexOf(enchant.originEntityId) !== -1 ||\r\n// \t\t\tvalidEnchantments.indexOf(enchant.cardId as CardIds) !== -1,\r\n// \t);\r\n// };\r\n"]}
@@ -162,7 +162,7 @@ const handleAddedMinionAuraEffect = (board, boardHero, otherBoard, otherHero, sp
162
162
  };
163
163
  exports.handleAddedMinionAuraEffect = handleAddedMinionAuraEffect;
164
164
  const applyAurasToSelf = (spawned, board, boardHero, gameState, applyAttackAuras = true, applyHealthAuras = true) => {
165
- var _a, _b, _c, _d, _e, _f, _g, _h;
165
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j;
166
166
  if (applyAttackAuras) {
167
167
  spawned.attack += boardHero.globalInfo.AdditionalAttack;
168
168
  }
@@ -393,7 +393,7 @@ const applyAurasToSelf = (spawned, board, boardHero, gameState, applyAttackAuras
393
393
  case "BG_TTN_401":
394
394
  case "BG_TTN_401_G":
395
395
  const multiplierAstral = spawned.cardId === "BG_TTN_401_G" ? 2 : 1;
396
- const statsBonusAstral = multiplierAstral * (boardHero.globalInfo.AstralAutomatonsSummonedThisGame - 1);
396
+ const statsBonusAstral = multiplierAstral * (((_j = boardHero.globalInfo.AstralAutomatonsSummonedThisGame) !== null && _j !== void 0 ? _j : 0) - 1);
397
397
  (0, stats_1.modifyStats)(spawned, null, applyAttackAuras ? 3 * statsBonusAstral : 0, applyHealthAuras ? 2 * statsBonusAstral : 0, board, boardHero, gameState, false);
398
398
  break;
399
399
  case "BG25_013":
@@ -406,7 +406,7 @@ const applyAurasToSelf = (spawned, board, boardHero, gameState, applyAttackAuras
406
406
  };
407
407
  exports.applyAurasToSelf = applyAurasToSelf;
408
408
  const removeAurasFromSelf = (entity, board, boardHero, gameState, applyAttackAuras = true, applyHealthAuras = true, isOnBoard = true) => {
409
- var _a, _b;
409
+ var _a, _b, _c, _d;
410
410
  if (applyAttackAuras) {
411
411
  entity.attack -= Math.max(0, boardHero.globalInfo.AdditionalAttack);
412
412
  entity.maxAttack -= Math.max(0, boardHero.globalInfo.AdditionalAttack);
@@ -637,8 +637,8 @@ const removeAurasFromSelf = (entity, board, boardHero, gameState, applyAttackAur
637
637
  const multiplierAstral = entity.cardId === "BG_TTN_401_G" ? 2 : 1;
638
638
  const statsBonusAstral = multiplierAstral *
639
639
  (isOnBoard
640
- ? boardHero.globalInfo.AstralAutomatonsSummonedThisGame - 1
641
- : boardHero.globalInfo.AstralAutomatonsSummonedThisGame);
640
+ ? ((_c = boardHero.globalInfo.AstralAutomatonsSummonedThisGame) !== null && _c !== void 0 ? _c : 0) - 1
641
+ : (_d = boardHero.globalInfo.AstralAutomatonsSummonedThisGame) !== null && _d !== void 0 ? _d : 0);
642
642
  if (applyAttackAuras) {
643
643
  entity.attack = Math.max(0, entity.attack - 3 * statsBonusAstral);
644
644
  entity.maxAttack = Math.max(0, entity.maxAttack - 3 * statsBonusAstral);
@@ -671,6 +671,7 @@ const removeAurasFromSelf = (entity, board, boardHero, gameState, applyAttackAur
671
671
  };
672
672
  exports.removeAurasFromSelf = removeAurasFromSelf;
673
673
  const handleMinionAddedAuraEffect = (spawnedCardId, spawned, board, boardHero, gameState, isActuallySpawned = true) => {
674
+ var _a;
674
675
  switch (spawnedCardId) {
675
676
  case "BG_NEW1_027":
676
677
  case "TB_BaconUps_136":
@@ -711,7 +712,8 @@ const handleMinionAddedAuraEffect = (spawnedCardId, spawned, board, boardHero, g
711
712
  case "BG_TTN_401":
712
713
  case "BG_TTN_401_G":
713
714
  if (isActuallySpawned) {
714
- boardHero.globalInfo.AstralAutomatonsSummonedThisGame++;
715
+ boardHero.globalInfo.AstralAutomatonsSummonedThisGame =
716
+ ((_a = boardHero.globalInfo.AstralAutomatonsSummonedThisGame) !== null && _a !== void 0 ? _a : 0) + 1;
715
717
  }
716
718
  board
717
719
  .filter((e) => e.entityId !== spawned.entityId)