chess-moments 1.2.0 → 1.2.2
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.
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const {
|
|
1
|
+
const { isNextFen } = require('../helpers');
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Always returns an array because there can be more than one next moment
|
|
@@ -23,81 +23,41 @@ const getNextMoments = (moments, current) => {
|
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
// Last move of a sideline should not have any next moves
|
|
26
|
-
if (
|
|
27
|
-
!nextMoment?.move &&
|
|
28
|
-
current.depth >= nextMoment.depth &&
|
|
29
|
-
getMoveNumber(nextMoment.fen) <= getMoveNumber(current.fen)
|
|
30
|
-
) {
|
|
26
|
+
if (!nextMoment?.move && current.depth >= nextMoment.depth) {
|
|
31
27
|
return [];
|
|
32
28
|
}
|
|
33
29
|
|
|
34
|
-
//
|
|
35
|
-
if (nextMoment.move && current.depth === nextMoment.depth) {
|
|
36
|
-
next.push(nextMoment);
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
// Return early if we have consecutive moves or no next next moment
|
|
40
|
-
if (!nextNextMoment || (nextMoment?.move && nextNextMoment?.move)) {
|
|
41
|
-
return next;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
// Second to last move of a sideline should not have any next moves
|
|
30
|
+
// Return early if there are two consecutive moves at the same depth or if the next next move does not exist
|
|
45
31
|
if (
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
current.depth
|
|
49
|
-
getMoveNumber(nextNextMoment.fen) <= getMoveNumber(current.fen)
|
|
32
|
+
current.move &&
|
|
33
|
+
current.depth === nextMoment.depth &&
|
|
34
|
+
(!nextNextMoment || current.depth === nextNextMoment.depth)
|
|
50
35
|
) {
|
|
51
|
-
return
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
// Remove all next moments until depth equals current.depth when next moment does not have a move
|
|
55
|
-
if (!nextMoment?.move) {
|
|
56
|
-
const filteredMoments = moments.filter((moment, index) => {
|
|
57
|
-
return index <= nextIndex || moment.depth === current.depth;
|
|
58
|
-
});
|
|
59
|
-
moments = filteredMoments;
|
|
36
|
+
return [nextMoment];
|
|
60
37
|
}
|
|
61
38
|
|
|
62
|
-
//
|
|
63
|
-
|
|
39
|
+
// Remove all moves before the current moment
|
|
40
|
+
moments = moments.filter((moment) => moment.index > current.index);
|
|
64
41
|
|
|
65
|
-
//
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
fullmove <= current.fullmove + 1 &&
|
|
71
|
-
moment.move // Also filter out moments without a move
|
|
72
|
-
);
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
// Active color after current move (who moves next)
|
|
76
|
-
const activeColorAfterCurrent = current.fen.split(' ')[1];
|
|
77
|
-
|
|
78
|
-
for (const moment of slim) {
|
|
79
|
-
// Only process main line and immediate variations
|
|
80
|
-
// Ignore next moments with depth lower than the current moment
|
|
81
|
-
if (moment.depth > current.depth + 1 || moment.depth < current.depth) {
|
|
82
|
-
continue;
|
|
42
|
+
// Remove all moments after the first moment that have a lower depth than the current moment
|
|
43
|
+
let filteredMoments = [];
|
|
44
|
+
for (const moment of moments) {
|
|
45
|
+
if (moment.depth < current.depth) {
|
|
46
|
+
break;
|
|
83
47
|
}
|
|
48
|
+
filteredMoments.push(moment);
|
|
49
|
+
}
|
|
84
50
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
activeColorAfterMoment === 'b' &&
|
|
92
|
-
fullmove === current.fullmove;
|
|
93
|
-
|
|
94
|
-
const isValidBlackMove =
|
|
95
|
-
activeColorAfterCurrent === 'b' &&
|
|
96
|
-
activeColorAfterMoment === 'w' &&
|
|
97
|
-
fullmove === current.fullmove + 1;
|
|
51
|
+
// If next moment does not have a move, remove all moments with the depth higher than current depth
|
|
52
|
+
if (!nextMoment.move) {
|
|
53
|
+
filteredMoments = filteredMoments.filter(
|
|
54
|
+
(moment) => moment.depth <= current.depth
|
|
55
|
+
);
|
|
56
|
+
}
|
|
98
57
|
|
|
99
|
-
|
|
100
|
-
|
|
58
|
+
// Finally check for next moments from filtered moments
|
|
59
|
+
for (const moment of filteredMoments) {
|
|
60
|
+
if (moment.move && isNextFen(current.fen, moment.fen)) {
|
|
101
61
|
next.push(moment);
|
|
102
62
|
}
|
|
103
63
|
}
|
|
@@ -2,6 +2,7 @@ const getBrushCode = require('./get-brush-code');
|
|
|
2
2
|
const getBrushColor = require('./get-brush-color');
|
|
3
3
|
const getMoveNumber = require('./get-move-number');
|
|
4
4
|
const insertMomentIntoTree = require('./insert-moment-into-tree');
|
|
5
|
+
const isNextFen = require('./is-next-fen');
|
|
5
6
|
const prepareMoment = require('./prepare-moment');
|
|
6
7
|
|
|
7
8
|
module.exports = {
|
|
@@ -9,5 +10,6 @@ module.exports = {
|
|
|
9
10
|
getBrushColor,
|
|
10
11
|
getMoveNumber,
|
|
11
12
|
insertMomentIntoTree,
|
|
13
|
+
isNextFen,
|
|
12
14
|
prepareMoment,
|
|
13
15
|
};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Determines if nextFen comes immediately after currentFen in a chess game
|
|
3
|
+
*
|
|
4
|
+
* @param {String} currentFen - The current FEN position
|
|
5
|
+
* @param {String} nextFen - The potential next FEN position
|
|
6
|
+
* @returns {Boolean} - True if nextFen comes immediately after currentFen
|
|
7
|
+
*/
|
|
8
|
+
const isNextFen = (currentFen, nextFen) => {
|
|
9
|
+
try {
|
|
10
|
+
// Parse FEN components
|
|
11
|
+
const currentParts = currentFen.split(' ');
|
|
12
|
+
const nextParts = nextFen.split(' ');
|
|
13
|
+
|
|
14
|
+
// Validate FEN format (should have 6 parts each)
|
|
15
|
+
if (currentParts.length !== 6 || nextParts.length !== 6) {
|
|
16
|
+
return false;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const currentActiveColor = currentParts[1]; // 'w' or 'b' - who moves in current position
|
|
20
|
+
const currentFullmove = Number(currentParts[5]);
|
|
21
|
+
|
|
22
|
+
const nextActiveColor = nextParts[1]; // 'w' or 'b' - who moves in next position
|
|
23
|
+
const nextFullmove = Number(nextParts[5]);
|
|
24
|
+
|
|
25
|
+
// Check if the active color and fullmove number progression is valid
|
|
26
|
+
if (currentActiveColor === 'w') {
|
|
27
|
+
// If white is to move in current position, then after white's move:
|
|
28
|
+
// - Black should be to move in next position
|
|
29
|
+
// - Fullmove number should remain the same
|
|
30
|
+
return nextActiveColor === 'b' && nextFullmove === currentFullmove;
|
|
31
|
+
} else {
|
|
32
|
+
// If black is to move in current position, then after black's move:
|
|
33
|
+
// - White should be to move in next position
|
|
34
|
+
// - Fullmove number should increment by 1
|
|
35
|
+
return nextActiveColor === 'w' && nextFullmove === currentFullmove + 1;
|
|
36
|
+
}
|
|
37
|
+
} catch (error) {
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
module.exports = isNextFen;
|