@firestone-hs/simulate-bgs-battle 1.1.722 → 1.1.724
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.
- package/dist/cards/card.interface.d.ts +4 -0
- package/dist/cards/card.interface.js +4 -2
- package/dist/cards/card.interface.js.map +1 -1
- package/dist/cards/impl/_card-mappings.js +2 -0
- package/dist/cards/impl/_card-mappings.js.map +1 -1
- package/dist/cards/impl/hero-power/lightning-invocation.js +4 -1
- package/dist/cards/impl/hero-power/lightning-invocation.js.map +1 -1
- package/dist/cards/impl/minion/sneeds-new-shredder.js +1 -1
- package/dist/cards/impl/minion/sneeds-new-shredder.js.map +1 -1
- package/dist/cards/impl/minion/timewarped-embalmer.d.ts +2 -2
- package/dist/cards/impl/minion/timewarped-embalmer.js +5 -1
- package/dist/cards/impl/minion/timewarped-embalmer.js.map +1 -1
- package/dist/cards/impl/minion/timewarped-pagle.d.ts +2 -0
- package/dist/cards/impl/minion/timewarped-pagle.js +15 -0
- package/dist/cards/impl/minion/timewarped-pagle.js.map +1 -0
- package/dist/input-clone.d.ts +1 -0
- package/dist/input-clone.js +13 -1
- package/dist/input-clone.js.map +1 -1
- package/dist/mechanics/rally.js +14 -12
- package/dist/mechanics/rally.js.map +1 -1
- package/dist/mechanics/tavern-spell-repeat.js +3 -4
- package/dist/mechanics/tavern-spell-repeat.js.map +1 -1
- package/dist/simulate-bgs-battle.d.ts +1 -1
- package/dist/simulate-bgs-battle.js +80 -77
- package/dist/simulate-bgs-battle.js.map +1 -1
- package/dist/simulation/add-minion-to-board.d.ts +1 -1
- package/dist/simulation/add-minion-to-board.js +5 -2
- package/dist/simulation/add-minion-to-board.js.map +1 -1
- package/dist/simulation/attack.js +3 -3
- package/dist/simulation/attack.js.map +1 -1
- package/dist/simulation/avenge.js +2 -2
- package/dist/simulation/avenge.js.map +1 -1
- package/dist/simulation/deathrattle-effects.js +48 -14
- package/dist/simulation/deathrattle-effects.js.map +1 -1
- package/dist/simulation/deathrattle-spawns.js +19 -12
- package/dist/simulation/deathrattle-spawns.js.map +1 -1
- package/dist/simulation/deathrattle-utils.d.ts +1 -0
- package/dist/simulation/deathrattle-utils.js +45 -5
- package/dist/simulation/deathrattle-utils.js.map +1 -1
- package/dist/simulation/on-attack.js +13 -14
- package/dist/simulation/on-attack.js.map +1 -1
- package/dist/simulation/reborn.js +11 -0
- package/dist/simulation/reborn.js.map +1 -1
- package/dist/simulation/simulator.d.ts +1 -0
- package/dist/simulation/simulator.js +39 -74
- package/dist/simulation/simulator.js.map +1 -1
- package/dist/simulation/spectator/resolve-trinket-hero-power.js +11 -2
- package/dist/simulation/spectator/resolve-trinket-hero-power.js.map +1 -1
- package/dist/simulation/spectator/spectator.d.ts +4 -0
- package/dist/simulation/spectator/spectator.js +39 -19
- package/dist/simulation/spectator/spectator.js.map +1 -1
- package/dist/simulation/stats.js +95 -66
- package/dist/simulation/stats.js.map +1 -1
- package/dist/simulation/summon-when-space.js +24 -21
- package/dist/simulation/summon-when-space.js.map +1 -1
- package/dist/utils.js +89 -48
- package/dist/utils.js.map +1 -1
- package/package.json +3 -2
|
@@ -29,8 +29,10 @@ const applyOnAttackEffects = (attacker, attackingBoard, attackingBoardHero, defe
|
|
|
29
29
|
damageDoneByDefender += dmgDoneByDefender;
|
|
30
30
|
}
|
|
31
31
|
}
|
|
32
|
-
const
|
|
33
|
-
|
|
32
|
+
for (const boardEntity of attackingBoard.slice()) {
|
|
33
|
+
if (boardEntity === attacker) {
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
34
36
|
const onAttackImpl = _card_mappings_1.cardMappings[boardEntity.cardId];
|
|
35
37
|
if ((0, card_interface_1.hasOnWheneverAnotherMinionAttacks)(onAttackImpl)) {
|
|
36
38
|
const { dmgDoneByAttacker, dmgDoneByDefender } = onAttackImpl.onWheneverAnotherMinionAttacks(boardEntity, {
|
|
@@ -91,20 +93,17 @@ const applyOnAttackEffects = (attacker, attackingBoard, attackingBoardHero, defe
|
|
|
91
93
|
}
|
|
92
94
|
}
|
|
93
95
|
}
|
|
94
|
-
const eclipsion = attackingBoard.find((e) =>
|
|
95
|
-
"
|
|
96
|
-
|
|
97
|
-
].includes(e.cardId) && e.abiityChargesLeft > 0);
|
|
96
|
+
const eclipsion = attackingBoard.find((e) => (e.cardId === "TB_BaconShop_HERO_08_Buddy" ||
|
|
97
|
+
e.cardId === "TB_BaconShop_HERO_08_Buddy_G") &&
|
|
98
|
+
e.abiityChargesLeft > 0);
|
|
98
99
|
if (!!eclipsion && attacker.immuneWhenAttackCharges == null) {
|
|
99
100
|
attacker.immuneWhenAttackCharges = 1;
|
|
100
|
-
attackingBoard
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
e.abiityChargesLeft--;
|
|
107
|
-
});
|
|
101
|
+
for (const e of attackingBoard) {
|
|
102
|
+
if (e.cardId === "TB_BaconShop_HERO_08_Buddy" ||
|
|
103
|
+
e.cardId === "TB_BaconShop_HERO_08_Buddy_G") {
|
|
104
|
+
e.abiityChargesLeft--;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
108
107
|
}
|
|
109
108
|
for (const trinket of attackingBoardHero.trinkets) {
|
|
110
109
|
switch (trinket.cardId) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"on-attack.js","sourceRoot":"","sources":["../../src/simulation/on-attack.ts"],"names":[],"mappings":"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","sourcesContent":["import { Race } from '@firestone-hs/reference-data';\r\nimport { BgsPlayerEntity } from '../bgs-player-entity';\r\nimport { BoardEntity } from '../board-entity';\r\nimport { hasOnWheneverAnotherMinionAttacks } from '../cards/card.interface';\r\nimport { cardMappings } from '../cards/impl/_card-mappings';\r\nimport { updateReborn } from '../keywords/reborn';\r\nimport { triggerRally } from '../mechanics/rally';\r\nimport { CardIds } from '../services/card-ids';\r\nimport { hasCorrectTribe } from '../utils';\r\nimport { FullGameState } from './internal-game-state';\r\nimport { modifyStats } from './stats';\r\n\r\n// Whenever it attacks\r\nexport const applyOnAttackEffects = (\r\n\tattacker: BoardEntity,\r\n\tattackingBoard: BoardEntity[],\r\n\tattackingBoardHero: BgsPlayerEntity,\r\n\tdefendingEntity: BoardEntity,\r\n\tdefendingBoard: BoardEntity[],\r\n\tdefendingBoardHero: BgsPlayerEntity,\r\n\tgameState: FullGameState,\r\n): { damageDoneByAttacker: number; damageDoneByDefender: number } => {\r\n\tlet damageDoneByAttacker = 0;\r\n\tlet damageDoneByDefender = 0;\r\n\r\n\tfor (const trinket of attackingBoardHero.trinkets ?? []) {\r\n\t\tconst onAttackImpl = cardMappings[trinket.cardId];\r\n\t\tif (hasOnWheneverAnotherMinionAttacks(onAttackImpl)) {\r\n\t\t\tconst { dmgDoneByAttacker, dmgDoneByDefender } = onAttackImpl.onWheneverAnotherMinionAttacks(trinket, {\r\n\t\t\t\tattacker: attacker,\r\n\t\t\t\tattackingHero: attackingBoardHero,\r\n\t\t\t\tattackingBoard: attackingBoard,\r\n\t\t\t\tdefendingEntity: defendingEntity,\r\n\t\t\t\tdefendingHero: defendingBoardHero,\r\n\t\t\t\tdefendingBoard: defendingBoard,\r\n\t\t\t\tgameState,\r\n\t\t\t\tplayerIsFriendly: attackingBoardHero.friendly,\r\n\t\t\t});\r\n\t\t\tdamageDoneByAttacker += dmgDoneByAttacker;\r\n\t\t\tdamageDoneByDefender += dmgDoneByDefender;\r\n\t\t}\r\n\t}\r\n\r\n\t// \"Whenever friendly minion attacks\" triggers before the rally itself?\r\n\t// https://replays.firestoneapp.com/?reviewId=04e6a624-ccd5-4068-9420-884843f3685f&turn=25&action=1\r\n\tconst attackingBoardOtherEntities = attackingBoard.filter((e) => e !== attacker);\r\n\tfor (const boardEntity of attackingBoardOtherEntities) {\r\n\t\tconst onAttackImpl = cardMappings[boardEntity.cardId];\r\n\t\tif (hasOnWheneverAnotherMinionAttacks(onAttackImpl)) {\r\n\t\t\tconst { dmgDoneByAttacker, dmgDoneByDefender } = onAttackImpl.onWheneverAnotherMinionAttacks(boardEntity, {\r\n\t\t\t\tattacker: attacker,\r\n\t\t\t\tattackingHero: attackingBoardHero,\r\n\t\t\t\tattackingBoard: attackingBoard,\r\n\t\t\t\tdefendingEntity: defendingEntity,\r\n\t\t\t\tdefendingHero: defendingBoardHero,\r\n\t\t\t\tdefendingBoard: defendingBoard,\r\n\t\t\t\tgameState,\r\n\t\t\t\tplayerIsFriendly: attackingBoardHero.friendly,\r\n\t\t\t});\r\n\t\t\tdamageDoneByAttacker += dmgDoneByAttacker;\r\n\t\t\tdamageDoneByDefender += dmgDoneByDefender;\r\n\t\t}\r\n\t\tconst enchantments = boardEntity.enchantments;\r\n\t\tfor (const enchantment of enchantments) {\r\n\t\t\tconst onAttackImpl = cardMappings[enchantment.cardId];\r\n\t\t\tif (hasOnWheneverAnotherMinionAttacks(onAttackImpl)) {\r\n\t\t\t\tconst { dmgDoneByAttacker, dmgDoneByDefender } = onAttackImpl.onWheneverAnotherMinionAttacks(\r\n\t\t\t\t\tenchantment,\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tattacker: attacker,\r\n\t\t\t\t\t\tattackingHero: attackingBoardHero,\r\n\t\t\t\t\t\tattackingBoard: attackingBoard,\r\n\t\t\t\t\t\tdefendingEntity: defendingEntity,\r\n\t\t\t\t\t\tdefendingHero: defendingBoardHero,\r\n\t\t\t\t\t\tdefendingBoard: defendingBoard,\r\n\t\t\t\t\t\tgameState,\r\n\t\t\t\t\t\tplayerIsFriendly: attackingBoardHero.friendly,\r\n\t\t\t\t\t},\r\n\t\t\t\t);\r\n\t\t\t\tdamageDoneByAttacker += dmgDoneByAttacker;\r\n\t\t\t\tdamageDoneByDefender += dmgDoneByDefender;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t// This assumes that only \"Rally\" effects trigger on attack\r\n\t// 2025-08-20: this is false. \"Whenever a friendly minion attacks\" is not a rally effect\r\n\tconst { dmgDoneByAttacker: dmgDoneByRally, dmgDoneByDefender: dmgDoneByRallyDefender } = triggerRally(\r\n\t\tattackingBoard,\r\n\t\tattackingBoardHero,\r\n\t\tattacker,\r\n\t\tdefendingBoard,\r\n\t\tdefendingBoardHero,\r\n\t\tdefendingEntity,\r\n\t\tgameState,\r\n\t);\r\n\tdamageDoneByAttacker += dmgDoneByRally;\r\n\tdamageDoneByDefender += dmgDoneByRallyDefender;\r\n\r\n\t// if (attacker.cardId === CardIds.GlyphGuardian_BGS_045) {\r\n\t// \t// For now the utility method only works additively, so we hack around it\r\n\t// \tmodifyStats(\r\n\t// \t\tattacker,\r\n\t// \t\tnull,\r\n\t// \t\t2 * attacker.attack - attacker.attack,\r\n\t// \t\t0,\r\n\t// \t\tattackingBoard,\r\n\t// \t\tattackingBoardHero,\r\n\t// \t\tgameState,\r\n\t// \t);\r\n\t// } else if (attacker.cardId === CardIds.GlyphGuardian_TB_BaconUps_115) {\r\n\t// \tmodifyStats(\r\n\t// \t\tattacker,\r\n\t// \t\tnull,\r\n\t// \t\t3 * attacker.attack - attacker.attack,\r\n\t// \t\t0,\r\n\t// \t\tattackingBoard,\r\n\t// \t\tattackingBoardHero,\r\n\t// \t\tgameState,\r\n\t// \t);\r\n\t// } else\r\n\tif (attacker.cardId === CardIds.GlimGuardian_BG29_888 || attacker.cardId === CardIds.GlimGuardian_BG29_888_G) {\r\n\t\tconst multiplier = attacker.cardId === CardIds.GlimGuardian_BG29_888_G ? 2 : 1;\r\n\t\tmodifyStats(attacker, attacker, 2 * multiplier, 0, attackingBoard, attackingBoardHero, gameState);\r\n\t} else if (\r\n\t\tattacker.cardId === CardIds.VanessaVancleef_BG24_708 ||\r\n\t\tattacker.cardId === CardIds.VanessaVancleef_BG24_708_G\r\n\t) {\r\n\t\tattackingBoard\r\n\t\t\t.filter((e) => hasCorrectTribe(e, attackingBoardHero, Race.PIRATE, gameState.anomalies, gameState.allCards))\r\n\t\t\t.forEach((e) => {\r\n\t\t\t\tmodifyStats(\r\n\t\t\t\t\te,\r\n\t\t\t\t\tattacker,\r\n\t\t\t\t\tattacker.cardId === CardIds.VanessaVancleef_BG24_708_G ? 4 : 2,\r\n\t\t\t\t\tattacker.cardId === CardIds.VanessaVancleef_BG24_708_G ? 4 : 2,\r\n\t\t\t\t\tattackingBoard,\r\n\t\t\t\t\tattackingBoardHero,\r\n\t\t\t\t\tgameState,\r\n\t\t\t\t);\r\n\t\t\t});\r\n\t} else if (attacker.cardId === CardIds.HatefulHag_BG29_120 || attacker.cardId === CardIds.HatefulHag_BG29_120_G) {\r\n\t\tconst loops = attacker.cardId === CardIds.HatefulHag_BG29_120_G ? 2 : 1;\r\n\t\tconst attackerIndex = attackingBoard.indexOf(attacker);\r\n\t\tfor (let i = 1; i <= loops; i++) {\r\n\t\t\tconst target = attackingBoard[attackerIndex + i];\r\n\t\t\tif (!!target) {\r\n\t\t\t\tupdateReborn(target, true, attackingBoard, attackingBoardHero, defendingBoardHero, gameState);\r\n\t\t\t\tgameState.spectator.registerPowerTarget(\r\n\t\t\t\t\tattacker,\r\n\t\t\t\t\ttarget,\r\n\t\t\t\t\tattackingBoard,\r\n\t\t\t\t\tattackingBoardHero,\r\n\t\t\t\t\tdefendingBoardHero,\r\n\t\t\t\t);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tconst eclipsion = attackingBoard.find(\r\n\t\t(e) =>\r\n\t\t\t[\r\n\t\t\t\tCardIds.EclipsionIllidari_TB_BaconShop_HERO_08_Buddy,\r\n\t\t\t\tCardIds.EclipsionIllidari_TB_BaconShop_HERO_08_Buddy_G,\r\n\t\t\t].includes(e.cardId as CardIds) && e.abiityChargesLeft > 0,\r\n\t);\r\n\t// Only once per minion\r\n\tif (!!eclipsion && attacker.immuneWhenAttackCharges == null) {\r\n\t\tattacker.immuneWhenAttackCharges = 1;\r\n\t\t// If we have 2 eclipsions, the first minion that attacks eats both charges\r\n\t\tattackingBoard\r\n\t\t\t.filter((e) =>\r\n\t\t\t\t[\r\n\t\t\t\t\tCardIds.EclipsionIllidari_TB_BaconShop_HERO_08_Buddy,\r\n\t\t\t\t\tCardIds.EclipsionIllidari_TB_BaconShop_HERO_08_Buddy_G,\r\n\t\t\t\t].includes(e.cardId as CardIds),\r\n\t\t\t)\r\n\t\t\t.forEach((e) => {\r\n\t\t\t\te.abiityChargesLeft--;\r\n\t\t\t});\r\n\t}\r\n\r\n\tfor (const trinket of attackingBoardHero.trinkets) {\r\n\t\tswitch (trinket.cardId) {\r\n\t\t\tcase CardIds.CeremonialSword_BG30_MagicItem_925:\r\n\t\t\t\tmodifyStats(attacker, trinket, 4, 0, attackingBoard, attackingBoardHero, gameState);\r\n\t\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n\treturn { damageDoneByAttacker, damageDoneByDefender };\r\n};\r\n\r\nexport interface OnAttackInput {\r\n\tattacker: BoardEntity;\r\n\tattackingHero: BgsPlayerEntity;\r\n\tattackingBoard: BoardEntity[];\r\n\tdefendingEntity: BoardEntity;\r\n\tdefendingHero: BgsPlayerEntity;\r\n\tdefendingBoard: BoardEntity[];\r\n\tgameState: FullGameState;\r\n\tplayerIsFriendly: boolean;\r\n}\r\n"]}
|
|
1
|
+
{"version":3,"file":"on-attack.js","sourceRoot":"","sources":["../../src/simulation/on-attack.ts"],"names":[],"mappings":";;;AAAA,iEAAoD;AAGpD,4DAA4E;AAC5E,iEAA4D;AAC5D,+CAAkD;AAClD,8CAAkD;AAElD,oCAA2C;AAE3C,mCAAsC;AAG/B,MAAM,oBAAoB,GAAG,CACnC,QAAqB,EACrB,cAA6B,EAC7B,kBAAmC,EACnC,eAA4B,EAC5B,cAA6B,EAC7B,kBAAmC,EACnC,SAAwB,EACyC,EAAE;;IACnE,IAAI,oBAAoB,GAAG,CAAC,CAAC;IAC7B,IAAI,oBAAoB,GAAG,CAAC,CAAC;IAE7B,KAAK,MAAM,OAAO,IAAI,MAAA,kBAAkB,CAAC,QAAQ,mCAAI,EAAE,EAAE;QACxD,MAAM,YAAY,GAAG,6BAAY,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QAClD,IAAI,IAAA,kDAAiC,EAAC,YAAY,CAAC,EAAE;YACpD,MAAM,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,GAAG,YAAY,CAAC,8BAA8B,CAAC,OAAO,EAAE;gBACrG,QAAQ,EAAE,QAAQ;gBAClB,aAAa,EAAE,kBAAkB;gBACjC,cAAc,EAAE,cAAc;gBAC9B,eAAe,EAAE,eAAe;gBAChC,aAAa,EAAE,kBAAkB;gBACjC,cAAc,EAAE,cAAc;gBAC9B,SAAS;gBACT,gBAAgB,EAAE,kBAAkB,CAAC,QAAQ;aAC7C,CAAC,CAAC;YACH,oBAAoB,IAAI,iBAAiB,CAAC;YAC1C,oBAAoB,IAAI,iBAAiB,CAAC;SAC1C;KACD;IAKD,KAAK,MAAM,WAAW,IAAI,cAAc,CAAC,KAAK,EAAE,EAAE;QACjD,IAAI,WAAW,KAAK,QAAQ,EAAE;YAC7B,SAAS;SACT;QACD,MAAM,YAAY,GAAG,6BAAY,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;QACtD,IAAI,IAAA,kDAAiC,EAAC,YAAY,CAAC,EAAE;YACpD,MAAM,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,GAAG,YAAY,CAAC,8BAA8B,CAAC,WAAW,EAAE;gBACzG,QAAQ,EAAE,QAAQ;gBAClB,aAAa,EAAE,kBAAkB;gBACjC,cAAc,EAAE,cAAc;gBAC9B,eAAe,EAAE,eAAe;gBAChC,aAAa,EAAE,kBAAkB;gBACjC,cAAc,EAAE,cAAc;gBAC9B,SAAS;gBACT,gBAAgB,EAAE,kBAAkB,CAAC,QAAQ;aAC7C,CAAC,CAAC;YACH,oBAAoB,IAAI,iBAAiB,CAAC;YAC1C,oBAAoB,IAAI,iBAAiB,CAAC;SAC1C;QACD,MAAM,YAAY,GAAG,WAAW,CAAC,YAAY,CAAC;QAC9C,KAAK,MAAM,WAAW,IAAI,YAAY,EAAE;YACvC,MAAM,YAAY,GAAG,6BAAY,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;YACtD,IAAI,IAAA,kDAAiC,EAAC,YAAY,CAAC,EAAE;gBACpD,MAAM,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,GAAG,YAAY,CAAC,8BAA8B,CAC3F,WAAW,EACX;oBACC,QAAQ,EAAE,QAAQ;oBAClB,aAAa,EAAE,kBAAkB;oBACjC,cAAc,EAAE,cAAc;oBAC9B,eAAe,EAAE,eAAe;oBAChC,aAAa,EAAE,kBAAkB;oBACjC,cAAc,EAAE,cAAc;oBAC9B,SAAS;oBACT,gBAAgB,EAAE,kBAAkB,CAAC,QAAQ;iBAC7C,CACD,CAAC;gBACF,oBAAoB,IAAI,iBAAiB,CAAC;gBAC1C,oBAAoB,IAAI,iBAAiB,CAAC;aAC1C;SACD;KACD;IAID,MAAM,EAAE,iBAAiB,EAAE,cAAc,EAAE,iBAAiB,EAAE,sBAAsB,EAAE,GAAG,IAAA,oBAAY,EACpG,cAAc,EACd,kBAAkB,EAClB,QAAQ,EACR,cAAc,EACd,kBAAkB,EAClB,eAAe,EACf,SAAS,CACT,CAAC;IACF,oBAAoB,IAAI,cAAc,CAAC;IACvC,oBAAoB,IAAI,sBAAsB,CAAC;IAwB/C,IAAI,QAAQ,CAAC,MAAM,eAAkC,IAAI,QAAQ,CAAC,MAAM,iBAAoC,EAAE;QAC7G,MAAM,UAAU,GAAG,QAAQ,CAAC,MAAM,iBAAoC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC/E,IAAA,mBAAW,EAAC,QAAQ,EAAE,QAAQ,EAAE,CAAC,GAAG,UAAU,EAAE,CAAC,EAAE,cAAc,EAAE,kBAAkB,EAAE,SAAS,CAAC,CAAC;KAClG;SAAM,IACN,QAAQ,CAAC,MAAM,eAAqC;QACpD,QAAQ,CAAC,MAAM,iBAAuC,EACrD;QACD,cAAc;aACZ,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAA,uBAAe,EAAC,CAAC,EAAE,kBAAkB,EAAE,qBAAI,CAAC,MAAM,EAAE,SAAS,CAAC,SAAS,EAAE,SAAS,CAAC,QAAQ,CAAC,CAAC;aAC3G,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE;YACd,IAAA,mBAAW,EACV,CAAC,EACD,QAAQ,EACR,QAAQ,CAAC,MAAM,iBAAuC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAC9D,QAAQ,CAAC,MAAM,iBAAuC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAC9D,cAAc,EACd,kBAAkB,EAClB,SAAS,CACT,CAAC;QACH,CAAC,CAAC,CAAC;KACJ;SAAM,IAAI,QAAQ,CAAC,MAAM,eAAgC,IAAI,QAAQ,CAAC,MAAM,iBAAkC,EAAE;QAChH,MAAM,KAAK,GAAG,QAAQ,CAAC,MAAM,iBAAkC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACxE,MAAM,aAAa,GAAG,cAAc,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QACvD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,KAAK,EAAE,CAAC,EAAE,EAAE;YAChC,MAAM,MAAM,GAAG,cAAc,CAAC,aAAa,GAAG,CAAC,CAAC,CAAC;YACjD,IAAI,CAAC,CAAC,MAAM,EAAE;gBACb,IAAA,qBAAY,EAAC,MAAM,EAAE,IAAI,EAAE,cAAc,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,SAAS,CAAC,CAAC;gBAC9F,SAAS,CAAC,SAAS,CAAC,mBAAmB,CACtC,QAAQ,EACR,MAAM,EACN,cAAc,EACd,kBAAkB,EAClB,kBAAkB,CAClB,CAAC;aACF;SACD;KACD;IAED,MAAM,SAAS,GAAG,cAAc,CAAC,IAAI,CACpC,CAAC,CAAC,EAAE,EAAE,CACL,CAAC,CAAC,CAAC,MAAM,iCAAyD;QACjE,CAAC,CAAC,MAAM,mCAA2D,CAAC;QACrE,CAAC,CAAC,iBAAiB,GAAG,CAAC,CACxB,CAAC;IAEF,IAAI,CAAC,CAAC,SAAS,IAAI,QAAQ,CAAC,uBAAuB,IAAI,IAAI,EAAE;QAC5D,QAAQ,CAAC,uBAAuB,GAAG,CAAC,CAAC;QAErC,KAAK,MAAM,CAAC,IAAI,cAAc,EAAE;YAC/B,IACC,CAAC,CAAC,MAAM,iCAAyD;gBACjE,CAAC,CAAC,MAAM,mCAA2D,EAClE;gBACD,CAAC,CAAC,iBAAiB,EAAE,CAAC;aACtB;SACD;KACD;IAED,KAAK,MAAM,OAAO,IAAI,kBAAkB,CAAC,QAAQ,EAAE;QAClD,QAAQ,OAAO,CAAC,MAAM,EAAE;YACvB;gBACC,IAAA,mBAAW,EAAC,QAAQ,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC,EAAE,cAAc,EAAE,kBAAkB,EAAE,SAAS,CAAC,CAAC;gBACpF,MAAM;SACP;KACD;IAED,OAAO,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,CAAC;AACvD,CAAC,CAAC;AAlLW,QAAA,oBAAoB,wBAkL/B","sourcesContent":["import { Race } from '@firestone-hs/reference-data';\r\nimport { BgsPlayerEntity } from '../bgs-player-entity';\r\nimport { BoardEntity } from '../board-entity';\r\nimport { hasOnWheneverAnotherMinionAttacks } from '../cards/card.interface';\r\nimport { cardMappings } from '../cards/impl/_card-mappings';\r\nimport { updateReborn } from '../keywords/reborn';\r\nimport { triggerRally } from '../mechanics/rally';\r\nimport { CardIds } from '../services/card-ids';\r\nimport { hasCorrectTribe } from '../utils';\r\nimport { FullGameState } from './internal-game-state';\r\nimport { modifyStats } from './stats';\r\n\r\n// Whenever it attacks\r\nexport const applyOnAttackEffects = (\r\n\tattacker: BoardEntity,\r\n\tattackingBoard: BoardEntity[],\r\n\tattackingBoardHero: BgsPlayerEntity,\r\n\tdefendingEntity: BoardEntity,\r\n\tdefendingBoard: BoardEntity[],\r\n\tdefendingBoardHero: BgsPlayerEntity,\r\n\tgameState: FullGameState,\r\n): { damageDoneByAttacker: number; damageDoneByDefender: number } => {\r\n\tlet damageDoneByAttacker = 0;\r\n\tlet damageDoneByDefender = 0;\r\n\r\n\tfor (const trinket of attackingBoardHero.trinkets ?? []) {\r\n\t\tconst onAttackImpl = cardMappings[trinket.cardId];\r\n\t\tif (hasOnWheneverAnotherMinionAttacks(onAttackImpl)) {\r\n\t\t\tconst { dmgDoneByAttacker, dmgDoneByDefender } = onAttackImpl.onWheneverAnotherMinionAttacks(trinket, {\r\n\t\t\t\tattacker: attacker,\r\n\t\t\t\tattackingHero: attackingBoardHero,\r\n\t\t\t\tattackingBoard: attackingBoard,\r\n\t\t\t\tdefendingEntity: defendingEntity,\r\n\t\t\t\tdefendingHero: defendingBoardHero,\r\n\t\t\t\tdefendingBoard: defendingBoard,\r\n\t\t\t\tgameState,\r\n\t\t\t\tplayerIsFriendly: attackingBoardHero.friendly,\r\n\t\t\t});\r\n\t\t\tdamageDoneByAttacker += dmgDoneByAttacker;\r\n\t\t\tdamageDoneByDefender += dmgDoneByDefender;\r\n\t\t}\r\n\t}\r\n\r\n\t// \"Whenever friendly minion attacks\" triggers before the rally itself?\r\n\t// https://replays.firestoneapp.com/?reviewId=04e6a624-ccd5-4068-9420-884843f3685f&turn=25&action=1\r\n\t// (slice() gives us a snapshot in case a handler mutates the board mid-iteration)\r\n\tfor (const boardEntity of attackingBoard.slice()) {\r\n\t\tif (boardEntity === attacker) {\r\n\t\t\tcontinue;\r\n\t\t}\r\n\t\tconst onAttackImpl = cardMappings[boardEntity.cardId];\r\n\t\tif (hasOnWheneverAnotherMinionAttacks(onAttackImpl)) {\r\n\t\t\tconst { dmgDoneByAttacker, dmgDoneByDefender } = onAttackImpl.onWheneverAnotherMinionAttacks(boardEntity, {\r\n\t\t\t\tattacker: attacker,\r\n\t\t\t\tattackingHero: attackingBoardHero,\r\n\t\t\t\tattackingBoard: attackingBoard,\r\n\t\t\t\tdefendingEntity: defendingEntity,\r\n\t\t\t\tdefendingHero: defendingBoardHero,\r\n\t\t\t\tdefendingBoard: defendingBoard,\r\n\t\t\t\tgameState,\r\n\t\t\t\tplayerIsFriendly: attackingBoardHero.friendly,\r\n\t\t\t});\r\n\t\t\tdamageDoneByAttacker += dmgDoneByAttacker;\r\n\t\t\tdamageDoneByDefender += dmgDoneByDefender;\r\n\t\t}\r\n\t\tconst enchantments = boardEntity.enchantments;\r\n\t\tfor (const enchantment of enchantments) {\r\n\t\t\tconst onAttackImpl = cardMappings[enchantment.cardId];\r\n\t\t\tif (hasOnWheneverAnotherMinionAttacks(onAttackImpl)) {\r\n\t\t\t\tconst { dmgDoneByAttacker, dmgDoneByDefender } = onAttackImpl.onWheneverAnotherMinionAttacks(\r\n\t\t\t\t\tenchantment,\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tattacker: attacker,\r\n\t\t\t\t\t\tattackingHero: attackingBoardHero,\r\n\t\t\t\t\t\tattackingBoard: attackingBoard,\r\n\t\t\t\t\t\tdefendingEntity: defendingEntity,\r\n\t\t\t\t\t\tdefendingHero: defendingBoardHero,\r\n\t\t\t\t\t\tdefendingBoard: defendingBoard,\r\n\t\t\t\t\t\tgameState,\r\n\t\t\t\t\t\tplayerIsFriendly: attackingBoardHero.friendly,\r\n\t\t\t\t\t},\r\n\t\t\t\t);\r\n\t\t\t\tdamageDoneByAttacker += dmgDoneByAttacker;\r\n\t\t\t\tdamageDoneByDefender += dmgDoneByDefender;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t// This assumes that only \"Rally\" effects trigger on attack\r\n\t// 2025-08-20: this is false. \"Whenever a friendly minion attacks\" is not a rally effect\r\n\tconst { dmgDoneByAttacker: dmgDoneByRally, dmgDoneByDefender: dmgDoneByRallyDefender } = triggerRally(\r\n\t\tattackingBoard,\r\n\t\tattackingBoardHero,\r\n\t\tattacker,\r\n\t\tdefendingBoard,\r\n\t\tdefendingBoardHero,\r\n\t\tdefendingEntity,\r\n\t\tgameState,\r\n\t);\r\n\tdamageDoneByAttacker += dmgDoneByRally;\r\n\tdamageDoneByDefender += dmgDoneByRallyDefender;\r\n\r\n\t// if (attacker.cardId === CardIds.GlyphGuardian_BGS_045) {\r\n\t// \t// For now the utility method only works additively, so we hack around it\r\n\t// \tmodifyStats(\r\n\t// \t\tattacker,\r\n\t// \t\tnull,\r\n\t// \t\t2 * attacker.attack - attacker.attack,\r\n\t// \t\t0,\r\n\t// \t\tattackingBoard,\r\n\t// \t\tattackingBoardHero,\r\n\t// \t\tgameState,\r\n\t// \t);\r\n\t// } else if (attacker.cardId === CardIds.GlyphGuardian_TB_BaconUps_115) {\r\n\t// \tmodifyStats(\r\n\t// \t\tattacker,\r\n\t// \t\tnull,\r\n\t// \t\t3 * attacker.attack - attacker.attack,\r\n\t// \t\t0,\r\n\t// \t\tattackingBoard,\r\n\t// \t\tattackingBoardHero,\r\n\t// \t\tgameState,\r\n\t// \t);\r\n\t// } else\r\n\tif (attacker.cardId === CardIds.GlimGuardian_BG29_888 || attacker.cardId === CardIds.GlimGuardian_BG29_888_G) {\r\n\t\tconst multiplier = attacker.cardId === CardIds.GlimGuardian_BG29_888_G ? 2 : 1;\r\n\t\tmodifyStats(attacker, attacker, 2 * multiplier, 0, attackingBoard, attackingBoardHero, gameState);\r\n\t} else if (\r\n\t\tattacker.cardId === CardIds.VanessaVancleef_BG24_708 ||\r\n\t\tattacker.cardId === CardIds.VanessaVancleef_BG24_708_G\r\n\t) {\r\n\t\tattackingBoard\r\n\t\t\t.filter((e) => hasCorrectTribe(e, attackingBoardHero, Race.PIRATE, gameState.anomalies, gameState.allCards))\r\n\t\t\t.forEach((e) => {\r\n\t\t\t\tmodifyStats(\r\n\t\t\t\t\te,\r\n\t\t\t\t\tattacker,\r\n\t\t\t\t\tattacker.cardId === CardIds.VanessaVancleef_BG24_708_G ? 4 : 2,\r\n\t\t\t\t\tattacker.cardId === CardIds.VanessaVancleef_BG24_708_G ? 4 : 2,\r\n\t\t\t\t\tattackingBoard,\r\n\t\t\t\t\tattackingBoardHero,\r\n\t\t\t\t\tgameState,\r\n\t\t\t\t);\r\n\t\t\t});\r\n\t} else if (attacker.cardId === CardIds.HatefulHag_BG29_120 || attacker.cardId === CardIds.HatefulHag_BG29_120_G) {\r\n\t\tconst loops = attacker.cardId === CardIds.HatefulHag_BG29_120_G ? 2 : 1;\r\n\t\tconst attackerIndex = attackingBoard.indexOf(attacker);\r\n\t\tfor (let i = 1; i <= loops; i++) {\r\n\t\t\tconst target = attackingBoard[attackerIndex + i];\r\n\t\t\tif (!!target) {\r\n\t\t\t\tupdateReborn(target, true, attackingBoard, attackingBoardHero, defendingBoardHero, gameState);\r\n\t\t\t\tgameState.spectator.registerPowerTarget(\r\n\t\t\t\t\tattacker,\r\n\t\t\t\t\ttarget,\r\n\t\t\t\t\tattackingBoard,\r\n\t\t\t\t\tattackingBoardHero,\r\n\t\t\t\t\tdefendingBoardHero,\r\n\t\t\t\t);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tconst eclipsion = attackingBoard.find(\r\n\t\t(e) =>\r\n\t\t\t(e.cardId === CardIds.EclipsionIllidari_TB_BaconShop_HERO_08_Buddy ||\r\n\t\t\t\te.cardId === CardIds.EclipsionIllidari_TB_BaconShop_HERO_08_Buddy_G) &&\r\n\t\t\te.abiityChargesLeft > 0,\r\n\t);\r\n\t// Only once per minion\r\n\tif (!!eclipsion && attacker.immuneWhenAttackCharges == null) {\r\n\t\tattacker.immuneWhenAttackCharges = 1;\r\n\t\t// If we have 2 eclipsions, the first minion that attacks eats both charges\r\n\t\tfor (const e of attackingBoard) {\r\n\t\t\tif (\r\n\t\t\t\te.cardId === CardIds.EclipsionIllidari_TB_BaconShop_HERO_08_Buddy ||\r\n\t\t\t\te.cardId === CardIds.EclipsionIllidari_TB_BaconShop_HERO_08_Buddy_G\r\n\t\t\t) {\r\n\t\t\t\te.abiityChargesLeft--;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tfor (const trinket of attackingBoardHero.trinkets) {\r\n\t\tswitch (trinket.cardId) {\r\n\t\t\tcase CardIds.CeremonialSword_BG30_MagicItem_925:\r\n\t\t\t\tmodifyStats(attacker, trinket, 4, 0, attackingBoard, attackingBoardHero, gameState);\r\n\t\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n\treturn { damageDoneByAttacker, damageDoneByDefender };\r\n};\r\n\r\nexport interface OnAttackInput {\r\n\tattacker: BoardEntity;\r\n\tattackingHero: BgsPlayerEntity;\r\n\tattackingBoard: BoardEntity[];\r\n\tdefendingEntity: BoardEntity;\r\n\tdefendingHero: BgsPlayerEntity;\r\n\tdefendingBoard: BoardEntity[];\r\n\tgameState: FullGameState;\r\n\tplayerIsFriendly: boolean;\r\n}\r\n"]}
|
|
@@ -16,6 +16,17 @@ const handleRebornForEntity = (boardWithKilledMinion, boardWithKilledMinionHero,
|
|
|
16
16
|
((_a = deadEntity.enchantments) === null || _a === void 0 ? void 0 : _a.some((e) => e.cardId === "BG31_HERO_801ptje"))) {
|
|
17
17
|
entityToSpawn = (0, sinrunner_blanchy_1.buildSinrunnerBlanchyRebornEntity)(deadEntity);
|
|
18
18
|
}
|
|
19
|
+
const rebornImpl = _card_mappings_1.cardMappings[deadEntity.cardId];
|
|
20
|
+
if ((0, card_interface_1.hasBeforeRebornSelfEffect)(rebornImpl)) {
|
|
21
|
+
rebornImpl.beforeRebornSelfEffect(deadEntity, {
|
|
22
|
+
rebornEntity: deadEntity,
|
|
23
|
+
boardWithKilledMinion,
|
|
24
|
+
boardWithKilledMinionHero,
|
|
25
|
+
opponentBoard,
|
|
26
|
+
opponentBoardHero,
|
|
27
|
+
gameState,
|
|
28
|
+
});
|
|
29
|
+
}
|
|
19
30
|
const entitiesFromReborn = deadEntity.reborn && deadMinionIndexFromRight >= 0
|
|
20
31
|
? (0, deathrattle_spawns_1.spawnEntities)(deadEntity.cardId, numberOfReborns, boardWithKilledMinion, boardWithKilledMinionHero, opponentBoard, opponentBoardHero, gameState, deadEntity.friendly, false, true, true, entityToSpawn, deadEntity)
|
|
21
32
|
: [];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reborn.js","sourceRoot":"","sources":["../../src/simulation/reborn.ts"],"names":[],"mappings":"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","sourcesContent":["import { BgsPlayerEntity } from '../bgs-player-entity';\r\nimport { BoardEntity } from '../board-entity';\r\nimport { hasAfterReborn, hasRebornEffect, hasRebornSelfEffect } from '../cards/card.interface';\r\nimport { cardMappings } from '../cards/impl/_card-mappings';\r\nimport { buildSinrunnerBlanchyRebornEntity, isSinrunnerBlanchy } from '../cards/impl/minion/sinrunner-blanchy';\r\nimport { CardIds } from '../services/card-ids';\r\nimport { addStatsToBoard } from '../utils';\r\nimport { spawnEntities } from './deathrattle-spawns';\r\nimport { FullGameState } from './internal-game-state';\r\nimport { performEntitySpawns } from './spawns';\r\nimport { modifyStats } from './stats';\r\n\r\nexport const handleRebornForEntity = (\r\n\tboardWithKilledMinion: BoardEntity[],\r\n\tboardWithKilledMinionHero: BgsPlayerEntity,\r\n\tdeadEntity: BoardEntity,\r\n\tdeadMinionIndexFromRight: number,\r\n\topponentBoard: BoardEntity[],\r\n\topponentBoardHero: BgsPlayerEntity,\r\n\tgameState: FullGameState,\r\n): void => {\r\n\tconst numberOfReborns = 1;\r\n\tlet entityToSpawn: BoardEntity = null;\r\n\tif (\r\n\t\tisSinrunnerBlanchy(deadEntity.cardId) ||\r\n\t\tdeadEntity.enchantments?.some(\r\n\t\t\t(e) => e.cardId === CardIds.UltraCapacitor_UltraCapacitorEnchantment_BG31_HERO_801ptje,\r\n\t\t)\r\n\t) {\r\n\t\tentityToSpawn = buildSinrunnerBlanchyRebornEntity(deadEntity);\r\n\t}\r\n\tconst entitiesFromReborn: readonly BoardEntity[] =\r\n\t\tdeadEntity.reborn && deadMinionIndexFromRight >= 0\r\n\t\t\t? spawnEntities(\r\n\t\t\t\tdeadEntity.cardId,\r\n\t\t\t\tnumberOfReborns,\r\n\t\t\t\tboardWithKilledMinion,\r\n\t\t\t\tboardWithKilledMinionHero,\r\n\t\t\t\topponentBoard,\r\n\t\t\t\topponentBoardHero,\r\n\t\t\t\tgameState,\r\n\t\t\t\tdeadEntity.friendly,\r\n\t\t\t\tfalse,\r\n\t\t\t\ttrue,\r\n\t\t\t\ttrue,\r\n\t\t\t\tentityToSpawn,\r\n\t\t\t\tdeadEntity,\r\n\t\t\t)\r\n\t\t\t: [];\r\n\tif (!entitiesFromReborn.length) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (\r\n\t\tdeadEntity.cardId === CardIds.WannabeGargoyle_BG30_109 ||\r\n\t\tdeadEntity.cardId === CardIds.WannabeGargoyle_BG30_109_G\r\n\t) {\r\n\t\tentitiesFromReborn.forEach((e) => {\r\n\t\t\tconst attack = deadEntity.maxAttack;\r\n\t\t\tconst health = deadEntity.cardId === CardIds.WannabeGargoyle_BG30_109_G ? deadEntity.maxHealth : 1;\r\n\t\t\te.attack = attack;\r\n\t\t\te.health = health;\r\n\t\t});\r\n\t}\r\n\r\n\tfor (const entity of entitiesFromReborn) {\r\n\t\tconst rebornImpl = cardMappings[entity.cardId];\r\n\t\tif (hasRebornSelfEffect(rebornImpl)) {\r\n\t\t\trebornImpl.rebornSelfEffect(entity, {\r\n\t\t\t\trebornEntity: deadEntity,\r\n\t\t\t\tboardWithKilledMinion,\r\n\t\t\t\tboardWithKilledMinionHero,\r\n\t\t\t\topponentBoard,\r\n\t\t\t\topponentBoardHero,\r\n\t\t\t\tgameState,\r\n\t\t\t});\r\n\t\t}\r\n\t}\r\n\r\n\tfor (const entity of boardWithKilledMinion) {\r\n\t\tconst rebornImpl = cardMappings[entity.cardId];\r\n\t\tif (hasRebornEffect(rebornImpl)) {\r\n\t\t\trebornImpl.rebornEffect(entity, {\r\n\t\t\t\trebornEntity: deadEntity,\r\n\t\t\t\tboardWithKilledMinion,\r\n\t\t\t\tboardWithKilledMinionHero,\r\n\t\t\t\topponentBoard,\r\n\t\t\t\topponentBoardHero,\r\n\t\t\t\tgameState,\r\n\t\t\t});\r\n\t\t}\r\n\t}\r\n\r\n\tconst entitiesThatWereReborn = performEntitySpawns(\r\n\t\tentitiesFromReborn,\r\n\t\tboardWithKilledMinion,\r\n\t\tboardWithKilledMinionHero,\r\n\t\tdeadEntity,\r\n\t\tdeadMinionIndexFromRight,\r\n\t\topponentBoard,\r\n\t\topponentBoardHero,\r\n\t\tgameState,\r\n\t);\r\n\tentitiesThatWereReborn.forEach((e) => (e.rebornFromEntityId = deadEntity.entityId));\r\n\tconst entityRightToSpawns =\r\n\t\tdeadMinionIndexFromRight === 0\r\n\t\t\t? null\r\n\t\t\t: boardWithKilledMinion[boardWithKilledMinion.length - deadMinionIndexFromRight];\r\n\tentitiesThatWereReborn.forEach((entity) => {\r\n\t\tentity.hasAttacked = deadEntity.hasAttacked > 1 ? 1 : entityRightToSpawns?.hasAttacked ?? undefined;\r\n\t});\r\n\r\n\tfor (const rebornEntity of entitiesThatWereReborn) {\r\n\t\tfor (const entity of boardWithKilledMinion) {\r\n\t\t\tconst rebornImpl = cardMappings[entity.cardId];\r\n\t\t\tif (hasAfterReborn(rebornImpl)) {\r\n\t\t\t\trebornImpl.afterReborn(entity, {\r\n\t\t\t\t\trebornEntity: rebornEntity,\r\n\t\t\t\t\tboardWithKilledMinion,\r\n\t\t\t\t\tboardWithKilledMinionHero,\r\n\t\t\t\t\topponentBoard,\r\n\t\t\t\t\topponentBoardHero,\r\n\t\t\t\t\tgameState,\r\n\t\t\t\t});\r\n\t\t\t}\r\n\t\t}\r\n\t\tfor (const trinket of boardWithKilledMinionHero.trinkets ?? []) {\r\n\t\t\tconst rebornImpl = cardMappings[trinket.cardId];\r\n\t\t\tif (hasAfterReborn(rebornImpl)) {\r\n\t\t\t\trebornImpl.afterReborn(trinket, {\r\n\t\t\t\t\trebornEntity: rebornEntity,\r\n\t\t\t\t\tboardWithKilledMinion,\r\n\t\t\t\t\tboardWithKilledMinionHero,\r\n\t\t\t\t\topponentBoard,\r\n\t\t\t\t\topponentBoardHero,\r\n\t\t\t\t\tgameState,\r\n\t\t\t\t});\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t// Arfus\r\n\tboardWithKilledMinion\r\n\t\t.filter(\r\n\t\t\t(e) =>\r\n\t\t\t\te.cardId === CardIds.Arfus_TB_BaconShop_HERO_22_Buddy ||\r\n\t\t\t\te.cardId === CardIds.Arfus_TB_BaconShop_HERO_22_Buddy_G,\r\n\t\t)\r\n\t\t.forEach((arfus) => {\r\n\t\t\tconst multiplier = arfus.cardId === CardIds.Arfus_TB_BaconShop_HERO_22_Buddy_G ? 2 : 1;\r\n\t\t\tconst attackBonus = arfus.attack * multiplier;\r\n\t\t\tentitiesThatWereReborn\r\n\t\t\t\t.filter((e) => e.entityId !== arfus.entityId && e.rebornFromEntityId !== arfus.entityId)\r\n\t\t\t\t.forEach((e) => {\r\n\t\t\t\t\tmodifyStats(e, arfus, attackBonus, 0, boardWithKilledMinion, boardWithKilledMinionHero, gameState);\r\n\t\t\t\t});\r\n\t\t});\r\n\r\n\tconst numberOfTriggersForDeathwhisper = Math.min(entitiesThatWereReborn.length, 1);\r\n\tfor (let i = 0; i < numberOfTriggersForDeathwhisper; i++) {\r\n\t\tboardWithKilledMinion\r\n\t\t\t.filter(\r\n\t\t\t\t(e) =>\r\n\t\t\t\t\te.cardId === CardIds.SisterDeathwhisper_BG25_020 ||\r\n\t\t\t\t\te.cardId === CardIds.SisterDeathwhisper_BG25_020_G,\r\n\t\t\t)\r\n\t\t\t.forEach((e) => {\r\n\t\t\t\tconst multiplier = e.cardId === CardIds.SisterDeathwhisper_BG25_020_G ? 2 : 1;\r\n\t\t\t\taddStatsToBoard(\r\n\t\t\t\t\te,\r\n\t\t\t\t\tboardWithKilledMinion,\r\n\t\t\t\t\tboardWithKilledMinionHero,\r\n\t\t\t\t\tmultiplier * 1,\r\n\t\t\t\t\tmultiplier * 3,\r\n\t\t\t\t\tgameState,\r\n\t\t\t\t);\r\n\t\t\t});\r\n\t}\r\n};\r\n\r\nexport interface RebornEffectInput {\r\n\treadonly rebornEntity: BoardEntity;\r\n\treadonly boardWithKilledMinion: BoardEntity[];\r\n\treadonly boardWithKilledMinionHero: BgsPlayerEntity;\r\n\treadonly opponentBoard: BoardEntity[];\r\n\treadonly opponentBoardHero: BgsPlayerEntity;\r\n\treadonly gameState: FullGameState;\r\n}\r\n"]}
|
|
1
|
+
{"version":3,"file":"reborn.js","sourceRoot":"","sources":["../../src/simulation/reborn.ts"],"names":[],"mappings":"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","sourcesContent":["import { BgsPlayerEntity } from '../bgs-player-entity';\r\nimport { BoardEntity } from '../board-entity';\r\nimport {\r\n\thasAfterReborn,\r\n\thasBeforeRebornSelfEffect,\r\n\thasRebornEffect,\r\n\thasRebornSelfEffect,\r\n} from '../cards/card.interface';\r\nimport { cardMappings } from '../cards/impl/_card-mappings';\r\nimport { buildSinrunnerBlanchyRebornEntity, isSinrunnerBlanchy } from '../cards/impl/minion/sinrunner-blanchy';\r\nimport { CardIds } from '../services/card-ids';\r\nimport { addStatsToBoard } from '../utils';\r\nimport { spawnEntities } from './deathrattle-spawns';\r\nimport { FullGameState } from './internal-game-state';\r\nimport { performEntitySpawns } from './spawns';\r\nimport { modifyStats } from './stats';\r\n\r\nexport const handleRebornForEntity = (\r\n\tboardWithKilledMinion: BoardEntity[],\r\n\tboardWithKilledMinionHero: BgsPlayerEntity,\r\n\tdeadEntity: BoardEntity,\r\n\tdeadMinionIndexFromRight: number,\r\n\topponentBoard: BoardEntity[],\r\n\topponentBoardHero: BgsPlayerEntity,\r\n\tgameState: FullGameState,\r\n): void => {\r\n\tconst numberOfReborns = 1;\r\n\tlet entityToSpawn: BoardEntity = null;\r\n\tif (\r\n\t\tisSinrunnerBlanchy(deadEntity.cardId) ||\r\n\t\tdeadEntity.enchantments?.some(\r\n\t\t\t(e) => e.cardId === CardIds.UltraCapacitor_UltraCapacitorEnchantment_BG31_HERO_801ptje,\r\n\t\t)\r\n\t) {\r\n\t\tentityToSpawn = buildSinrunnerBlanchyRebornEntity(deadEntity);\r\n\t}\r\n\r\n\tconst rebornImpl = cardMappings[deadEntity.cardId];\r\n\tif (hasBeforeRebornSelfEffect(rebornImpl)) {\r\n\t\trebornImpl.beforeRebornSelfEffect(deadEntity, {\r\n\t\t\trebornEntity: deadEntity,\r\n\t\t\tboardWithKilledMinion,\r\n\t\t\tboardWithKilledMinionHero,\r\n\t\t\topponentBoard,\r\n\t\t\topponentBoardHero,\r\n\t\t\tgameState,\r\n\t\t});\r\n\t}\r\n\r\n\tconst entitiesFromReborn: readonly BoardEntity[] =\r\n\t\tdeadEntity.reborn && deadMinionIndexFromRight >= 0\r\n\t\t\t? spawnEntities(\r\n\t\t\t\t\tdeadEntity.cardId,\r\n\t\t\t\t\tnumberOfReborns,\r\n\t\t\t\t\tboardWithKilledMinion,\r\n\t\t\t\t\tboardWithKilledMinionHero,\r\n\t\t\t\t\topponentBoard,\r\n\t\t\t\t\topponentBoardHero,\r\n\t\t\t\t\tgameState,\r\n\t\t\t\t\tdeadEntity.friendly,\r\n\t\t\t\t\tfalse,\r\n\t\t\t\t\ttrue,\r\n\t\t\t\t\ttrue,\r\n\t\t\t\t\tentityToSpawn,\r\n\t\t\t\t\tdeadEntity,\r\n\t\t\t )\r\n\t\t\t: [];\r\n\tif (!entitiesFromReborn.length) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tif (\r\n\t\tdeadEntity.cardId === CardIds.WannabeGargoyle_BG30_109 ||\r\n\t\tdeadEntity.cardId === CardIds.WannabeGargoyle_BG30_109_G\r\n\t) {\r\n\t\tentitiesFromReborn.forEach((e) => {\r\n\t\t\tconst attack = deadEntity.maxAttack;\r\n\t\t\tconst health = deadEntity.cardId === CardIds.WannabeGargoyle_BG30_109_G ? deadEntity.maxHealth : 1;\r\n\t\t\te.attack = attack;\r\n\t\t\te.health = health;\r\n\t\t});\r\n\t}\r\n\r\n\tfor (const entity of entitiesFromReborn) {\r\n\t\tconst rebornImpl = cardMappings[entity.cardId];\r\n\t\tif (hasRebornSelfEffect(rebornImpl)) {\r\n\t\t\trebornImpl.rebornSelfEffect(entity, {\r\n\t\t\t\trebornEntity: deadEntity,\r\n\t\t\t\tboardWithKilledMinion,\r\n\t\t\t\tboardWithKilledMinionHero,\r\n\t\t\t\topponentBoard,\r\n\t\t\t\topponentBoardHero,\r\n\t\t\t\tgameState,\r\n\t\t\t});\r\n\t\t}\r\n\t}\r\n\r\n\tfor (const entity of boardWithKilledMinion) {\r\n\t\tconst rebornImpl = cardMappings[entity.cardId];\r\n\t\tif (hasRebornEffect(rebornImpl)) {\r\n\t\t\trebornImpl.rebornEffect(entity, {\r\n\t\t\t\trebornEntity: deadEntity,\r\n\t\t\t\tboardWithKilledMinion,\r\n\t\t\t\tboardWithKilledMinionHero,\r\n\t\t\t\topponentBoard,\r\n\t\t\t\topponentBoardHero,\r\n\t\t\t\tgameState,\r\n\t\t\t});\r\n\t\t}\r\n\t}\r\n\r\n\tconst entitiesThatWereReborn = performEntitySpawns(\r\n\t\tentitiesFromReborn,\r\n\t\tboardWithKilledMinion,\r\n\t\tboardWithKilledMinionHero,\r\n\t\tdeadEntity,\r\n\t\tdeadMinionIndexFromRight,\r\n\t\topponentBoard,\r\n\t\topponentBoardHero,\r\n\t\tgameState,\r\n\t);\r\n\tentitiesThatWereReborn.forEach((e) => (e.rebornFromEntityId = deadEntity.entityId));\r\n\tconst entityRightToSpawns =\r\n\t\tdeadMinionIndexFromRight === 0\r\n\t\t\t? null\r\n\t\t\t: boardWithKilledMinion[boardWithKilledMinion.length - deadMinionIndexFromRight];\r\n\tentitiesThatWereReborn.forEach((entity) => {\r\n\t\tentity.hasAttacked = deadEntity.hasAttacked > 1 ? 1 : entityRightToSpawns?.hasAttacked ?? undefined;\r\n\t});\r\n\r\n\tfor (const rebornEntity of entitiesThatWereReborn) {\r\n\t\tfor (const entity of boardWithKilledMinion) {\r\n\t\t\tconst rebornImpl = cardMappings[entity.cardId];\r\n\t\t\tif (hasAfterReborn(rebornImpl)) {\r\n\t\t\t\trebornImpl.afterReborn(entity, {\r\n\t\t\t\t\trebornEntity: rebornEntity,\r\n\t\t\t\t\tboardWithKilledMinion,\r\n\t\t\t\t\tboardWithKilledMinionHero,\r\n\t\t\t\t\topponentBoard,\r\n\t\t\t\t\topponentBoardHero,\r\n\t\t\t\t\tgameState,\r\n\t\t\t\t});\r\n\t\t\t}\r\n\t\t}\r\n\t\tfor (const trinket of boardWithKilledMinionHero.trinkets ?? []) {\r\n\t\t\tconst rebornImpl = cardMappings[trinket.cardId];\r\n\t\t\tif (hasAfterReborn(rebornImpl)) {\r\n\t\t\t\trebornImpl.afterReborn(trinket, {\r\n\t\t\t\t\trebornEntity: rebornEntity,\r\n\t\t\t\t\tboardWithKilledMinion,\r\n\t\t\t\t\tboardWithKilledMinionHero,\r\n\t\t\t\t\topponentBoard,\r\n\t\t\t\t\topponentBoardHero,\r\n\t\t\t\t\tgameState,\r\n\t\t\t\t});\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t// Arfus\r\n\tboardWithKilledMinion\r\n\t\t.filter(\r\n\t\t\t(e) =>\r\n\t\t\t\te.cardId === CardIds.Arfus_TB_BaconShop_HERO_22_Buddy ||\r\n\t\t\t\te.cardId === CardIds.Arfus_TB_BaconShop_HERO_22_Buddy_G,\r\n\t\t)\r\n\t\t.forEach((arfus) => {\r\n\t\t\tconst multiplier = arfus.cardId === CardIds.Arfus_TB_BaconShop_HERO_22_Buddy_G ? 2 : 1;\r\n\t\t\tconst attackBonus = arfus.attack * multiplier;\r\n\t\t\tentitiesThatWereReborn\r\n\t\t\t\t.filter((e) => e.entityId !== arfus.entityId && e.rebornFromEntityId !== arfus.entityId)\r\n\t\t\t\t.forEach((e) => {\r\n\t\t\t\t\tmodifyStats(e, arfus, attackBonus, 0, boardWithKilledMinion, boardWithKilledMinionHero, gameState);\r\n\t\t\t\t});\r\n\t\t});\r\n\r\n\tconst numberOfTriggersForDeathwhisper = Math.min(entitiesThatWereReborn.length, 1);\r\n\tfor (let i = 0; i < numberOfTriggersForDeathwhisper; i++) {\r\n\t\tboardWithKilledMinion\r\n\t\t\t.filter(\r\n\t\t\t\t(e) =>\r\n\t\t\t\t\te.cardId === CardIds.SisterDeathwhisper_BG25_020 ||\r\n\t\t\t\t\te.cardId === CardIds.SisterDeathwhisper_BG25_020_G,\r\n\t\t\t)\r\n\t\t\t.forEach((e) => {\r\n\t\t\t\tconst multiplier = e.cardId === CardIds.SisterDeathwhisper_BG25_020_G ? 2 : 1;\r\n\t\t\t\taddStatsToBoard(\r\n\t\t\t\t\te,\r\n\t\t\t\t\tboardWithKilledMinion,\r\n\t\t\t\t\tboardWithKilledMinionHero,\r\n\t\t\t\t\tmultiplier * 1,\r\n\t\t\t\t\tmultiplier * 3,\r\n\t\t\t\t\tgameState,\r\n\t\t\t\t);\r\n\t\t\t});\r\n\t}\r\n};\r\n\r\nexport interface RebornEffectInput {\r\n\treadonly rebornEntity: BoardEntity;\r\n\treadonly boardWithKilledMinion: BoardEntity[];\r\n\treadonly boardWithKilledMinionHero: BgsPlayerEntity;\r\n\treadonly opponentBoard: BoardEntity[];\r\n\treadonly opponentBoardHero: BgsPlayerEntity;\r\n\treadonly gameState: FullGameState;\r\n}\r\n"]}
|
|
@@ -7,6 +7,7 @@ export declare class Simulator {
|
|
|
7
7
|
private hasShowShortCircuitWarning;
|
|
8
8
|
constructor(gameState: FullGameState);
|
|
9
9
|
simulateSingleBattle(playerState: PlayerState, opponentState: PlayerState): SingleSimulationResult;
|
|
10
|
+
private logRunawayEntityDiagnostics;
|
|
10
11
|
private simulateSingleBattlePass;
|
|
11
12
|
private buildBoardTotalDamage;
|
|
12
13
|
}
|
|
@@ -16,81 +16,30 @@ class Simulator {
|
|
|
16
16
|
this.hasShowShortCircuitWarning = false;
|
|
17
17
|
}
|
|
18
18
|
simulateSingleBattle(playerState, opponentState) {
|
|
19
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j
|
|
19
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
|
|
20
20
|
let playerBoard = playerState.board;
|
|
21
21
|
let playerEntity = playerState.player;
|
|
22
22
|
let opponentBoard = opponentState.board;
|
|
23
23
|
let opponentEntity = opponentState.player;
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
entity.entityId
|
|
29
|
-
|
|
30
|
-
]
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
}),
|
|
39
|
-
...((_b = (_a = playerEntity.hand) === null || _a === void 0 ? void 0 : _a.flatMap((entity) => {
|
|
40
|
-
var _a, _b;
|
|
41
|
-
return [
|
|
42
|
-
entity.entityId,
|
|
43
|
-
...((_b = (_a = entity.enchantments) === null || _a === void 0 ? void 0 : _a.map((e) => e.originEntityId)) !== null && _b !== void 0 ? _b : []),
|
|
44
|
-
];
|
|
45
|
-
})) !== null && _b !== void 0 ? _b : []),
|
|
46
|
-
...((_d = (_c = opponentEntity.hand) === null || _c === void 0 ? void 0 : _c.flatMap((entity) => {
|
|
47
|
-
var _a, _b;
|
|
48
|
-
return [
|
|
49
|
-
entity.entityId,
|
|
50
|
-
...((_b = (_a = entity.enchantments) === null || _a === void 0 ? void 0 : _a.map((e) => e.originEntityId)) !== null && _b !== void 0 ? _b : []),
|
|
51
|
-
];
|
|
52
|
-
})) !== null && _d !== void 0 ? _d : []),
|
|
53
|
-
];
|
|
54
|
-
this.gameState.sharedState.currentEntityId = Math.max(...allEntityIds) + 1;
|
|
24
|
+
let maxEntityId = -Infinity;
|
|
25
|
+
for (const group of [playerBoard, opponentBoard, playerEntity.hand, opponentEntity.hand]) {
|
|
26
|
+
for (const entity of group !== null && group !== void 0 ? group : []) {
|
|
27
|
+
if (entity.entityId > maxEntityId) {
|
|
28
|
+
maxEntityId = entity.entityId;
|
|
29
|
+
}
|
|
30
|
+
for (const enchantment of (_a = entity.enchantments) !== null && _a !== void 0 ? _a : []) {
|
|
31
|
+
if (enchantment.originEntityId > maxEntityId) {
|
|
32
|
+
maxEntityId = enchantment.originEntityId;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
this.gameState.sharedState.currentEntityId = maxEntityId + 1;
|
|
55
38
|
while (!playerEntity.startOfCombatDone ||
|
|
56
39
|
!opponentEntity.startOfCombatDone ||
|
|
57
40
|
((playerBoard === null || playerBoard === void 0 ? void 0 : playerBoard.length) > 0 && (opponentBoard === null || opponentBoard === void 0 ? void 0 : opponentBoard.length) > 0)) {
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
var _a, _b;
|
|
61
|
-
const result = [entity.entityId, ...((_b = (_a = entity.enchantments) === null || _a === void 0 ? void 0 : _a.map((e) => e.originEntityId)) !== null && _b !== void 0 ? _b : [])];
|
|
62
|
-
if (result.length > 200) {
|
|
63
|
-
console.log('too many entities for entity', result.length, (0, utils_1.stringifySimpleCard)(entity, this.gameState.allCards));
|
|
64
|
-
}
|
|
65
|
-
return result;
|
|
66
|
-
}),
|
|
67
|
-
...opponentBoard.flatMap((entity) => {
|
|
68
|
-
var _a, _b;
|
|
69
|
-
const result = [entity.entityId, ...((_b = (_a = entity.enchantments) === null || _a === void 0 ? void 0 : _a.map((e) => e.originEntityId)) !== null && _b !== void 0 ? _b : [])];
|
|
70
|
-
if (result.length > 200) {
|
|
71
|
-
console.log('too many entities for entity', result.length, (0, utils_1.stringifySimpleCard)(entity, this.gameState.allCards));
|
|
72
|
-
}
|
|
73
|
-
return result;
|
|
74
|
-
}),
|
|
75
|
-
...playerEntity.hand.flatMap((entity) => {
|
|
76
|
-
var _a, _b;
|
|
77
|
-
const result = [entity.entityId, ...((_b = (_a = entity.enchantments) === null || _a === void 0 ? void 0 : _a.map((e) => e.originEntityId)) !== null && _b !== void 0 ? _b : [])];
|
|
78
|
-
if (result.length > 200) {
|
|
79
|
-
console.log('too many entities for entity', result.length, (0, utils_1.stringifySimpleCard)(entity, this.gameState.allCards));
|
|
80
|
-
}
|
|
81
|
-
return result;
|
|
82
|
-
}),
|
|
83
|
-
...opponentEntity.hand.flatMap((entity) => {
|
|
84
|
-
var _a, _b;
|
|
85
|
-
const result = [entity.entityId, ...((_b = (_a = entity.enchantments) === null || _a === void 0 ? void 0 : _a.map((e) => e.originEntityId)) !== null && _b !== void 0 ? _b : [])];
|
|
86
|
-
if (result.length > 200) {
|
|
87
|
-
console.log('too many entities for entity', result.length, (0, utils_1.stringifySimpleCard)(entity, this.gameState.allCards));
|
|
88
|
-
}
|
|
89
|
-
return result;
|
|
90
|
-
}),
|
|
91
|
-
];
|
|
92
|
-
if (allEntityIds.length > 10000) {
|
|
93
|
-
console.log('allEntityIds2', allEntityIds, new Error().stack);
|
|
41
|
+
if (debug_state_1.debugState === null || debug_state_1.debugState === void 0 ? void 0 : debug_state_1.debugState.active) {
|
|
42
|
+
this.logRunawayEntityDiagnostics(playerBoard, playerEntity, opponentBoard, opponentEntity);
|
|
94
43
|
}
|
|
95
44
|
this.simulateSingleBattlePass(playerBoard, playerEntity, opponentBoard, opponentEntity);
|
|
96
45
|
if (this.hasShowShortCircuitWarning) {
|
|
@@ -107,18 +56,18 @@ class Simulator {
|
|
|
107
56
|
const isPlayerDefeated = playerState.board.length === 0 || playerState.player.hpLeft <= 0;
|
|
108
57
|
const isOpponentDefeated = opponentState.board.length === 0 || opponentState.player.hpLeft <= 0;
|
|
109
58
|
if (isPlayerDefeated) {
|
|
110
|
-
playerBoard = (
|
|
59
|
+
playerBoard = (_b = playerState.teammate) === null || _b === void 0 ? void 0 : _b.board;
|
|
111
60
|
playerState.board = [];
|
|
112
|
-
playerEntity = (
|
|
61
|
+
playerEntity = (_c = playerState.teammate) === null || _c === void 0 ? void 0 : _c.player;
|
|
113
62
|
}
|
|
114
63
|
else {
|
|
115
64
|
playerBoard = playerState.board;
|
|
116
65
|
playerEntity = playerState.player;
|
|
117
66
|
}
|
|
118
67
|
if (isOpponentDefeated) {
|
|
119
|
-
opponentBoard = (
|
|
68
|
+
opponentBoard = (_d = opponentState.teammate) === null || _d === void 0 ? void 0 : _d.board;
|
|
120
69
|
opponentState.board = [];
|
|
121
|
-
opponentEntity = (
|
|
70
|
+
opponentEntity = (_e = opponentState.teammate) === null || _e === void 0 ? void 0 : _e.player;
|
|
122
71
|
}
|
|
123
72
|
else {
|
|
124
73
|
opponentBoard = opponentState.board;
|
|
@@ -153,7 +102,7 @@ class Simulator {
|
|
|
153
102
|
};
|
|
154
103
|
}
|
|
155
104
|
if (!(playerBoard === null || playerBoard === void 0 ? void 0 : playerBoard.length) || playerEntity.hpLeft <= 0) {
|
|
156
|
-
const damage = this.buildBoardTotalDamage(opponentBoard, (
|
|
105
|
+
const damage = this.buildBoardTotalDamage(opponentBoard, (_g = (_f = this.gameState.gameState.opponent) === null || _f === void 0 ? void 0 : _f.teammate) === null || _g === void 0 ? void 0 : _g.board) +
|
|
157
106
|
opponentEntity.tavernTier;
|
|
158
107
|
this.gameState.spectator.registerOpponentAttack(playerBoard, opponentBoard, damage);
|
|
159
108
|
return {
|
|
@@ -161,7 +110,7 @@ class Simulator {
|
|
|
161
110
|
damageDealt: damage,
|
|
162
111
|
};
|
|
163
112
|
}
|
|
164
|
-
const damage = this.buildBoardTotalDamage(playerBoard, (
|
|
113
|
+
const damage = this.buildBoardTotalDamage(playerBoard, (_j = (_h = this.gameState.gameState.player) === null || _h === void 0 ? void 0 : _h.teammate) === null || _j === void 0 ? void 0 : _j.board) +
|
|
165
114
|
playerEntity.tavernTier;
|
|
166
115
|
this.gameState.spectator.registerPlayerAttack(playerBoard, opponentBoard, damage);
|
|
167
116
|
return {
|
|
@@ -169,6 +118,22 @@ class Simulator {
|
|
|
169
118
|
damageDealt: damage,
|
|
170
119
|
};
|
|
171
120
|
}
|
|
121
|
+
logRunawayEntityDiagnostics(playerBoard, playerEntity, opponentBoard, opponentEntity) {
|
|
122
|
+
var _a, _b;
|
|
123
|
+
const allEntityIds = [];
|
|
124
|
+
for (const group of [playerBoard, opponentBoard, playerEntity.hand, opponentEntity.hand]) {
|
|
125
|
+
for (const entity of group !== null && group !== void 0 ? group : []) {
|
|
126
|
+
const result = [entity.entityId, ...((_b = (_a = entity.enchantments) === null || _a === void 0 ? void 0 : _a.map((e) => e.originEntityId)) !== null && _b !== void 0 ? _b : [])];
|
|
127
|
+
if (result.length > 200) {
|
|
128
|
+
console.log('too many entities for entity', result.length, (0, utils_1.stringifySimpleCard)(entity, this.gameState.allCards));
|
|
129
|
+
}
|
|
130
|
+
allEntityIds.push(...result);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
if (allEntityIds.length > 10000) {
|
|
134
|
+
console.log('allEntityIds2', allEntityIds, new Error().stack);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
172
137
|
simulateSingleBattlePass(playerBoard, playerEntity, opponentBoard, opponentEntity) {
|
|
173
138
|
var _a;
|
|
174
139
|
if (debug_state_1.debugState === null || debug_state_1.debugState === void 0 ? void 0 : debug_state_1.debugState.active) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"simulator.js","sourceRoot":"","sources":["../../src/simulation/simulator.ts"],"names":[],"mappings":"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","sourcesContent":["import { getEffectiveTechLevel } from '@firestone-hs/reference-data';\r\nimport { BgsPlayerEntity } from '../bgs-player-entity';\r\nimport { BoardEntity } from '../board-entity';\r\nimport { debugState } from '../debug-state';\r\nimport { SingleSimulationResult } from '../single-simulation-result';\r\nimport { stringifySimple, stringifySimpleCard } from '../utils';\r\nimport { simulateAttack } from './attack';\r\nimport { clearStealthIfNeeded } from './auras';\r\nimport { FullGameState, PlayerState } from './internal-game-state';\r\nimport { resolvePendingEffects } from './pending-effects';\r\nimport { handleStartOfCombat } from './start-of-combat/start-of-combat';\r\nimport { handleSummonsWhenSpace } from './summon-when-space';\r\n\r\n// New simulator should be instantiated for each match\r\nexport class Simulator {\r\n\tprivate currentAttacker: number;\r\n\tprivate currentSpeedAttacker = -1;\r\n\r\n\tprivate hasShowShortCircuitWarning = false;\r\n\r\n\t// It should come already initialized\r\n\tconstructor(private readonly gameState: FullGameState) {}\r\n\r\n\t// Here we suppose that the BoardEntity only contain at most the enchantments that are linked\r\n\t// to auras (so we probably should hand-filter that, since there are actually few auras)\r\n\tpublic simulateSingleBattle(playerState: PlayerState, opponentState: PlayerState): SingleSimulationResult {\r\n\t\tlet playerBoard: BoardEntity[] = playerState.board;\r\n\t\tlet playerEntity: BgsPlayerEntity = playerState.player;\r\n\t\tlet opponentBoard: BoardEntity[] = opponentState.board;\r\n\t\tlet opponentEntity: BgsPlayerEntity = opponentState.player;\r\n\r\n\t\tconst allEntityIds = [\r\n\t\t\t...playerBoard.flatMap((entity) => [\r\n\t\t\t\tentity.entityId,\r\n\t\t\t\t...(entity.enchantments?.map((e) => e.originEntityId) ?? []),\r\n\t\t\t]),\r\n\t\t\t...opponentBoard.flatMap((entity) => [\r\n\t\t\t\tentity.entityId,\r\n\t\t\t\t...(entity.enchantments?.map((e) => e.originEntityId) ?? []),\r\n\t\t\t]),\r\n\t\t\t...(playerEntity.hand?.flatMap((entity) => [\r\n\t\t\t\tentity.entityId,\r\n\t\t\t\t...(entity.enchantments?.map((e) => e.originEntityId) ?? []),\r\n\t\t\t]) ?? []),\r\n\t\t\t...(opponentEntity.hand?.flatMap((entity) => [\r\n\t\t\t\tentity.entityId,\r\n\t\t\t\t...(entity.enchantments?.map((e) => e.originEntityId) ?? []),\r\n\t\t\t]) ?? []),\r\n\t\t];\r\n\t\tthis.gameState.sharedState.currentEntityId = Math.max(...allEntityIds) + 1;\r\n\r\n\t\twhile (\r\n\t\t\t!playerEntity.startOfCombatDone ||\r\n\t\t\t!opponentEntity.startOfCombatDone ||\r\n\t\t\t(playerBoard?.length > 0 && opponentBoard?.length > 0)\r\n\t\t) {\r\n\t\t\tconst allEntityIds = [\r\n\t\t\t\t...playerBoard.flatMap((entity) => {\r\n\t\t\t\t\tconst result = [entity.entityId, ...(entity.enchantments?.map((e) => e.originEntityId) ?? [])];\r\n\t\t\t\t\tif (result.length > 200) {\r\n\t\t\t\t\t\tconsole.log(\r\n\t\t\t\t\t\t\t'too many entities for entity',\r\n\t\t\t\t\t\t\tresult.length,\r\n\t\t\t\t\t\t\tstringifySimpleCard(entity, this.gameState.allCards),\r\n\t\t\t\t\t\t);\r\n\t\t\t\t\t}\r\n\t\t\t\t\treturn result;\r\n\t\t\t\t}),\r\n\t\t\t\t...opponentBoard.flatMap((entity) => {\r\n\t\t\t\t\tconst result = [entity.entityId, ...(entity.enchantments?.map((e) => e.originEntityId) ?? [])];\r\n\t\t\t\t\tif (result.length > 200) {\r\n\t\t\t\t\t\tconsole.log(\r\n\t\t\t\t\t\t\t'too many entities for entity',\r\n\t\t\t\t\t\t\tresult.length,\r\n\t\t\t\t\t\t\tstringifySimpleCard(entity, this.gameState.allCards),\r\n\t\t\t\t\t\t);\r\n\t\t\t\t\t}\r\n\t\t\t\t\treturn result;\r\n\t\t\t\t}),\r\n\t\t\t\t...playerEntity.hand.flatMap((entity) => {\r\n\t\t\t\t\tconst result = [entity.entityId, ...(entity.enchantments?.map((e) => e.originEntityId) ?? [])];\r\n\t\t\t\t\tif (result.length > 200) {\r\n\t\t\t\t\t\tconsole.log(\r\n\t\t\t\t\t\t\t'too many entities for entity',\r\n\t\t\t\t\t\t\tresult.length,\r\n\t\t\t\t\t\t\tstringifySimpleCard(entity, this.gameState.allCards),\r\n\t\t\t\t\t\t);\r\n\t\t\t\t\t}\r\n\t\t\t\t\treturn result;\r\n\t\t\t\t}),\r\n\t\t\t\t...opponentEntity.hand.flatMap((entity) => {\r\n\t\t\t\t\tconst result = [entity.entityId, ...(entity.enchantments?.map((e) => e.originEntityId) ?? [])];\r\n\t\t\t\t\tif (result.length > 200) {\r\n\t\t\t\t\t\tconsole.log(\r\n\t\t\t\t\t\t\t'too many entities for entity',\r\n\t\t\t\t\t\t\tresult.length,\r\n\t\t\t\t\t\t\tstringifySimpleCard(entity, this.gameState.allCards),\r\n\t\t\t\t\t\t);\r\n\t\t\t\t\t}\r\n\t\t\t\t\treturn result;\r\n\t\t\t\t}),\r\n\t\t\t];\r\n\t\t\tif (allEntityIds.length > 10000) {\r\n\t\t\t\tconsole.log('allEntityIds2', allEntityIds, new Error().stack);\r\n\t\t\t}\r\n\t\t\tthis.simulateSingleBattlePass(playerBoard, playerEntity, opponentBoard, opponentEntity);\r\n\t\t\tif (this.hasShowShortCircuitWarning) {\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\r\n\t\t\t// The only case where there can only 0-attack minions on a board is when both boards\r\n\t\t\t// are that way (otherwise one side would kill the other)\r\n\t\t\tconst areBothBoards0Attack =\r\n\t\t\t\tplayerState.board.length > 0 &&\r\n\t\t\t\tplayerState.board.every((entity) => entity.attack === 0) &&\r\n\t\t\t\topponentState.board.length > 0 &&\r\n\t\t\t\topponentState.board.every((entity) => entity.attack === 0);\r\n\t\t\tif (areBothBoards0Attack) {\r\n\t\t\t\tplayerState.board = [];\r\n\t\t\t\topponentState.board = [];\r\n\t\t\t}\r\n\r\n\t\t\tconst isPlayerDefeated = playerState.board.length === 0 || playerState.player.hpLeft <= 0;\r\n\t\t\tconst isOpponentDefeated = opponentState.board.length === 0 || opponentState.player.hpLeft <= 0;\r\n\t\t\tif (isPlayerDefeated) {\r\n\t\t\t\tplayerBoard = playerState.teammate?.board;\r\n\t\t\t\tplayerState.board = [];\r\n\t\t\t\tplayerEntity = playerState.teammate?.player;\r\n\t\t\t} else {\r\n\t\t\t\tplayerBoard = playerState.board;\r\n\t\t\t\tplayerEntity = playerState.player;\r\n\t\t\t}\r\n\t\t\tif (isOpponentDefeated) {\r\n\t\t\t\topponentBoard = opponentState.teammate?.board;\r\n\t\t\t\topponentState.board = [];\r\n\t\t\t\topponentEntity = opponentState.teammate?.player;\r\n\t\t\t} else {\r\n\t\t\t\topponentBoard = opponentState.board;\r\n\t\t\t\topponentEntity = opponentState.player;\r\n\t\t\t}\r\n\t\t\t// So that gameState.player always refers to the active player\r\n\t\t\tif (isPlayerDefeated) {\r\n\t\t\t\t// Reset deaths\r\n\t\t\t\tthis.gameState.sharedState.deaths = this.gameState.sharedState.deaths.filter(\r\n\t\t\t\t\t(e) => e.friendly !== this.gameState.gameState.player.player.friendly,\r\n\t\t\t\t);\r\n\t\t\t\tthis.gameState.gameState.player.teammate = {\r\n\t\t\t\t\tboard: this.gameState.gameState.player.board,\r\n\t\t\t\t\tplayer: this.gameState.gameState.player.player,\r\n\t\t\t\t};\r\n\t\t\t\tthis.gameState.gameState.player.player = playerEntity;\r\n\t\t\t\tthis.gameState.gameState.player.board = playerBoard;\r\n\r\n\t\t\t\t// const initialPlayer = this.gameState.gameState.playerInitial;\r\n\t\t\t\t// const initialPlayerTeammate = initialPlayer.teammate;\r\n\t\t\t}\r\n\t\t\tif (isOpponentDefeated) {\r\n\t\t\t\t// Reset deaths\r\n\t\t\t\tthis.gameState.sharedState.deaths = this.gameState.sharedState.deaths.filter(\r\n\t\t\t\t\t(e) => e.friendly !== this.gameState.gameState.opponent.player.friendly,\r\n\t\t\t\t);\r\n\t\t\t\tthis.gameState.gameState.opponent.teammate = {\r\n\t\t\t\t\tboard: this.gameState.gameState.opponent.board,\r\n\t\t\t\t\tplayer: this.gameState.gameState.opponent.player,\r\n\t\t\t\t};\r\n\t\t\t\tthis.gameState.gameState.opponent.player = opponentEntity;\r\n\t\t\t\tthis.gameState.gameState.opponent.board = opponentBoard;\r\n\t\t\t}\r\n\r\n\t\t\tif (!playerEntity || !opponentEntity) {\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif (\r\n\t\t\t(!playerBoard?.length && !opponentBoard?.length) ||\r\n\t\t\t// E.g. when both players have a 0-attack minion\r\n\t\t\t(playerBoard?.length > 0 && opponentBoard?.length > 0)\r\n\t\t) {\r\n\t\t\treturn {\r\n\t\t\t\tresult: 'tied',\r\n\t\t\t} as SingleSimulationResult;\r\n\t\t}\r\n\t\tif (!playerBoard?.length || playerEntity.hpLeft <= 0) {\r\n\t\t\tconst damage =\r\n\t\t\t\tthis.buildBoardTotalDamage(opponentBoard, this.gameState.gameState.opponent?.teammate?.board) +\r\n\t\t\t\topponentEntity.tavernTier;\r\n\t\t\tthis.gameState.spectator.registerOpponentAttack(playerBoard, opponentBoard, damage);\r\n\t\t\treturn {\r\n\t\t\t\tresult: 'lost',\r\n\t\t\t\tdamageDealt: damage,\r\n\t\t\t};\r\n\t\t}\r\n\r\n\t\tconst damage =\r\n\t\t\tthis.buildBoardTotalDamage(playerBoard, this.gameState.gameState.player?.teammate?.board) +\r\n\t\t\tplayerEntity.tavernTier;\r\n\t\tthis.gameState.spectator.registerPlayerAttack(playerBoard, opponentBoard, damage);\r\n\t\treturn {\r\n\t\t\tresult: 'won',\r\n\t\t\tdamageDealt: damage,\r\n\t\t};\r\n\t}\r\n\r\n\tprivate simulateSingleBattlePass(\r\n\t\tplayerBoard: BoardEntity[],\r\n\t\tplayerEntity: BgsPlayerEntity,\r\n\t\topponentBoard: BoardEntity[],\r\n\t\topponentEntity: BgsPlayerEntity,\r\n\t) {\r\n\t\tif (debugState?.active) {\r\n\t\t\tdebugState.onBattleStart();\r\n\t\t}\r\n\t\t// Start of combat happens only once, so we need to flag whether it has already happened for a\r\n\t\t// given player\r\n\t\tthis.gameState.spectator.registerStartOfCombat(playerBoard, opponentBoard, playerEntity, opponentEntity);\r\n\r\n\t\t// Who attacks first is decided by the game before the hero power comes into effect. However, the full board (with the generated minion)\r\n\t\t// is sent tothe simulator\r\n\t\t// But in fact, the first player decision takes into account that additional minion. See\r\n\t\t// https://replays.firestoneapp.com/?reviewId=ddbbbe93-464b-4400-8e8d-4abca8680a2e\r\n\t\tconst effectivePlayerBoardLength = playerBoard.length;\r\n\t\tconst effectiveOpponentBoardLength = opponentBoard.length;\r\n\t\tthis.currentAttacker =\r\n\t\t\teffectivePlayerBoardLength > effectiveOpponentBoardLength\r\n\t\t\t\t? 0\r\n\t\t\t\t: effectiveOpponentBoardLength > effectivePlayerBoardLength\r\n\t\t\t\t? 1\r\n\t\t\t\t: Math.round(Math.random());\r\n\t\tconst suggestedNewCurrentAttacker = handleStartOfCombat(\r\n\t\t\tplayerEntity,\r\n\t\t\tplayerBoard,\r\n\t\t\topponentEntity,\r\n\t\t\topponentBoard,\r\n\t\t\tthis.currentAttacker,\r\n\t\t\tthis.gameState,\r\n\t\t);\r\n\t\tthis.currentAttacker = suggestedNewCurrentAttacker;\r\n\t\tlet counter = 0;\r\n\t\tif (debugState?.active) {\r\n\t\t\tthis.currentAttacker = debugState.forcedCurrentAttacker ?? this.currentAttacker;\r\n\t\t}\r\n\t\twhile (\r\n\t\t\tplayerBoard.length > 0 &&\r\n\t\t\topponentBoard.length > 0 &&\r\n\t\t\tplayerEntity.hpLeft > 0 &&\r\n\t\t\topponentEntity.hpLeft > 0\r\n\t\t) {\r\n\t\t\thandleSummonsWhenSpace(playerBoard, playerEntity, opponentBoard, opponentEntity, this.gameState);\r\n\t\t\tclearStealthIfNeeded(playerBoard, playerEntity, opponentBoard, opponentEntity, this.gameState);\r\n\t\t\t// console.log('this.currentSpeedAttacker', this.currentAttacker);\r\n\t\t\t// If there are \"attack immediately\" minions, we keep the same player\r\n\t\t\t// We put it here so that it can kick in after the start of combat effects. However here we don't want\r\n\t\t\t// to change who attacks first, so we repeat that block again after all the attacks have been resolved\r\n\t\t\t// FIXME: This is not strictly correct - if there are multiple attack immediately\r\n\t\t\t// minions that spawn on both player sides it might get a bit more complex\r\n\t\t\t// but overall it works\r\n\t\t\t// Also, this doesn't work when there are several deathrattle competing\r\n\t\t\t// to know who triggers first. See the second test case of the scallywag.test.ts\r\n\t\t\t// that is not handled properly today (the attack should in some cases happen before\r\n\t\t\t// the other deathrattle procs)\r\n\t\t\tif (playerBoard.some((entity) => entity.attackImmediately)) {\r\n\t\t\t\tthis.currentSpeedAttacker = 0;\r\n\t\t\t} else if (opponentBoard.some((entity) => entity.attackImmediately)) {\r\n\t\t\t\tthis.currentSpeedAttacker = 1;\r\n\t\t\t} else {\r\n\t\t\t\tthis.currentSpeedAttacker = -1;\r\n\t\t\t}\r\n\t\t\tif (\r\n\t\t\t\tplayerBoard.filter((e) => e.attack > 0).length === 0 &&\r\n\t\t\t\topponentBoard.filter((e) => e.attack > 0).length === 0\r\n\t\t\t) {\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\r\n\t\t\t// console.log('this.currentSpeedAttacker 2', this.currentAttacker, this.currentSpeedAttacker);\r\n\t\t\tif (this.currentSpeedAttacker === 0 || (this.currentSpeedAttacker === -1 && this.currentAttacker === 0)) {\r\n\t\t\t\tsimulateAttack(playerBoard, playerEntity, opponentBoard, opponentEntity, this.gameState);\r\n\t\t\t} else {\r\n\t\t\t\tsimulateAttack(opponentBoard, opponentEntity, playerBoard, playerEntity, this.gameState);\r\n\t\t\t}\r\n\r\n\t\t\tresolvePendingEffects(playerBoard, playerEntity, opponentBoard, opponentEntity, this.gameState);\r\n\t\t\t// Update the attacker indices in case there were some deaths\r\n\t\t\tif (playerBoard.some((entity) => entity.attackImmediately)) {\r\n\t\t\t\tthis.currentSpeedAttacker = 0;\r\n\t\t\t} else if (opponentBoard.some((entity) => entity.attackImmediately)) {\r\n\t\t\t\tthis.currentSpeedAttacker = 1;\r\n\t\t\t} else {\r\n\t\t\t\tthis.currentSpeedAttacker = -1;\r\n\t\t\t\tthis.currentAttacker = (this.currentAttacker + 1) % 2;\r\n\t\t\t}\r\n\t\t\tcounter++;\r\n\t\t\tif (counter > 400 && !this.hasShowShortCircuitWarning) {\r\n\t\t\t\tconsole.warn(\r\n\t\t\t\t\t'short-circuiting simulation, too many iterations',\r\n\t\t\t\t\tcounter,\r\n\t\t\t\t\t'\\n',\r\n\t\t\t\t\tstringifySimple(playerBoard, this.gameState.allCards),\r\n\t\t\t\t\t'\\n',\r\n\t\t\t\t\tstringifySimple(opponentBoard, this.gameState.allCards),\r\n\t\t\t\t);\r\n\t\t\t\tthis.hasShowShortCircuitWarning = true;\r\n\t\t\t\tbreak;\r\n\t\t\t\t// return null;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tprivate buildBoardTotalDamage(playerBoard: readonly BoardEntity[], teammateBoard?: BoardEntity[]): number {\r\n\t\tconst damageFromPlayerBoard = playerBoard\r\n\t\t\t.map((entity) =>\r\n\t\t\t\tgetEffectiveTechLevel(this.gameState.allCards.getCard(entity.cardId), this.gameState.allCards),\r\n\t\t\t)\r\n\t\t\t.reduce((a, b) => a + b, 0);\r\n\t\tconst numberOfTeamateMinionsToSummnon = 7 - playerBoard.length;\r\n\t\tconst damageFromTeammateBoard =\r\n\t\t\tteammateBoard\r\n\t\t\t\t?.slice(0, numberOfTeamateMinionsToSummnon)\r\n\t\t\t\t.map((entity) =>\r\n\t\t\t\t\tgetEffectiveTechLevel(this.gameState.allCards.getCard(entity.cardId), this.gameState.allCards),\r\n\t\t\t\t)\r\n\t\t\t\t.reduce((a, b) => a + b, 0) ?? 0;\r\n\t\treturn damageFromPlayerBoard + damageFromTeammateBoard;\r\n\t}\r\n}\r\n"]}
|
|
1
|
+
{"version":3,"file":"simulator.js","sourceRoot":"","sources":["../../src/simulation/simulator.ts"],"names":[],"mappings":"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","sourcesContent":["import { getEffectiveTechLevel } from '@firestone-hs/reference-data';\r\nimport { BgsPlayerEntity } from '../bgs-player-entity';\r\nimport { BoardEntity } from '../board-entity';\r\nimport { debugState } from '../debug-state';\r\nimport { SingleSimulationResult } from '../single-simulation-result';\r\nimport { stringifySimple, stringifySimpleCard } from '../utils';\r\nimport { simulateAttack } from './attack';\r\nimport { clearStealthIfNeeded } from './auras';\r\nimport { FullGameState, PlayerState } from './internal-game-state';\r\nimport { resolvePendingEffects } from './pending-effects';\r\nimport { handleStartOfCombat } from './start-of-combat/start-of-combat';\r\nimport { handleSummonsWhenSpace } from './summon-when-space';\r\n\r\n// New simulator should be instantiated for each match\r\nexport class Simulator {\r\n\tprivate currentAttacker: number;\r\n\tprivate currentSpeedAttacker = -1;\r\n\r\n\tprivate hasShowShortCircuitWarning = false;\r\n\r\n\t// It should come already initialized\r\n\tconstructor(private readonly gameState: FullGameState) {}\r\n\r\n\t// Here we suppose that the BoardEntity only contain at most the enchantments that are linked\r\n\t// to auras (so we probably should hand-filter that, since there are actually few auras)\r\n\tpublic simulateSingleBattle(playerState: PlayerState, opponentState: PlayerState): SingleSimulationResult {\r\n\t\tlet playerBoard: BoardEntity[] = playerState.board;\r\n\t\tlet playerEntity: BgsPlayerEntity = playerState.player;\r\n\t\tlet opponentBoard: BoardEntity[] = opponentState.board;\r\n\t\tlet opponentEntity: BgsPlayerEntity = opponentState.player;\r\n\r\n\t\tlet maxEntityId = -Infinity;\r\n\t\tfor (const group of [playerBoard, opponentBoard, playerEntity.hand, opponentEntity.hand]) {\r\n\t\t\tfor (const entity of group ?? []) {\r\n\t\t\t\tif (entity.entityId > maxEntityId) {\r\n\t\t\t\t\tmaxEntityId = entity.entityId;\r\n\t\t\t\t}\r\n\t\t\t\tfor (const enchantment of entity.enchantments ?? []) {\r\n\t\t\t\t\tif (enchantment.originEntityId > maxEntityId) {\r\n\t\t\t\t\t\tmaxEntityId = enchantment.originEntityId;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\tthis.gameState.sharedState.currentEntityId = maxEntityId + 1;\r\n\r\n\t\twhile (\r\n\t\t\t!playerEntity.startOfCombatDone ||\r\n\t\t\t!opponentEntity.startOfCombatDone ||\r\n\t\t\t(playerBoard?.length > 0 && opponentBoard?.length > 0)\r\n\t\t) {\r\n\t\t\t// Diagnostic only: detect runaway enchantment growth. The full entity id arrays are\r\n\t\t\t// only built in debug mode, since this allocates a lot on every battle pass\r\n\t\t\tif (debugState?.active) {\r\n\t\t\t\tthis.logRunawayEntityDiagnostics(playerBoard, playerEntity, opponentBoard, opponentEntity);\r\n\t\t\t}\r\n\t\t\tthis.simulateSingleBattlePass(playerBoard, playerEntity, opponentBoard, opponentEntity);\r\n\t\t\tif (this.hasShowShortCircuitWarning) {\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\r\n\t\t\t// The only case where there can only 0-attack minions on a board is when both boards\r\n\t\t\t// are that way (otherwise one side would kill the other)\r\n\t\t\tconst areBothBoards0Attack =\r\n\t\t\t\tplayerState.board.length > 0 &&\r\n\t\t\t\tplayerState.board.every((entity) => entity.attack === 0) &&\r\n\t\t\t\topponentState.board.length > 0 &&\r\n\t\t\t\topponentState.board.every((entity) => entity.attack === 0);\r\n\t\t\tif (areBothBoards0Attack) {\r\n\t\t\t\tplayerState.board = [];\r\n\t\t\t\topponentState.board = [];\r\n\t\t\t}\r\n\r\n\t\t\tconst isPlayerDefeated = playerState.board.length === 0 || playerState.player.hpLeft <= 0;\r\n\t\t\tconst isOpponentDefeated = opponentState.board.length === 0 || opponentState.player.hpLeft <= 0;\r\n\t\t\tif (isPlayerDefeated) {\r\n\t\t\t\tplayerBoard = playerState.teammate?.board;\r\n\t\t\t\tplayerState.board = [];\r\n\t\t\t\tplayerEntity = playerState.teammate?.player;\r\n\t\t\t} else {\r\n\t\t\t\tplayerBoard = playerState.board;\r\n\t\t\t\tplayerEntity = playerState.player;\r\n\t\t\t}\r\n\t\t\tif (isOpponentDefeated) {\r\n\t\t\t\topponentBoard = opponentState.teammate?.board;\r\n\t\t\t\topponentState.board = [];\r\n\t\t\t\topponentEntity = opponentState.teammate?.player;\r\n\t\t\t} else {\r\n\t\t\t\topponentBoard = opponentState.board;\r\n\t\t\t\topponentEntity = opponentState.player;\r\n\t\t\t}\r\n\t\t\t// So that gameState.player always refers to the active player\r\n\t\t\tif (isPlayerDefeated) {\r\n\t\t\t\t// Reset deaths\r\n\t\t\t\tthis.gameState.sharedState.deaths = this.gameState.sharedState.deaths.filter(\r\n\t\t\t\t\t(e) => e.friendly !== this.gameState.gameState.player.player.friendly,\r\n\t\t\t\t);\r\n\t\t\t\tthis.gameState.gameState.player.teammate = {\r\n\t\t\t\t\tboard: this.gameState.gameState.player.board,\r\n\t\t\t\t\tplayer: this.gameState.gameState.player.player,\r\n\t\t\t\t};\r\n\t\t\t\tthis.gameState.gameState.player.player = playerEntity;\r\n\t\t\t\tthis.gameState.gameState.player.board = playerBoard;\r\n\r\n\t\t\t\t// const initialPlayer = this.gameState.gameState.playerInitial;\r\n\t\t\t\t// const initialPlayerTeammate = initialPlayer.teammate;\r\n\t\t\t}\r\n\t\t\tif (isOpponentDefeated) {\r\n\t\t\t\t// Reset deaths\r\n\t\t\t\tthis.gameState.sharedState.deaths = this.gameState.sharedState.deaths.filter(\r\n\t\t\t\t\t(e) => e.friendly !== this.gameState.gameState.opponent.player.friendly,\r\n\t\t\t\t);\r\n\t\t\t\tthis.gameState.gameState.opponent.teammate = {\r\n\t\t\t\t\tboard: this.gameState.gameState.opponent.board,\r\n\t\t\t\t\tplayer: this.gameState.gameState.opponent.player,\r\n\t\t\t\t};\r\n\t\t\t\tthis.gameState.gameState.opponent.player = opponentEntity;\r\n\t\t\t\tthis.gameState.gameState.opponent.board = opponentBoard;\r\n\t\t\t}\r\n\r\n\t\t\tif (!playerEntity || !opponentEntity) {\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif (\r\n\t\t\t(!playerBoard?.length && !opponentBoard?.length) ||\r\n\t\t\t// E.g. when both players have a 0-attack minion\r\n\t\t\t(playerBoard?.length > 0 && opponentBoard?.length > 0)\r\n\t\t) {\r\n\t\t\treturn {\r\n\t\t\t\tresult: 'tied',\r\n\t\t\t} as SingleSimulationResult;\r\n\t\t}\r\n\t\tif (!playerBoard?.length || playerEntity.hpLeft <= 0) {\r\n\t\t\tconst damage =\r\n\t\t\t\tthis.buildBoardTotalDamage(opponentBoard, this.gameState.gameState.opponent?.teammate?.board) +\r\n\t\t\t\topponentEntity.tavernTier;\r\n\t\t\tthis.gameState.spectator.registerOpponentAttack(playerBoard, opponentBoard, damage);\r\n\t\t\treturn {\r\n\t\t\t\tresult: 'lost',\r\n\t\t\t\tdamageDealt: damage,\r\n\t\t\t};\r\n\t\t}\r\n\r\n\t\tconst damage =\r\n\t\t\tthis.buildBoardTotalDamage(playerBoard, this.gameState.gameState.player?.teammate?.board) +\r\n\t\t\tplayerEntity.tavernTier;\r\n\t\tthis.gameState.spectator.registerPlayerAttack(playerBoard, opponentBoard, damage);\r\n\t\treturn {\r\n\t\t\tresult: 'won',\r\n\t\t\tdamageDealt: damage,\r\n\t\t};\r\n\t}\r\n\r\n\tprivate logRunawayEntityDiagnostics(\r\n\t\tplayerBoard: BoardEntity[],\r\n\t\tplayerEntity: BgsPlayerEntity,\r\n\t\topponentBoard: BoardEntity[],\r\n\t\topponentEntity: BgsPlayerEntity,\r\n\t): void {\r\n\t\tconst allEntityIds: number[] = [];\r\n\t\tfor (const group of [playerBoard, opponentBoard, playerEntity.hand, opponentEntity.hand]) {\r\n\t\t\tfor (const entity of group ?? []) {\r\n\t\t\t\tconst result = [entity.entityId, ...(entity.enchantments?.map((e) => e.originEntityId) ?? [])];\r\n\t\t\t\tif (result.length > 200) {\r\n\t\t\t\t\tconsole.log(\r\n\t\t\t\t\t\t'too many entities for entity',\r\n\t\t\t\t\t\tresult.length,\r\n\t\t\t\t\t\tstringifySimpleCard(entity, this.gameState.allCards),\r\n\t\t\t\t\t);\r\n\t\t\t\t}\r\n\t\t\t\tallEntityIds.push(...result);\r\n\t\t\t}\r\n\t\t}\r\n\t\tif (allEntityIds.length > 10000) {\r\n\t\t\tconsole.log('allEntityIds2', allEntityIds, new Error().stack);\r\n\t\t}\r\n\t}\r\n\r\n\tprivate simulateSingleBattlePass(\r\n\t\tplayerBoard: BoardEntity[],\r\n\t\tplayerEntity: BgsPlayerEntity,\r\n\t\topponentBoard: BoardEntity[],\r\n\t\topponentEntity: BgsPlayerEntity,\r\n\t) {\r\n\t\tif (debugState?.active) {\r\n\t\t\tdebugState.onBattleStart();\r\n\t\t}\r\n\t\t// Start of combat happens only once, so we need to flag whether it has already happened for a\r\n\t\t// given player\r\n\t\tthis.gameState.spectator.registerStartOfCombat(playerBoard, opponentBoard, playerEntity, opponentEntity);\r\n\r\n\t\t// Who attacks first is decided by the game before the hero power comes into effect. However, the full board (with the generated minion)\r\n\t\t// is sent tothe simulator\r\n\t\t// But in fact, the first player decision takes into account that additional minion. See\r\n\t\t// https://replays.firestoneapp.com/?reviewId=ddbbbe93-464b-4400-8e8d-4abca8680a2e\r\n\t\tconst effectivePlayerBoardLength = playerBoard.length;\r\n\t\tconst effectiveOpponentBoardLength = opponentBoard.length;\r\n\t\tthis.currentAttacker =\r\n\t\t\teffectivePlayerBoardLength > effectiveOpponentBoardLength\r\n\t\t\t\t? 0\r\n\t\t\t\t: effectiveOpponentBoardLength > effectivePlayerBoardLength\r\n\t\t\t\t? 1\r\n\t\t\t\t: Math.round(Math.random());\r\n\t\tconst suggestedNewCurrentAttacker = handleStartOfCombat(\r\n\t\t\tplayerEntity,\r\n\t\t\tplayerBoard,\r\n\t\t\topponentEntity,\r\n\t\t\topponentBoard,\r\n\t\t\tthis.currentAttacker,\r\n\t\t\tthis.gameState,\r\n\t\t);\r\n\t\tthis.currentAttacker = suggestedNewCurrentAttacker;\r\n\t\tlet counter = 0;\r\n\t\tif (debugState?.active) {\r\n\t\t\tthis.currentAttacker = debugState.forcedCurrentAttacker ?? this.currentAttacker;\r\n\t\t}\r\n\t\twhile (\r\n\t\t\tplayerBoard.length > 0 &&\r\n\t\t\topponentBoard.length > 0 &&\r\n\t\t\tplayerEntity.hpLeft > 0 &&\r\n\t\t\topponentEntity.hpLeft > 0\r\n\t\t) {\r\n\t\t\thandleSummonsWhenSpace(playerBoard, playerEntity, opponentBoard, opponentEntity, this.gameState);\r\n\t\t\tclearStealthIfNeeded(playerBoard, playerEntity, opponentBoard, opponentEntity, this.gameState);\r\n\t\t\t// console.log('this.currentSpeedAttacker', this.currentAttacker);\r\n\t\t\t// If there are \"attack immediately\" minions, we keep the same player\r\n\t\t\t// We put it here so that it can kick in after the start of combat effects. However here we don't want\r\n\t\t\t// to change who attacks first, so we repeat that block again after all the attacks have been resolved\r\n\t\t\t// FIXME: This is not strictly correct - if there are multiple attack immediately\r\n\t\t\t// minions that spawn on both player sides it might get a bit more complex\r\n\t\t\t// but overall it works\r\n\t\t\t// Also, this doesn't work when there are several deathrattle competing\r\n\t\t\t// to know who triggers first. See the second test case of the scallywag.test.ts\r\n\t\t\t// that is not handled properly today (the attack should in some cases happen before\r\n\t\t\t// the other deathrattle procs)\r\n\t\t\tif (playerBoard.some((entity) => entity.attackImmediately)) {\r\n\t\t\t\tthis.currentSpeedAttacker = 0;\r\n\t\t\t} else if (opponentBoard.some((entity) => entity.attackImmediately)) {\r\n\t\t\t\tthis.currentSpeedAttacker = 1;\r\n\t\t\t} else {\r\n\t\t\t\tthis.currentSpeedAttacker = -1;\r\n\t\t\t}\r\n\t\t\tif (\r\n\t\t\t\tplayerBoard.filter((e) => e.attack > 0).length === 0 &&\r\n\t\t\t\topponentBoard.filter((e) => e.attack > 0).length === 0\r\n\t\t\t) {\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\r\n\t\t\t// console.log('this.currentSpeedAttacker 2', this.currentAttacker, this.currentSpeedAttacker);\r\n\t\t\tif (this.currentSpeedAttacker === 0 || (this.currentSpeedAttacker === -1 && this.currentAttacker === 0)) {\r\n\t\t\t\tsimulateAttack(playerBoard, playerEntity, opponentBoard, opponentEntity, this.gameState);\r\n\t\t\t} else {\r\n\t\t\t\tsimulateAttack(opponentBoard, opponentEntity, playerBoard, playerEntity, this.gameState);\r\n\t\t\t}\r\n\r\n\t\t\tresolvePendingEffects(playerBoard, playerEntity, opponentBoard, opponentEntity, this.gameState);\r\n\t\t\t// Update the attacker indices in case there were some deaths\r\n\t\t\tif (playerBoard.some((entity) => entity.attackImmediately)) {\r\n\t\t\t\tthis.currentSpeedAttacker = 0;\r\n\t\t\t} else if (opponentBoard.some((entity) => entity.attackImmediately)) {\r\n\t\t\t\tthis.currentSpeedAttacker = 1;\r\n\t\t\t} else {\r\n\t\t\t\tthis.currentSpeedAttacker = -1;\r\n\t\t\t\tthis.currentAttacker = (this.currentAttacker + 1) % 2;\r\n\t\t\t}\r\n\t\t\tcounter++;\r\n\t\t\tif (counter > 400 && !this.hasShowShortCircuitWarning) {\r\n\t\t\t\tconsole.warn(\r\n\t\t\t\t\t'short-circuiting simulation, too many iterations',\r\n\t\t\t\t\tcounter,\r\n\t\t\t\t\t'\\n',\r\n\t\t\t\t\tstringifySimple(playerBoard, this.gameState.allCards),\r\n\t\t\t\t\t'\\n',\r\n\t\t\t\t\tstringifySimple(opponentBoard, this.gameState.allCards),\r\n\t\t\t\t);\r\n\t\t\t\tthis.hasShowShortCircuitWarning = true;\r\n\t\t\t\tbreak;\r\n\t\t\t\t// return null;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tprivate buildBoardTotalDamage(playerBoard: readonly BoardEntity[], teammateBoard?: BoardEntity[]): number {\r\n\t\tconst damageFromPlayerBoard = playerBoard\r\n\t\t\t.map((entity) =>\r\n\t\t\t\tgetEffectiveTechLevel(this.gameState.allCards.getCard(entity.cardId), this.gameState.allCards),\r\n\t\t\t)\r\n\t\t\t.reduce((a, b) => a + b, 0);\r\n\t\tconst numberOfTeamateMinionsToSummnon = 7 - playerBoard.length;\r\n\t\tconst damageFromTeammateBoard =\r\n\t\t\tteammateBoard\r\n\t\t\t\t?.slice(0, numberOfTeamateMinionsToSummnon)\r\n\t\t\t\t.map((entity) =>\r\n\t\t\t\t\tgetEffectiveTechLevel(this.gameState.allCards.getCard(entity.cardId), this.gameState.allCards),\r\n\t\t\t\t)\r\n\t\t\t\t.reduce((a, b) => a + b, 0) ?? 0;\r\n\t\treturn damageFromPlayerBoard + damageFromTeammateBoard;\r\n\t}\r\n}\r\n"]}
|
|
@@ -3,11 +3,21 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.resolveTrinketHeroPowerCardId = void 0;
|
|
4
4
|
const reference_data_1 = require("@firestone-hs/reference-data");
|
|
5
5
|
const TRINKET_SLOT_HERO_POWER = 3;
|
|
6
|
+
const resolutionCache = new WeakMap();
|
|
6
7
|
const resolveTrinketHeroPowerCardId = (trinkets) => {
|
|
7
|
-
var _a;
|
|
8
8
|
if (!(trinkets === null || trinkets === void 0 ? void 0 : trinkets.length)) {
|
|
9
9
|
return null;
|
|
10
10
|
}
|
|
11
|
+
if (resolutionCache.has(trinkets)) {
|
|
12
|
+
return resolutionCache.get(trinkets);
|
|
13
|
+
}
|
|
14
|
+
const result = doResolveTrinketHeroPowerCardId(trinkets);
|
|
15
|
+
resolutionCache.set(trinkets, result);
|
|
16
|
+
return result;
|
|
17
|
+
};
|
|
18
|
+
exports.resolveTrinketHeroPowerCardId = resolveTrinketHeroPowerCardId;
|
|
19
|
+
const doResolveTrinketHeroPowerCardId = (trinkets) => {
|
|
20
|
+
var _a;
|
|
11
21
|
const regularTrinketCardIds = new Set(trinkets
|
|
12
22
|
.filter((trinket) => trinket.scriptDataNum6 !== TRINKET_SLOT_HERO_POWER && !!trinket.cardId)
|
|
13
23
|
.map((trinket) => trinket.cardId));
|
|
@@ -23,5 +33,4 @@ const resolveTrinketHeroPowerCardId = (trinkets) => {
|
|
|
23
33
|
}
|
|
24
34
|
return slot3Trinket.cardId;
|
|
25
35
|
};
|
|
26
|
-
exports.resolveTrinketHeroPowerCardId = resolveTrinketHeroPowerCardId;
|
|
27
36
|
//# sourceMappingURL=resolve-trinket-hero-power.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolve-trinket-hero-power.js","sourceRoot":"","sources":["../../../src/simulation/spectator/resolve-trinket-hero-power.ts"],"names":[],"mappings":";;;AAAA,iEAAuD;AAGvD,MAAM,uBAAuB,GAAG,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"resolve-trinket-hero-power.js","sourceRoot":"","sources":["../../../src/simulation/spectator/resolve-trinket-hero-power.ts"],"names":[],"mappings":";;;AAAA,iEAAuD;AAGvD,MAAM,uBAAuB,GAAG,CAAC,CAAC;AAKlC,MAAM,eAAe,GAAG,IAAI,OAAO,EAAyB,CAAC;AAEtD,MAAM,6BAA6B,GAAG,CAC5C,QAAoD,EACpC,EAAE;IAClB,IAAI,CAAC,CAAA,QAAQ,aAAR,QAAQ,uBAAR,QAAQ,CAAE,MAAM,CAAA,EAAE;QACtB,OAAO,IAAI,CAAC;KACZ;IACD,IAAI,eAAe,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE;QAClC,OAAO,eAAe,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;KACrC;IACD,MAAM,MAAM,GAAG,+BAA+B,CAAC,QAAQ,CAAC,CAAC;IACzD,eAAe,CAAC,GAAG,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IACtC,OAAO,MAAM,CAAC;AACf,CAAC,CAAC;AAZW,QAAA,6BAA6B,iCAYxC;AAEF,MAAM,+BAA+B,GAAG,CAAC,QAAiC,EAAiB,EAAE;;IAC5F,MAAM,qBAAqB,GAAG,IAAI,GAAG,CACpC,QAAQ;SACN,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,cAAc,KAAK,uBAAuB,IAAI,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC;SAC3F,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,CAClC,CAAC;IACF,MAAM,YAAY,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,cAAc,KAAK,uBAAuB,CAAC,CAAC;IACpG,IAAI,CAAC,CAAA,YAAY,aAAZ,YAAY,uBAAZ,YAAY,CAAE,MAAM,CAAA,EAAE;QAC1B,OAAO,IAAI,CAAC;KACZ;IACD,IAAI,CAAA,MAAA,YAAY,CAAC,IAAI,0CAAG,wBAAO,CAAC,2BAA2B,CAAC,MAAK,CAAC,EAAE;QACnE,OAAO,IAAI,CAAC;KACZ;IACD,IAAI,qBAAqB,CAAC,GAAG,CAAC,YAAY,CAAC,MAAM,CAAC,EAAE;QACnD,OAAO,IAAI,CAAC;KACZ;IACD,OAAO,YAAY,CAAC,MAAM,CAAC;AAC5B,CAAC,CAAC","sourcesContent":["import { GameTag } from '@firestone-hs/reference-data';\r\nimport { BoardTrinket } from '../../bgs-player-entity';\r\n\r\nconst TRINKET_SLOT_HERO_POWER = 3;\r\n\r\n// The fields this resolution depends on (cardId, scriptDataNum6, ADDITIONAL_HERO_POWER_INDEX tag)\r\n// never change during a battle, and this is called for every recorded action, so cache the\r\n// result per trinkets array instance\r\nconst resolutionCache = new WeakMap<object, string | null>();\r\n\r\nexport const resolveTrinketHeroPowerCardId = (\r\n\ttrinkets: readonly BoardTrinket[] | null | undefined,\r\n): string | null => {\r\n\tif (!trinkets?.length) {\r\n\t\treturn null;\r\n\t}\r\n\tif (resolutionCache.has(trinkets)) {\r\n\t\treturn resolutionCache.get(trinkets);\r\n\t}\r\n\tconst result = doResolveTrinketHeroPowerCardId(trinkets);\r\n\tresolutionCache.set(trinkets, result);\r\n\treturn result;\r\n};\r\n\r\nconst doResolveTrinketHeroPowerCardId = (trinkets: readonly BoardTrinket[]): string | null => {\r\n\tconst regularTrinketCardIds = new Set(\r\n\t\ttrinkets\r\n\t\t\t.filter((trinket) => trinket.scriptDataNum6 !== TRINKET_SLOT_HERO_POWER && !!trinket.cardId)\r\n\t\t\t.map((trinket) => trinket.cardId),\r\n\t);\r\n\tconst slot3Trinket = trinkets.find((trinket) => trinket.scriptDataNum6 === TRINKET_SLOT_HERO_POWER);\r\n\tif (!slot3Trinket?.cardId) {\r\n\t\treturn null;\r\n\t}\r\n\tif (slot3Trinket.tags?.[GameTag.ADDITIONAL_HERO_POWER_INDEX] === 1) {\r\n\t\treturn null;\r\n\t}\r\n\tif (regularTrinketCardIds.has(slot3Trinket.cardId)) {\r\n\t\treturn null;\r\n\t}\r\n\treturn slot3Trinket.cardId;\r\n};\r\n"]}
|
|
@@ -9,7 +9,11 @@ export declare class Spectator {
|
|
|
9
9
|
private wonBattles;
|
|
10
10
|
private tiedBattles;
|
|
11
11
|
private lostBattles;
|
|
12
|
+
private recording;
|
|
12
13
|
constructor(enabled: boolean);
|
|
14
|
+
startRecording(): void;
|
|
15
|
+
stopRecording(): void;
|
|
16
|
+
hasSampleFor(result: 'won' | 'lost' | 'tied'): boolean;
|
|
13
17
|
prune(): void;
|
|
14
18
|
buildOutcomeSamples(gameState: BgsGameState): {
|
|
15
19
|
won: readonly GameSample[];
|