@firestone-hs/simulate-bgs-battle 1.1.222 → 1.1.223

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 (39) hide show
  1. package/dist/bgs-player-entity.d.ts +5 -0
  2. package/dist/bgs-player-entity.js.map +1 -1
  3. package/dist/board-entity.d.ts +1 -0
  4. package/dist/board-entity.js.map +1 -1
  5. package/dist/cards/cards-data.d.ts +0 -3
  6. package/dist/cards/cards-data.js +20 -27
  7. package/dist/cards/cards-data.js.map +1 -1
  8. package/dist/simulate-bgs-battle.js +2 -2
  9. package/dist/simulate-bgs-battle.js.map +1 -1
  10. package/dist/simulation/add-minion-to-board.d.ts +7 -0
  11. package/dist/simulation/add-minion-to-board.js +277 -0
  12. package/dist/simulation/add-minion-to-board.js.map +1 -0
  13. package/dist/simulation/attack.d.ts +1 -1
  14. package/dist/simulation/attack.js +52 -43
  15. package/dist/simulation/attack.js.map +1 -1
  16. package/dist/simulation/auras.d.ts +2 -5
  17. package/dist/simulation/auras.js +65 -232
  18. package/dist/simulation/auras.js.map +1 -1
  19. package/dist/simulation/avenge.js +13 -0
  20. package/dist/simulation/avenge.js.map +1 -1
  21. package/dist/simulation/deathrattle-effects.d.ts +1 -0
  22. package/dist/simulation/deathrattle-effects.js +67 -20
  23. package/dist/simulation/deathrattle-effects.js.map +1 -1
  24. package/dist/simulation/deathrattle-spawns.js +16 -80
  25. package/dist/simulation/deathrattle-spawns.js.map +1 -1
  26. package/dist/simulation/frenzy.js +3 -1
  27. package/dist/simulation/frenzy.js.map +1 -1
  28. package/dist/simulation/remove-minion-from-board.d.ts +4 -0
  29. package/dist/simulation/remove-minion-from-board.js +52 -0
  30. package/dist/simulation/remove-minion-from-board.js.map +1 -0
  31. package/dist/simulation/start-of-combat.js +38 -45
  32. package/dist/simulation/start-of-combat.js.map +1 -1
  33. package/dist/utils.d.ts +6 -4
  34. package/dist/utils.js +82 -73
  35. package/dist/utils.js.map +1 -1
  36. package/package.json +2 -2
  37. package/dist/simulation/spawn-effect.d.ts +0 -5
  38. package/dist/simulation/spawn-effect.js +0 -54
  39. package/dist/simulation/spawn-effect.js.map +0 -1
@@ -11,5 +11,10 @@ export interface BgsPlayerEntity {
11
11
  cardsInHand?: number;
12
12
  avengeCurrent?: number;
13
13
  avengeDefault?: number;
14
+ globalInfo?: BgsPlayerGlobalInfo;
14
15
  deadEyeDamageDone?: number;
15
16
  }
17
+ export interface BgsPlayerGlobalInfo {
18
+ EternalKnightsDeadThisGame: number;
19
+ UndeadAttackBonus: number;
20
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"bgs-player-entity.js","sourceRoot":"","sources":["../src/bgs-player-entity.ts"],"names":[],"mappings":"","sourcesContent":["export interface BgsPlayerEntity {\r\n\treadonly cardId: string;\r\n\treadonly nonGhostCardId?: string;\r\n\treadonly hpLeft: number;\r\n\treadonly tavernTier: number;\r\n\treadonly heroPowerId?: string | undefined | null;\r\n\treadonly heroPowerUsed: boolean;\r\n\treadonly heroPowerInfo?: number;\r\n\tentityId?: number;\r\n\tquestRewards?: readonly string[];\r\n\tcardsInHand?: number;\r\n\tavengeCurrent?: number;\r\n\tavengeDefault?: number;\r\n\r\n\tdeadEyeDamageDone?: number;\r\n}\r\n"]}
1
+ {"version":3,"file":"bgs-player-entity.js","sourceRoot":"","sources":["../src/bgs-player-entity.ts"],"names":[],"mappings":"","sourcesContent":["export interface BgsPlayerEntity {\r\n\treadonly cardId: string;\r\n\treadonly nonGhostCardId?: string;\r\n\treadonly hpLeft: number;\r\n\treadonly tavernTier: number;\r\n\treadonly heroPowerId?: string | undefined | null;\r\n\treadonly heroPowerUsed: boolean;\r\n\treadonly heroPowerInfo?: number;\r\n\tentityId?: number;\r\n\tquestRewards?: readonly string[];\r\n\tcardsInHand?: number;\r\n\tavengeCurrent?: number;\r\n\tavengeDefault?: number;\r\n\tglobalInfo?: BgsPlayerGlobalInfo;\r\n\r\n\tdeadEyeDamageDone?: number;\r\n}\r\n\r\nexport interface BgsPlayerGlobalInfo {\r\n\tEternalKnightsDeadThisGame: number;\r\n\tUndeadAttackBonus: number;\r\n}\r\n"]}
@@ -21,6 +21,7 @@ export interface BoardEntity {
21
21
  originEntityId?: number;
22
22
  timing: number;
23
23
  repeats?: number;
24
+ value?: number;
24
25
  }[];
