valtech-components 4.0.573 → 4.0.575

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.
@@ -59,7 +59,7 @@ import fixWebmDuration from 'fix-webm-duration';
59
59
  * Current version of valtech-components.
60
60
  * This is automatically updated during the publish process.
61
61
  */
62
- const VERSION = '4.0.573';
62
+ const VERSION = '4.0.575';
63
63
 
64
64
  // Control de estado de refresco (singleton a nivel de módulo)
65
65
  let isRefreshing = false;
@@ -61711,28 +61711,250 @@ const CHESSIMALS_BOT_PROFILES = [
61711
61711
  },
61712
61712
  ];
61713
61713
  const BOT_STYLES = {
61714
- explorer: { advancement: 1.05, capture: 0.82, safety: 0.62, power: 0.8, center: 1.15, unlock: 1.05, reply: 0.7, randomness: 260, spread: 0.68, mobility: 0.75, trap: 0.5, endgame: 0.55 },
61715
- impulsive: { advancement: 0.9, capture: 1.45, safety: 0.48, power: 1.15, center: 0.8, unlock: 0.9, reply: 0.55, randomness: 290, spread: 0.62, mobility: 0.85, trap: 0.62, endgame: 0.5 },
61716
- runner: { advancement: 1.55, capture: 0.78, safety: 0.5, power: 0.95, center: 0.7, unlock: 1.1, reply: 0.55, randomness: 250, spread: 0.6, mobility: 0.72, trap: 0.45, endgame: 1.1 },
61717
- hunter: { advancement: 0.95, capture: 1.45, safety: 0.9, power: 1.05, center: 0.95, unlock: 0.95, reply: 1, randomness: 90, spread: 0.3, mobility: 0.95, trap: 0.82, endgame: 0.76 },
61718
- guardian: { advancement: 0.88, capture: 1, safety: 1.45, power: 0.85, center: 1.05, unlock: 1, reply: 1.15, randomness: 70, spread: 0.26, mobility: 0.82, trap: 0.72, endgame: 0.72 },
61719
- jumper: { advancement: 1.12, capture: 1, safety: 0.92, power: 1.42, center: 1.18, unlock: 1.08, reply: 0.95, randomness: 95, spread: 0.32, mobility: 1.15, trap: 0.9, endgame: 0.82 },
61720
- strategist: { advancement: 1.05, capture: 1.08, safety: 1.22, power: 1.08, center: 1.16, unlock: 1.1, reply: 1.25, randomness: 22, spread: 0.14, mobility: 1.08, trap: 1.06, endgame: 1 },
61721
- predator: { advancement: 0.98, capture: 1.68, safety: 1.02, power: 1.34, center: 1, unlock: 1, reply: 1.12, randomness: 28, spread: 0.16, mobility: 1.02, trap: 1.18, endgame: 0.82 },
61722
- sprinter: { advancement: 1.72, capture: 0.9, safety: 0.95, power: 1.08, center: 0.86, unlock: 1.18, reply: 1, randomness: 26, spread: 0.15, mobility: 0.95, trap: 0.78, endgame: 1.42 },
61723
- sentinel: { advancement: 0.9, capture: 1.12, safety: 1.72, power: 0.95, center: 1.28, unlock: 1.05, reply: 1.38, randomness: 18, spread: 0.12, mobility: 0.86, trap: 1.04, endgame: 0.84 },
61724
- oracle: { advancement: 1, capture: 1.12, safety: 1.42, power: 1.1, center: 1.18, unlock: 1.08, reply: 1.8, randomness: 8, spread: 0.08, mobility: 1.06, trap: 1.22, endgame: 1.08 },
61725
- ambusher: { advancement: 0.9, capture: 1.48, safety: 1.08, power: 1.46, center: 1.05, unlock: 1.02, reply: 1.32, randomness: 14, spread: 0.1, mobility: 1.12, trap: 1.72, endgame: 0.92 },
61726
- locksmith: { advancement: 0.88, capture: 1.04, safety: 1.55, power: 1.02, center: 1.48, unlock: 1.12, reply: 1.52, randomness: 12, spread: 0.1, mobility: 1.58, trap: 1.24, endgame: 0.86 },
61727
- storm: { advancement: 1.18, capture: 1.38, safety: 0.98, power: 1.62, center: 1.08, unlock: 1.18, reply: 1.22, randomness: 18, spread: 0.13, mobility: 1.36, trap: 1.28, endgame: 1.02 },
61728
- matriarch: { advancement: 0.96, capture: 1.18, safety: 1.64, power: 1.18, center: 1.22, unlock: 1.08, reply: 1.66, randomness: 10, spread: 0.08, mobility: 1.02, trap: 1.36, endgame: 1 },
61729
- endgame: { advancement: 1.46, capture: 1, safety: 1.28, power: 1.04, center: 0.94, unlock: 1.08, reply: 1.44, randomness: 10, spread: 0.09, mobility: 0.98, trap: 1.02, endgame: 1.86 },
61730
- magnus: { advancement: 1.04, capture: 1.22, safety: 1.9, power: 0.9, center: 1.42, unlock: 1.08, reply: 2.08, randomness: 3, spread: 0.04, mobility: 1.08, trap: 1.42, endgame: 1.86 },
61714
+ explorer: {
61715
+ advancement: 1.05,
61716
+ capture: 0.82,
61717
+ safety: 0.62,
61718
+ power: 0.8,
61719
+ center: 1.15,
61720
+ unlock: 1.05,
61721
+ reply: 0.7,
61722
+ randomness: 260,
61723
+ spread: 0.68,
61724
+ mobility: 0.75,
61725
+ trap: 0.5,
61726
+ endgame: 0.55,
61727
+ },
61728
+ impulsive: {
61729
+ advancement: 0.9,
61730
+ capture: 1.45,
61731
+ safety: 0.48,
61732
+ power: 1.15,
61733
+ center: 0.8,
61734
+ unlock: 0.9,
61735
+ reply: 0.55,
61736
+ randomness: 290,
61737
+ spread: 0.62,
61738
+ mobility: 0.85,
61739
+ trap: 0.62,
61740
+ endgame: 0.5,
61741
+ },
61742
+ runner: {
61743
+ advancement: 1.55,
61744
+ capture: 0.78,
61745
+ safety: 0.5,
61746
+ power: 0.95,
61747
+ center: 0.7,
61748
+ unlock: 1.1,
61749
+ reply: 0.55,
61750
+ randomness: 250,
61751
+ spread: 0.6,
61752
+ mobility: 0.72,
61753
+ trap: 0.45,
61754
+ endgame: 1.1,
61755
+ },
61756
+ hunter: {
61757
+ advancement: 0.95,
61758
+ capture: 1.45,
61759
+ safety: 0.9,
61760
+ power: 1.05,
61761
+ center: 0.95,
61762
+ unlock: 0.95,
61763
+ reply: 1,
61764
+ randomness: 90,
61765
+ spread: 0.3,
61766
+ mobility: 0.95,
61767
+ trap: 0.82,
61768
+ endgame: 0.76,
61769
+ },
61770
+ guardian: {
61771
+ advancement: 0.88,
61772
+ capture: 1,
61773
+ safety: 1.45,
61774
+ power: 0.85,
61775
+ center: 1.05,
61776
+ unlock: 1,
61777
+ reply: 1.15,
61778
+ randomness: 70,
61779
+ spread: 0.26,
61780
+ mobility: 0.82,
61781
+ trap: 0.72,
61782
+ endgame: 0.72,
61783
+ },
61784
+ jumper: {
61785
+ advancement: 1.12,
61786
+ capture: 1,
61787
+ safety: 0.92,
61788
+ power: 1.42,
61789
+ center: 1.18,
61790
+ unlock: 1.08,
61791
+ reply: 0.95,
61792
+ randomness: 95,
61793
+ spread: 0.32,
61794
+ mobility: 1.15,
61795
+ trap: 0.9,
61796
+ endgame: 0.82,
61797
+ },
61798
+ strategist: {
61799
+ advancement: 1.05,
61800
+ capture: 1.08,
61801
+ safety: 1.22,
61802
+ power: 1.08,
61803
+ center: 1.16,
61804
+ unlock: 1.1,
61805
+ reply: 1.25,
61806
+ randomness: 22,
61807
+ spread: 0.14,
61808
+ mobility: 1.08,
61809
+ trap: 1.06,
61810
+ endgame: 1,
61811
+ },
61812
+ predator: {
61813
+ advancement: 0.98,
61814
+ capture: 1.68,
61815
+ safety: 1.02,
61816
+ power: 1.34,
61817
+ center: 1,
61818
+ unlock: 1,
61819
+ reply: 1.12,
61820
+ randomness: 28,
61821
+ spread: 0.16,
61822
+ mobility: 1.02,
61823
+ trap: 1.18,
61824
+ endgame: 0.82,
61825
+ },
61826
+ sprinter: {
61827
+ advancement: 1.72,
61828
+ capture: 0.9,
61829
+ safety: 0.95,
61830
+ power: 1.08,
61831
+ center: 0.86,
61832
+ unlock: 1.18,
61833
+ reply: 1,
61834
+ randomness: 26,
61835
+ spread: 0.15,
61836
+ mobility: 0.95,
61837
+ trap: 0.78,
61838
+ endgame: 1.42,
61839
+ },
61840
+ sentinel: {
61841
+ advancement: 0.9,
61842
+ capture: 1.12,
61843
+ safety: 1.72,
61844
+ power: 0.95,
61845
+ center: 1.28,
61846
+ unlock: 1.05,
61847
+ reply: 1.38,
61848
+ randomness: 18,
61849
+ spread: 0.12,
61850
+ mobility: 0.86,
61851
+ trap: 1.04,
61852
+ endgame: 0.84,
61853
+ },
61854
+ oracle: {
61855
+ advancement: 1,
61856
+ capture: 1.12,
61857
+ safety: 1.42,
61858
+ power: 1.1,
61859
+ center: 1.18,
61860
+ unlock: 1.08,
61861
+ reply: 1.8,
61862
+ randomness: 8,
61863
+ spread: 0.08,
61864
+ mobility: 1.06,
61865
+ trap: 1.22,
61866
+ endgame: 1.08,
61867
+ },
61868
+ ambusher: {
61869
+ advancement: 0.9,
61870
+ capture: 1.48,
61871
+ safety: 1.08,
61872
+ power: 1.46,
61873
+ center: 1.05,
61874
+ unlock: 1.02,
61875
+ reply: 1.32,
61876
+ randomness: 14,
61877
+ spread: 0.1,
61878
+ mobility: 1.12,
61879
+ trap: 1.72,
61880
+ endgame: 0.92,
61881
+ },
61882
+ locksmith: {
61883
+ advancement: 0.88,
61884
+ capture: 1.04,
61885
+ safety: 1.55,
61886
+ power: 1.02,
61887
+ center: 1.48,
61888
+ unlock: 1.12,
61889
+ reply: 1.52,
61890
+ randomness: 12,
61891
+ spread: 0.1,
61892
+ mobility: 1.58,
61893
+ trap: 1.24,
61894
+ endgame: 0.86,
61895
+ },
61896
+ storm: {
61897
+ advancement: 1.18,
61898
+ capture: 1.38,
61899
+ safety: 0.98,
61900
+ power: 1.62,
61901
+ center: 1.08,
61902
+ unlock: 1.18,
61903
+ reply: 1.22,
61904
+ randomness: 18,
61905
+ spread: 0.13,
61906
+ mobility: 1.36,
61907
+ trap: 1.28,
61908
+ endgame: 1.02,
61909
+ },
61910
+ matriarch: {
61911
+ advancement: 0.96,
61912
+ capture: 1.18,
61913
+ safety: 1.64,
61914
+ power: 1.18,
61915
+ center: 1.22,
61916
+ unlock: 1.08,
61917
+ reply: 1.66,
61918
+ randomness: 10,
61919
+ spread: 0.08,
61920
+ mobility: 1.02,
61921
+ trap: 1.36,
61922
+ endgame: 1,
61923
+ },
61924
+ endgame: {
61925
+ advancement: 1.46,
61926
+ capture: 1,
61927
+ safety: 1.28,
61928
+ power: 1.04,
61929
+ center: 0.94,
61930
+ unlock: 1.08,
61931
+ reply: 1.44,
61932
+ randomness: 10,
61933
+ spread: 0.09,
61934
+ mobility: 0.98,
61935
+ trap: 1.02,
61936
+ endgame: 1.86,
61937
+ },
61938
+ magnus: {
61939
+ advancement: 1.04,
61940
+ capture: 1.22,
61941
+ safety: 1.9,
61942
+ power: 0.9,
61943
+ center: 1.42,
61944
+ unlock: 1.08,
61945
+ reply: 2.08,
61946
+ randomness: 3,
61947
+ spread: 0.04,
61948
+ mobility: 1.08,
61949
+ trap: 1.42,
61950
+ endgame: 1.86,
61951
+ },
61731
61952
  };
61732
61953
  const DEFAULT_BOT_PROFILE_BY_DIFFICULTY = {
61733
61954
  easy: 'explorer',
61734
61955
  normal: 'hunter',
61735
61956
  hard: 'strategist',
61957
+ master: 'magnus',
61736
61958
  };
61737
61959
  function createChessimalsGame(boardSize = 6, options = {}) {
61738
61960
  const pieces = [];
@@ -61772,12 +61994,12 @@ function createChessimalsGame(boardSize = 6, options = {}) {
61772
61994
  };
61773
61995
  }
