chess-tactics 0.0.5 → 0.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/TacticFactory.js +3 -1
- package/dist/tactics/BaseTactic.js +4 -1
- package/dist/tactics/HangingPiece.js +14 -5
- package/dist/tactics/Trap.js +5 -1
- package/dist/utils/SequenceInterpreter.d.ts +4 -1
- package/dist/utils/SequenceInterpreter.js +14 -2
- package/dist/utils/TacticContextParser.js +7 -0
- package/package.json +1 -1
package/dist/TacticFactory.js
CHANGED
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.TacticFactory = void 0;
|
|
4
4
|
const _tactics_1 = require("./tactics/index");
|
|
5
5
|
const _utils_1 = require("./utils/index");
|
|
6
|
+
const SequenceInterpreter_1 = require("./utils/SequenceInterpreter");
|
|
6
7
|
class TacticFactory {
|
|
7
8
|
static create(type) {
|
|
8
9
|
const sequenceInterpreter = new _utils_1.SequenceInterpreter();
|
|
@@ -16,7 +17,8 @@ class TacticFactory {
|
|
|
16
17
|
case "sacrifice":
|
|
17
18
|
return new _tactics_1.SacrificeTactics(sequenceInterpreter);
|
|
18
19
|
case "trap":
|
|
19
|
-
|
|
20
|
+
const trapInterpreter = new SequenceInterpreter_1.TrapTacticsSequenceInterpreter();
|
|
21
|
+
return new _tactics_1.TrapTactics(trapInterpreter);
|
|
20
22
|
case "hanging":
|
|
21
23
|
return new _tactics_1.HangingPieceTactics(sequenceInterpreter);
|
|
22
24
|
}
|
|
@@ -14,11 +14,14 @@ class BaseTactic {
|
|
|
14
14
|
const chess = new chess_js_1.Chess(context.position);
|
|
15
15
|
let isForcing = true;
|
|
16
16
|
let i = 0;
|
|
17
|
-
while (isForcing && i < sequence.length - 2) {
|
|
17
|
+
while (isForcing && i < Math.min(sequence.length - 2, 4)) {
|
|
18
18
|
const newContext = this.contextAtState(context, chess.fen(), sequence, i);
|
|
19
19
|
this.sequenceInterpreter.setContext(newContext);
|
|
20
20
|
const tactic = this.isTactic(newContext);
|
|
21
21
|
if (tactic) {
|
|
22
|
+
if (tactic.type === "hanging" && i > 0) {
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
22
25
|
return this.wrapTactic(tactic, context, sequence, i);
|
|
23
26
|
}
|
|
24
27
|
// Play your move and opponent's response
|
|
@@ -6,14 +6,14 @@ const _utils_1 = require("../utils/index");
|
|
|
6
6
|
const _tactics_1 = require("./index");
|
|
7
7
|
class HangingPieceTactics extends _tactics_1.BaseTactic {
|
|
8
8
|
isTactic(context) {
|
|
9
|
-
const { position, evaluation, prevMove } = context;
|
|
9
|
+
const { position, evaluation, prevMove, prevPosition } = context;
|
|
10
|
+
const prevChess = new chess_js_1.Chess(prevPosition);
|
|
10
11
|
const chess = new chess_js_1.Chess(position);
|
|
11
12
|
const currentMove = evaluation.sequence[0];
|
|
12
|
-
if (!currentMove.captured) {
|
|
13
|
+
if (!currentMove.captured || currentMove.captured === "p") {
|
|
13
14
|
return null;
|
|
14
15
|
}
|
|
15
|
-
if (prevMove.captured &&
|
|
16
|
-
_utils_1.PIECE_VALUES[prevMove.captured] >= _utils_1.PIECE_VALUES[currentMove.captured]) {
|
|
16
|
+
if (prevChess.inCheck() || (prevMove.captured && prevMove.captured !== "p")) {
|
|
17
17
|
return null;
|
|
18
18
|
}
|
|
19
19
|
chess.load(position);
|
|
@@ -21,7 +21,16 @@ class HangingPieceTactics extends _tactics_1.BaseTactic {
|
|
|
21
21
|
const tacticalSequence = this.sequenceInterpreter.identifyWinningSequence(attackers, [
|
|
22
22
|
currentMove.to,
|
|
23
23
|
]);
|
|
24
|
-
|
|
24
|
+
this.sequenceInterpreter.setContext({
|
|
25
|
+
evaluation: context.prevEvaluation,
|
|
26
|
+
position: context.prevPosition,
|
|
27
|
+
});
|
|
28
|
+
const prevSequence = this.sequenceInterpreter.identifyWinningSequence(attackers, [
|
|
29
|
+
currentMove.to,
|
|
30
|
+
]);
|
|
31
|
+
if (tacticalSequence &&
|
|
32
|
+
tacticalSequence.materialChange >= _utils_1.PIECE_VALUES[currentMove.captured] &&
|
|
33
|
+
(!prevSequence || prevSequence.materialChange < _utils_1.PIECE_VALUES[currentMove.captured])) {
|
|
25
34
|
return {
|
|
26
35
|
type: "hanging",
|
|
27
36
|
attackedPieces: [{ square: currentMove.to, piece: chess.get(currentMove.to) }],
|
package/dist/tactics/Trap.js
CHANGED
|
@@ -72,12 +72,16 @@ class TrapTactics extends _tactics_1.BaseTactic {
|
|
|
72
72
|
getCapturablePieces(currentMove, position) {
|
|
73
73
|
// A capturable piece is one that can be taken. No other assumptions
|
|
74
74
|
// game must be the initial position
|
|
75
|
+
const chess = new chess_js_1.Chess(position);
|
|
76
|
+
const originalMoves = chess.moves({ verbose: true });
|
|
75
77
|
const chessCopy = new chess_js_1.Chess(position);
|
|
76
78
|
chessCopy.move(currentMove);
|
|
77
79
|
(0, _utils_1.invertTurn)(chessCopy);
|
|
78
80
|
const possibleMoves = chessCopy.moves({ verbose: true });
|
|
81
|
+
// moveDiff ensures the move you made is responsible for revealing the trap, either directly or indirectly
|
|
82
|
+
const moveDiff = (0, _utils_1.getMoveDiff)(originalMoves, possibleMoves);
|
|
79
83
|
let targetedPieces = [];
|
|
80
|
-
for (const m of
|
|
84
|
+
for (const m of moveDiff) {
|
|
81
85
|
if (m.captured) {
|
|
82
86
|
targetedPieces.push(m);
|
|
83
87
|
}
|
|
@@ -7,7 +7,10 @@ export declare class SequenceInterpreter {
|
|
|
7
7
|
setContext(context: _TacticContext): void;
|
|
8
8
|
getCaptureSequence(position: Fen, sequence: Move[]): any[];
|
|
9
9
|
identifyWinningSequence(attackerSquares: Square[], attackedSquares: Square[]): SequenceInterpretation | null;
|
|
10
|
-
|
|
10
|
+
protected capturedAttackedPieces(move: Move, attackerSquares: Square[], attackedSquares: Square[]): boolean;
|
|
11
11
|
private isDesparado;
|
|
12
12
|
positionAfterSequence(position: Fen, sequence: string[] | Move[] | null): string;
|
|
13
13
|
}
|
|
14
|
+
export declare class TrapTacticsSequenceInterpreter extends SequenceInterpreter {
|
|
15
|
+
protected capturedAttackedPieces(move: Move, attackerSquares: Square[], attackedSquares: Square[]): boolean;
|
|
16
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.SequenceInterpreter = void 0;
|
|
3
|
+
exports.TrapTacticsSequenceInterpreter = exports.SequenceInterpreter = void 0;
|
|
4
4
|
const chess_js_1 = require("chess.js");
|
|
5
5
|
const _utils_1 = require("./index");
|
|
6
6
|
class SequenceInterpreter {
|
|
@@ -66,7 +66,9 @@ class SequenceInterpreter {
|
|
|
66
66
|
capturedAttackedPieces(move, attackerSquares, attackedSquares) {
|
|
67
67
|
const capturedSquares = attackedSquares.filter((s) => {
|
|
68
68
|
// move came from an attacker square, to an attackedSquare, and captured a piece
|
|
69
|
-
return
|
|
69
|
+
return (attackerSquares.filter((t) => t === move.from).length > 0 &&
|
|
70
|
+
s === move.to &&
|
|
71
|
+
move.captured);
|
|
70
72
|
});
|
|
71
73
|
return capturedSquares.length > 0;
|
|
72
74
|
}
|
|
@@ -86,3 +88,13 @@ class SequenceInterpreter {
|
|
|
86
88
|
}
|
|
87
89
|
}
|
|
88
90
|
exports.SequenceInterpreter = SequenceInterpreter;
|
|
91
|
+
class TrapTacticsSequenceInterpreter extends SequenceInterpreter {
|
|
92
|
+
capturedAttackedPieces(move, attackerSquares, attackedSquares) {
|
|
93
|
+
const capturedSquares = attackedSquares.filter((s) => {
|
|
94
|
+
// move came from an attacker square, to an attackedSquare, and captured a piece
|
|
95
|
+
return s === move.to && move.captured;
|
|
96
|
+
});
|
|
97
|
+
return capturedSquares.length > 0;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
exports.TrapTacticsSequenceInterpreter = TrapTacticsSequenceInterpreter;
|
|
@@ -7,6 +7,13 @@ class TacticContextParser {
|
|
|
7
7
|
static parse(context, options) {
|
|
8
8
|
const evaluation = this.parseEvaluation(context.position, context.evaluation, options);
|
|
9
9
|
if ("prevEvaluation" in context) {
|
|
10
|
+
const prevChess = new chess_js_1.Chess(context.prevPosition);
|
|
11
|
+
try {
|
|
12
|
+
prevChess.move(context.prevMove);
|
|
13
|
+
}
|
|
14
|
+
catch (e) {
|
|
15
|
+
throw new _chess_tactics_1.ChessTacticsParserError(`prevMove ${context.prevMove.san} is not playable in prevPosition ${context.prevPosition}`, "INVALID_MOVE", { cause: e });
|
|
16
|
+
}
|
|
10
17
|
const prevEvaluation = this.parseEvaluation(context.prevPosition, context.prevEvaluation, options);
|
|
11
18
|
return {
|
|
12
19
|
evaluation: evaluation,
|