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.
- package/esm2022/lib/components/organisms/mini-games/chessimals-engine.mjs +365 -67
- package/esm2022/lib/components/organisms/mini-games/chessimals-game.component.mjs +415 -262
- package/esm2022/lib/components/organisms/mini-games/mini-games.i18n.mjs +3 -1
- package/esm2022/lib/components/organisms/mini-games/types.mjs +1 -1
- package/esm2022/lib/version.mjs +2 -2
- package/fesm2022/valtech-components.mjs +781 -328
- package/fesm2022/valtech-components.mjs.map +1 -1
- package/lib/components/organisms/mini-games/chessimals-game.component.d.ts +2 -1
- package/lib/components/organisms/mini-games/types.d.ts +1 -1
- package/lib/version.d.ts +1 -1
- package/package.json +1 -1
|
@@ -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.
|
|
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: {
|
|
61715
|
-
|
|
61716
|
-
|
|
61717
|
-
|
|
61718
|
-
|
|
61719
|
-
|
|
61720
|
-
|
|
61721
|
-
|
|
61722
|
-
|
|
61723
|
-
|
|
61724
|
-
|
|
61725
|
-
|
|
61726
|
-
|
|
61727
|
-
|
|
61728
|
-
|
|
61729
|
-
|
|
61730
|
-
|
|
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(
|
|
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(
|
|
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(
|
|
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'
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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 +=
|
|
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 +=
|
|
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 +=
|
|
62147
|
-
|
|
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(
|
|
62403
|
+
const opponentImmediateWin = opponentMoves.some(opponentMove => opponentMove.kind === 'basic' &&
|
|
62167
62404
|
isPromotionRow(afterMove.boardSize, afterMove.currentTurn, opponentMove.to));
|
|
62168
62405
|
if (opponentImmediateWin) {
|
|
62169
|
-
score -=
|
|
62170
|
-
|
|
62171
|
-
|
|
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(
|
|
62415
|
+
const canCaptureMovedPiece = opponentMoves.some(opponentMove => opponentMove.capturesPieceId === move.pieceId);
|
|
62174
62416
|
if (canCaptureMovedPiece) {
|
|
62175
|
-
score -=
|
|
62176
|
-
|
|
62177
|
-
|
|
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(
|
|
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'
|
|
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
|
|
62478
|
+
if (!round)
|
|
62198
62479
|
return 0;
|
|
62199
|
-
return Math.min(1, Math.max(0,
|
|
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'
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
62303
|
-
return enemyPieces.filter(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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
|
-
{
|
|
66377
|
-
|
|
66378
|
-
|
|
66379
|
-
|
|
66380
|
-
|
|
66381
|
-
|
|
66382
|
-
|
|
66383
|
-
|
|
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:
|
|
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:
|
|
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
|
-
|
|
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(
|
|
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(
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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(
|
|
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(
|
|
66771
|
-
this.captureMoveKeys = computed(() => new Set(this.legalMoves()
|
|
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()
|
|
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(
|
|
66784
|
-
return new Set(moves.map(
|
|
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(
|
|
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(
|
|
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(
|
|
67331
|
+
this.resultCaptures = computed(() => this.replayEntries().filter(entry => !!entry.move?.capturesPieceId).length);
|
|
66963
67332
|
this.resultPowers = computed(() => this.replayEntries()
|
|
66964
|
-
.map(
|
|
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(
|
|
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(
|
|
67016
|
-
const captures = botMoves.filter(
|
|
67017
|
-
const powers = botMoves.filter(
|
|
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(
|
|
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(
|
|
67039
|
-
rival: games.filter(
|
|
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(
|
|
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(
|
|
67169
|
-
this.routeSubscription.add(this.musicVolumeControl.valueChanges.subscribe(
|
|
67170
|
-
this.routeSubscription.add(this.sfxVolumeControl.valueChanges.subscribe(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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
|
-
|
|
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
|
|
67972
|
+
void this.challengeProgress
|
|
67973
|
+
.applyRoundResult({
|
|
67606
67974
|
run: nextRun,
|
|
67607
67975
|
roundReached: roundIndex,
|
|
67608
67976
|
won,
|
|
67609
67977
|
completed,
|
|
67610
67978
|
roundStats,
|
|
67611
|
-
})
|
|
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(
|
|
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(
|
|
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(
|
|
68080
|
-
.flatMap(
|
|
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 ||
|
|
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(
|
|
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(
|
|
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(
|
|
68222
|
-
.flatMap(
|
|
68223
|
-
const basicMoves = moves.filter(
|
|
68224
|
-
return basicMoves.find(
|
|
68225
|
-
|
|
68226
|
-
|
|
68227
|
-
|
|
68228
|
-
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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(
|
|
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(
|
|
69510
|
+
return this.botProfiles.find(profile => profile.id === profileId)?.avatar ?? '♟';
|
|
69139
69511
|
}
|
|
69140
69512
|
botProfileAvatarSrc(profileId) {
|
|
69141
|
-
return this.botProfiles.find(
|
|
69513
|
+
return this.botProfiles.find(profile => profile.id === profileId)?.avatarSrc ?? '';
|
|
69142
69514
|
}
|
|
69143
69515
|
challengeBotProfile(bot) {
|
|
69144
|
-
return this.botProfiles.find(
|
|
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(
|
|
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(
|
|
69552
|
-
...achievements.filter(
|
|
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
|
-
|
|
69654
|
-
|
|
69655
|
-
|
|
69656
|
-
|
|
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(
|
|
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:
|
|
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
|
|
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
|
-
|
|
69974
|
-
|
|
69975
|
-
|
|
69976
|
-
|
|
69977
|
-
|
|
69978
|
-
|
|
69979
|
-
|
|
69980
|
-
|
|
69981
|
-
|
|
69982
|
-
|
|
69983
|
-
|
|
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
|
-
{{
|
|
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
|
|
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
|
-
|
|
70432
|
-
|
|
70433
|
-
|
|
70434
|
-
|
|
70435
|
-
|
|
70436
|
-
|
|
70437
|
-
|
|
70438
|
-
|
|
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
|
-
|
|
70442
|
-
|
|
70443
|
-
|
|
70444
|
-
|
|
70445
|
-
|
|
70446
|
-
|
|
70447
|
-
|
|
70448
|
-
|
|
70449
|
-
|
|
70450
|
-
|
|
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]="
|
|
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]="
|
|
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
|
|
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
|
|
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
|
|
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
|
-
{{
|
|
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: [
|
|
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
|
|
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
|
-
|
|
71356
|
-
|
|
71357
|
-
|
|
71358
|
-
|
|
71359
|
-
|
|
71360
|
-
|
|
71361
|
-
|
|
71362
|
-
|
|
71363
|
-
|
|
71364
|
-
|
|
71365
|
-
|
|
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
|
-
{{
|
|
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
|
|
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
|
-
|
|
71814
|
-
|
|
71815
|
-
|
|
71816
|
-
|
|
71817
|
-
|
|
71818
|
-
|
|
71819
|
-
|
|
71820
|
-
|
|
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
|
-
|
|
71824
|
-
|
|
71825
|
-
|
|
71826
|
-
|
|
71827
|
-
|
|
71828
|
-
|
|
71829
|
-
|
|
71830
|
-
|
|
71831
|
-
|
|
71832
|
-
|
|
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]="
|
|
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]="
|
|
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
|
|
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
|
|
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
|
|
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
|
-
{{
|
|
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') {
|