61774
61996
  function getChessimalsPieceAt(state, position) {
61775
- return activePieces(state).find((piece) => !piece.captured && piece.position.row === position.row && piece.position.col === position.col);
61997
+ return activePieces(state).find(piece => !piece.captured && piece.position.row === position.row && piece.position.col === position.col);
61776
61998
  }
61777
61999
  function getChessimalsLegalMoves(state, pieceId, animal) {
61778
62000
  if (state.status !== 'in_progress')
61779
62001
  return [];
61780
- const piece = activePieces(state).find((item) => item.id === pieceId && !item.captured);
62002
+ const piece = activePieces(state).find(item => item.id === pieceId && !item.captured);
61781
62003
  if (!piece || piece.color !== state.currentTurn)
61782
62004
  return [];
61783
62005
  if (animal) {
@@ -61816,9 +62038,18 @@ function chooseChessimalsBotMove(state, difficulty = 'normal', profileId = DEFAU
61816
62038
  const challengePressure = getChallengePressure(options.challengeRound);
61817
62039
  const style = tuneBotStyle(baseStyle, difficulty, challengePressure, options.nightmareMode);
61818
62040
  const quickScored = moves
61819
- .map((move) => ({ move, score: scoreBotMove(state, move, difficulty, style, challengePressure, false, options.nightmareMode) }))
62041
+ .map(move => ({
62042
+ move,
62043
+ score: scoreBotMove(state, move, difficulty, style, challengePressure, false, options.nightmareMode),
62044
+ }))
61820
62045
  .sort((a, b) => b.score - a.score);
61821
- const lookaheadLimit = options.nightmareMode === 'magnus' ? 48 : difficulty === 'hard' ? 32 : difficulty === 'normal' ? 24 : 0;
62046
+ const lookaheadLimit = options.nightmareMode === 'magnus' || difficulty === 'master'
62047
+ ? 48
62048
+ : difficulty === 'hard'
62049
+ ? 32
62050
+ : difficulty === 'normal'
62051
+ ? 24
62052
+ : 0;
61822
62053
  const scored = quickScored
61823
62054
  .map((item, index) => ({
61824
62055
  move: item.move,
@@ -61828,18 +62059,18 @@ function chooseChessimalsBotMove(state, difficulty = 'normal', profileId = DEFAU
61828
62059
  }))
61829
62060
  .sort((a, b) => b.score - a.score);
61830
62061
  if (difficulty === 'easy') {
61831
- const playable = scored.filter((item) => item.score > -3000);
62062
+ const playable = scored.filter(item => item.score > -3000);
61832
62063
  return pickNoisyBotMove(playable.length ? playable : scored, 0.55);
61833
62064
  }
61834
62065
  if (difficulty === 'normal') {
61835
62066
  return scored[0]?.move;
61836
62067
  }
61837
- const winningMove = scored.find((item) => item.score >= 10000);
62068
+ const winningMove = scored.find(item => item.score >= 10000);
61838
62069
  if (winningMove)
61839
62070
  return winningMove.move;
61840
- const opponentWinningTargets = new Set(getImmediateWinningMoves(state, otherColor(state.currentTurn)).map((move) => positionKey(move.to)));
62071
+ const opponentWinningTargets = new Set(getImmediateWinningMoves(state, otherColor(state.currentTurn)).map(move => positionKey(move.to)));
61841
62072
  if (opponentWinningTargets.size > 0) {
61842
- const blockingMove = scored.find((item) => item.move.capturesPieceId || opponentWinningTargets.has(positionKey(item.move.to)));
62073
+ const blockingMove = scored.find(item => item.move.capturesPieceId || opponentWinningTargets.has(positionKey(item.move.to)));
61843
62074
  if (blockingMove)
61844
62075
  return blockingMove.move;
61845
62076
  }
@@ -61855,15 +62086,15 @@ function chooseChessimalsBotMove(state, difficulty = 'normal', profileId = DEFAU
61855
62086
  return scored[0]?.move;
61856
62087
  }
61857
62088
  function applyChessimalsMove(state, candidate) {
61858
- const legalMove = getChessimalsLegalMoves(state, candidate.pieceId, candidate.animal).find((move) => samePosition(move.from, candidate.from) && samePosition(move.to, candidate.to));
62089
+ const legalMove = getChessimalsLegalMoves(state, candidate.pieceId, candidate.animal).find(move => samePosition(move.from, candidate.from) && samePosition(move.to, candidate.to));
61859
62090
  if (!legalMove) {
61860
62091
  throw new Error('CHESSIMALS_ILLEGAL_MOVE');
61861
62092
  }
61862
- const movedPiece = activePieces(state).find((piece) => piece.id === legalMove.pieceId);
62093
+ const movedPiece = activePieces(state).find(piece => piece.id === legalMove.pieceId);
61863
62094
  if (!movedPiece) {
61864
62095
  throw new Error('CHESSIMALS_PIECE_NOT_FOUND');
61865
62096
  }
61866
- const pieces = activePieces(state).map((piece) => {
62097
+ const pieces = activePieces(state).map(piece => {
61867
62098
  if (piece.id === legalMove.pieceId) {
61868
62099
  return { ...piece, position: { ...legalMove.to } };
61869
62100
  }
@@ -61893,7 +62124,7 @@ function applyChessimalsMove(state, candidate) {
61893
62124
  lastMove: legalMove,
61894
62125
  });
61895
62126
  const promoted = isPromotionRow(nextState.boardSize, movedPiece.color, legalMove.to);
61896
- const enemyPieces = activePieces(nextState).filter((piece) => piece.color !== movedPiece.color && !piece.captured);
62127
+ const enemyPieces = activePieces(nextState).filter(piece => piece.color !== movedPiece.color && !piece.captured);
61897
62128
  const enemyHasLegalMoves = getChessimalsAllLegalMoves(nextState, nextState.currentTurn).length > 0;
61898
62129
  const resolvedState = promoted || enemyPieces.length === 0 || !enemyHasLegalMoves
61899
62130
  ? {
@@ -61909,10 +62140,7 @@ function applyChessimalsMove(state, candidate) {
61909
62140
  : nextState;
61910
62141
  return {
61911
62142
  ...resolvedState,
61912
- moveHistory: [
61913
- ...ensureMoveHistory(state),
61914
- createMoveHistoryEntry(resolvedState, legalMove),
61915
- ],
62143
+ moveHistory: [...ensureMoveHistory(state), createMoveHistoryEntry(resolvedState, legalMove)],
61916
62144
  };
61917
62145
  }
61918
62146
  function createChessimalsReviewState(state, entry) {
@@ -61955,7 +62183,7 @@ function cloneMoveHistoryEntry(entry) {
61955
62183
  };
61956
62184
  }
61957
62185
  function clonePieces(pieces) {
61958
- return pieces.map((piece) => ({
62186
+ return pieces.map(piece => ({
61959
62187
  ...piece,
61960
62188
  position: { ...piece.position },
61961
62189
  }));
@@ -61979,10 +62207,7 @@ function resignChessimalsGame(state, color) {
61979
62207
  };
61980
62208
  return {
61981
62209
  ...resignedState,
61982
- moveHistory: [
61983
- ...ensureMoveHistory(state),
61984
- createMoveHistoryEntry(resignedState),
61985
- ],
62210
+ moveHistory: [...ensureMoveHistory(state), createMoveHistoryEntry(resignedState)],
61986
62211
  };
61987
62212
  }
61988
62213
  function positionKey(position) {
@@ -62109,12 +62334,16 @@ function getKangarooMoves(state, piece) {
62109
62334
  function scoreBotMove(state, move, difficulty, style, challengePressure = 0, includeTacticalPressure = true, nightmareMode = 'none') {
62110
62335
  const color = state.currentTurn;
62111
62336
  const targetPiece = move.capturesPieceId
62112
- ? activePieces(state).find((piece) => piece.id === move.capturesPieceId)
62337
+ ? activePieces(state).find(piece => piece.id === move.capturesPieceId)
62113
62338
  : undefined;
62114
62339
  const advancement = color === 'white' ? state.boardSize - 1 - move.to.row : move.to.row;
62115
62340
  let score = advancement * 24 * style.advancement;
62116
62341
  const stepsToPromotion = color === 'white' ? move.to.row : state.boardSize - 1 - move.to.row;
62117
- score += Math.max(0, state.boardSize - 1 - stepsToPromotion) * 10 * challengePressure * style.advancement;
62342
+ score +=
62343
+ Math.max(0, state.boardSize - 1 - stepsToPromotion) *
62344
+ 10 *
62345
+ challengePressure *
62346
+ style.advancement;
62118
62347
  if (move.kind === 'basic' && isPromotionRow(state.boardSize, color, move.to)) {
62119
62348
  score += 10000 + 2500 * challengePressure;
62120
62349
  }
@@ -62131,7 +62360,9 @@ function scoreBotMove(state, move, difficulty, style, challengePressure = 0, inc
62131
62360
  score += targetAdvancement * (16 + 8 * challengePressure) * style.capture;
62132
62361
  }
62133
62362
  if (move.kind === 'power') {
62134
- score += (targetPiece ? 120 : difficulty === 'hard' ? -60 - 170 * challengePressure : -30) * style.power;
62363
+ score +=
62364
+ (targetPiece ? 120 : difficulty === 'hard' ? -60 - 170 * challengePressure : -30) *
62365
+ style.power;
62135
62366
  }
62136
62367
  if (nightmareMode === 'magnus' && move.kind === 'power') {
62137
62368
  score += scoreMagnusPowerPatience(state, move, targetPiece, style);
@@ -62143,8 +62374,14 @@ function scoreBotMove(state, move, difficulty, style, challengePressure = 0, inc
62143
62374
  if (wouldUnlockPower(state, color, move.to))
62144
62375
  score += 90 * style.unlock;
62145
62376
  if (includeTacticalPressure && state.boardSize <= 6) {
62146
- score += countPowerReachAfterMove(state, move, color) * (difficulty === 'hard' ? 8 : 4) * style.mobility;
62147
- score += countProtectedThreatsAfterMove(state, move, color) * (difficulty === 'hard' ? 36 : 18) * style.trap;
62377
+ score +=
62378
+ countPowerReachAfterMove(state, move, color) *
62379
+ (difficulty === 'hard' ? 8 : 4) *
62380
+ style.mobility;
62381
+ score +=
62382
+ countProtectedThreatsAfterMove(state, move, color) *
62383
+ (difficulty === 'hard' ? 36 : 18) *
62384
+ style.trap;
62148
62385
  score += scoreEndgamePressure(state, move, color) * style.endgame;
62149
62386
  }
62150
62387
  else {
@@ -62163,30 +62400,74 @@ function scoreBotMoveWithLookahead(state, move, difficulty, style, challengePres
62163
62400
  if (afterMove.status === 'finished')
62164
62401
  return score + 5000;
62165
62402
  const opponentMoves = getChessimalsAllLegalMoves(afterMove);
62166
- const opponentImmediateWin = opponentMoves.some((opponentMove) => opponentMove.kind === 'basic' &&
62403
+ const opponentImmediateWin = opponentMoves.some(opponentMove => opponentMove.kind === 'basic' &&
62167
62404
  isPromotionRow(afterMove.boardSize, afterMove.currentTurn, opponentMove.to));
62168
62405
  if (opponentImmediateWin) {
62169
- score -= (difficulty === 'easy' ? 1800 : difficulty === 'normal' ? 5200 : 8000 + 4200 * challengePressure) * style.safety;
62170
- }
62171
- const movedPiece = afterMove.pieces.find((piece) => piece.id === move.pieceId && !piece.captured);
62406
+ score -=
62407
+ (difficulty === 'easy'
62408
+ ? 1800
62409
+ : difficulty === 'normal'
62410
+ ? 5200
62411
+ : 8000 + 4200 * challengePressure) * style.safety;
62412
+ }
62413
+ const movedPiece = afterMove.pieces.find(piece => piece.id === move.pieceId && !piece.captured);
62172
62414
  if (movedPiece) {
62173
- const canCaptureMovedPiece = opponentMoves.some((opponentMove) => opponentMove.capturesPieceId === move.pieceId);
62415
+ const canCaptureMovedPiece = opponentMoves.some(opponentMove => opponentMove.capturesPieceId === move.pieceId);
62174
62416
  if (canCaptureMovedPiece) {
62175
- score -= (move.capturesPieceId ? 180 : difficulty === 'easy' ? 120 : difficulty === 'normal' ? 360 : 560)
62176
- * style.safety
62177
- * (1 + challengePressure);
62417
+ score -=
62418
+ (move.capturesPieceId
62419
+ ? 180
62420
+ : difficulty === 'easy'
62421
+ ? 120
62422
+ : difficulty === 'normal'
62423
+ ? 360
62424
+ : 560) *
62425
+ style.safety *
62426
+ (1 + challengePressure);
62178
62427
  }
62179
62428
  const center = (afterMove.boardSize - 1) / 2;
62180
62429
  const centerControl = Math.max(0, afterMove.boardSize / 2 - Math.abs(movedPiece.position.col - center));
62181
62430
  score += centerControl * (difficulty === 'hard' ? 18 : 10) * style.center;
62182
62431
  }
62183
62432
  const opponentBestReply = opponentMoves
62184
- .map((opponentMove) => scoreBotMove(afterMove, opponentMove, difficulty, style, challengePressure, false, nightmareMode))
62433
+ .map(opponentMove => scoreBotMove(afterMove, opponentMove, difficulty, style, challengePressure, false, nightmareMode))
62185
62434
  .sort((a, b) => b - a)[0];
62186
62435
  if (opponentBestReply) {
62187
- const replyWeight = difficulty === 'easy' ? 0.12 : difficulty === 'normal' ? 0.32 + 0.08 * challengePressure : 0.48 + 0.16 * challengePressure;
62436
+ const replyWeight = difficulty === 'easy'
62437
+ ? 0.12
62438
+ : difficulty === 'normal'
62439
+ ? 0.4 + 0.1 * challengePressure
62440
+ : difficulty === 'master'
62441
+ ? 0.72 + 0.22 * challengePressure
62442
+ : 0.48 + 0.16 * challengePressure;
62188
62443
  score -= opponentBestReply * replyWeight * style.reply;
62189
62444
  }
62445
+ if (difficulty === 'hard' || difficulty === 'master') {
62446
+ const topOppMoves = opponentMoves
62447
+ .map(m => ({
62448
+ move: m,
62449
+ score: scoreBotMove(afterMove, m, difficulty, style, challengePressure, false, nightmareMode),
62450
+ }))
62451
+ .sort((a, b) => b.score - a.score)
62452
+ .slice(0, 4);
62453
+ for (const { move: oppMove } of topOppMoves) {
62454
+ try {
62455
+ const s2 = applyChessimalsMove(afterMove, oppMove);
62456
+ if (s2.status === 'finished')
62457
+ continue;
62458
+ const myCounters = getChessimalsAllLegalMoves(s2);
62459
+ if (myCounters.length === 0)
62460
+ continue;
62461
+ const myBest = myCounters
62462
+ .map(m => scoreBotMove(s2, m, difficulty, style, challengePressure, false, nightmareMode))
62463
+ .sort((a, b) => b - a)[0] ?? 0;
62464
+ score += myBest * (difficulty === 'master' ? 0.22 : 0.14) * style.reply;
62465
+ }
62466
+ catch {
62467
+ // skip
62468
+ }
62469
+ }
62470
+ }
62190
62471
  }
62191
62472
  catch {
62192
62473
  score -= 1000;
@@ -62194,9 +62475,9 @@ function scoreBotMoveWithLookahead(state, move, difficulty, style, challengePres
62194
62475
  return score;
62195
62476
  }
62196
62477
  function getChallengePressure(round) {
62197
- if (!round || round <= 2)
62478
+ if (!round)
62198
62479
  return 0;
62199
- return Math.min(1, Math.max(0, (round - 2) / 6));
62480
+ return Math.min(1, Math.max(0, round / 8));
62200
62481
  }
62201
62482
  function tuneBotStyle(style, difficulty, challengePressure, nightmareMode = 'none') {
62202
62483
  if (nightmareMode === 'hunt') {
@@ -62234,9 +62515,26 @@ function tuneBotStyle(style, difficulty, challengePressure, nightmareMode = 'non
62234
62515
  endgame: style.endgame * 1.28,
62235
62516
  };
62236
62517
  }
62518
+ if (difficulty === 'master') {
62519
+ style = {
62520
+ ...style,
62521
+ capture: style.capture * 1.08,
62522
+ safety: style.safety * 1.22,
62523
+ reply: style.reply * 1.32,
62524
+ center: style.center * 1.12,
62525
+ randomness: Math.min(style.randomness, 3),
62526
+ spread: style.spread * 0.5,
62527
+ trap: style.trap * 1.14,
62528
+ endgame: style.endgame * 1.18,
62529
+ };
62530
+ }
62237
62531
  if (!challengePressure)
62238
62532
  return style;
62239
- const pressure = difficulty === 'easy' ? challengePressure * 0.45 : challengePressure;
62533
+ const pressure = difficulty === 'easy'
62534
+ ? challengePressure * 0.45
62535
+ : difficulty === 'master'
62536
+ ? challengePressure * 1.15
62537
+ : challengePressure;
62240
62538
  return {
62241
62539
  ...style,
62242
62540
  capture: style.capture * (1 + pressure * 0.28),
@@ -62251,7 +62549,7 @@ function chooseChallengeBasicCapture(scored, challengePressure) {
62251
62549
  if (challengePressure < 0.5)
62252
62550
  return undefined;
62253
62551
  const best = scored[0];
62254
- const bestBasicCapture = scored.find((item) => item.move.kind === 'basic' && item.move.capturesPieceId);
62552
+ const bestBasicCapture = scored.find(item => item.move.kind === 'basic' && item.move.capturesPieceId);
62255
62553
  if (!best || !bestBasicCapture)
62256
62554
  return undefined;
62257
62555
  if (best.move.kind === 'basic' && best.move.capturesPieceId)
@@ -62263,7 +62561,7 @@ function chooseNightmareCapture(scored, nightmareMode) {
62263
62561
  if (nightmareMode !== 'hunt')
62264
62562
  return undefined;
62265
62563
  const best = scored[0];
62266
- const capture = scored.find((item) => item.move.capturesPieceId);
62564
+ const capture = scored.find(item => item.move.capturesPieceId);
62267
62565
  if (!best || !capture)
62268
62566
  return undefined;
62269
62567
  return best.score - capture.score <= 1800 ? capture.move : undefined;
@@ -62288,7 +62586,7 @@ function countPowerReachAfterMove(state, move, color) {
62288
62586
  try {
62289
62587
  const afterMove = applyChessimalsMove(state, move);
62290
62588
  const evaluationState = { ...afterMove, currentTurn: color };
62291
- return getChessimalsAllLegalMoves(evaluationState, color).filter((nextMove) => nextMove.kind === 'power').length;
62589
+ return getChessimalsAllLegalMoves(evaluationState, color).filter(nextMove => nextMove.kind === 'power').length;
62292
62590
  }
62293
62591
  catch {
62294
62592
  return 0;
@@ -62299,15 +62597,15 @@ function countProtectedThreatsAfterMove(state, move, color) {
62299
62597
  const afterMove = applyChessimalsMove(state, move);
62300
62598
  const evaluationState = { ...afterMove, currentTurn: color };
62301
62599
  const ourMoves = getChessimalsAllLegalMoves(evaluationState, color);
62302
- const enemyPieces = activePieces(afterMove).filter((piece) => piece.color !== color && !piece.captured);
62303
- return enemyPieces.filter((piece) => ourMoves.some((nextMove) => nextMove.capturesPieceId === piece.id)).length;
62600
+ const enemyPieces = activePieces(afterMove).filter(piece => piece.color !== color && !piece.captured);
62601
+ return enemyPieces.filter(piece => ourMoves.some(nextMove => nextMove.capturesPieceId === piece.id)).length;
62304
62602
  }
62305
62603
  catch {
62306
62604
  return 0;
62307
62605
  }
62308
62606
  }
62309
62607
  function scoreEndgamePressure(state, move, color) {
62310
- const remainingEnemyPieces = activePieces(state).filter((piece) => piece.color !== color && !piece.captured).length;
62608
+ const remainingEnemyPieces = activePieces(state).filter(piece => piece.color !== color && !piece.captured).length;
62311
62609
  const urgency = remainingEnemyPieces <= Math.max(2, Math.floor(state.boardSize / 2)) ? 1.6 : 1;
62312
62610
  const distanceToPromotion = color === 'white' ? move.to.row : state.boardSize - 1 - move.to.row;
62313
62611
  return Math.max(0, state.boardSize - distanceToPromotion) * 14 * urgency;
@@ -62319,7 +62617,7 @@ function chooseConservativeHardCapture(state, scored) {
62319
62617
  if (!best || best.move.kind !== 'power' || !best.move.capturesPieceId || best.score >= 10000) {
62320
62618
  return undefined;
62321
62619
  }
62322
- const bestBasicCapture = scored.find((item) => item.move.kind === 'basic' && item.move.capturesPieceId);
62620
+ const bestBasicCapture = scored.find(item => item.move.kind === 'basic' && item.move.capturesPieceId);
62323
62621
  if (!bestBasicCapture)
62324
62622
  return undefined;
62325
62623
  return best.score - bestBasicCapture.score <= 650 ? bestBasicCapture.move : undefined;
@@ -62345,7 +62643,7 @@ function pickNoisyBotMove(scored, spread) {
62345
62643
  return pool[0]?.move;
62346
62644
  }
62347
62645
  function getImmediateWinningMoves(state, color) {
62348
- return getChessimalsAllLegalMoves(state, color).filter((move) => move.kind === 'basic' && isPromotionRow(state.boardSize, color, move.to));
62646
+ return getChessimalsAllLegalMoves(state, color).filter(move => move.kind === 'basic' && isPromotionRow(state.boardSize, color, move.to));
62349
62647
  }
62350
62648
  function wouldUnlockPower(state, color, position) {
62351
62649
  if (state.players[color].powerUnlocked)
@@ -62359,7 +62657,7 @@ function isSquareVulnerableAfterMove(state, move) {
62359
62657
  const afterMove = applyChessimalsMove(state, move);
62360
62658
  if (afterMove.status === 'finished')
62361
62659
  return false;
62362
- return getChessimalsAllLegalMoves(afterMove).some((enemyMove) => samePosition(enemyMove.to, move.to) && !!enemyMove.capturesPieceId);
62660
+ return getChessimalsAllLegalMoves(afterMove).some(enemyMove => samePosition(enemyMove.to, move.to) && !!enemyMove.capturesPieceId);
62363
62661
  }
62364
62662
  catch {
62365
62663
  return false;
@@ -62415,7 +62713,7 @@ function refreshChessimalsPowerUnlocks(state) {
62415
62713
  function hasCrossedCenter(state, color) {
62416
62714
  const centerTop = state.boardSize / 2 - 1;
62417
62715
  const centerBottom = state.boardSize / 2;
62418
- return activePieces(state).some((piece) => {
62716
+ return activePieces(state).some(piece => {
62419
62717
  if (piece.color !== color || piece.captured)
62420
62718
  return false;
62421
62719
  return color === 'white' ? piece.position.row <= centerTop : piece.position.row >= centerBottom;
@@ -62425,7 +62723,7 @@ function hasEnemyEnteredHome(state, color) {
62425
62723
  const centerTop = state.boardSize / 2 - 1;
62426
62724
  const centerBottom = state.boardSize / 2;
62427
62725
  const enemy = otherColor(color);
62428
- return activePieces(state).some((piece) => {
62726
+ return activePieces(state).some(piece => {
62429
62727
  if (piece.color !== enemy || piece.captured)
62430
62728
  return false;
62431
62729
  return color === 'white' ? piece.position.row >= centerBottom : piece.position.row <= centerTop;
@@ -64009,6 +64307,7 @@ const MINI_GAMES_I18N = {
64009
64307
  chessimalsBotEasy: 'Suave',
64010
64308
  chessimalsBotNormal: 'Normal',
64011
64309
  chessimalsBotHard: 'Maestro',
64310
+ chessimalsBotMaster: 'Experto',
64012
64311
  chessimalsBotNightmare: 'Pesadilla',
64013
64312
  chessimalsNightmareRivals: 'Rivales pesadilla',
64014
64313
  chessimalsNightmareMode: 'Modo pesadilla',
@@ -64803,6 +65102,7 @@ const MINI_GAMES_I18N = {
64803
65102
  chessimalsBotEasy: 'Gentle',
64804
65103
  chessimalsBotNormal: 'Normal',
64805
65104
  chessimalsBotHard: 'Master',
65105
+ chessimalsBotMaster: 'Expert',
64806
65106
  chessimalsBotNightmare: 'Nightmare',
64807
65107
  chessimalsNightmareRivals: 'Nightmare rivals',
64808
65108
  chessimalsNightmareMode: 'Nightmare mode',
@@ -66373,14 +66673,70 @@ const ANIMALS = [
66373
66673
  { type: 'lion', assetSrc: `${CHESSIMALS_POWER_ASSET_BASE}/lion-power.png`, tone: 392 },
66374
66674
  ];
66375
66675
  const CHESSIMALS_CHALLENGE_LADDER = [
66376
- { id: 'sprout', round: 1, profileId: 'explorer', difficulty: 'easy', boardSize: 6, introKey: 'chessimalsChallengeBotSproutIntro' },
66377
- { id: 'sentinel', round: 2, profileId: 'guardian', difficulty: 'normal', boardSize: 6, introKey: 'chessimalsChallengeBotSentinelIntro' },
66378
- { id: 'hunter', round: 3, profileId: 'hunter', difficulty: 'normal', boardSize: 6, introKey: 'chessimalsChallengeBotHunterIntro' },
66379
- { id: 'jumper', round: 4, profileId: 'jumper', difficulty: 'normal', boardSize: 6, introKey: 'chessimalsChallengeBotJumperIntro' },
66380
- { id: 'predator', round: 5, profileId: 'predator', difficulty: 'hard', boardSize: 8, introKey: 'chessimalsChallengeBotPredatorIntro' },
66381
- { id: 'oracle', round: 6, profileId: 'strategist', difficulty: 'hard', boardSize: 8, introKey: 'chessimalsChallengeBotOracleIntro' },
66382
- { id: 'sprinter', round: 7, profileId: 'sprinter', difficulty: 'hard', boardSize: 8, introKey: 'chessimalsChallengeBotSprinterIntro' },
66383
- { id: 'champion', round: 8, profileId: 'sentinel', difficulty: 'hard', boardSize: 8, introKey: 'chessimalsChallengeBotChampionIntro' },
66676
+ {
66677
+ id: 'sprout',
66678
+ round: 1,
66679
+ profileId: 'explorer',
66680
+ difficulty: 'easy',
66681
+ boardSize: 6,
66682
+ introKey: 'chessimalsChallengeBotSproutIntro',
66683
+ },
66684
+ {
66685
+ id: 'sentinel',
66686
+ round: 2,
66687
+ profileId: 'guardian',
66688
+ difficulty: 'normal',
66689
+ boardSize: 6,
66690
+ introKey: 'chessimalsChallengeBotSentinelIntro',
66691
+ },
66692
+ {
66693
+ id: 'hunter',
66694
+ round: 3,
66695
+ profileId: 'hunter',
66696
+ difficulty: 'normal',
66697
+ boardSize: 6,
66698
+ introKey: 'chessimalsChallengeBotHunterIntro',
66699
+ },
66700
+ {
66701
+ id: 'jumper',
66702
+ round: 4,
66703
+ profileId: 'jumper',
66704
+ difficulty: 'normal',
66705
+ boardSize: 6,
66706
+ introKey: 'chessimalsChallengeBotJumperIntro',
66707
+ },
66708
+ {
66709
+ id: 'predator',
66710
+ round: 5,
66711
+ profileId: 'predator',
66712
+ difficulty: 'hard',
66713
+ boardSize: 8,
66714
+ introKey: 'chessimalsChallengeBotPredatorIntro',
66715
+ },
66716
+ {
66717
+ id: 'oracle',
66718
+ round: 6,
66719
+ profileId: 'strategist',
66720
+ difficulty: 'hard',
66721
+ boardSize: 8,
66722
+ introKey: 'chessimalsChallengeBotOracleIntro',
66723
+ },
66724
+ {
66725
+ id: 'sprinter',
66726
+ round: 7,
66727
+ profileId: 'sprinter',
66728
+ difficulty: 'master',
66729
+ boardSize: 8,
66730
+ introKey: 'chessimalsChallengeBotSprinterIntro',
66731
+ },
66732
+ {
66733
+ id: 'champion',
66734
+ round: 8,
66735
+ profileId: 'magnus',
66736
+ difficulty: 'master',
66737
+ boardSize: 8,
66738
+ introKey: 'chessimalsChallengeBotChampionIntro',
66739
+ },
66384
66740
  ];
66385
66741
  class ChessimalsGameComponent {
66386
66742
  set onlineGameId(value) {
@@ -66410,7 +66766,7 @@ class ChessimalsGameComponent {
66410
66766
  this.turnTimerExpiredKey = '';
66411
66767
  this.boardSizes = [6, 8];
66412
66768
  this.localModes = ['one-device', 'bot'];
66413
- this.botDifficulties = ['easy', 'normal', 'hard', 'nightmare'];
66769
+ this.botDifficulties = ['easy', 'normal', 'hard', 'master', 'nightmare'];
66414
66770
  this.nightmareRivals = ['hunt', 'pride', 'magnus'];
66415
66771
  this.botProfiles = CHESSIMALS_BOT_PROFILES;
66416
66772
  this.challengeLadder = CHESSIMALS_CHALLENGE_LADDER;
@@ -66617,7 +66973,7 @@ class ChessimalsGameComponent {
66617
66973
  color: 'primary',
66618
66974
  startLabel: '0',
66619
66975
  endLabel: '100',
66620
- pinFormatter: (value) => `${value}%`,
66976
+ pinFormatter: value => `${value}%`,
66621
66977
  }));
66622
66978
  this.sfxVolumeProps = computed(() => ({
66623
66979
  control: this.sfxVolumeControl,
@@ -66629,30 +66985,39 @@ class ChessimalsGameComponent {
66629
66985
  color: 'primary',
66630
66986
  startLabel: '0',
66631
66987
  endLabel: '100',
66632
- pinFormatter: (value) => `${value}%`,
66988
+ pinFormatter: value => `${value}%`,
66633
66989
  }));
66634
66990
  this.availableBotProfiles = computed(() => {
66635
66991
  const difficulty = this.selectedBotDifficulty();
66636
66992
  if (difficulty === 'nightmare')
66637
66993
  return [];
66638
- return this.botProfiles.filter((profile) => profile.difficulty === difficulty && profile.id !== 'magnus');
66994
+ if (difficulty === 'master')
66995
+ return this.botProfiles.filter(profile => profile.id === 'magnus');
66996
+ return this.botProfiles.filter(profile => profile.difficulty === difficulty && profile.id !== 'magnus');
66639
66997
  });
66640
- this.selectedBotProfile = computed(() => this.botProfiles.find((profile) => profile.id === this.selectedBotProfileId()));
66998
+ this.selectedBotProfile = computed(() => this.botProfiles.find(profile => profile.id === this.selectedBotProfileId()));
66641
66999
  this.gameBotProfile = computed(() => {
66642
67000
  const profileId = this.gameBotProfileId();
66643
- return profileId ? this.botProfiles.find((profile) => profile.id === profileId) : undefined;
67001
+ return profileId ? this.botProfiles.find(profile => profile.id === profileId) : undefined;
67002
+ });
67003
+ this.challengeHeaderBot = computed(() => {
67004
+ if (!this.isChallengeActive())
67005
+ return undefined;
67006
+ if (this.challengePhase() === 'playing')
67007
+ return this.activeChallengeBot();
67008
+ return this.challengeLastBot() ?? this.activeChallengeBot();
66644
67009
  });
66645
67010
  this.botOpponentProfile = computed(() => {
66646
67011
  const game = this.game();
66647
67012
  if (game.mode !== 'local' || this.selectedLocalMode() !== 'bot')
66648
67013
  return undefined;
66649
- const challengeBot = this.isChallengeActive() ? this.activeChallengeBot() : undefined;
67014
+ const challengeBot = this.challengeHeaderBot();
66650
67015
  if (challengeBot)
66651
67016
  return this.challengeBotProfile(challengeBot);
66652
67017
  return this.gameBotProfile() ?? this.selectedBotProfile();
66653
67018
  });
66654
67019
  this.botOpponentEyebrow = computed(() => {
66655
- const challengeBot = this.isChallengeActive() ? this.activeChallengeBot() : undefined;
67020
+ const challengeBot = this.challengeHeaderBot();
66656
67021
  if (challengeBot)
66657
67022
  return this.challengeBotDifficultyLabel(challengeBot);
66658
67023
  return this.botDifficultyLabel(this.selectedBotDifficulty());
@@ -66663,7 +67028,7 @@ class ChessimalsGameComponent {
66663
67028
  return this.t('chessimalsBotReportVs').replace('{bot}', botName);
66664
67029
  });
66665
67030
  this.botOpponentDescription = computed(() => {
66666
- const challengeBot = this.isChallengeActive() ? this.activeChallengeBot() : undefined;
67031
+ const challengeBot = this.challengeHeaderBot();
66667
67032
  if (challengeBot)
66668
67033
  return this.challengeBotStyleLine(challengeBot);
66669
67034
  const profile = this.botOpponentProfile();
@@ -66673,7 +67038,7 @@ class ChessimalsGameComponent {
66673
67038
  const game = this.game();
66674
67039
  if (game.mode !== 'local' || this.selectedLocalMode() !== 'bot')
66675
67040
  return undefined;
66676
- const challengeBot = this.isChallengeActive() ? this.activeChallengeBot() : undefined;
67041
+ const challengeBot = this.challengeHeaderBot();
66677
67042
  if (challengeBot) {
66678
67043
  const profile = this.challengeBotProfile(challengeBot);
66679
67044
  const botName = profile ? this.botProfileLabel(profile) : this.t('chessimalsBotName');
@@ -66763,25 +67128,29 @@ class ChessimalsGameComponent {
66763
67128
  const expected = this.tutorialExpectedMove();
66764
67129
  if (!expected)
66765
67130
  return moves;
66766
- return moves.filter((move) => move.pieceId === expected.pieceId &&
67131
+ return moves.filter(move => move.pieceId === expected.pieceId &&
66767
67132
  positionKey(move.to) === positionKey(expected.to) &&
66768
67133
  (move.animal ?? undefined) === (expected.animal ?? undefined));
66769
67134
  });
66770
- this.legalMoveKeys = computed(() => new Set(this.legalMoves().map((move) => positionKey(move.to))));
66771
- this.captureMoveKeys = computed(() => new Set(this.legalMoves().filter((move) => !!move.capturesPieceId).map((move) => positionKey(move.to))));
67135
+ this.legalMoveKeys = computed(() => new Set(this.legalMoves().map(move => positionKey(move.to))));
67136
+ this.captureMoveKeys = computed(() => new Set(this.legalMoves()
67137
+ .filter(move => !!move.capturesPieceId)
67138
+ .map(move => positionKey(move.to))));
66772
67139
  this.winningMoveKeys = computed(() => {
66773
67140
  const game = this.game();
66774
67141
  if (game.status !== 'in_progress')
66775
67142
  return new Set();
66776
67143
  const promotionRow = game.currentTurn === 'white' ? 0 : game.boardSize - 1;
66777
- return new Set(this.legalMoves().filter((move) => move.to.row === promotionRow).map((move) => positionKey(move.to)));
67144
+ return new Set(this.legalMoves()
67145
+ .filter(move => move.to.row === promotionRow)
67146
+ .map(move => positionKey(move.to)));
66778
67147
  });
66779
67148
  this.captureReadyPieceIds = computed(() => {
66780
67149
  const game = this.game();
66781
67150
  if (this.activeReviewIndex() !== undefined || game.status !== 'in_progress')
66782
67151
  return new Set();
66783
- const moves = this.basicMovesForColor(game, game.currentTurn).filter((move) => !!move.capturesPieceId);
66784
- return new Set(moves.map((move) => move.pieceId));
67152
+ const moves = this.basicMovesForColor(game, game.currentTurn).filter(move => !!move.capturesPieceId);
67153
+ return new Set(moves.map(move => move.pieceId));
66785
67154
  });
66786
67155
  this.threatenedPieceIds = computed(() => {
66787
67156
  const game = this.game();
@@ -66789,7 +67158,7 @@ class ChessimalsGameComponent {
66789
67158
  return new Set();
66790
67159
  const opponent = game.currentTurn === 'white' ? 'black' : 'white';
66791
67160
  const threatened = this.basicMovesForColor(game, opponent)
66792
- .map((move) => move.capturesPieceId)
67161
+ .map(move => move.capturesPieceId)
66793
67162
  .filter((pieceId) => !!pieceId);
66794
67163
  return new Set(threatened);
66795
67164
  });
@@ -66805,7 +67174,7 @@ class ChessimalsGameComponent {
66805
67174
  if (this.tutorialMode())
66806
67175
  return 'white';
66807
67176
  if (game.mode === 'online')
66808
- return uid ? this.online.participantSide(game, uid) ?? 'white' : 'white';
67177
+ return uid ? (this.online.participantSide(game, uid) ?? 'white') : 'white';
66809
67178
  if (game.mode === 'local' && this.selectedLocalMode() === 'bot')
66810
67179
  return 'white';
66811
67180
  return game.currentTurn;
@@ -66953,15 +67322,15 @@ class ChessimalsGameComponent {
66953
67322
  const move = entry.move;
66954
67323
  if (!move?.capturesPieceId)
66955
67324
  continue;
66956
- const piece = entry.pieces.find((item) => item.id === move.pieceId);
67325
+ const piece = entry.pieces.find(item => item.id === move.pieceId);
66957
67326
  if (piece?.color)
66958
67327
  score[piece.color] += 1;
66959
67328
  }
66960
67329
  return score;
66961
67330
  });
66962
- this.resultCaptures = computed(() => this.replayEntries().filter((entry) => !!entry.move?.capturesPieceId).length);
67331
+ this.resultCaptures = computed(() => this.replayEntries().filter(entry => !!entry.move?.capturesPieceId).length);
66963
67332
  this.resultPowers = computed(() => this.replayEntries()
66964
- .map((entry) => entry.move?.animal)
67333
+ .map(entry => entry.move?.animal)
66965
67334
  .filter((animal) => !!animal));
66966
67335
  this.liveScore = computed(() => this.isChallengeActive() ? this.createGameScore(this.game(), 'W').score : this.createGameScore(this.game()).score);
66967
67336
  this.resultScore = computed(() => this.createGameScore(this.game()));
@@ -66991,7 +67360,7 @@ class ChessimalsGameComponent {
66991
67360
  const powers = this.resultPowers();
66992
67361
  if (!powers.length)
66993
67362
  return this.t('chessimalsResultNoPowers');
66994
- return powers.map((animal) => this.animalLabel(animal)).join(' · ');
67363
+ return powers.map(animal => this.animalLabel(animal)).join(' · ');
66995
67364
  });
66996
67365
  this.liveScoreLabel = computed(() => String(this.liveScore()));
66997
67366
  this.resultBestMoveLabel = computed(() => {
@@ -67012,12 +67381,10 @@ class ChessimalsGameComponent {
67012
67381
  });
67013
67382
  this.botReportBody = computed(() => {
67014
67383
  const profile = this.gameBotProfile();
67015
- const botMoves = this.replayEntries().filter((entry) => entry.move?.pieceId.startsWith('B'));
67016
- const captures = botMoves.filter((entry) => !!entry.move?.capturesPieceId).length;
67017
- const powers = botMoves.filter((entry) => !!entry.move?.animal).length;
67018
- const outcomeKey = this.game().winner === CHESSIMALS_BOT_COLOR
67019
- ? 'chessimalsBotReportOutcomeWon'
67020
- : 'chessimalsBotReportOutcomeLost';
67384
+ const botMoves = this.replayEntries().filter(entry => entry.move?.pieceId.startsWith('B'));
67385
+ const captures = botMoves.filter(entry => !!entry.move?.capturesPieceId).length;
67386
+ const powers = botMoves.filter(entry => !!entry.move?.animal).length;
67387
+ const outcomeKey = this.game().winner === CHESSIMALS_BOT_COLOR ? 'chessimalsBotReportOutcomeWon' : 'chessimalsBotReportOutcomeLost';
67021
67388
  return this.t('chessimalsBotReportBody')
67022
67389
  .replace('{outcome}', this.t(outcomeKey))
67023
67390
  .replace('{captures}', String(captures))
@@ -67028,15 +67395,15 @@ class ChessimalsGameComponent {
67028
67395
  const opponentUid = this.currentOpponentUid();
67029
67396
  if (!opponentUid)
67030
67397
  return [];
67031
- return this.onlineHistory().filter((entry) => entry.opponentUid === opponentUid && entry.status === 'finished');
67398
+ return this.onlineHistory().filter(entry => entry.opponentUid === opponentUid && entry.status === 'finished');
67032
67399
  });
67033
67400
  this.seriesScore = computed(() => {
67034
67401
  const games = this.seriesGames();
67035
67402
  if (!games.length)
67036
67403
  return undefined;
67037
67404
  return {
67038
- mine: games.filter((entry) => entry.outcome === 'won').length,
67039
- rival: games.filter((entry) => entry.outcome === 'lost').length,
67405
+ mine: games.filter(entry => entry.outcome === 'won').length,
67406
+ rival: games.filter(entry => entry.outcome === 'lost').length,
67040
67407
  total: games.length,
67041
67408
  };
67042
67409
  });
@@ -67160,14 +67527,14 @@ class ChessimalsGameComponent {
67160
67527
  this.audio.preloadChessimalsSamples();
67161
67528
  this.audio.stopMusic();
67162
67529
  this.startChessimalsMenuMusicSoon();
67163
- this.routeSubscription.add(this.musicEnabledControl.valueChanges.subscribe((enabled) => {
67530
+ this.routeSubscription.add(this.musicEnabledControl.valueChanges.subscribe(enabled => {
67164
67531
  this.audio.setMusicEnabled(enabled);
67165
67532
  if (enabled)
67166
67533
  this.syncChessimalsMusicAfterSettingsChange();
67167
67534
  }));
67168
- this.routeSubscription.add(this.sfxEnabledControl.valueChanges.subscribe((enabled) => this.audio.setSfxEnabled(enabled)));
67169
- this.routeSubscription.add(this.musicVolumeControl.valueChanges.subscribe((volume) => this.setMusicVolume(volume)));
67170
- this.routeSubscription.add(this.sfxVolumeControl.valueChanges.subscribe((volume) => this.setSfxVolume(volume)));
67535
+ this.routeSubscription.add(this.sfxEnabledControl.valueChanges.subscribe(enabled => this.audio.setSfxEnabled(enabled)));
67536
+ this.routeSubscription.add(this.musicVolumeControl.valueChanges.subscribe(volume => this.setMusicVolume(volume)));
67537
+ this.routeSubscription.add(this.sfxVolumeControl.valueChanges.subscribe(volume => this.setSfxVolume(volume)));
67171
67538
  effect(() => {
67172
67539
  const user = this.loggedInUser();
67173
67540
  if (user) {
@@ -67210,7 +67577,7 @@ class ChessimalsGameComponent {
67210
67577
  if (this.lastModeStatsHandledKey === key)
67211
67578
  return;
67212
67579
  this.lastModeStatsHandledKey = key;
67213
- void this.challengeProgress.recordModeResult(result.mode, result.won, result.roundStats).catch((error) => {
67580
+ void this.challengeProgress.recordModeResult(result.mode, result.won, result.roundStats).catch(error => {
67214
67581
  console.warn('[Chessimals] mode stats save failed', error);
67215
67582
  });
67216
67583
  }, { allowSignalWrites: true });
@@ -67248,7 +67615,7 @@ class ChessimalsGameComponent {
67248
67615
  this.challengeActiveRunSubscription?.unsubscribe();
67249
67616
  }
67250
67617
  ngOnInit() {
67251
- this.routeSubscription.add(this.router.events.subscribe((event) => {
67618
+ this.routeSubscription.add(this.router.events.subscribe(event => {
67252
67619
  if (event instanceof NavigationStart) {
67253
67620
  this.resetFinishedLocalGameForNextVisit(true);
67254
67621
  }
@@ -67269,7 +67636,7 @@ class ChessimalsGameComponent {
67269
67636
  return `${normalized.slice(0, 4)}…${normalized.slice(-4)}`;
67270
67637
  }
67271
67638
  rangeValueToNumber(value) {
67272
- const raw = typeof value === 'number' ? value : value.upper ?? value.lower ?? 0;
67639
+ const raw = typeof value === 'number' ? value : (value.upper ?? value.lower ?? 0);
67273
67640
  return Math.min(100, Math.max(0, Math.round(raw)));
67274
67641
  }
67275
67642
  startChallenge() {
@@ -67335,7 +67702,7 @@ class ChessimalsGameComponent {
67335
67702
  losses: 0,
67336
67703
  bestStreakInRun: 0,
67337
67704
  currentStreak: 0,
67338
- botLadder: this.challengeLadder.map((bot) => bot.id),
67705
+ botLadder: this.challengeLadder.map(bot => bot.id),
67339
67706
  roundResults: [],
67340
67707
  startedAt: now,
67341
67708
  lastEventAt: now,
@@ -67344,7 +67711,7 @@ class ChessimalsGameComponent {
67344
67711
  this.challengeRun.set(run);
67345
67712
  this.activeStoredChallengeRun.set(run);
67346
67713
  this.startChallengeRound(run);
67347
- void this.challengeProgress.recordChallengeStarted(this.challengeRun() ?? run).catch((error) => {
67714
+ void this.challengeProgress.recordChallengeStarted(this.challengeRun() ?? run).catch(error => {
67348
67715
  console.warn('[Chessimals] challenge run save failed', error);
67349
67716
  });
67350
67717
  }
@@ -67599,16 +67966,18 @@ class ChessimalsGameComponent {
67599
67966
  this.challengeLastWon.set(won);
67600
67967
  this.challengeLastBot.set(bot);
67601
67968
  this.challengeLastRoundStats.set(roundStats);
67602
- this.challengeNewRecord.set(roundIndex > this.challengeStats().bestRoundReached
67603
- || Math.max(run.bestStreakInRun, nextStreak) > this.challengeStats().bestWinStreak);
67969
+ this.challengeNewRecord.set(roundIndex > this.challengeStats().bestRoundReached ||
67970
+ Math.max(run.bestStreakInRun, nextStreak) > this.challengeStats().bestWinStreak);
67604
67971
  this.challengePhase.set(completed ? 'completed' : failed ? 'failed' : 'between');
67605
- void this.challengeProgress.applyRoundResult({
67972
+ void this.challengeProgress
67973
+ .applyRoundResult({
67606
67974
  run: nextRun,
67607
67975
  roundReached: roundIndex,
67608
67976
  won,
67609
67977
  completed,
67610
67978
  roundStats,
67611
- }).catch((error) => {
67979
+ })
67980
+ .catch(error => {
67612
67981
  console.warn('[Chessimals] challenge stats save failed', error);
67613
67982
  });
67614
67983
  }
@@ -67629,7 +67998,7 @@ class ChessimalsGameComponent {
67629
67998
  finishedAt: now,
67630
67999
  };
67631
68000
  this.activeStoredChallengeRun.set(undefined);
67632
- void this.challengeProgress.saveRun(nextRun).catch((error) => {
68001
+ void this.challengeProgress.saveRun(nextRun).catch(error => {
67633
68002
  console.warn('[Chessimals] challenge abandon save failed', error);
67634
68003
  });
67635
68004
  }
@@ -68066,7 +68435,7 @@ class ChessimalsGameComponent {
68066
68435
  moveHistory: [
68067
68436
  {
68068
68437
  moveNumber: 0,
68069
- pieces: pieces.map((piece) => ({ ...piece, position: { ...piece.position } })),
68438
+ pieces: pieces.map(piece => ({ ...piece, position: { ...piece.position } })),
68070
68439
  currentTurn: 'white',
68071
68440
  status: 'in_progress',
68072
68441
  },
@@ -68076,19 +68445,23 @@ class ChessimalsGameComponent {
68076
68445
  basicMovesForColor(game, color) {
68077
68446
  const turnState = color === game.currentTurn ? game : { ...game, currentTurn: color };
68078
68447
  return turnState.pieces
68079
- .filter((piece) => piece.color === color && !piece.captured)
68080
- .flatMap((piece) => getChessimalsLegalMoves(turnState, piece.id));
68448
+ .filter(piece => piece.color === color && !piece.captured)
68449
+ .flatMap(piece => getChessimalsLegalMoves(turnState, piece.id));
68081
68450
  }
68082
68451
  selectCell(position) {
68083
68452
  const game = this.game();
68084
- if (this.projectionMode || game.status !== 'in_progress' || !this.canPlayCurrentTurn() || this.movingPiece() || this.moveSyncing())
68453
+ if (this.projectionMode ||
68454
+ game.status !== 'in_progress' ||
68455
+ !this.canPlayCurrentTurn() ||
68456
+ this.movingPiece() ||
68457
+ this.moveSyncing())
68085
68458
  return;
68086
68459
  const piece = getChessimalsPieceAt(game, position);
68087
68460
  if (piece?.color === game.currentTurn) {
68088
68461
  this.selectedPieceId.set(piece.id);
68089
68462
  return;
68090
68463
  }
68091
- const move = this.legalMoves().find((item) => positionKey(item.to) === positionKey(position));
68464
+ const move = this.legalMoves().find(item => positionKey(item.to) === positionKey(position));
68092
68465
  if (!move)
68093
68466
  return;
68094
68467
  this.commitChessimalsMove(game, move);
@@ -68108,7 +68481,7 @@ class ChessimalsGameComponent {
68108
68481
  .then(() => {
68109
68482
  void this.haptics.impact(move.capturesPieceId ? 'medium' : 'light');
68110
68483
  })
68111
- .catch((error) => {
68484
+ .catch(error => {
68112
68485
  console.warn('[Chessimals] online move failed', { gameId: game.id, move, error });
68113
68486
  this.game.set(game);
68114
68487
  this.onlineError.set(this.t('chessimalsOnlineError'));
@@ -68218,14 +68591,14 @@ class ChessimalsGameComponent {
68218
68591
  }
68219
68592
  chooseAutomaticTurnMove(game) {
68220
68593
  const moves = game.pieces
68221
- .filter((piece) => piece.color === game.currentTurn && !piece.captured)
68222
- .flatMap((piece) => getChessimalsLegalMoves(game, piece.id));
68223
- const basicMoves = moves.filter((move) => move.kind === 'basic');
68224
- return basicMoves.find((move) => this.isPromotionMove(game, move))
68225
- ?? basicMoves.find((move) => !!move.capturesPieceId)
68226
- ?? basicMoves[0]
68227
- ?? moves.find((move) => !!move.capturesPieceId)
68228
- ?? moves[0];
68594
+ .filter(piece => piece.color === game.currentTurn && !piece.captured)
68595
+ .flatMap(piece => getChessimalsLegalMoves(game, piece.id));
68596
+ const basicMoves = moves.filter(move => move.kind === 'basic');
68597
+ return (basicMoves.find(move => this.isPromotionMove(game, move)) ??
68598
+ basicMoves.find(move => !!move.capturesPieceId) ??
68599
+ basicMoves[0] ??
68600
+ moves.find(move => !!move.capturesPieceId) ??
68601
+ moves[0]);
68229
68602
  }
68230
68603
  isPromotionMove(game, move) {
68231
68604
  return move.kind === 'basic' && move.to.row === (game.currentTurn === 'white' ? 0 : game.boardSize - 1);
@@ -68234,7 +68607,7 @@ class ChessimalsGameComponent {
68234
68607
  if (this.moveAnimationTimer)
68235
68608
  clearTimeout(this.moveAnimationTimer);
68236
68609
  this.queueMoveEffect(move);
68237
- const movingPiece = game.pieces.find((piece) => piece.id === move.pieceId);
68610
+ const movingPiece = game.pieces.find(piece => piece.id === move.pieceId);
68238
68611
  if (!movingPiece) {
68239
68612
  this.applyAnimatedMove(game, updated);
68240
68613
  return;
@@ -68292,7 +68665,7 @@ class ChessimalsGameComponent {
68292
68665
  updatedAt: new Date().toISOString(),
68293
68666
  };
68294
68667
  this.challengeRun.set(nextRun);
68295
- void this.challengeProgress.saveRun(nextRun).catch((error) => {
68668
+ void this.challengeProgress.saveRun(nextRun).catch(error => {
68296
68669
  console.warn('[Chessimals] challenge snapshot save failed', error);
68297
68670
  });
68298
68671
  }
@@ -68566,7 +68939,7 @@ class ChessimalsGameComponent {
68566
68939
  const next = current === animal.type ? undefined : animal.type;
68567
68940
  this.selectedAnimal.set(next);
68568
68941
  if (!this.selectedPieceId()) {
68569
- const firstPiece = this.game().pieces.find((piece) => !piece.captured && piece.color === this.game().currentTurn);
68942
+ const firstPiece = this.game().pieces.find(piece => !piece.captured && piece.color === this.game().currentTurn);
68570
68943
  this.selectedPieceId.set(firstPiece?.id);
68571
68944
  }
68572
68945
  if (next)
@@ -68710,7 +69083,7 @@ class ChessimalsGameComponent {
68710
69083
  .split(/\s+/)
68711
69084
  .filter(Boolean)
68712
69085
  .slice(0, 2)
68713
- .map((part) => part.charAt(0).toUpperCase())
69086
+ .map(part => part.charAt(0).toUpperCase())
68714
69087
  .join('');
68715
69088
  return initials || this.winnerSideLabel().charAt(0).toUpperCase();
68716
69089
  }
@@ -68836,10 +69209,7 @@ class ChessimalsGameComponent {
68836
69209
  canReviewPendingGuest() {
68837
69210
  const game = this.game();
68838
69211
  const uid = this.onlineUid();
68839
- return !!uid
68840
- && game.mode === 'online'
68841
- && this.online.isHostWaiting(game, uid)
68842
- && !!game.online.pendingGuest;
69212
+ return !!uid && game.mode === 'online' && this.online.isHostWaiting(game, uid) && !!game.online.pendingGuest;
68843
69213
  }
68844
69214
  pendingGuestName() {
68845
69215
  return this.game().online?.pendingGuest?.name ?? this.t('defaultPlayerName');
@@ -68857,7 +69227,7 @@ class ChessimalsGameComponent {
68857
69227
  .split(/\s+/)
68858
69228
  .filter(Boolean)
68859
69229
  .slice(0, 2)
68860
- .map((part) => part.charAt(0).toUpperCase())
69230
+ .map(part => part.charAt(0).toUpperCase())
68861
69231
  .join('');
68862
69232
  return initials || '?';
68863
69233
  }
@@ -68889,7 +69259,7 @@ class ChessimalsGameComponent {
68889
69259
  .split(/\s+/)
68890
69260
  .filter(Boolean)
68891
69261
  .slice(0, 2)
68892
- .map((part) => part.charAt(0).toUpperCase())
69262
+ .map(part => part.charAt(0).toUpperCase())
68893
69263
  .join('');
68894
69264
  return initials || '?';
68895
69265
  }
@@ -68972,7 +69342,7 @@ class ChessimalsGameComponent {
68972
69342
  historyOutcomeLabel(entry) {
68973
69343
  const outcomeKey = `chessimalsHistory${entry.outcome
68974
69344
  .split('_')
68975
- .map((part) => this.capitalize(part))
69345
+ .map(part => this.capitalize(part))
68976
69346
  .join('')}`;
68977
69347
  const opponent = entry.opponentName
68978
69348
  ? ` · ${this.t('chessimalsHistoryAgainst').replace('{player}', entry.opponentName)}`
@@ -69023,7 +69393,7 @@ class ChessimalsGameComponent {
69023
69393
  this.historyUid = uid;
69024
69394
  this.historySubscription?.unsubscribe();
69025
69395
  this.historySubscription = this.online.watchHistory(24).subscribe({
69026
- next: (history) => this.onlineHistory.set(history),
69396
+ next: history => this.onlineHistory.set(history),
69027
69397
  error: () => this.onlineHistory.set([]),
69028
69398
  });
69029
69399
  }
@@ -69031,15 +69401,15 @@ class ChessimalsGameComponent {
69031
69401
  if (this.challengeStatsSubscription)
69032
69402
  return;
69033
69403
  this.challengeStatsSubscription = this.challengeProgress.watchStats().subscribe({
69034
- next: (stats) => this.challengeStats.set(stats ?? this.challengeProgress.emptyStats()),
69404
+ next: stats => this.challengeStats.set(stats ?? this.challengeProgress.emptyStats()),
69035
69405
  error: () => this.challengeStats.set(this.challengeProgress.emptyStats()),
69036
69406
  });
69037
69407
  this.challengeRunsSubscription = this.challengeProgress.watchRecentRuns(4).subscribe({
69038
- next: (runs) => this.challengeHistory.set(runs),
69408
+ next: runs => this.challengeHistory.set(runs),
69039
69409
  error: () => this.challengeHistory.set([]),
69040
69410
  });
69041
69411
  this.challengeActiveRunSubscription = this.challengeProgress.watchActiveRun().subscribe({
69042
- next: (run) => this.activeStoredChallengeRun.set(this.isResumableChallengeRun(run) ? run : undefined),
69412
+ next: run => this.activeStoredChallengeRun.set(this.isResumableChallengeRun(run) ? run : undefined),
69043
69413
  error: () => this.activeStoredChallengeRun.set(undefined),
69044
69414
  });
69045
69415
  }
@@ -69060,7 +69430,7 @@ class ChessimalsGameComponent {
69060
69430
  return;
69061
69431
  }
69062
69432
  this.selectedNightmareMode.set('none');
69063
- const profile = this.botProfiles.find((item) => item.difficulty === difficulty);
69433
+ const profile = this.botProfiles.find(item => item.difficulty === difficulty);
69064
69434
  if (profile)
69065
69435
  this.selectedBotProfileId.set(profile.id);
69066
69436
  }
@@ -69121,6 +69491,8 @@ class ChessimalsGameComponent {
69121
69491
  return this.t('chessimalsBotEasy');
69122
69492
  if (difficulty === 'hard')
69123
69493
  return this.t('chessimalsBotHard');
69494
+ if (difficulty === 'master')
69495
+ return this.t('chessimalsBotMaster');
69124
69496
  if (difficulty === 'nightmare')
69125
69497
  return this.t('chessimalsBotNightmare');
69126
69498
  return this.t('chessimalsBotNormal');
@@ -69135,13 +69507,13 @@ class ChessimalsGameComponent {
69135
69507
  return this.t(`chessimalsBot${this.capitalize(profile.id)}Tendency`);
69136
69508
  }
69137
69509
  botProfileAvatar(profileId) {
69138
- return this.botProfiles.find((profile) => profile.id === profileId)?.avatar ?? '♟';
69510
+ return this.botProfiles.find(profile => profile.id === profileId)?.avatar ?? '♟';
69139
69511
  }
69140
69512
  botProfileAvatarSrc(profileId) {
69141
- return this.botProfiles.find((profile) => profile.id === profileId)?.avatarSrc ?? '';
69513
+ return this.botProfiles.find(profile => profile.id === profileId)?.avatarSrc ?? '';
69142
69514
  }
69143
69515
  challengeBotProfile(bot) {
69144
- return this.botProfiles.find((profile) => profile.id === bot.profileId);
69516
+ return this.botProfiles.find(profile => profile.id === bot.profileId);
69145
69517
  }
69146
69518
  challengeOpeningBot() {
69147
69519
  return this.challengeLadder[0];
@@ -69217,7 +69589,7 @@ class ChessimalsGameComponent {
69217
69589
  return this.challengePhase() !== 'idle' && !!this.challengeRun();
69218
69590
  }
69219
69591
  shouldShowChallengeInGamePanel() {
69220
- return !this.projectionMode && this.screen() === 'game' && this.challengePhase() === 'playing' && !!this.challengeRun();
69592
+ return (!this.projectionMode && this.screen() === 'game' && this.challengePhase() === 'playing' && !!this.challengeRun());
69221
69593
  }
69222
69594
  showChallengeIntro() {
69223
69595
  if (this.projectionMode || this.challengePhase() !== 'playing' || !this.activeChallengeBot())
@@ -69320,7 +69692,7 @@ class ChessimalsGameComponent {
69320
69692
  challengeRoundStageLabel() {
69321
69693
  const bot = this.challengePhase() === 'playing'
69322
69694
  ? this.activeChallengeBot()
69323
- : this.challengeLastBot() ?? this.activeChallengeBot();
69695
+ : (this.challengeLastBot() ?? this.activeChallengeBot());
69324
69696
  const run = this.challengeRun();
69325
69697
  const round = bot?.round ?? (run ? this.challengeRunRoundIndex(run) : 1);
69326
69698
  return this.t('chessimalsChallengeRoundStage')
@@ -69425,7 +69797,7 @@ class ChessimalsGameComponent {
69425
69797
  pathHighlights() {
69426
69798
  const stats = this.challengeStats();
69427
69799
  const favoritePower = this.favoritePowerLabel();
69428
- const nextAchievement = this.challengeAchievements().find((achievement) => !achievement.unlocked);
69800
+ const nextAchievement = this.challengeAchievements().find(achievement => !achievement.unlocked);
69429
69801
  return [
69430
69802
  {
69431
69803
  title: this.t('chessimalsPathWinsTitle'),
@@ -69548,8 +69920,8 @@ class ChessimalsGameComponent {
69548
69920
  challengeFeaturedAchievements() {
69549
69921
  const achievements = this.challengeAchievements();
69550
69922
  return [
69551
- ...achievements.filter((achievement) => achievement.unlocked),
69552
- ...achievements.filter((achievement) => !achievement.unlocked),
69923
+ ...achievements.filter(achievement => achievement.unlocked),
69924
+ ...achievements.filter(achievement => !achievement.unlocked),
69553
69925
  ].slice(0, 4);
69554
69926
  }
69555
69927
  challengeTensionMoment() {
@@ -69560,7 +69932,7 @@ class ChessimalsGameComponent {
69560
69932
  if (!run)
69561
69933
  return undefined;
69562
69934
  const nextBot = this.activeChallengeBot();
69563
- const lastBot = phase === 'playing' ? nextBot : this.challengeLastBot() ?? nextBot;
69935
+ const lastBot = phase === 'playing' ? nextBot : (this.challengeLastBot() ?? nextBot);
69564
69936
  const botName = lastBot ? this.challengeBotName(lastBot) : this.t('chessimalsBotName');
69565
69937
  if (run.livesRemaining <= 1) {
69566
69938
  return {
@@ -69649,11 +70021,11 @@ class ChessimalsGameComponent {
69649
70021
  scoreChessimalsMove(move, promotion, currentCombo) {
69650
70022
  const capture = !!move.capturesPieceId;
69651
70023
  const combo = capture ? currentCombo + 1 : 0;
69652
- const score = 1
69653
- + (capture ? (move.animal ? 5 : 3) : 0)
69654
- + (move.animal && !capture ? 1 : 0)
69655
- + (promotion ? 8 : 0)
69656
- + (combo > 1 ? combo - 1 : 0);
70024
+ const score = 1 +
70025
+ (capture ? (move.animal ? 5 : 3) : 0) +
70026
+ (move.animal && !capture ? 1 : 0) +
70027
+ (promotion ? 8 : 0) +
70028
+ (combo > 1 ? combo - 1 : 0);
69657
70029
  const labelKey = promotion
69658
70030
  ? 'chessimalsScorePromotion'
69659
70031
  : capture && move.animal
@@ -69740,7 +70112,7 @@ class ChessimalsGameComponent {
69740
70112
  return glyphs[type];
69741
70113
  }
69742
70114
  animalAssetSrc(type) {
69743
- return ANIMALS.find((animal) => animal.type === type)?.assetSrc ?? '';
70115
+ return ANIMALS.find(animal => animal.type === type)?.assetSrc ?? '';
69744
70116
  }
69745
70117
  powerCalloutTone(type) {
69746
70118
  const tones = {
@@ -69802,7 +70174,7 @@ class ChessimalsGameComponent {
69802
70174
  watchOnlineGame(gameId) {
69803
70175
  this.onlineSubscription?.unsubscribe();
69804
70176
  this.onlineSubscription = this.online.watchGame(gameId).subscribe({
69805
- next: (state) => {
70177
+ next: state => {
69806
70178
  this.ngZone.run(() => {
69807
70179
  if (!state) {
69808
70180
  this.onlineConnectionState.set('error');
@@ -69916,7 +70288,11 @@ class ChessimalsGameComponent {
69916
70288
 
69917
70289
  <section class="chessimals-panel">
69918
70290
  <section class="chessimals-home-actions" [attr.aria-label]="t('chessimalsHomeChoose')">
69919
- <button class="chessimals-home-action chessimals-home-action--play" type="button" (click)="openPlayOptionsModal()">
70291
+ <button
70292
+ class="chessimals-home-action chessimals-home-action--play"
70293
+ type="button"
70294
+ (click)="openPlayOptionsModal()"
70295
+ >
69920
70296
  <img
69921
70297
  class="chessimals-mode-icon"
69922
70298
  src="assets/games/chessimals/mode-icons/solo-borderless.png"
@@ -69970,60 +70346,60 @@ class ChessimalsGameComponent {
69970
70346
  </summary>
69971
70347
 
69972
70348
  <article class="chessimals-online">
69973
- <div>
69974
- <h2>{{ t('chessimalsOnlineTitle') }}</h2>
69975
- <p>{{ t('chessimalsOnlineBody') }}</p>
69976
- </div>
69977
- @if (onlineError()) {
69978
- <p class="chessimals-online__error">{{ onlineError() }}</p>
69979
- }
69980
- @if (onlineLoading()) {
69981
- <div class="chessimals-online__loading" role="status" aria-live="polite">
69982
- <span aria-hidden="true"></span>
69983
- <strong>{{ t('chessimalsOnlineLoading') }}</strong>
70349
+ <div>
70350
+ <h2>{{ t('chessimalsOnlineTitle') }}</h2>
70351
+ <p>{{ t('chessimalsOnlineBody') }}</p>
70352
+ </div>
70353
+ @if (onlineError()) {
70354
+ <p class="chessimals-online__error">{{ onlineError() }}</p>
70355
+ }
70356
+ @if (onlineLoading()) {
70357
+ <div class="chessimals-online__loading" role="status" aria-live="polite">
70358
+ <span aria-hidden="true"></span>
70359
+ <strong>{{ t('chessimalsOnlineLoading') }}</strong>
70360
+ </div>
70361
+ }
70362
+ <div class="chessimals-online__create">
70363
+ <button
70364
+ class="chessimals-primary"
70365
+ type="button"
70366
+ [class.is-working]="onlineAction() === 'create'"
70367
+ [attr.aria-busy]="onlineAction() === 'create'"
70368
+ [disabled]="onlineLoading()"
70369
+ (click)="createOnlineGame()"
70370
+ >
70371
+ @if (onlineAction() === 'create') {
70372
+ <span class="chessimals-button-spinner" aria-hidden="true"></span>
70373
+ }
70374
+ {{ t('chessimalsCreateOnline') }}
70375
+ </button>
70376
+ <small>{{ t('chessimalsCreateOnlineHint') }}</small>
70377
+ </div>
70378
+ <div class="chessimals-online__join">
70379
+ <strong>{{ t('chessimalsJoinOnlineTitle') }}</strong>
70380
+ <label class="chessimals-online-code">
70381
+ <span>{{ t('chessimalsJoinCode') }}</span>
70382
+ <input
70383
+ type="text"
70384
+ [value]="onlineJoinCode()"
70385
+ [placeholder]="t('chessimalsJoinCodePlaceholder')"
70386
+ (input)="onlineJoinCode.set(normalizeGameId($any($event.target).value))"
70387
+ />
70388
+ </label>
70389
+ <button
70390
+ class="chessimals-primary"
70391
+ type="button"
70392
+ [class.is-working]="onlineAction() === 'join'"
70393
+ [attr.aria-busy]="onlineAction() === 'join'"
70394
+ [disabled]="onlineLoading() || !onlineJoinCode()"
70395
+ (click)="joinOnlineGameByCode()"
70396
+ >
70397
+ @if (onlineAction() === 'join') {
70398
+ <span class="chessimals-button-spinner" aria-hidden="true"></span>
70399
+ }
70400
+ {{ t('chessimalsJoinOnline') }}
70401
+ </button>
69984
70402
  </div>
69985
- }
69986
- <div class="chessimals-online__create">
69987
- <button
69988
- class="chessimals-primary"
69989
- type="button"
69990
- [class.is-working]="onlineAction() === 'create'"
69991
- [attr.aria-busy]="onlineAction() === 'create'"
69992
- [disabled]="onlineLoading()"
69993
- (click)="createOnlineGame()"
69994
- >
69995
- @if (onlineAction() === 'create') {
69996
- <span class="chessimals-button-spinner" aria-hidden="true"></span>
69997
- }
69998
- {{ t('chessimalsCreateOnline') }}
69999
- </button>
70000
- <small>{{ t('chessimalsCreateOnlineHint') }}</small>
70001
- </div>
70002
- <div class="chessimals-online__join">
70003
- <strong>{{ t('chessimalsJoinOnlineTitle') }}</strong>
70004
- <label class="chessimals-online-code">
70005
- <span>{{ t('chessimalsJoinCode') }}</span>
70006
- <input
70007
- type="text"
70008
- [value]="onlineJoinCode()"
70009
- [placeholder]="t('chessimalsJoinCodePlaceholder')"
70010
- (input)="onlineJoinCode.set(normalizeGameId($any($event.target).value))"
70011
- />
70012
- </label>
70013
- <button
70014
- class="chessimals-primary"
70015
- type="button"
70016
- [class.is-working]="onlineAction() === 'join'"
70017
- [attr.aria-busy]="onlineAction() === 'join'"
70018
- [disabled]="onlineLoading() || !onlineJoinCode()"
70019
- (click)="joinOnlineGameByCode()"
70020
- >
70021
- @if (onlineAction() === 'join') {
70022
- <span class="chessimals-button-spinner" aria-hidden="true"></span>
70023
- }
70024
- {{ t('chessimalsJoinOnline') }}
70025
- </button>
70026
- </div>
70027
70403
  </article>
70028
70404
  </details>
70029
70405
 
@@ -70106,7 +70482,12 @@ class ChessimalsGameComponent {
70106
70482
  <strong>{{ challengeBotName(challengeMenuBot()) }}</strong>
70107
70483
  <p>{{ t(challengeMenuBot().introKey) }}</p>
70108
70484
  <em>
70109
- {{ t('chessimalsChallengeBoardLabel').replace('{size}', challengeMenuBot().boardSize + 'x' + challengeMenuBot().boardSize) }}
70485
+ {{
70486
+ t('chessimalsChallengeBoardLabel').replace(
70487
+ '{size}',
70488
+ challengeMenuBot().boardSize + 'x' + challengeMenuBot().boardSize
70489
+ )
70490
+ }}
70110
70491
  , {{ challengeBotDifficultyLabel(challengeMenuBot()) }}
70111
70492
  </em>
70112
70493
  </div>
@@ -70368,7 +70749,10 @@ class ChessimalsGameComponent {
70368
70749
  @if (pendingGuestAvatarUrl()) {
70369
70750
  <val-user-avatar [props]="pendingGuestAvatarProps()" />
70370
70751
  } @else {
70371
- <span class="chessimals-player-strip__avatar chessimals-player-strip__avatar--initials" aria-hidden="true">
70752
+ <span
70753
+ class="chessimals-player-strip__avatar chessimals-player-strip__avatar--initials"
70754
+ aria-hidden="true"
70755
+ >
70372
70756
  {{ pendingGuestInitials() }}
70373
70757
  </span>
70374
70758
  }
@@ -70428,26 +70812,26 @@ class ChessimalsGameComponent {
70428
70812
  @if (isChallengeActive() || turnSecondsRemaining() !== undefined) {
70429
70813
  <div class="chessimals-status chessimals-status--simple">
70430
70814
  @if (isChallengeActive()) {
70431
- <div>
70432
- <small>{{ t('chessimalsChallengeRound') }}</small>
70433
- <strong>{{ challengeRoundLabel() }}</strong>
70434
- </div>
70435
- <div>
70436
- <small>{{ t('chessimalsChallengeLives') }}</small>
70437
- <strong>{{ challengeLivesLabel() }}</strong>
70438
- </div>
70815
+ <div>
70816
+ <small>{{ t('chessimalsChallengeRound') }}</small>
70817
+ <strong>{{ challengeRoundLabel() }}</strong>
70818
+ </div>
70819
+ <div>
70820
+ <small>{{ t('chessimalsChallengeLives') }}</small>
70821
+ <strong>{{ challengeLivesLabel() }}</strong>
70822
+ </div>
70439
70823
  }
70440
70824
  @if (turnSecondsRemaining() !== undefined) {
70441
- <div
70442
- class="chessimals-status__timer"
70443
- [class.is-low]="isTurnTimerLow()"
70444
- [style.--timer-progress]="turnTimerProgress()"
70445
- role="timer"
70446
- aria-live="polite"
70447
- >
70448
- <small>{{ t('chessimalsTurnTimer') }}</small>
70449
- <strong>{{ turnTimerLabel() }}</strong>
70450
- </div>
70825
+ <div
70826
+ class="chessimals-status__timer"
70827
+ [class.is-low]="isTurnTimerLow()"
70828
+ [style.--timer-progress]="turnTimerProgress()"
70829
+ role="timer"
70830
+ aria-live="polite"
70831
+ >
70832
+ <small>{{ t('chessimalsTurnTimer') }}</small>
70833
+ <strong>{{ turnTimerLabel() }}</strong>
70834
+ </div>
70451
70835
  }
70452
70836
  </div>
70453
70837
  }
@@ -70545,7 +70929,14 @@ class ChessimalsGameComponent {
70545
70929
  [class.effect-bull]="isMoveEffectCell(row, col, 'bull')"
70546
70930
  [class.effect-kangaroo]="isMoveEffectCell(row, col, 'kangaroo')"
70547
70931
  [class.effect-lion]="isMoveEffectCell(row, col, 'lion')"
70548
- [disabled]="projectionMode || game().status !== 'in_progress' || !canPlayCurrentTurn() || !!movingPiece() || botThinking() || moveSyncing()"
70932
+ [disabled]="
70933
+ projectionMode ||
70934
+ game().status !== 'in_progress' ||
70935
+ !canPlayCurrentTurn() ||
70936
+ !!movingPiece() ||
70937
+ botThinking() ||
70938
+ moveSyncing()
70939
+ "
70549
70940
  (click)="selectCell({ row, col })"
70550
70941
  >
70551
70942
  <span class="chessimals-cell-texture" aria-hidden="true"></span>
@@ -70698,7 +71089,11 @@ class ChessimalsGameComponent {
70698
71089
  type="button"
70699
71090
  [class.is-selected]="selectedAnimal() === animal.type"
70700
71091
  [class.is-used]="powerPlayer().cards[animal.type].used"
70701
- [disabled]="!canUsePowerCards() || powerPlayer().cards[animal.type].used || isPowerCardBlockedByTutorial(animal.type)"
71092
+ [disabled]="
71093
+ !canUsePowerCards() ||
71094
+ powerPlayer().cards[animal.type].used ||
71095
+ isPowerCardBlockedByTutorial(animal.type)
71096
+ "
70702
71097
  (click)="toggleAnimal(animal)"
70703
71098
  >
70704
71099
  <span class="chessimals-animal-face" aria-hidden="true">
@@ -70793,11 +71188,19 @@ class ChessimalsGameComponent {
70793
71188
  </div>
70794
71189
  <div class="chessimals-challenge-summary__actions">
70795
71190
  @if (challengePhase() === 'between') {
70796
- <button class="chessimals-primary chessimals-challenge-summary__play" type="button" (click)="continueChallenge()">
71191
+ <button
71192
+ class="chessimals-primary chessimals-challenge-summary__play"
71193
+ type="button"
71194
+ (click)="continueChallenge()"
71195
+ >
70797
71196
  {{ challengeContinueLabel() }}
70798
71197
  </button>
70799
71198
  } @else {
70800
- <button class="chessimals-primary chessimals-challenge-summary__play" type="button" (click)="startChallenge()">
71199
+ <button
71200
+ class="chessimals-primary chessimals-challenge-summary__play"
71201
+ type="button"
71202
+ (click)="startChallenge()"
71203
+ >
70801
71204
  {{ t('chessimalsChallengePlayAgain') }}
70802
71205
  </button>
70803
71206
  }
@@ -70872,7 +71275,10 @@ class ChessimalsGameComponent {
70872
71275
  @if (rematchOpponentAvatarUrl()) {
70873
71276
  <val-user-avatar [props]="rematchOpponentAvatarProps()" />
70874
71277
  } @else {
70875
- <span class="chessimals-player-strip__avatar chessimals-player-strip__avatar--initials" aria-hidden="true">
71278
+ <span
71279
+ class="chessimals-player-strip__avatar chessimals-player-strip__avatar--initials"
71280
+ aria-hidden="true"
71281
+ >
70876
71282
  {{ rematchOpponentInitials() }}
70877
71283
  </span>
70878
71284
  }
@@ -70995,7 +71401,9 @@ class ChessimalsGameComponent {
70995
71401
 
70996
71402
  <article class="chessimals-play-options__group">
70997
71403
  <h3 id="chessimals-play-bot">
70998
- {{ selectedBotDifficulty() === 'nightmare' ? t('chessimalsNightmareRivals') : t('chessimalsBotStyle') }}
71404
+ {{
71405
+ selectedBotDifficulty() === 'nightmare' ? t('chessimalsNightmareRivals') : t('chessimalsBotStyle')
71406
+ }}
70999
71407
  </h3>
71000
71408
  <div class="chessimals-bots" role="radiogroup" aria-labelledby="chessimals-play-bot">
71001
71409
  @if (selectedBotDifficulty() === 'nightmare') {
@@ -71275,7 +71683,16 @@ class ChessimalsGameComponent {
71275
71683
  }
71276
71684
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ChessimalsGameComponent, decorators: [{
71277
71685
  type: Component,
71278
- args: [{ selector: 'val-chessimals-game', standalone: true, imports: [IonModal, MiniGameCalloutComponent, MiniGameScorePopComponent, ModalLayoutComponent, RangeInputComponent, ToggleInputComponent, ButtonComponent, UserAvatarComponent], template: `
71686
+ args: [{ selector: 'val-chessimals-game', standalone: true, imports: [
71687
+ IonModal,
71688
+ MiniGameCalloutComponent,
71689
+ MiniGameScorePopComponent,
71690
+ ModalLayoutComponent,
71691
+ RangeInputComponent,
71692
+ ToggleInputComponent,
71693
+ ButtonComponent,
71694
+ UserAvatarComponent,
71695
+ ], template: `
71279
71696
  <main class="chessimals-shell" [class.chessimals-shell--projection]="projectionMode">
71280
71697
  @if (screen() === 'home') {
71281
71698
  <section class="chessimals-hero">
@@ -71298,7 +71715,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
71298
71715
 
71299
71716
  <section class="chessimals-panel">
71300
71717
  <section class="chessimals-home-actions" [attr.aria-label]="t('chessimalsHomeChoose')">
71301
- <button class="chessimals-home-action chessimals-home-action--play" type="button" (click)="openPlayOptionsModal()">
71718
+ <button
71719
+ class="chessimals-home-action chessimals-home-action--play"
71720
+ type="button"
71721
+ (click)="openPlayOptionsModal()"
71722
+ >
71302
71723
  <img
71303
71724
  class="chessimals-mode-icon"
71304
71725
  src="assets/games/chessimals/mode-icons/solo-borderless.png"
@@ -71352,60 +71773,60 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
71352
71773
  </summary>
71353
71774
 
71354
71775
  <article class="chessimals-online">
71355
- <div>
71356
- <h2>{{ t('chessimalsOnlineTitle') }}</h2>
71357
- <p>{{ t('chessimalsOnlineBody') }}</p>
71358
- </div>
71359
- @if (onlineError()) {
71360
- <p class="chessimals-online__error">{{ onlineError() }}</p>
71361
- }
71362
- @if (onlineLoading()) {
71363
- <div class="chessimals-online__loading" role="status" aria-live="polite">
71364
- <span aria-hidden="true"></span>
71365
- <strong>{{ t('chessimalsOnlineLoading') }}</strong>
71776
+ <div>
71777
+ <h2>{{ t('chessimalsOnlineTitle') }}</h2>
71778
+ <p>{{ t('chessimalsOnlineBody') }}</p>
71779
+ </div>
71780
+ @if (onlineError()) {
71781
+ <p class="chessimals-online__error">{{ onlineError() }}</p>
71782
+ }
71783
+ @if (onlineLoading()) {
71784
+ <div class="chessimals-online__loading" role="status" aria-live="polite">
71785
+ <span aria-hidden="true"></span>
71786
+ <strong>{{ t('chessimalsOnlineLoading') }}</strong>
71787
+ </div>
71788
+ }
71789
+ <div class="chessimals-online__create">
71790
+ <button
71791
+ class="chessimals-primary"
71792
+ type="button"
71793
+ [class.is-working]="onlineAction() === 'create'"
71794
+ [attr.aria-busy]="onlineAction() === 'create'"
71795
+ [disabled]="onlineLoading()"
71796
+ (click)="createOnlineGame()"
71797
+ >
71798
+ @if (onlineAction() === 'create') {
71799
+ <span class="chessimals-button-spinner" aria-hidden="true"></span>
71800
+ }
71801
+ {{ t('chessimalsCreateOnline') }}
71802
+ </button>
71803
+ <small>{{ t('chessimalsCreateOnlineHint') }}</small>
71804
+ </div>
71805
+ <div class="chessimals-online__join">
71806
+ <strong>{{ t('chessimalsJoinOnlineTitle') }}</strong>
71807
+ <label class="chessimals-online-code">
71808
+ <span>{{ t('chessimalsJoinCode') }}</span>
71809
+ <input
71810
+ type="text"
71811
+ [value]="onlineJoinCode()"
71812
+ [placeholder]="t('chessimalsJoinCodePlaceholder')"
71813
+ (input)="onlineJoinCode.set(normalizeGameId($any($event.target).value))"
71814
+ />
71815
+ </label>
71816
+ <button
71817
+ class="chessimals-primary"
71818
+ type="button"
71819
+ [class.is-working]="onlineAction() === 'join'"
71820
+ [attr.aria-busy]="onlineAction() === 'join'"
71821
+ [disabled]="onlineLoading() || !onlineJoinCode()"
71822
+ (click)="joinOnlineGameByCode()"
71823
+ >
71824
+ @if (onlineAction() === 'join') {
71825
+ <span class="chessimals-button-spinner" aria-hidden="true"></span>
71826
+ }
71827
+ {{ t('chessimalsJoinOnline') }}
71828
+ </button>
71366
71829
  </div>
71367
- }
71368
- <div class="chessimals-online__create">
71369
- <button
71370
- class="chessimals-primary"
71371
- type="button"
71372
- [class.is-working]="onlineAction() === 'create'"
71373
- [attr.aria-busy]="onlineAction() === 'create'"
71374
- [disabled]="onlineLoading()"
71375
- (click)="createOnlineGame()"
71376
- >
71377
- @if (onlineAction() === 'create') {
71378
- <span class="chessimals-button-spinner" aria-hidden="true"></span>
71379
- }
71380
- {{ t('chessimalsCreateOnline') }}
71381
- </button>
71382
- <small>{{ t('chessimalsCreateOnlineHint') }}</small>
71383
- </div>
71384
- <div class="chessimals-online__join">
71385
- <strong>{{ t('chessimalsJoinOnlineTitle') }}</strong>
71386
- <label class="chessimals-online-code">
71387
- <span>{{ t('chessimalsJoinCode') }}</span>
71388
- <input
71389
- type="text"
71390
- [value]="onlineJoinCode()"
71391
- [placeholder]="t('chessimalsJoinCodePlaceholder')"
71392
- (input)="onlineJoinCode.set(normalizeGameId($any($event.target).value))"
71393
- />
71394
- </label>
71395
- <button
71396
- class="chessimals-primary"
71397
- type="button"
71398
- [class.is-working]="onlineAction() === 'join'"
71399
- [attr.aria-busy]="onlineAction() === 'join'"
71400
- [disabled]="onlineLoading() || !onlineJoinCode()"
71401
- (click)="joinOnlineGameByCode()"
71402
- >
71403
- @if (onlineAction() === 'join') {
71404
- <span class="chessimals-button-spinner" aria-hidden="true"></span>
71405
- }
71406
- {{ t('chessimalsJoinOnline') }}
71407
- </button>
71408
- </div>
71409
71830
  </article>
71410
71831
  </details>
71411
71832
 
@@ -71488,7 +71909,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
71488
71909
  <strong>{{ challengeBotName(challengeMenuBot()) }}</strong>
71489
71910
  <p>{{ t(challengeMenuBot().introKey) }}</p>
71490
71911
  <em>
71491
- {{ t('chessimalsChallengeBoardLabel').replace('{size}', challengeMenuBot().boardSize + 'x' + challengeMenuBot().boardSize) }}
71912
+ {{
71913
+ t('chessimalsChallengeBoardLabel').replace(
71914
+ '{size}',
71915
+ challengeMenuBot().boardSize + 'x' + challengeMenuBot().boardSize
71916
+ )
71917
+ }}
71492
71918
  , {{ challengeBotDifficultyLabel(challengeMenuBot()) }}
71493
71919
  </em>
71494
71920
  </div>
@@ -71750,7 +72176,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
71750
72176
  @if (pendingGuestAvatarUrl()) {
71751
72177
  <val-user-avatar [props]="pendingGuestAvatarProps()" />
71752
72178
  } @else {
71753
- <span class="chessimals-player-strip__avatar chessimals-player-strip__avatar--initials" aria-hidden="true">
72179
+ <span
72180
+ class="chessimals-player-strip__avatar chessimals-player-strip__avatar--initials"
72181
+ aria-hidden="true"
72182
+ >
71754
72183
  {{ pendingGuestInitials() }}
71755
72184
  </span>
71756
72185
  }
@@ -71810,26 +72239,26 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
71810
72239
  @if (isChallengeActive() || turnSecondsRemaining() !== undefined) {
71811
72240
  <div class="chessimals-status chessimals-status--simple">
71812
72241
  @if (isChallengeActive()) {
71813
- <div>
71814
- <small>{{ t('chessimalsChallengeRound') }}</small>
71815
- <strong>{{ challengeRoundLabel() }}</strong>
71816
- </div>
71817
- <div>
71818
- <small>{{ t('chessimalsChallengeLives') }}</small>
71819
- <strong>{{ challengeLivesLabel() }}</strong>
71820
- </div>
72242
+ <div>
72243
+ <small>{{ t('chessimalsChallengeRound') }}</small>
72244
+ <strong>{{ challengeRoundLabel() }}</strong>
72245
+ </div>
72246
+ <div>
72247
+ <small>{{ t('chessimalsChallengeLives') }}</small>
72248
+ <strong>{{ challengeLivesLabel() }}</strong>
72249
+ </div>
71821
72250
  }
71822
72251
  @if (turnSecondsRemaining() !== undefined) {
71823
- <div
71824
- class="chessimals-status__timer"
71825
- [class.is-low]="isTurnTimerLow()"
71826
- [style.--timer-progress]="turnTimerProgress()"
71827
- role="timer"
71828
- aria-live="polite"
71829
- >
71830
- <small>{{ t('chessimalsTurnTimer') }}</small>
71831
- <strong>{{ turnTimerLabel() }}</strong>
71832
- </div>
72252
+ <div
72253
+ class="chessimals-status__timer"
72254
+ [class.is-low]="isTurnTimerLow()"
72255
+ [style.--timer-progress]="turnTimerProgress()"
72256
+ role="timer"
72257
+ aria-live="polite"
72258
+ >
72259
+ <small>{{ t('chessimalsTurnTimer') }}</small>
72260
+ <strong>{{ turnTimerLabel() }}</strong>
72261
+ </div>
71833
72262
  }
71834
72263
  </div>
71835
72264
  }
@@ -71927,7 +72356,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
71927
72356
  [class.effect-bull]="isMoveEffectCell(row, col, 'bull')"
71928
72357
  [class.effect-kangaroo]="isMoveEffectCell(row, col, 'kangaroo')"
71929
72358
  [class.effect-lion]="isMoveEffectCell(row, col, 'lion')"
71930
- [disabled]="projectionMode || game().status !== 'in_progress' || !canPlayCurrentTurn() || !!movingPiece() || botThinking() || moveSyncing()"
72359
+ [disabled]="
72360
+ projectionMode ||
72361
+ game().status !== 'in_progress' ||
72362
+ !canPlayCurrentTurn() ||
72363
+ !!movingPiece() ||
72364
+ botThinking() ||
72365
+ moveSyncing()
72366
+ "
71931
72367
  (click)="selectCell({ row, col })"
71932
72368
  >
71933
72369
  <span class="chessimals-cell-texture" aria-hidden="true"></span>
@@ -72080,7 +72516,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
72080
72516
  type="button"
72081
72517
  [class.is-selected]="selectedAnimal() === animal.type"
72082
72518
  [class.is-used]="powerPlayer().cards[animal.type].used"
72083
- [disabled]="!canUsePowerCards() || powerPlayer().cards[animal.type].used || isPowerCardBlockedByTutorial(animal.type)"
72519
+ [disabled]="
72520
+ !canUsePowerCards() ||
72521
+ powerPlayer().cards[animal.type].used ||
72522
+ isPowerCardBlockedByTutorial(animal.type)
72523
+ "
72084
72524
  (click)="toggleAnimal(animal)"
72085
72525
  >
72086
72526
  <span class="chessimals-animal-face" aria-hidden="true">
@@ -72175,11 +72615,19 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
72175
72615
  </div>
72176
72616
  <div class="chessimals-challenge-summary__actions">
72177
72617
  @if (challengePhase() === 'between') {
72178
- <button class="chessimals-primary chessimals-challenge-summary__play" type="button" (click)="continueChallenge()">
72618
+ <button
72619
+ class="chessimals-primary chessimals-challenge-summary__play"
72620
+ type="button"
72621
+ (click)="continueChallenge()"
72622
+ >
72179
72623
  {{ challengeContinueLabel() }}
72180
72624
  </button>
72181
72625
  } @else {
72182
- <button class="chessimals-primary chessimals-challenge-summary__play" type="button" (click)="startChallenge()">
72626
+ <button
72627
+ class="chessimals-primary chessimals-challenge-summary__play"
72628
+ type="button"
72629
+ (click)="startChallenge()"
72630
+ >
72183
72631
  {{ t('chessimalsChallengePlayAgain') }}
72184
72632
  </button>
72185
72633
  }
@@ -72254,7 +72702,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
72254
72702
  @if (rematchOpponentAvatarUrl()) {
72255
72703
  <val-user-avatar [props]="rematchOpponentAvatarProps()" />
72256
72704
  } @else {
72257
- <span class="chessimals-player-strip__avatar chessimals-player-strip__avatar--initials" aria-hidden="true">
72705
+ <span
72706
+ class="chessimals-player-strip__avatar chessimals-player-strip__avatar--initials"
72707
+ aria-hidden="true"
72708
+ >
72258
72709
  {{ rematchOpponentInitials() }}
72259
72710
  </span>
72260
72711
  }
@@ -72377,7 +72828,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
72377
72828
 
72378
72829
  <article class="chessimals-play-options__group">
72379
72830
  <h3 id="chessimals-play-bot">
72380
- {{ selectedBotDifficulty() === 'nightmare' ? t('chessimalsNightmareRivals') : t('chessimalsBotStyle') }}
72831
+ {{
72832
+ selectedBotDifficulty() === 'nightmare' ? t('chessimalsNightmareRivals') : t('chessimalsBotStyle')
72833
+ }}
72381
72834
  </h3>
72382
72835
  <div class="chessimals-bots" role="radiogroup" aria-labelledby="chessimals-play-bot">
72383
72836
  @if (selectedBotDifficulty() === 'nightmare') {