25
26
  rememberedDeathrattles?: {
26
27
  cardId: string;
@@ -1 +1 @@
1
- {"version":3,"file":"board-entity.js","sourceRoot":"","sources":["../src/board-entity.ts"],"names":[],"mappings":"","sourcesContent":["export interface BoardEntity {\r\n\tentityId: number;\r\n\tcardId: string;\r\n\tattack: number;\r\n\thealth: number;\r\n\r\n\tmaxHealth?: number;\r\n\tavengeCurrent?: number;\r\n\tavengeDefault?: number;\r\n\tfrenzyApplied?: boolean;\r\n\tdefinitelyDead?: boolean;\r\n\ttaunt?: boolean;\r\n\tdivineShield?: boolean;\r\n\tpoisonous?: boolean;\r\n\treborn?: boolean;\r\n\tcleave?: boolean;\r\n\twindfury?: boolean;\r\n\tmegaWindfury?: boolean;\r\n\tstealth?: boolean;\r\n\tenchantments?: { cardId: string; originEntityId?: number; timing: number; repeats?: number }[];\r\n\t// We only store the card id, because we want all the attack and other data to be computed at runtime, based on the\r\n\t// current stats of the Fish\r\n\trememberedDeathrattles?: { cardId: string; timing: number; repeats: number }[];\r\n\tdamageMultiplier?: number;\r\n\r\n\tfriendly?: boolean;\r\n\tcantAttack?: boolean;\r\n\tattacksPerformed?: number;\r\n\timmuneWhenAttackCharges?: number;\r\n\tattackImmediately?: boolean;\r\n\t// Used only to handle murkeye aura?\r\n\tpreviousAttack?: number;\r\n\tlastAffectedByEntity?: BoardEntity;\r\n\tattacking?: boolean;\r\n}\r\n"]}
1
+ {"version":3,"file":"board-entity.js","sourceRoot":"","sources":["../src/board-entity.ts"],"names":[],"mappings":"","sourcesContent":["export interface BoardEntity {\r\n\tentityId: number;\r\n\tcardId: string;\r\n\tattack: number;\r\n\thealth: number;\r\n\r\n\tmaxHealth?: number;\r\n\tavengeCurrent?: number;\r\n\tavengeDefault?: number;\r\n\tfrenzyApplied?: boolean;\r\n\tdefinitelyDead?: boolean;\r\n\ttaunt?: boolean;\r\n\tdivineShield?: boolean;\r\n\tpoisonous?: boolean;\r\n\treborn?: boolean;\r\n\tcleave?: boolean;\r\n\twindfury?: boolean;\r\n\tmegaWindfury?: boolean;\r\n\tstealth?: boolean;\r\n\tenchantments?: { cardId: string; originEntityId?: number; timing: number; repeats?: number; value?: number }[];\r\n\t// We only store the card id, because we want all the attack and other data to be computed at runtime, based on the\r\n\t// current stats of the Fish\r\n\trememberedDeathrattles?: { cardId: string; timing: number; repeats: number }[];\r\n\tdamageMultiplier?: number;\r\n\r\n\tfriendly?: boolean;\r\n\tcantAttack?: boolean;\r\n\tattacksPerformed?: number;\r\n\timmuneWhenAttackCharges?: number;\r\n\tattackImmediately?: boolean;\r\n\t// Used only to handle murkeye aura?\r\n\tpreviousAttack?: number;\r\n\tlastAffectedByEntity?: BoardEntity;\r\n\tattacking?: boolean;\r\n}\r\n"]}
@@ -1,6 +1,4 @@
1
1
  import { AllCardsService, CardIds, Race } from '@firestone-hs/reference-data';
2
- export declare const AURA_ENCHANTMENTS: readonly string[][];
3
- export declare const AURA_ORIGINS: readonly string[];
4
2
  export declare const START_OF_COMBAT_CARD_IDS: CardIds[];
5
3
  export declare const WHELP_CARD_IDS: CardIds[];
6
4
  export declare class CardsData {
@@ -12,7 +10,6 @@ export declare class CardsData {
12
10
  kilrekSpawns: readonly string[];
13
11
  brannEpicEggSpawns: readonly string[];
14
12
  pirateSpawns: readonly string[];
15
- auraOrigins: readonly string[];
16
13
  private minionsForTier;
17
14
  constructor(allCards: AllCardsService, init?: boolean);
18
15
  inititialize(validTribes?: readonly Race[]): void;
@@ -1,26 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.CardsData = exports.WHELP_CARD_IDS = exports.START_OF_COMBAT_CARD_IDS = exports.AURA_ORIGINS = exports.AURA_ENCHANTMENTS = void 0;
3
+ exports.CardsData = exports.WHELP_CARD_IDS = exports.START_OF_COMBAT_CARD_IDS = void 0;
4
4
  const reference_data_1 = require("@firestone-hs/reference-data");
5
5
  const utils_1 = require("../services/utils");
6
6
  const utils_2 = require("../utils");
7
- exports.AURA_ENCHANTMENTS = [
8
- ["BG21_039", "BG21_039e"],
9
- ["BG21_039_G", "BG21_039_Ge"],
10
- ["BG_EX1_507", "EX1_507e"],
11
- ["TB_BaconUps_008", "TB_BaconUps_008e"],
12
- ["BG_NEW1_027", "NEW1_027e"],
13
- ["TB_BaconUps_136", "TB_BaconUps_136e"],
14
- [
15
- "TB_BaconShop_HERO_52_Buddy",
16
- "TB_BaconShop_HERO_52_Buddy_e",
17
- ],
18
- [
19
- "TB_BaconShop_HERO_52_Buddy_G",
20
- "TB_BaconShop_HERO_52_Buddy_G_e",
21
- ],
22
- ];
23
- exports.AURA_ORIGINS = exports.AURA_ENCHANTMENTS.map((pair) => pair[0]);
24
7
  exports.START_OF_COMBAT_CARD_IDS = [
25
8
  "BG23_012",
26
9
  "BG23_012_G",
@@ -36,6 +19,8 @@ exports.START_OF_COMBAT_CARD_IDS = [
36
19
  "BG24_500_G",
37
20
  "BG24_704",
38
21
  "BG24_704_G",
22
+ "BG25_023",
23
+ "BG25_023_G",
39
24
  ];
40
25
  exports.WHELP_CARD_IDS = ["BGS_019", "TB_BaconUps_102", "BG22_HERO_305t"];
41
26
  class CardsData {
@@ -57,25 +42,25 @@ class CardsData {
57
42
  .filter((card) => !this.isGolden(card))
58
43
  .filter((card) => card.id !== 'BGS_008')
59
44
  .filter((card) => utils_2.hasMechanic(card, 'DEATHRATTLE'))
60
- .filter((card) => this.isValidTribe(validTribes, card.race))
45
+ .filter((card) => this.isValidTribe(validTribes, card.races))
61
46
  .map((card) => card.id);
62
47
  this.validDeathrattles = pool
63
48
  .filter((card) => utils_2.hasMechanic(card, 'DEATHRATTLE'))
64
- .filter((card) => this.isValidTribe(validTribes, card.race))
49
+ .filter((card) => this.isValidTribe(validTribes, card.races))
65
50
  .map((card) => card.id);
66
51
  this.impMamaSpawns = pool
67
52
  .filter((card) => !this.isGolden(card))
68
- .filter((card) => card.race === 'DEMON')
53
+ .filter((card) => utils_2.isCorrectTribe(card.races, reference_data_1.Race.DEMON))
69
54
  .filter((card) => card.id !== "BGS_044")
70
55
  .map((card) => card.id);
71
56
  this.gentleDjinniSpawns = pool
72
57
  .filter((card) => !this.isGolden(card))
73
- .filter((card) => card.race === 'ELEMENTAL')
58
+ .filter((card) => utils_2.isCorrectTribe(card.races, reference_data_1.Race.ELEMENTAL))
74
59
  .filter((card) => card.id !== "BGS_121")
75
60
  .map((card) => card.id);
76
61
  this.kilrekSpawns = pool
77
62
  .filter((card) => !this.isGolden(card))
78
- .filter((card) => card.race === reference_data_1.Race[reference_data_1.Race.DEMON])
63
+ .filter((card) => utils_2.isCorrectTribe(card.races, reference_data_1.Race.DEMON))
79
64
  .filter((card) => card.id !== "TB_BaconShop_HERO_37_Buddy")
80
65
  .map((card) => card.id);
81
66
  this.brannEpicEggSpawns = pool
@@ -84,13 +69,17 @@ class CardsData {
84
69
  .map((card) => card.id);
85
70
  this.pirateSpawns = pool
86
71
  .filter((card) => !this.isGolden(card))
87
- .filter((card) => card.race === 'PIRATE')
72
+ .filter((card) => utils_2.isCorrectTribe(card.races, reference_data_1.Race.PIRATE))
88
73
  .map((card) => card.id);
89
74
  }
90
75
  avengeValue(cardId) {
91
76
  switch (cardId) {
92
77
  case "BG21_002":
93
78
  case "BG21_002_G":
79
+ case "BG25_002":
80
+ case "BG25_002_G":
81
+ case "BG25_014":
82
+ case "BG25_014_G":
94
83
  return 1;
95
84
  case "BG22_HERO_002_Buddy":
96
85
  case "BG22_HERO_002_Buddy_G":
@@ -136,9 +125,13 @@ class CardsData {
136
125
  isGolden(card) {
137
126
  return !!card.battlegroundsNormalDbfId;
138
127
  }
139
- isValidTribe(validTribes, race) {
140
- const raceEnum = utils_2.getRaceEnum(race);
141
- return raceEnum === reference_data_1.Race.ALL || !(validTribes === null || validTribes === void 0 ? void 0 : validTribes.length) || validTribes.includes(raceEnum);
128
+ isValidTribe(validTribes, races) {
129
+ if (!(races === null || races === void 0 ? void 0 : races.length)) {
130
+ return false;
131
+ }
132
+ return races
133
+ .map((race) => utils_2.getRaceEnum(race))
134
+ .some((raceEnum) => raceEnum === reference_data_1.Race.ALL || !(validTribes === null || validTribes === void 0 ? void 0 : validTribes.length) || validTribes.includes(raceEnum));
142
135
  }
143
136
  }
144
137
  exports.CardsData = CardsData;
@@ -1 +1 @@
1
- {"version":3,"file":"cards-data.js","sourceRoot":"","sources":["../../src/cards/cards-data.ts"],"names":[],"mappings":"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","sourcesContent":["import { AllCardsService, CardIds, GameTag, isBattlegroundsCard, Race, ReferenceCard } from '@firestone-hs/reference-data';\r\nimport { groupByFunction, pickRandom } from '../services/utils';\r\nimport { getRaceEnum, hasMechanic } from '../utils';\r\n\r\nexport const AURA_ENCHANTMENTS: readonly string[][] = [\r\n\t[CardIds.Kathranatir_BG21_039, CardIds.Kathranatir_GraspOfKathranatirEnchantment_BG21_039e],\r\n\t[CardIds.KathranatirBattlegrounds, CardIds.Kathranatir_GraspOfKathranatirEnchantment_BG21_039_Ge],\r\n\t[CardIds.MurlocWarleaderLegacy_BG_EX1_507, CardIds.MurlocWarleader_MrgglaarglLegacyEnchantment],\r\n\t[CardIds.MurlocWarleaderLegacyBattlegrounds, CardIds.MurlocWarleader_MrgglaarglEnchantmentBattlegrounds],\r\n\t[CardIds.SouthseaCaptainLegacy_BG_NEW1_027, CardIds.SouthseaCaptain_YarrrLegacyEnchantment],\r\n\t[CardIds.SouthseaCaptainLegacyBattlegrounds, CardIds.SouthseaCaptain_YarrrEnchantmentBattlegrounds],\r\n\t[\r\n\t\tCardIds.LadySinestraBattlegrounds_TB_BaconShop_HERO_52_Buddy,\r\n\t\tCardIds.DraconicBlessingEnchantmentBattlegrounds_TB_BaconShop_HERO_52_Buddy_e,\r\n\t],\r\n\t[\r\n\t\tCardIds.LadySinestraBattlegrounds_TB_BaconShop_HERO_52_Buddy_G,\r\n\t\tCardIds.DraconicBlessingEnchantmentBattlegrounds_TB_BaconShop_HERO_52_Buddy_G_e,\r\n\t],\r\n];\r\n// Auras are effects that are permanent (unlike deathrattles or \"whenever\" effects)\r\n// and that stop once the origin entity leaves play (so it doesn't include buffs)\r\nexport const AURA_ORIGINS: readonly string[] = AURA_ENCHANTMENTS.map((pair) => pair[0]);\r\nexport const START_OF_COMBAT_CARD_IDS = [\r\n\tCardIds.CorruptedMyrmidon,\r\n\tCardIds.CorruptedMyrmidonBattlegrounds,\r\n\tCardIds.Crabby_BG22_HERO_000_Buddy,\r\n\tCardIds.CrabbyBattlegrounds,\r\n\tCardIds.MantidQueen,\r\n\tCardIds.MantidQueenBattlegrounds,\r\n\tCardIds.PrizedPromoDrake,\r\n\tCardIds.PrizedPromoDrakeBattlegrounds,\r\n\tCardIds.RedWhelp,\r\n\tCardIds.RedWhelpBattlegrounds,\r\n\tCardIds.AmberGuardian,\r\n\tCardIds.AmberGuardianBattlegrounds,\r\n\tCardIds.InterrogatorWhitemane,\r\n\tCardIds.InterrogatorWhitemaneBattlegrounds,\r\n];\r\nexport const WHELP_CARD_IDS = [CardIds.RedWhelp, CardIds.RedWhelpBattlegrounds, CardIds.Onyxia_OnyxianWhelpToken];\r\n\r\nexport class CardsData {\r\n\t// public shredderSpawns: readonly string[];\r\n\tpublic ghastcoilerSpawns: readonly string[];\r\n\tpublic validDeathrattles: readonly string[];\r\n\tpublic impMamaSpawns: readonly string[];\r\n\tpublic gentleDjinniSpawns: readonly string[];\r\n\tpublic kilrekSpawns: readonly string[];\r\n\tpublic brannEpicEggSpawns: readonly string[];\r\n\t// public sneedsSpawns: readonly string[];\r\n\t// public treasureChestSpawns: readonly string[];\r\n\tpublic pirateSpawns: readonly string[];\r\n\tpublic auraOrigins: readonly string[];\r\n\r\n\tprivate minionsForTier: { [key: string]: readonly ReferenceCard[] };\r\n\r\n\tconstructor(private readonly allCards: AllCardsService, init = true) {\r\n\t\tif (init) {\r\n\t\t\tthis.inititialize();\r\n\t\t}\r\n\t}\r\n\r\n\tpublic inititialize(validTribes?: readonly Race[]): void {\r\n\t\tconst pool = this.allCards\r\n\t\t\t.getCards()\r\n\t\t\t.filter((card) => isBattlegroundsCard(card))\r\n\t\t\t.filter((card) => !!card.techLevel)\r\n\t\t\t.filter((card) => !hasMechanic(card, GameTag[GameTag.BACON_BUDDY]))\r\n\t\t\t.filter((card) => card.set !== 'Vanilla');\r\n\t\tthis.minionsForTier = groupByFunction((card: ReferenceCard) => card.techLevel)(pool.filter((card) => !this.isGolden(card)));\r\n\t\tthis.ghastcoilerSpawns = pool\r\n\t\t\t.filter((card) => !this.isGolden(card))\r\n\t\t\t.filter((card) => card.id !== 'BGS_008')\r\n\t\t\t.filter((card) => hasMechanic(card, 'DEATHRATTLE'))\r\n\t\t\t// .filter((card) => REMOVED_CARD_IDS.indexOf(card.id) === -1)\r\n\t\t\t.filter((card) => this.isValidTribe(validTribes, card.race))\r\n\t\t\t.map((card) => card.id);\r\n\t\tthis.validDeathrattles = pool\r\n\t\t\t// .filter((card) => !card.id.startsWith('TB_BaconUps')) // Ignore golden\r\n\t\t\t.filter((card) => hasMechanic(card, 'DEATHRATTLE'))\r\n\t\t\t// .filter((card) => REMOVED_CARD_IDS.indexOf(card.id) === -1)\r\n\t\t\t.filter((card) => this.isValidTribe(validTribes, card.race))\r\n\t\t\t.map((card) => card.id);\r\n\t\tthis.impMamaSpawns = pool\r\n\t\t\t.filter((card) => !this.isGolden(card))\r\n\t\t\t.filter((card) => card.race === 'DEMON')\r\n\t\t\t.filter((card) => card.id !== CardIds.ImpMama)\r\n\t\t\t// .filter((card) => REMOVED_CARD_IDS.indexOf(card.id) === -1)\r\n\t\t\t.map((card) => card.id);\r\n\t\tthis.gentleDjinniSpawns = pool\r\n\t\t\t.filter((card) => !this.isGolden(card))\r\n\t\t\t.filter((card) => card.race === 'ELEMENTAL')\r\n\t\t\t.filter((card) => card.id !== CardIds.GentleDjinni)\r\n\t\t\t// .filter((card) => REMOVED_CARD_IDS.indexOf(card.id) === -1)\r\n\t\t\t.map((card) => card.id);\r\n\t\tthis.kilrekSpawns = pool\r\n\t\t\t.filter((card) => !this.isGolden(card))\r\n\t\t\t.filter((card) => card.race === Race[Race.DEMON])\r\n\t\t\t.filter((card) => card.id !== CardIds.KilrekBattlegrounds_TB_BaconShop_HERO_37_Buddy)\r\n\t\t\t// .filter((card) => REMOVED_CARD_IDS.indexOf(card.id) === -1)\r\n\t\t\t.map((card) => card.id);\r\n\t\tthis.brannEpicEggSpawns = pool\r\n\t\t\t.filter((card) => !this.isGolden(card))\r\n\t\t\t.filter((card) => hasMechanic(card, 'BATTLECRY'))\r\n\t\t\t.map((card) => card.id);\r\n\t\tthis.pirateSpawns = pool\r\n\t\t\t.filter((card) => !this.isGolden(card))\r\n\t\t\t.filter((card) => card.race === 'PIRATE')\r\n\t\t\t// .filter((card) => REMOVED_CARD_IDS.indexOf(card.id) === -1)\r\n\t\t\t.map((card) => card.id);\r\n\t}\r\n\r\n\tpublic avengeValue(cardId: string): number {\r\n\t\tswitch (cardId) {\r\n\t\t\tcase CardIds.BirdBuddy:\r\n\t\t\tcase CardIds.BirdBuddyBattlegrounds:\r\n\t\t\t\treturn 1;\r\n\t\t\tcase CardIds.FrostwolfLieutenant:\r\n\t\t\tcase CardIds.FrostwolfLieutenantBattlegrounds:\r\n\t\t\tcase CardIds.MechanoTank:\r\n\t\t\tcase CardIds.MechanoTankBattlegrounds:\r\n\t\t\tcase CardIds.PalescaleCrocolisk:\r\n\t\t\tcase CardIds.PalescaleCrocoliskBattlegrounds:\r\n\t\t\tcase CardIds.StormpikeLieutenant:\r\n\t\t\tcase CardIds.StormpikeLieutenantBattlegrounds:\r\n\t\t\tcase CardIds.VanndarStormpike_LeadTheStormpikes:\r\n\t\t\t\treturn 2;\r\n\t\t\tcase CardIds.BuddingGreenthumb_BG21_030:\r\n\t\t\tcase CardIds.BuddingGreenthumb_BG21_030_G:\r\n\t\t\tcase CardIds.PashmarTheVengeful:\r\n\t\t\tcase CardIds.PashmarTheVengefulBattlegrounds:\r\n\t\t\tcase CardIds.WitchwingNestmatron_BG21_038:\r\n\t\t\tcase CardIds.WitchwingNestmatron_BG21_038_G:\r\n\t\t\tcase CardIds.Drekthar_LeadTheFrostwolves:\r\n\t\t\t\treturn 3;\r\n\t\t\tcase CardIds.ImpatientDoomsayer:\r\n\t\t\tcase CardIds.ImpatientDoomsayerBattlegrounds:\r\n\t\t\tcase CardIds.Sisefin_BG21_009:\r\n\t\t\tcase CardIds.Sisefin_BG21_009_G:\r\n\t\t\tcase CardIds.TonyTwoTusk:\r\n\t\t\tcase CardIds.TonyTwoTuskBattlegrounds:\r\n\t\t\tcase CardIds.Onyxia_Broodmother:\r\n\t\t\t\treturn 4;\r\n\t\t}\r\n\t\treturn 0;\r\n\t}\r\n\r\n\tpublic getTavernLevel(cardId: string): number {\r\n\t\treturn this.allCards.getCard(cardId).techLevel ?? 1;\r\n\t}\r\n\r\n\tpublic getRandomMinionForTavernTier(tavernTier: number): string {\r\n\t\t// Tzvern tier can be undefined for hero-power specific tokens, like the Amalgam, or when\r\n\t\t// for some reason tokens end up in the shop. For now, defaulting to 1 for tavern\r\n\t\t// level seems to work in all cases\r\n\t\tconst minionsForTier = this.minionsForTier[tavernTier ?? 1];\r\n\t\tif (!minionsForTier?.length) {\r\n\t\t\tconsole.error('incorrect minions for tier', tavernTier, this.minionsForTier, minionsForTier);\r\n\t\t}\r\n\t\treturn pickRandom(this.minionsForTier[tavernTier ?? 1])?.id;\r\n\t}\r\n\r\n\tprivate isGolden(card: ReferenceCard): boolean {\r\n\t\treturn !!card.battlegroundsNormalDbfId;\r\n\t}\r\n\r\n\tprivate isValidTribe(validTribes: readonly Race[], race: string): boolean {\r\n\t\tconst raceEnum: Race = getRaceEnum(race);\r\n\t\treturn raceEnum === Race.ALL || !validTribes?.length || validTribes.includes(raceEnum);\r\n\t}\r\n}\r\n"]}
1
+ {"version":3,"file":"cards-data.js","sourceRoot":"","sources":["../../src/cards/cards-data.ts"],"names":[],"mappings":"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","sourcesContent":["import { AllCardsService, CardIds, GameTag, isBattlegroundsCard, Race, ReferenceCard } from '@firestone-hs/reference-data';\r\nimport { groupByFunction, pickRandom } from '../services/utils';\r\nimport { getRaceEnum, hasMechanic, isCorrectTribe } from '../utils';\r\n\r\nexport const START_OF_COMBAT_CARD_IDS = [\r\n\tCardIds.CorruptedMyrmidon,\r\n\tCardIds.CorruptedMyrmidonBattlegrounds,\r\n\tCardIds.Crabby_BG22_HERO_000_Buddy,\r\n\tCardIds.CrabbyBattlegrounds,\r\n\tCardIds.MantidQueen,\r\n\tCardIds.MantidQueenBattlegrounds,\r\n\tCardIds.PrizedPromoDrake,\r\n\tCardIds.PrizedPromoDrakeBattlegrounds,\r\n\tCardIds.RedWhelp,\r\n\tCardIds.RedWhelpBattlegrounds,\r\n\tCardIds.AmberGuardian,\r\n\tCardIds.AmberGuardianBattlegrounds,\r\n\tCardIds.InterrogatorWhitemane_BG24_704,\r\n\tCardIds.InterrogatorWhitemane_BG24_704_G,\r\n\tCardIds.Soulsplitter,\r\n\tCardIds.SoulsplitterBattlegrounds,\r\n];\r\nexport const WHELP_CARD_IDS = [CardIds.RedWhelp, CardIds.RedWhelpBattlegrounds, CardIds.Onyxia_OnyxianWhelpToken];\r\n\r\nexport class CardsData {\r\n\t// public shredderSpawns: readonly string[];\r\n\tpublic ghastcoilerSpawns: readonly string[];\r\n\tpublic validDeathrattles: readonly string[];\r\n\tpublic impMamaSpawns: readonly string[];\r\n\tpublic gentleDjinniSpawns: readonly string[];\r\n\tpublic kilrekSpawns: readonly string[];\r\n\tpublic brannEpicEggSpawns: readonly string[];\r\n\t// public sneedsSpawns: readonly string[];\r\n\t// public treasureChestSpawns: readonly string[];\r\n\tpublic pirateSpawns: readonly string[];\r\n\r\n\tprivate minionsForTier: { [key: string]: readonly ReferenceCard[] };\r\n\r\n\tconstructor(private readonly allCards: AllCardsService, init = true) {\r\n\t\tif (init) {\r\n\t\t\tthis.inititialize();\r\n\t\t}\r\n\t}\r\n\r\n\tpublic inititialize(validTribes?: readonly Race[]): void {\r\n\t\tconst pool = this.allCards\r\n\t\t\t.getCards()\r\n\t\t\t.filter((card) => isBattlegroundsCard(card))\r\n\t\t\t.filter((card) => !!card.techLevel)\r\n\t\t\t.filter((card) => !hasMechanic(card, GameTag[GameTag.BACON_BUDDY]))\r\n\t\t\t.filter((card) => card.set !== 'Vanilla');\r\n\t\tthis.minionsForTier = groupByFunction((card: ReferenceCard) => card.techLevel)(pool.filter((card) => !this.isGolden(card)));\r\n\t\tthis.ghastcoilerSpawns = pool\r\n\t\t\t.filter((card) => !this.isGolden(card))\r\n\t\t\t.filter((card) => card.id !== 'BGS_008')\r\n\t\t\t.filter((card) => hasMechanic(card, 'DEATHRATTLE'))\r\n\t\t\t// .filter((card) => REMOVED_CARD_IDS.indexOf(card.id) === -1)\r\n\t\t\t.filter((card) => this.isValidTribe(validTribes, card.races))\r\n\t\t\t.map((card) => card.id);\r\n\t\tthis.validDeathrattles = pool\r\n\t\t\t// .filter((card) => !card.id.startsWith('TB_BaconUps')) // Ignore golden\r\n\t\t\t.filter((card) => hasMechanic(card, 'DEATHRATTLE'))\r\n\t\t\t// .filter((card) => REMOVED_CARD_IDS.indexOf(card.id) === -1)\r\n\t\t\t.filter((card) => this.isValidTribe(validTribes, card.races))\r\n\t\t\t.map((card) => card.id);\r\n\t\tthis.impMamaSpawns = pool\r\n\t\t\t.filter((card) => !this.isGolden(card))\r\n\t\t\t.filter((card) => isCorrectTribe(card.races, Race.DEMON))\r\n\t\t\t.filter((card) => card.id !== CardIds.ImpMama)\r\n\t\t\t// .filter((card) => REMOVED_CARD_IDS.indexOf(card.id) === -1)\r\n\t\t\t.map((card) => card.id);\r\n\t\tthis.gentleDjinniSpawns = pool\r\n\t\t\t.filter((card) => !this.isGolden(card))\r\n\t\t\t.filter((card) => isCorrectTribe(card.races, Race.ELEMENTAL))\r\n\t\t\t.filter((card) => card.id !== CardIds.GentleDjinni)\r\n\t\t\t// .filter((card) => REMOVED_CARD_IDS.indexOf(card.id) === -1)\r\n\t\t\t.map((card) => card.id);\r\n\t\tthis.kilrekSpawns = pool\r\n\t\t\t.filter((card) => !this.isGolden(card))\r\n\t\t\t.filter((card) => isCorrectTribe(card.races, Race.DEMON))\r\n\t\t\t.filter((card) => card.id !== CardIds.KilrekBattlegrounds_TB_BaconShop_HERO_37_Buddy)\r\n\t\t\t// .filter((card) => REMOVED_CARD_IDS.indexOf(card.id) === -1)\r\n\t\t\t.map((card) => card.id);\r\n\t\tthis.brannEpicEggSpawns = pool\r\n\t\t\t.filter((card) => !this.isGolden(card))\r\n\t\t\t.filter((card) => hasMechanic(card, 'BATTLECRY'))\r\n\t\t\t.map((card) => card.id);\r\n\t\tthis.pirateSpawns = pool\r\n\t\t\t.filter((card) => !this.isGolden(card))\r\n\t\t\t.filter((card) => isCorrectTribe(card.races, Race.PIRATE))\r\n\t\t\t// .filter((card) => REMOVED_CARD_IDS.indexOf(card.id) === -1)\r\n\t\t\t.map((card) => card.id);\r\n\t}\r\n\r\n\tpublic avengeValue(cardId: string): number {\r\n\t\tswitch (cardId) {\r\n\t\t\tcase CardIds.BirdBuddy:\r\n\t\t\tcase CardIds.BirdBuddyBattlegrounds:\r\n\t\t\tcase CardIds.GhoulOfTheFeast:\r\n\t\t\tcase CardIds.GhoulOfTheFeastBattlegrounds:\r\n\t\t\tcase CardIds.HungeringAbomination:\r\n\t\t\tcase CardIds.HungeringAbominationBattlegrounds:\r\n\t\t\t\treturn 1;\r\n\t\t\tcase CardIds.FrostwolfLieutenant:\r\n\t\t\tcase CardIds.FrostwolfLieutenantBattlegrounds:\r\n\t\t\tcase CardIds.MechanoTank_BG21_023:\r\n\t\t\tcase CardIds.MechanoTank_BG21_023_G:\r\n\t\t\tcase CardIds.PalescaleCrocolisk_BG21_001:\r\n\t\t\tcase CardIds.PalescaleCrocolisk_BG21_001_G:\r\n\t\t\tcase CardIds.StormpikeLieutenant:\r\n\t\t\tcase CardIds.StormpikeLieutenantBattlegrounds:\r\n\t\t\tcase CardIds.VanndarStormpike_LeadTheStormpikes:\r\n\t\t\t\treturn 2;\r\n\t\t\tcase CardIds.BuddingGreenthumb:\r\n\t\t\tcase CardIds.BuddingGreenthumbBattlegrounds:\r\n\t\t\tcase CardIds.PashmarTheVengeful:\r\n\t\t\tcase CardIds.PashmarTheVengefulBattlegrounds:\r\n\t\t\tcase CardIds.WitchwingNestmatron:\r\n\t\t\tcase CardIds.WitchwingNestmatronBattlegrounds:\r\n\t\t\tcase CardIds.Drekthar_LeadTheFrostwolves:\r\n\t\t\t\treturn 3;\r\n\t\t\tcase CardIds.ImpatientDoomsayer:\r\n\t\t\tcase CardIds.ImpatientDoomsayerBattlegrounds:\r\n\t\t\tcase CardIds.Sisefin_BG21_009:\r\n\t\t\tcase CardIds.Sisefin_BG21_009_G:\r\n\t\t\tcase CardIds.TonyTwoTusk_BG21_031:\r\n\t\t\tcase CardIds.TonyTwoTusk_BG21_031_G:\r\n\t\t\tcase CardIds.Onyxia_Broodmother:\r\n\t\t\t\treturn 4;\r\n\t\t}\r\n\t\treturn 0;\r\n\t}\r\n\r\n\tpublic getTavernLevel(cardId: string): number {\r\n\t\treturn this.allCards.getCard(cardId).techLevel ?? 1;\r\n\t}\r\n\r\n\tpublic getRandomMinionForTavernTier(tavernTier: number): string {\r\n\t\t// Tzvern tier can be undefined for hero-power specific tokens, like the Amalgam, or when\r\n\t\t// for some reason tokens end up in the shop. For now, defaulting to 1 for tavern\r\n\t\t// level seems to work in all cases\r\n\t\tconst minionsForTier = this.minionsForTier[tavernTier ?? 1];\r\n\t\tif (!minionsForTier?.length) {\r\n\t\t\tconsole.error('incorrect minions for tier', tavernTier, this.minionsForTier, minionsForTier);\r\n\t\t}\r\n\t\treturn pickRandom(this.minionsForTier[tavernTier ?? 1])?.id;\r\n\t}\r\n\r\n\tprivate isGolden(card: ReferenceCard): boolean {\r\n\t\treturn !!card.battlegroundsNormalDbfId;\r\n\t}\r\n\r\n\tprivate isValidTribe(validTribes: readonly Race[], races: readonly string[]): boolean {\r\n\t\tif (!races?.length) {\r\n\t\t\treturn false;\r\n\t\t}\r\n\t\treturn races\r\n\t\t\t.map((race) => getRaceEnum(race))\r\n\t\t\t.some((raceEnum) => raceEnum === Race.ALL || !validTribes?.length || validTribes.includes(raceEnum));\r\n\t}\r\n}\r\n"]}
@@ -47,8 +47,8 @@ const simulateBattle = (battleInput, cards, cardsData) => {
47
47
  const opponentInfo = battleInput.opponentBoard;
48
48
  const playerBoard = playerInfo.board.map((entity) => ({ ...utils_1.addImpliedMechanics(entity), friendly: true }));
49
49
  const opponentBoard = opponentInfo.board.map((entity) => ({ ...utils_1.addImpliedMechanics(entity), friendly: false }));
50
- auras_1.removeAuras(playerBoard, cardsData);
51
- auras_1.removeAuras(opponentBoard, cardsData);
50
+ auras_1.setMissingAuras(playerBoard, playerInfo.player, opponentInfo.player);
51
+ auras_1.setMissingAuras(opponentBoard, opponentInfo.player, playerInfo.player);
52
52
  auras_1.setImplicitData(playerBoard, cardsData);
53
53
  auras_1.setImplicitData(opponentBoard, cardsData);
54
54
  auras_1.setImplicitDataHero(playerInfo.player, cardsData, true);
@@ -1 +1 @@
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, CardIds } from '@firestone-hs/reference-data';\r\nimport { BgsBattleInfo } from './bgs-battle-info';\r\nimport { BoardEntity } from './board-entity';\r\nimport { CardsData } from './cards/cards-data';\r\nimport { SimulationResult } from './simulation-result';\r\nimport { removeAuras, setImplicitData, setImplicitDataHero } from './simulation/auras';\r\nimport { Simulator } from './simulation/simulator';\r\nimport { Spectator } from './simulation/spectator/spectator';\r\nimport { addImpliedMechanics } from './utils';\r\n\r\nconst cards = new AllCardsService();\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\tconst battleInput: BgsBattleInfo = JSON.parse(event.body);\r\n\tawait cards.initializeCardsDb();\r\n\tconst cardsData = new CardsData(cards, false);\r\n\tcardsData.inititialize(battleInput.gameState?.validTribes ?? battleInput.options?.validTribes);\r\n\tconst simulationResult = simulateBattle(battleInput, cards, cardsData);\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 = (battleInput: BgsBattleInfo, cards: AllCardsService, cardsData: CardsData): SimulationResult => {\r\n\tconst start = Date.now();\r\n\r\n\tconst maxAcceptableDuration = battleInput.options?.maxAcceptableDuration || 8000;\r\n\tconst numberOfSimulations = battleInput.options?.numberOfSimulations || 5000;\r\n\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\tdamageWon: 0,\r\n\t\tdamageLost: 0,\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 playerInfo = battleInput.playerBoard;\r\n\tconst opponentInfo = battleInput.opponentBoard;\r\n\r\n\tconst playerBoard = playerInfo.board.map((entity) => ({ ...addImpliedMechanics(entity), friendly: true } as BoardEntity));\r\n\tconst opponentBoard = opponentInfo.board.map((entity) => ({ ...addImpliedMechanics(entity), friendly: false } as BoardEntity));\r\n\tremoveAuras(playerBoard, cardsData);\r\n\tremoveAuras(opponentBoard, cardsData);\r\n\tsetImplicitData(playerBoard, cardsData); // Avenge, maxHealth, etc.\r\n\tsetImplicitData(opponentBoard, cardsData); // Avenge, maxHealth, etc.\r\n\tsetImplicitDataHero(playerInfo.player, cardsData, true);\r\n\t// console.log('after implicit data', playerInfo.player.avengeCurrent, playerInfo.player.avengeDefault);\r\n\tsetImplicitDataHero(opponentInfo.player, cardsData, false);\r\n\r\n\t// We do this so that we can have mutated objects inside the simulation and still\r\n\t// be able to start from a fresh copy for each simulation\r\n\tconst inputReady: BgsBattleInfo = {\r\n\t\tplayerBoard: {\r\n\t\t\tboard: playerBoard,\r\n\t\t\tplayer: playerInfo.player,\r\n\t\t},\r\n\t\topponentBoard: {\r\n\t\t\tboard: opponentBoard,\r\n\t\t\tplayer: opponentInfo.player,\r\n\t\t},\r\n\t} as BgsBattleInfo;\r\n\tconst inputStr = JSON.stringify(inputReady);\r\n\tconst spectator = new Spectator(\r\n\t\tbattleInput.playerBoard.player.cardId,\r\n\t\tbattleInput.playerBoard.player.heroPowerId,\r\n\t\tbattleInput.opponentBoard.player.cardId,\r\n\t\tbattleInput.opponentBoard.player.heroPowerId,\r\n\t);\r\n\t!battleInput.options?.skipInfoLogs && console.time('simulation');\r\n\tconst outcomes = {};\r\n\tfor (let i = 0; i < numberOfSimulations; i++) {\r\n\t\tconst simulator = new Simulator(cards, cardsData);\r\n\t\tconst input: BgsBattleInfo = JSON.parse(inputStr);\r\n\t\tconst battleResult = simulator.simulateSingleBattle(\r\n\t\t\tinput.playerBoard.board,\r\n\t\t\tinput.playerBoard.player,\r\n\t\t\tinput.opponentBoard.board,\r\n\t\t\tinput.opponentBoard.player,\r\n\t\t\tinput.gameState,\r\n\t\t\tspectator,\r\n\t\t);\r\n\t\tif (Date.now() - start > maxAcceptableDuration) {\r\n\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\tconsole.warn('Stopping simulation after', i, 'iterations and ', Date.now() - start, 'ms', battleResult);\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tif (!battleResult) {\r\n\t\t\tcontinue;\r\n\t\t}\r\n\t\tif (battleResult.result === 'won') {\r\n\t\t\tsimulationResult.won++;\r\n\t\t\tsimulationResult.damageWon += battleResult.damageDealt;\r\n\t\t\tif (battleResult.damageDealt >= battleInput.opponentBoard.player.hpLeft) {\r\n\t\t\t\tsimulationResult.wonLethal++;\r\n\t\t\t}\r\n\t\t} else if (battleResult.result === 'lost') {\r\n\t\t\tsimulationResult.lost++;\r\n\t\t\tsimulationResult.damageLost += battleResult.damageDealt;\r\n\t\t\toutcomes[battleResult.damageDealt] = (outcomes[battleResult.damageDealt] ?? 0) + 1;\r\n\t\t\tif (battleInput.playerBoard.player.hpLeft && battleResult.damageDealt >= battleInput.playerBoard.player.hpLeft) {\r\n\t\t\t\tsimulationResult.lostLethal++;\r\n\t\t\t}\r\n\t\t} else if (battleResult.result === 'tied') {\r\n\t\t\tsimulationResult.tied++;\r\n\t\t}\r\n\t\tspectator.commitBattleResult(battleResult.result);\r\n\t}\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.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\t// simulationResult.tiedPercent = checkRounding(Math.round((10 * (100 * simulationResult.tied)) / totalMatches) / 10, simulationResult.tied, totalMatches);\r\n\tsimulationResult.tiedPercent = checkRounding(\r\n\t\t100 - simulationResult.lostPercent - simulationResult.wonPercent,\r\n\t\tsimulationResult.tied,\r\n\t\ttotalMatches,\r\n\t);\r\n\r\n\tsimulationResult.wonLethalPercent = Math.round((10 * (100 * simulationResult.wonLethal)) / totalMatches) / 10;\r\n\tsimulationResult.lostLethalPercent = Math.round((10 * (100 * simulationResult.lostLethal)) / totalMatches) / 10;\r\n\tsimulationResult.averageDamageWon = simulationResult.won ? simulationResult.damageWon / simulationResult.won : 0;\r\n\tsimulationResult.averageDamageLost = simulationResult.lost ? simulationResult.damageLost / simulationResult.lost : 0;\r\n\tif (simulationResult.averageDamageWon > 0 && simulationResult.averageDamageWon < playerInfo.player.tavernTier) {\r\n\t\tconsole.warn('average damage won issue', simulationResult, playerInfo);\r\n\t}\r\n\tif (simulationResult.averageDamageLost > 0 && simulationResult.averageDamageLost < opponentInfo.player.tavernTier) {\r\n\t\tconsole.warn('average damage lost issue', simulationResult, opponentInfo);\r\n\t}\r\n\t!battleInput.options?.skipInfoLogs && console.timeEnd('simulation');\r\n\tspectator.prune();\r\n\tsimulationResult.outcomeSamples = spectator.buildOutcomeSamples();\r\n\treturn simulationResult;\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\nconst cleanEnchantments = (board: readonly BoardEntity[]): readonly BoardEntity[] => {\r\n\tconst entityIds = board.map((entity) => entity.entityId);\r\n\treturn board.map((entity) => ({\r\n\t\t...entity,\r\n\t\tenchantments: cleanEnchantmentsForEntity(entity.enchantments, entityIds),\r\n\t}));\r\n};\r\n\r\nexport const validEnchantments = [\r\n\tCardIds.ReplicatingMenace_ReplicatingMenaceEnchantment_BG_BOT_312e,\r\n\tCardIds.ReplicatingMenace_ReplicatingMenaceEnchantmentBattlegrounds,\r\n\tCardIds.LivingSpores_LivingSporesEnchantment,\r\n\tCardIds.Leapfrogger_LeapfrogginEnchantment_BG21_000e,\r\n\tCardIds.Leapfrogger_LeapfrogginEnchantment_BG21_000_Ge,\r\n\tCardIds.Sneed_SneedsReplicator,\r\n\tCardIds.SneedsReplicator_ReplicateEnchantment,\r\n\tCardIds.EarthRecollectionEnchantment, // Spirit Raptor\r\n\tCardIds.FireRecollectionEnchantment,\r\n\tCardIds.LightningRecollectionEnchantment,\r\n\tCardIds.WaterRecollectionEnchantment,\r\n\tCardIds.EarthInvocation_ElementEarthEnchantment, // Summon a 1/1\r\n\t// CardIds.FireInvocation_ElementFireEnchantment, // Attack is doubled, probably no use to keep it\r\n\t// CardIds.WaterInvocation_ElementWaterEnchantment, // +3 health and taunt, same\r\n\tCardIds.LightningInvocation, // Deal 1 damage to 5 enemy minions\r\n];\r\n\r\nconst 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) => entityIds.indexOf(enchant.originEntityId) !== -1 || validEnchantments.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, CardIds } from '@firestone-hs/reference-data';\r\nimport { BgsBattleInfo } from './bgs-battle-info';\r\nimport { BoardEntity } from './board-entity';\r\nimport { CardsData } from './cards/cards-data';\r\nimport { SimulationResult } from './simulation-result';\r\nimport { setImplicitData, setImplicitDataHero, setMissingAuras } from './simulation/auras';\r\nimport { Simulator } from './simulation/simulator';\r\nimport { Spectator } from './simulation/spectator/spectator';\r\nimport { addImpliedMechanics } from './utils';\r\n\r\nconst cards = new AllCardsService();\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\tconst battleInput: BgsBattleInfo = JSON.parse(event.body);\r\n\tawait cards.initializeCardsDb();\r\n\tconst cardsData = new CardsData(cards, false);\r\n\tcardsData.inititialize(battleInput.gameState?.validTribes ?? battleInput.options?.validTribes);\r\n\tconst simulationResult = simulateBattle(battleInput, cards, cardsData);\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 = (battleInput: BgsBattleInfo, cards: AllCardsService, cardsData: CardsData): SimulationResult => {\r\n\tconst start = Date.now();\r\n\r\n\tconst maxAcceptableDuration = battleInput.options?.maxAcceptableDuration || 8000;\r\n\tconst numberOfSimulations = battleInput.options?.numberOfSimulations || 5000;\r\n\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\tdamageWon: 0,\r\n\t\tdamageLost: 0,\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 playerInfo = battleInput.playerBoard;\r\n\tconst opponentInfo = battleInput.opponentBoard;\r\n\r\n\tconst playerBoard = playerInfo.board.map((entity) => ({ ...addImpliedMechanics(entity), friendly: true } as BoardEntity));\r\n\tconst opponentBoard = opponentInfo.board.map((entity) => ({ ...addImpliedMechanics(entity), friendly: false } as BoardEntity));\r\n\t// When using the simulator, the aura is not applied when receiving the board state. When\r\n\tsetMissingAuras(playerBoard, playerInfo.player, opponentInfo.player);\r\n\tsetMissingAuras(opponentBoard, opponentInfo.player, playerInfo.player);\r\n\t// Avenge, maxHealth, etc.\r\n\tsetImplicitData(playerBoard, cardsData);\r\n\tsetImplicitData(opponentBoard, cardsData);\r\n\t// Avenge, globalInfo\r\n\tsetImplicitDataHero(playerInfo.player, cardsData, true);\r\n\tsetImplicitDataHero(opponentInfo.player, cardsData, false);\r\n\r\n\t// We do this so that we can have mutated objects inside the simulation and still\r\n\t// be able to start from a fresh copy for each simulation\r\n\tconst inputReady: BgsBattleInfo = {\r\n\t\tplayerBoard: {\r\n\t\t\tboard: playerBoard,\r\n\t\t\tplayer: playerInfo.player,\r\n\t\t},\r\n\t\topponentBoard: {\r\n\t\t\tboard: opponentBoard,\r\n\t\t\tplayer: opponentInfo.player,\r\n\t\t},\r\n\t} as BgsBattleInfo;\r\n\tconst inputStr = JSON.stringify(inputReady);\r\n\tconst spectator = new Spectator(\r\n\t\tbattleInput.playerBoard.player.cardId,\r\n\t\tbattleInput.playerBoard.player.heroPowerId,\r\n\t\tbattleInput.opponentBoard.player.cardId,\r\n\t\tbattleInput.opponentBoard.player.heroPowerId,\r\n\t);\r\n\t!battleInput.options?.skipInfoLogs && console.time('simulation');\r\n\tconst outcomes = {};\r\n\tfor (let i = 0; i < numberOfSimulations; i++) {\r\n\t\tconst simulator = new Simulator(cards, cardsData);\r\n\t\tconst input: BgsBattleInfo = JSON.parse(inputStr);\r\n\t\tconst battleResult = simulator.simulateSingleBattle(\r\n\t\t\tinput.playerBoard.board,\r\n\t\t\tinput.playerBoard.player,\r\n\t\t\tinput.opponentBoard.board,\r\n\t\t\tinput.opponentBoard.player,\r\n\t\t\tinput.gameState,\r\n\t\t\tspectator,\r\n\t\t);\r\n\t\tif (Date.now() - start > maxAcceptableDuration) {\r\n\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\tconsole.warn('Stopping simulation after', i, 'iterations and ', Date.now() - start, 'ms', battleResult);\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tif (!battleResult) {\r\n\t\t\tcontinue;\r\n\t\t}\r\n\t\tif (battleResult.result === 'won') {\r\n\t\t\tsimulationResult.won++;\r\n\t\t\tsimulationResult.damageWon += battleResult.damageDealt;\r\n\t\t\tif (battleResult.damageDealt >= battleInput.opponentBoard.player.hpLeft) {\r\n\t\t\t\tsimulationResult.wonLethal++;\r\n\t\t\t}\r\n\t\t} else if (battleResult.result === 'lost') {\r\n\t\t\tsimulationResult.lost++;\r\n\t\t\tsimulationResult.damageLost += battleResult.damageDealt;\r\n\t\t\toutcomes[battleResult.damageDealt] = (outcomes[battleResult.damageDealt] ?? 0) + 1;\r\n\t\t\tif (battleInput.playerBoard.player.hpLeft && battleResult.damageDealt >= battleInput.playerBoard.player.hpLeft) {\r\n\t\t\t\tsimulationResult.lostLethal++;\r\n\t\t\t}\r\n\t\t} else if (battleResult.result === 'tied') {\r\n\t\t\tsimulationResult.tied++;\r\n\t\t}\r\n\t\tspectator.commitBattleResult(battleResult.result);\r\n\t}\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.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\t// simulationResult.tiedPercent = checkRounding(Math.round((10 * (100 * simulationResult.tied)) / totalMatches) / 10, simulationResult.tied, totalMatches);\r\n\tsimulationResult.tiedPercent = checkRounding(\r\n\t\t100 - simulationResult.lostPercent - simulationResult.wonPercent,\r\n\t\tsimulationResult.tied,\r\n\t\ttotalMatches,\r\n\t);\r\n\r\n\tsimulationResult.wonLethalPercent = Math.round((10 * (100 * simulationResult.wonLethal)) / totalMatches) / 10;\r\n\tsimulationResult.lostLethalPercent = Math.round((10 * (100 * simulationResult.lostLethal)) / totalMatches) / 10;\r\n\tsimulationResult.averageDamageWon = simulationResult.won ? simulationResult.damageWon / simulationResult.won : 0;\r\n\tsimulationResult.averageDamageLost = simulationResult.lost ? simulationResult.damageLost / simulationResult.lost : 0;\r\n\tif (simulationResult.averageDamageWon > 0 && simulationResult.averageDamageWon < playerInfo.player.tavernTier) {\r\n\t\tconsole.warn('average damage won issue', simulationResult, playerInfo);\r\n\t}\r\n\tif (simulationResult.averageDamageLost > 0 && simulationResult.averageDamageLost < opponentInfo.player.tavernTier) {\r\n\t\tconsole.warn('average damage lost issue', simulationResult, opponentInfo);\r\n\t}\r\n\t!battleInput.options?.skipInfoLogs && console.timeEnd('simulation');\r\n\tspectator.prune();\r\n\tsimulationResult.outcomeSamples = spectator.buildOutcomeSamples();\r\n\treturn simulationResult;\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\nconst cleanEnchantments = (board: readonly BoardEntity[]): readonly BoardEntity[] => {\r\n\tconst entityIds = board.map((entity) => entity.entityId);\r\n\treturn board.map((entity) => ({\r\n\t\t...entity,\r\n\t\tenchantments: cleanEnchantmentsForEntity(entity.enchantments, entityIds),\r\n\t}));\r\n};\r\n\r\nexport const validEnchantments = [\r\n\tCardIds.ReplicatingMenace_ReplicatingMenaceEnchantment_BG_BOT_312e,\r\n\tCardIds.ReplicatingMenace_ReplicatingMenaceEnchantmentBattlegrounds,\r\n\tCardIds.LivingSpores_LivingSporesEnchantment,\r\n\tCardIds.Leapfrogger_LeapfrogginEnchantment_BG21_000e,\r\n\tCardIds.Leapfrogger_LeapfrogginEnchantment_BG21_000_Ge,\r\n\tCardIds.Sneed_SneedsReplicator,\r\n\tCardIds.SneedsReplicator_ReplicateEnchantment,\r\n\tCardIds.EarthRecollectionEnchantment, // Spirit Raptor\r\n\tCardIds.FireRecollectionEnchantment,\r\n\tCardIds.LightningRecollectionEnchantment,\r\n\tCardIds.WaterRecollectionEnchantment,\r\n\tCardIds.EarthInvocation_ElementEarthEnchantment, // Summon a 1/1\r\n\t// CardIds.FireInvocation_ElementFireEnchantment, // Attack is doubled, probably no use to keep it\r\n\t// CardIds.WaterInvocation_ElementWaterEnchantment, // +3 health and taunt, same\r\n\tCardIds.LightningInvocation, // Deal 1 damage to 5 enemy minions\r\n];\r\n\r\nconst 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) => entityIds.indexOf(enchant.originEntityId) !== -1 || validEnchantments.indexOf(enchant.cardId as CardIds) !== -1,\r\n\t);\r\n};\r\n"]}
@@ -0,0 +1,7 @@
1
+ import { AllCardsService } from '@firestone-hs/reference-data';
2
+ import { BgsPlayerEntity } from '../bgs-player-entity';
3
+ import { BoardEntity } from '../board-entity';
4
+ import { SharedState } from './shared-state';
5
+ import { Spectator } from './spectator/spectator';
6
+ export declare const addMinionsToBoard: (board: BoardEntity[], boardHero: BgsPlayerEntity, otherHero: BgsPlayerEntity, index: number, minionsToAdd: readonly BoardEntity[], allCards: AllCardsService, spectator: Spectator, sharedState: SharedState) => void;
7
+ export declare const addMinionToBoard: (board: BoardEntity[], boardHero: BgsPlayerEntity, otherHero: BgsPlayerEntity, index: number, minionToAdd: BoardEntity, allCards: AllCardsService, spectator: Spectator, sharedState: SharedState) => void;
@@ -0,0 +1,277 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.addMinionToBoard = exports.addMinionsToBoard = void 0;
4
+ const reference_data_1 = require("@firestone-hs/reference-data");
5
+ const cards_data_1 = require("../cards/cards-data");
6
+ const utils_1 = require("../utils");
7
+ const addMinionsToBoard = (board, boardHero, otherHero, index, minionsToAdd, allCards, spectator, sharedState) => {
8
+ board.splice(index, 0, ...minionsToAdd);
9
+ for (const minionToAdd of [...minionsToAdd].reverse()) {
10
+ exports.addMinionToBoard(board, boardHero, otherHero, index, minionToAdd, allCards, spectator, sharedState);
11
+ }
12
+ handleAfterSpawnEffects(board, minionsToAdd, allCards, spectator);
13
+ };
14
+ exports.addMinionsToBoard = addMinionsToBoard;
15
+ const addMinionToBoard = (board, boardHero, otherHero, index, minionToAdd, allCards, spectator, sharedState) => {
16
+ board.splice(index, 0, minionToAdd);
17
+ handleSpawnEffect(board, boardHero, otherHero, minionToAdd, allCards, spectator, sharedState);
18
+ };
19
+ exports.addMinionToBoard = addMinionToBoard;
20
+ const handleSpawnEffect = (board, boardHero, otherHero, spawned, allCards, spectator, sharedState) => {
21
+ switch (spawned.cardId) {
22
+ case "BG_NEW1_027":
23
+ case "TB_BaconUps_136":
24
+ board
25
+ .filter((e) => utils_1.hasCorrectTribe(e, reference_data_1.Race.PIRATE, allCards))
26
+ .forEach((e) => {
27
+ e.attack += spawned.cardId === "TB_BaconUps_136" ? 2 : 1;
28
+ e.health += spawned.cardId === "TB_BaconUps_136" ? 2 : 1;
29
+ });
30
+ break;
31
+ case "BG_EX1_507":
32
+ case "TB_BaconUps_008":
33
+ board
34
+ .filter((e) => utils_1.hasCorrectTribe(e, reference_data_1.Race.MURLOC, allCards))
35
+ .forEach((e) => {
36
+ e.attack += spawned.cardId === "TB_BaconUps_008" ? 4 : 2;
37
+ });
38
+ break;
39
+ case "TB_BaconShop_HERO_52_Buddy":
40
+ case "TB_BaconShop_HERO_52_Buddy_G":
41
+ board.forEach((e) => {
42
+ e.attack += spawned.cardId === "TB_BaconShop_HERO_52_Buddy_G" ? 6 : 3;
43
+ });
44
+ break;
45
+ case "BG21_039":
46
+ case "BG21_039_G":
47
+ board
48
+ .filter((e) => utils_1.hasCorrectTribe(e, reference_data_1.Race.DEMON, allCards))
49
+ .forEach((e) => {
50
+ e.attack += spawned.cardId === "BG21_039_G" ? 4 : 2;
51
+ });
52
+ break;
53
+ case "BG25_043":
54
+ case "BG25_043_G":
55
+ board
56
+ .filter((e) => e.divineShield)
57
+ .forEach((e) => {
58
+ e.attack += spawned.cardId === "BG25_043_G" ? 20 : 10;
59
+ });
60
+ break;
61
+ case "BG25_008":
62
+ case "BG25_008_G":
63
+ const multiplierKnight = spawned.cardId === "BG25_008_G" ? 2 : 1;
64
+ const statsBonusKnight = multiplierKnight * boardHero.globalInfo.EternalKnightsDeadThisGame;
65
+ utils_1.modifyAttack(spawned, statsBonusKnight, board, allCards);
66
+ utils_1.modifyHealth(spawned, statsBonusKnight, board, allCards);
67
+ utils_1.afterStatsUpdate(spawned, board, allCards);
68
+ break;
69
+ case "BG25_013":
70
+ case "BG25_013_G":
71
+ const multiplierGnoll = spawned.cardId === "BG25_013_G" ? 2 : 1;
72
+ const statsBonusGnoll = multiplierGnoll * sharedState.deaths.filter((e) => e.friendly === spawned.friendly).length;
73
+ utils_1.modifyAttack(spawned, statsBonusGnoll, board, allCards);
74
+ utils_1.afterStatsUpdate(spawned, board, allCards);
75
+ break;
76
+ }
77
+ if (utils_1.hasCorrectTribe(spawned, reference_data_1.Race.UNDEAD, allCards)) {
78
+ if (boardHero.globalInfo.UndeadAttackBonus > 0) {
79
+ utils_1.modifyAttack(spawned, boardHero.globalInfo.UndeadAttackBonus, board, allCards);
80
+ utils_1.afterStatsUpdate(spawned, board, allCards);
81
+ }
82
+ }
83
+ if (cards_data_1.WHELP_CARD_IDS.includes(spawned.cardId)) {
84
+ const manyWhelps = board.filter((entity) => entity.cardId === "BG22_HERO_305_Buddy");
85
+ const goldenManyWhelps = board.filter((entity) => entity.cardId === "BG22_HERO_305_Buddy_G");
86
+ manyWhelps.forEach((entity) => {
87
+ utils_1.modifyAttack(entity, 2, board, allCards);
88
+ utils_1.modifyHealth(entity, 2, board, allCards);
89
+ utils_1.afterStatsUpdate(entity, board, allCards);
90
+ });
91
+ goldenManyWhelps.forEach((entity) => {
92
+ utils_1.modifyAttack(entity, 4, board, allCards);
93
+ utils_1.modifyHealth(entity, 4, board, allCards);
94
+ utils_1.afterStatsUpdate(entity, board, allCards);
95
+ });
96
+ }
97
+ for (const entity of board) {
98
+ switch (entity.cardId) {
99
+ case "BG_EX1_507":
100
+ case "TB_BaconUps_008":
101
+ if (utils_1.hasCorrectTribe(spawned, reference_data_1.Race.MURLOC, allCards)) {
102
+ spawned.attack += entity.cardId === "TB_BaconUps_008" ? 4 : 2;
103
+ }
104
+ break;
105
+ case "BG_NEW1_027":
106
+ case "TB_BaconUps_136":
107
+ if (utils_1.hasCorrectTribe(spawned, reference_data_1.Race.PIRATE, allCards)) {
108
+ spawned.attack += entity.cardId === "TB_BaconUps_136" ? 2 : 1;
109
+ spawned.health += entity.cardId === "TB_BaconUps_136" ? 2 : 1;
110
+ }
111
+ break;
112
+ case "TB_BaconShop_HERO_52_Buddy":
113
+ case "TB_BaconShop_HERO_52_Buddy_G":
114
+ spawned.attack += entity.cardId === "TB_BaconShop_HERO_52_Buddy_G" ? 6 : 3;
115
+ break;
116
+ case "BG21_039":
117
+ case "BG21_039_G":
118
+ if (utils_1.hasCorrectTribe(spawned, reference_data_1.Race.DEMON, allCards)) {
119
+ spawned.attack += entity.cardId === "BG21_039_G" ? 2 : 1;
120
+ }
121
+ break;
122
+ case "BG25_043":
123
+ case "BG25_043_G":
124
+ if (spawned.divineShield) {
125
+ spawned.attack += entity.cardId === "BG25_043_G" ? 20 : 10;
126
+ }
127
+ break;
128
+ case "TB_BaconShop_HERO_92_Buddy":
129
+ case "TB_BaconShop_HERO_92_Buddy_G":
130
+ if (allCards.getCard(spawned.cardId).techLevel === boardHero.tavernTier) {
131
+ const statsBonus = entity.cardId === "TB_BaconShop_HERO_92_Buddy_G" ? 8 : 4;
132
+ utils_1.modifyAttack(spawned, statsBonus, board, allCards);
133
+ utils_1.modifyHealth(spawned, statsBonus, board, allCards);
134
+ utils_1.afterStatsUpdate(spawned, board, allCards);
135
+ }
136
+ break;
137
+ case "TB_BaconShop_HERO_95_Buddy":
138
+ case "TB_BaconShop_HERO_95_Buddy_G":
139
+ if (spawned.taunt) {
140
+ const statsBonus = entity.cardId === "TB_BaconShop_HERO_95_Buddy_G" ? 4 : 2;
141
+ utils_1.modifyAttack(spawned, statsBonus, board, allCards);
142
+ utils_1.modifyHealth(spawned, statsBonus, board, allCards);
143
+ utils_1.afterStatsUpdate(spawned, board, allCards);
144
+ }
145
+ break;
146
+ case "GVG_062":
147
+ if (utils_1.hasCorrectTribe(spawned, reference_data_1.Race.MECH, allCards)) {
148
+ if (!entity.divineShield) {
149
+ utils_1.updateDivineShield(entity, board, true, allCards);
150
+ }
151
+ utils_1.modifyAttack(entity, 2, board, allCards);
152
+ utils_1.afterStatsUpdate(entity, board, allCards);
153
+ spectator.registerPowerTarget(entity, entity, board);
154
+ }
155
+ break;
156
+ case "BGS_071":
157
+ case "TB_BaconUps_123":
158
+ if (utils_1.hasCorrectTribe(spawned, reference_data_1.Race.MECH, allCards)) {
159
+ const statsBonus = entity.cardId === "TB_BaconUps_123" ? 4 : 2;
160
+ if (!entity.divineShield) {
161
+ utils_1.updateDivineShield(entity, board, true, allCards);
162
+ }
163
+ utils_1.modifyAttack(entity, statsBonus, board, allCards);
164
+ utils_1.afterStatsUpdate(entity, board, allCards);
165
+ spectator.registerPowerTarget(entity, entity, board);
166
+ }
167
+ break;
168
+ case "BGS_204":
169
+ case "TB_BaconUps_304":
170
+ if (utils_1.hasCorrectTribe(spawned, reference_data_1.Race.DEMON, allCards)) {
171
+ const statsBonus = entity.cardId === "TB_BaconUps_304" ? 2 : 1;
172
+ utils_1.modifyAttack(entity, statsBonus, board, allCards);
173
+ utils_1.modifyHealth(entity, statsBonus, board, allCards);
174
+ utils_1.afterStatsUpdate(entity, board, allCards);
175
+ spectator.registerPowerTarget(entity, entity, board);
176
+ }
177
+ break;
178
+ case "BGS_021":
179
+ case "TB_BaconUps_090":
180
+ if (utils_1.hasCorrectTribe(spawned, reference_data_1.Race.BEAST, allCards)) {
181
+ const statsBonus = entity.cardId === "TB_BaconUps_090" ? 10 : 5;
182
+ utils_1.modifyAttack(spawned, statsBonus, board, allCards);
183
+ utils_1.modifyHealth(spawned, statsBonus, board, allCards);
184
+ utils_1.afterStatsUpdate(entity, board, allCards);
185
+ spectator.registerPowerTarget(entity, entity, board);
186
+ }
187
+ break;
188
+ case "BGS_017":
189
+ case "TB_BaconUps_086":
190
+ if (utils_1.hasCorrectTribe(spawned, reference_data_1.Race.BEAST, allCards)) {
191
+ const statsBonus = entity.cardId === "TB_BaconUps_086" ? 4 : 2;
192
+ utils_1.modifyAttack(spawned, statsBonus, board, allCards);
193
+ utils_1.afterStatsUpdate(entity, board, allCards);
194
+ spectator.registerPowerTarget(entity, entity, board);
195
+ }
196
+ break;
197
+ }
198
+ }
199
+ if (otherHero.heroPowerId === "TB_BaconShop_HP_061") {
200
+ spawned.attack += 3;
201
+ }
202
+ switch (boardHero.heroPowerId) {
203
+ case "TB_BaconShop_HP_061":
204
+ spawned.attack += 3;
205
+ break;
206
+ case "BG24_Reward_125":
207
+ spawned.attack += 5;
208
+ break;
209
+ case "BG24_Reward_364":
210
+ spawned.attack += 7;
211
+ spawned.health += 7;
212
+ spawned.enchantments.push({
213
+ cardId: "BG24_Reward_364e",
214
+ originEntityId: undefined,
215
+ timing: sharedState.currentEntityId++,
216
+ });
217
+ break;
218
+ case "TB_BaconShop_HP_107":
219
+ spawned.taunt = true;
220
+ utils_1.modifyAttack(spawned, 1, board, allCards);
221
+ utils_1.modifyHealth(spawned, 2, board, allCards);
222
+ utils_1.afterStatsUpdate(spawned, board, allCards);
223
+ break;
224
+ case "BG20_HERO_280p3":
225
+ utils_1.modifyAttack(spawned, 2, board, allCards);
226
+ utils_1.modifyHealth(spawned, 2, board, allCards);
227
+ utils_1.afterStatsUpdate(spawned, board, allCards);
228
+ break;
229
+ case "TB_BaconShop_HP_015":
230
+ if (utils_1.hasCorrectTribe(spawned, reference_data_1.Race.MECH, allCards)) {
231
+ utils_1.modifyAttack(spawned, 2, board, allCards);
232
+ utils_1.afterStatsUpdate(spawned, board, allCards);
233
+ }
234
+ break;
235
+ }
236
+ };
237
+ const handleAfterSpawnEffects = (board, allSpawned, allCards, spectator) => {
238
+ for (const spawned of allSpawned) {
239
+ handleAfterSpawnEffect(board, spawned, allCards, spectator);
240
+ }
241
+ };
242
+ const handleAfterSpawnEffect = (board, spawned, allCards, spectator) => {
243
+ for (const entity of board) {
244
+ switch (entity.cardId) {
245
+ case "EX1_509":
246
+ case "TB_BaconUps_011":
247
+ const multiplier = entity.cardId === "TB_BaconUps_011" ? 2 : 1;
248
+ const buffAmount = multiplier * (utils_1.isCorrectTribe(allCards.getCard(spawned.cardId).races, reference_data_1.Race.MURLOC) ? 1 : 0);
249
+ if (buffAmount > 0) {
250
+ utils_1.modifyAttack(entity, buffAmount, board, allCards);
251
+ utils_1.afterStatsUpdate(entity, board, allCards);
252
+ spectator.registerPowerTarget(entity, entity, board);
253
+ }
254
+ break;
255
+ case "BG22_401":
256
+ case "BG22_401_G":
257
+ const multiplier2 = entity.cardId === "BG22_401_G" ? 2 : 1;
258
+ const buffAmount2 = multiplier2 * (utils_1.isCorrectTribe(allCards.getCard(spawned.cardId).races, reference_data_1.Race.MURLOC) ? 1 : 0);
259
+ if (buffAmount2 > 0) {
260
+ utils_1.modifyAttack(entity, buffAmount2, board, allCards);
261
+ utils_1.afterStatsUpdate(entity, board, allCards);
262
+ spectator.registerPowerTarget(entity, entity, board);
263
+ }
264
+ break;
265
+ case "BG25_042":
266
+ case "BG25_042_G":
267
+ const felstomperBuff = entity.cardId === "BG25_042_G" ? 6 : 3;
268
+ board.forEach((e) => {
269
+ utils_1.modifyAttack(e, felstomperBuff, board, allCards);
270
+ utils_1.afterStatsUpdate(e, board, allCards);
271
+ spectator.registerPowerTarget(entity, e, board);
272
+ });
273
+ break;
274
+ }
275
+ }
276
+ };
277
+ //# sourceMappingURL=add-minion-to-board.js.map