@datamoc/mw_games 0.20.0 → 0.22.0
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/CHANGELOG.md +83 -0
- package/dist/audio/Channels.d.ts +19 -0
- package/dist/audio/Channels.d.ts.map +1 -1
- package/dist/audio/Channels.js +33 -4
- package/dist/audio/Channels.js.map +1 -1
- package/dist/audio/LoopTags.d.ts +37 -0
- package/dist/audio/LoopTags.d.ts.map +1 -0
- package/dist/audio/LoopTags.js +116 -0
- package/dist/audio/LoopTags.js.map +1 -0
- package/dist/audio/Midi.d.ts +5 -0
- package/dist/audio/Midi.d.ts.map +1 -1
- package/dist/audio/Midi.js +9 -1
- package/dist/audio/Midi.js.map +1 -1
- package/dist/audio/MidiRender.d.ts +3 -2
- package/dist/audio/MidiRender.d.ts.map +1 -1
- package/dist/audio/MidiRender.js +2 -2
- package/dist/audio/MidiRender.js.map +1 -1
- package/dist/audio/index.d.ts +3 -1
- package/dist/audio/index.d.ts.map +1 -1
- package/dist/audio/index.js +1 -0
- package/dist/audio/index.js.map +1 -1
- package/dist/board/bitboard.d.ts +132 -0
- package/dist/board/bitboard.d.ts.map +1 -0
- package/dist/board/bitboard.js +495 -0
- package/dist/board/bitboard.js.map +1 -0
- package/dist/board/chess.d.ts +16 -0
- package/dist/board/chess.d.ts.map +1 -1
- package/dist/board/chess.js +43 -0
- package/dist/board/chess.js.map +1 -1
- package/dist/board/index.d.ts +9 -1
- package/dist/board/index.d.ts.map +1 -1
- package/dist/board/index.js +5 -1
- package/dist/board/index.js.map +1 -1
- package/dist/board/openings.d.ts +58 -0
- package/dist/board/openings.d.ts.map +1 -0
- package/dist/board/openings.js +45 -0
- package/dist/board/openings.js.map +1 -0
- package/dist/board/tablebase.d.ts +118 -0
- package/dist/board/tablebase.d.ts.map +1 -0
- package/dist/board/tablebase.js +414 -0
- package/dist/board/tablebase.js.map +1 -0
- package/dist/board/tourney.d.ts +90 -0
- package/dist/board/tourney.d.ts.map +1 -0
- package/dist/board/tourney.js +1013 -0
- package/dist/board/tourney.js.map +1 -0
- package/dist/core/JavaRandom.d.ts +55 -0
- package/dist/core/JavaRandom.d.ts.map +1 -0
- package/dist/core/JavaRandom.js +81 -0
- package/dist/core/JavaRandom.js.map +1 -0
- package/dist/core/index.d.ts +2 -0
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +1 -0
- package/dist/core/index.js.map +1 -1
- package/dist/mw_games.global.js +123 -116
- package/dist/rpg/EventRunner.d.ts +7 -0
- package/dist/rpg/EventRunner.d.ts.map +1 -1
- package/dist/rpg/EventRunner.js +6 -0
- package/dist/rpg/EventRunner.js.map +1 -1
- package/dist/two-d/render/FogLayer.d.ts +68 -0
- package/dist/two-d/render/FogLayer.d.ts.map +1 -0
- package/dist/two-d/render/FogLayer.js +83 -0
- package/dist/two-d/render/FogLayer.js.map +1 -0
- package/dist/two-d/render/LiquidLayer.d.ts +62 -0
- package/dist/two-d/render/LiquidLayer.d.ts.map +1 -0
- package/dist/two-d/render/LiquidLayer.js +102 -0
- package/dist/two-d/render/LiquidLayer.js.map +1 -0
- package/dist/two-d/render/RpgmAutotile.d.ts +5 -0
- package/dist/two-d/render/RpgmAutotile.d.ts.map +1 -1
- package/dist/two-d/render/RpgmAutotile.js +4 -3
- package/dist/two-d/render/RpgmAutotile.js.map +1 -1
- package/dist/two-d/render/TileMap.d.ts +14 -2
- package/dist/two-d/render/TileMap.d.ts.map +1 -1
- package/dist/two-d/render/TileMap.js +32 -2
- package/dist/two-d/render/TileMap.js.map +1 -1
- package/dist/two-d/render/index.d.ts +4 -0
- package/dist/two-d/render/index.d.ts.map +1 -1
- package/dist/two-d/render/index.js +2 -0
- package/dist/two-d/render/index.js.map +1 -1
- package/dist/two-d/ui/Label.d.ts.map +1 -1
- package/dist/two-d/ui/Label.js +11 -2
- package/dist/two-d/ui/Label.js.map +1 -1
- package/dist/two-d/ui/ListView.d.ts +24 -0
- package/dist/two-d/ui/ListView.d.ts.map +1 -1
- package/dist/two-d/ui/ListView.js +97 -4
- package/dist/two-d/ui/ListView.js.map +1 -1
- package/dist/two-d/ui/MessageLog.d.ts +62 -0
- package/dist/two-d/ui/MessageLog.d.ts.map +1 -0
- package/dist/two-d/ui/MessageLog.js +114 -0
- package/dist/two-d/ui/MessageLog.js.map +1 -0
- package/dist/two-d/ui/RadioGroup.d.ts +68 -0
- package/dist/two-d/ui/RadioGroup.d.ts.map +1 -0
- package/dist/two-d/ui/RadioGroup.js +177 -0
- package/dist/two-d/ui/RadioGroup.js.map +1 -0
- package/dist/two-d/ui/TextModel.d.ts +26 -1
- package/dist/two-d/ui/TextModel.d.ts.map +1 -1
- package/dist/two-d/ui/TextModel.js +56 -7
- package/dist/two-d/ui/TextModel.js.map +1 -1
- package/dist/two-d/ui/TextSharpness.d.ts +33 -0
- package/dist/two-d/ui/TextSharpness.d.ts.map +1 -0
- package/dist/two-d/ui/TextSharpness.js +56 -0
- package/dist/two-d/ui/TextSharpness.js.map +1 -0
- package/dist/two-d/ui/index.d.ts +5 -0
- package/dist/two-d/ui/index.d.ts.map +1 -1
- package/dist/two-d/ui/index.js +3 -0
- package/dist/two-d/ui/index.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +14 -2
- package/sbom.cdx.json +6 -6
- package/tools/build-tablebases.d.mts +22 -0
- package/tools/build-tablebases.mjs +549 -0
- package/tools/compile-openings.d.mts +20 -0
- package/tools/compile-openings.mjs +130 -0
- package/tools/play-uci.d.mts +26 -0
- package/tools/play-uci.mjs +194 -0
|
@@ -0,0 +1,495 @@
|
|
|
1
|
+
import { startingChess } from './chess.js';
|
|
2
|
+
const KIND_INDEX = { pawn: 0, knight: 1, bishop: 2, rook: 3, queen: 4, king: 5 };
|
|
3
|
+
const PROMOTION_ORDER = ['queen', 'rook', 'bishop', 'knight'];
|
|
4
|
+
const KNIGHT_STEPS = [
|
|
5
|
+
[1, 2],
|
|
6
|
+
[2, 1],
|
|
7
|
+
[2, -1],
|
|
8
|
+
[1, -2],
|
|
9
|
+
[-1, -2],
|
|
10
|
+
[-2, -1],
|
|
11
|
+
[-2, 1],
|
|
12
|
+
[-1, 2],
|
|
13
|
+
];
|
|
14
|
+
const KING_STEPS = [
|
|
15
|
+
[1, 0],
|
|
16
|
+
[1, 1],
|
|
17
|
+
[0, 1],
|
|
18
|
+
[-1, 1],
|
|
19
|
+
[-1, 0],
|
|
20
|
+
[-1, -1],
|
|
21
|
+
[0, -1],
|
|
22
|
+
[1, -1],
|
|
23
|
+
];
|
|
24
|
+
const DIAGONALS = [
|
|
25
|
+
[1, 1],
|
|
26
|
+
[-1, 1],
|
|
27
|
+
[-1, -1],
|
|
28
|
+
[1, -1],
|
|
29
|
+
];
|
|
30
|
+
const STRAIGHTS = [
|
|
31
|
+
[1, 0],
|
|
32
|
+
[0, 1],
|
|
33
|
+
[-1, 0],
|
|
34
|
+
[0, -1],
|
|
35
|
+
];
|
|
36
|
+
/** the single bit for a square */
|
|
37
|
+
function bit(square) {
|
|
38
|
+
return 1n << BigInt(square);
|
|
39
|
+
}
|
|
40
|
+
/** exact index of a single-bit board: powers of two survive the trip through Number */
|
|
41
|
+
function bitIndex(single) {
|
|
42
|
+
return Math.log2(Number(single));
|
|
43
|
+
}
|
|
44
|
+
function leaperTable(steps) {
|
|
45
|
+
return Array.from({ length: 64 }, (_, square) => {
|
|
46
|
+
const file = square & 7;
|
|
47
|
+
const rank = square >> 3;
|
|
48
|
+
let attacks = 0n;
|
|
49
|
+
for (const [df, dr] of steps) {
|
|
50
|
+
const f = file + df;
|
|
51
|
+
const r = rank + dr;
|
|
52
|
+
if (f >= 0 && f < 8 && r >= 0 && r < 8)
|
|
53
|
+
attacks |= bit(r * 8 + f);
|
|
54
|
+
}
|
|
55
|
+
return attacks;
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
const KNIGHT_TABLE = leaperTable(KNIGHT_STEPS);
|
|
59
|
+
const KING_TABLE = leaperTable(KING_STEPS);
|
|
60
|
+
function occupancyOf(board, colorBase) {
|
|
61
|
+
return (board.pieces[colorBase] |
|
|
62
|
+
board.pieces[colorBase + 1] |
|
|
63
|
+
board.pieces[colorBase + 2] |
|
|
64
|
+
board.pieces[colorBase + 3] |
|
|
65
|
+
board.pieces[colorBase + 4] |
|
|
66
|
+
board.pieces[colorBase + 5]);
|
|
67
|
+
}
|
|
68
|
+
/** piece-board index holding the square, or -1 */
|
|
69
|
+
function squareBoard(board, square) {
|
|
70
|
+
const mask = bit(square);
|
|
71
|
+
for (let i = 0; i < 12; i++) {
|
|
72
|
+
if (board.pieces[i] & mask)
|
|
73
|
+
return i;
|
|
74
|
+
}
|
|
75
|
+
return -1;
|
|
76
|
+
}
|
|
77
|
+
/** true when `byWhite` attacks the square, whatever its own king thinks of the move */
|
|
78
|
+
function isAttacked(board, square, byWhite) {
|
|
79
|
+
const by = byWhite ? 0 : 6;
|
|
80
|
+
const file = square & 7;
|
|
81
|
+
const rank = square >> 3;
|
|
82
|
+
//pawns attack one step diagonally towards the other side
|
|
83
|
+
const pawnRank = byWhite ? rank - 1 : rank + 1;
|
|
84
|
+
for (const df of [-1, 1]) {
|
|
85
|
+
const f = file + df;
|
|
86
|
+
if (pawnRank >= 0 && pawnRank < 8 && f >= 0 && f < 8 && board.pieces[by] & bit(pawnRank * 8 + f))
|
|
87
|
+
return true;
|
|
88
|
+
}
|
|
89
|
+
if (KNIGHT_TABLE[square] & board.pieces[by + 1])
|
|
90
|
+
return true;
|
|
91
|
+
if (KING_TABLE[square] & board.pieces[by + 5])
|
|
92
|
+
return true;
|
|
93
|
+
//sliders see until something stands in the way
|
|
94
|
+
const rays = [
|
|
95
|
+
{ steps: DIAGONALS, kinds: [2, 4] },
|
|
96
|
+
{ steps: STRAIGHTS, kinds: [3, 4] },
|
|
97
|
+
];
|
|
98
|
+
for (const { steps, kinds } of rays) {
|
|
99
|
+
for (const [df, dr] of steps) {
|
|
100
|
+
let f = file + df;
|
|
101
|
+
let r = rank + dr;
|
|
102
|
+
while (f >= 0 && f < 8 && r >= 0 && r < 8) {
|
|
103
|
+
const found = squareBoard(board, r * 8 + f);
|
|
104
|
+
if (found !== -1) {
|
|
105
|
+
if (found >= by && found < by + 6 && kinds.includes(found - by))
|
|
106
|
+
return true;
|
|
107
|
+
break;
|
|
108
|
+
}
|
|
109
|
+
f += df;
|
|
110
|
+
r += dr;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
return false;
|
|
115
|
+
}
|
|
116
|
+
function rightBit(side, kingside) {
|
|
117
|
+
return side === 'white' ? (kingside ? 1 : 2) : kingside ? 4 : 8;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Reads a `chess.ts` position onto bitboards: the bridge the differential tests cross
|
|
121
|
+
* in both directions, and the way a FEN reaches the fast board.
|
|
122
|
+
*
|
|
123
|
+
* @example
|
|
124
|
+
* ```ts
|
|
125
|
+
* import { bitboardFromChess, bitboardMoves, startingChess } from '@datamoc/mw_games/board';
|
|
126
|
+
*
|
|
127
|
+
* const moves = bitboardMoves(bitboardFromChess(startingChess()));
|
|
128
|
+
* console.log(moves.length); // 20 - the opening position's own count
|
|
129
|
+
* ```
|
|
130
|
+
*/
|
|
131
|
+
export function bitboardFromChess(state) {
|
|
132
|
+
const pieces = new Array(12).fill(0n);
|
|
133
|
+
const kings = [-1, -1];
|
|
134
|
+
state.board.forEach((piece, square) => {
|
|
135
|
+
if (!piece)
|
|
136
|
+
return;
|
|
137
|
+
const index = (piece.side === 'white' ? 0 : 6) + KIND_INDEX[piece.kind];
|
|
138
|
+
pieces[index] |= bit(square);
|
|
139
|
+
if (piece.kind === 'king')
|
|
140
|
+
kings[piece.side === 'white' ? 0 : 1] = square;
|
|
141
|
+
});
|
|
142
|
+
if (kings[0] === -1 || kings[1] === -1)
|
|
143
|
+
throw new Error('a position without both kings cannot go on bitboards');
|
|
144
|
+
return {
|
|
145
|
+
pieces,
|
|
146
|
+
turn: state.turn,
|
|
147
|
+
castling: (state.castling.whiteKingside ? 1 : 0) |
|
|
148
|
+
(state.castling.whiteQueenside ? 2 : 0) |
|
|
149
|
+
(state.castling.blackKingside ? 4 : 0) |
|
|
150
|
+
(state.castling.blackQueenside ? 8 : 0),
|
|
151
|
+
enPassant: state.enPassant,
|
|
152
|
+
halfmove: 0,
|
|
153
|
+
kings,
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* The standard opening array on bitboards, white to move with every right intact.
|
|
158
|
+
*
|
|
159
|
+
* @example
|
|
160
|
+
* ```ts
|
|
161
|
+
* import { bitboardMoves, startingBitboard } from '@datamoc/mw_games/board';
|
|
162
|
+
*
|
|
163
|
+
* console.log(bitboardMoves(startingBitboard()).length); // 20 - 16 pawn moves, 4 knight moves
|
|
164
|
+
* ```
|
|
165
|
+
*/
|
|
166
|
+
export function startingBitboard() {
|
|
167
|
+
return bitboardFromChess(startingChess());
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Every legal move for the side to play, in stable square order: pseudo-moves that leave
|
|
171
|
+
* their own king safe, each tried with `makeMove` and taken back with `unmakeMove`.
|
|
172
|
+
* Castling needs its rights, an empty passage and no check on the way over; en passant
|
|
173
|
+
* pins fall out of the make-and-test filter rather than special-casing.
|
|
174
|
+
*
|
|
175
|
+
* @example
|
|
176
|
+
* ```ts
|
|
177
|
+
* import { bitboardMoves, startingBitboard } from '@datamoc/mw_games/board';
|
|
178
|
+
*
|
|
179
|
+
* const moves = bitboardMoves(startingBitboard());
|
|
180
|
+
* console.log(moves.every((move) => move.from >= 0 && move.to < 64)); // true
|
|
181
|
+
* ```
|
|
182
|
+
*/
|
|
183
|
+
export function bitboardMoves(board) {
|
|
184
|
+
const white = board.turn === 'white';
|
|
185
|
+
const us = white ? 0 : 6;
|
|
186
|
+
const own = occupancyOf(board, us);
|
|
187
|
+
const enemy = occupancyOf(board, us === 0 ? 6 : 0);
|
|
188
|
+
const all = own | enemy;
|
|
189
|
+
const out = [];
|
|
190
|
+
const pseudo = [];
|
|
191
|
+
for (let from = 0; from < 64; from++) {
|
|
192
|
+
if (!(own & bit(from)))
|
|
193
|
+
continue;
|
|
194
|
+
let kind = -1;
|
|
195
|
+
for (let k = 0; k < 6; k++) {
|
|
196
|
+
if (board.pieces[us + k] & bit(from)) {
|
|
197
|
+
kind = k;
|
|
198
|
+
break;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
pseudo.length = 0;
|
|
202
|
+
pseudoMoves(board, from, kind, all, enemy, pseudo);
|
|
203
|
+
for (const move of pseudo) {
|
|
204
|
+
const undo = makeMove(board, move);
|
|
205
|
+
if (!isAttacked(board, board.kings[white ? 0 : 1], !white))
|
|
206
|
+
out.push({ ...move });
|
|
207
|
+
unmakeMove(board, move, undo);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
return out;
|
|
211
|
+
}
|
|
212
|
+
/** pseudo-moves for the piece on `from`, ignoring its own king; castling checks rights and passage */
|
|
213
|
+
function pseudoMoves(board, from, kind, all, enemy, out) {
|
|
214
|
+
const white = board.turn === 'white';
|
|
215
|
+
const file = from & 7;
|
|
216
|
+
const rank = from >> 3;
|
|
217
|
+
const push = (to, promotion) => {
|
|
218
|
+
out.push(promotion ? { from, to, promotion } : { from, to });
|
|
219
|
+
};
|
|
220
|
+
const slide = (steps) => {
|
|
221
|
+
for (const [df, dr] of steps) {
|
|
222
|
+
let f = file + df;
|
|
223
|
+
let r = rank + dr;
|
|
224
|
+
while (f >= 0 && f < 8 && r >= 0 && r < 8) {
|
|
225
|
+
const to = r * 8 + f;
|
|
226
|
+
const mask = bit(to);
|
|
227
|
+
if (!(all & mask))
|
|
228
|
+
push(to);
|
|
229
|
+
else {
|
|
230
|
+
if (enemy & mask)
|
|
231
|
+
push(to);
|
|
232
|
+
break;
|
|
233
|
+
}
|
|
234
|
+
f += df;
|
|
235
|
+
r += dr;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
};
|
|
239
|
+
switch (kind) {
|
|
240
|
+
case 0: {
|
|
241
|
+
const dir = white ? 8 : -8;
|
|
242
|
+
const home = white ? 1 : 6;
|
|
243
|
+
const last = white ? 7 : 0;
|
|
244
|
+
const one = from + dir;
|
|
245
|
+
if (one >= 0 && one < 64 && !(all & bit(one))) {
|
|
246
|
+
if (one >> 3 === last) {
|
|
247
|
+
for (const promotion of PROMOTION_ORDER)
|
|
248
|
+
push(one, promotion);
|
|
249
|
+
}
|
|
250
|
+
else {
|
|
251
|
+
push(one);
|
|
252
|
+
const two = from + 2 * dir;
|
|
253
|
+
if (rank === home && !(all & bit(two)))
|
|
254
|
+
push(two);
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
for (const df of [-1, 1]) {
|
|
258
|
+
const f = file + df;
|
|
259
|
+
if (f < 0 || f > 7)
|
|
260
|
+
continue;
|
|
261
|
+
const to = from + dir + df;
|
|
262
|
+
if (to < 0 || to >= 64)
|
|
263
|
+
continue;
|
|
264
|
+
const mask = bit(to);
|
|
265
|
+
if (enemy & mask) {
|
|
266
|
+
if (to >> 3 === last) {
|
|
267
|
+
for (const promotion of PROMOTION_ORDER)
|
|
268
|
+
push(to, promotion);
|
|
269
|
+
}
|
|
270
|
+
else
|
|
271
|
+
push(to);
|
|
272
|
+
}
|
|
273
|
+
else if (to === board.enPassant)
|
|
274
|
+
push(to);
|
|
275
|
+
}
|
|
276
|
+
break;
|
|
277
|
+
}
|
|
278
|
+
case 1: {
|
|
279
|
+
let targets = KNIGHT_TABLE[from] & ~occupancyOf(board, white ? 0 : 6);
|
|
280
|
+
while (targets) {
|
|
281
|
+
const single = targets & -targets;
|
|
282
|
+
push(bitIndex(single));
|
|
283
|
+
targets ^= single;
|
|
284
|
+
}
|
|
285
|
+
break;
|
|
286
|
+
}
|
|
287
|
+
case 2:
|
|
288
|
+
slide(DIAGONALS);
|
|
289
|
+
break;
|
|
290
|
+
case 3:
|
|
291
|
+
slide(STRAIGHTS);
|
|
292
|
+
break;
|
|
293
|
+
case 4:
|
|
294
|
+
slide(DIAGONALS);
|
|
295
|
+
slide(STRAIGHTS);
|
|
296
|
+
break;
|
|
297
|
+
case 5: {
|
|
298
|
+
let targets = KING_TABLE[from] & ~occupancyOf(board, white ? 0 : 6);
|
|
299
|
+
//never capture the other king: kings are never adjacent after a legal move
|
|
300
|
+
targets &= ~board.pieces[white ? 11 : 5];
|
|
301
|
+
while (targets) {
|
|
302
|
+
const single = targets & -targets;
|
|
303
|
+
push(bitIndex(single));
|
|
304
|
+
targets ^= single;
|
|
305
|
+
}
|
|
306
|
+
const home = white ? 0 : 56;
|
|
307
|
+
const rights = board.castling;
|
|
308
|
+
const kingside = white ? rights & 1 : rights & 4;
|
|
309
|
+
const queenside = white ? rights & 2 : rights & 8;
|
|
310
|
+
if (from === home + 4 && !isAttacked(board, from, !white)) {
|
|
311
|
+
if (kingside &&
|
|
312
|
+
!(all & bit(home + 5)) &&
|
|
313
|
+
!(all & bit(home + 6)) &&
|
|
314
|
+
!isAttacked(board, home + 5, !white) &&
|
|
315
|
+
!isAttacked(board, home + 6, !white)) {
|
|
316
|
+
push(home + 6);
|
|
317
|
+
}
|
|
318
|
+
if (queenside &&
|
|
319
|
+
!(all & bit(home + 3)) &&
|
|
320
|
+
!(all & bit(home + 2)) &&
|
|
321
|
+
!(all & bit(home + 1)) &&
|
|
322
|
+
!isAttacked(board, home + 3, !white) &&
|
|
323
|
+
!isAttacked(board, home + 2, !white)) {
|
|
324
|
+
push(home + 2);
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
break;
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
/**
|
|
332
|
+
* Plays a move, mutating the position, and returns what `unmakeMove` needs to take it
|
|
333
|
+
* back. Special moves are read off the position rather than flagged on the move: a pawn
|
|
334
|
+
* onto the en passant square captures the pawn behind it, a king stepping two squares
|
|
335
|
+
* swings its rook, a pawn stride of sixteen leaves a square behind it.
|
|
336
|
+
*
|
|
337
|
+
* @example
|
|
338
|
+
* ```ts
|
|
339
|
+
* import { bitboardMoves, makeMove, startingBitboard, unmakeMove } from '@datamoc/mw_games/board';
|
|
340
|
+
*
|
|
341
|
+
* const board = startingBitboard();
|
|
342
|
+
* const move = bitboardMoves(board)[0];
|
|
343
|
+
* const undo = makeMove(board, move);
|
|
344
|
+
* console.log(board.turn); // 'black' - the move is played
|
|
345
|
+
* unmakeMove(board, move, undo);
|
|
346
|
+
* ```
|
|
347
|
+
*/
|
|
348
|
+
export function makeMove(board, move) {
|
|
349
|
+
const white = board.turn === 'white';
|
|
350
|
+
const us = white ? 0 : 1;
|
|
351
|
+
const colorBase = us * 6;
|
|
352
|
+
const fromBit = bit(move.from);
|
|
353
|
+
const toBit = bit(move.to);
|
|
354
|
+
let kind = -1;
|
|
355
|
+
for (let k = 0; k < 6; k++) {
|
|
356
|
+
if (board.pieces[colorBase + k] & fromBit) {
|
|
357
|
+
kind = k;
|
|
358
|
+
break;
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
if (kind === -1)
|
|
362
|
+
throw new Error(`no piece on ${move.from} to move`);
|
|
363
|
+
const undo = {
|
|
364
|
+
captured: null,
|
|
365
|
+
castling: board.castling,
|
|
366
|
+
enPassant: board.enPassant,
|
|
367
|
+
halfmove: board.halfmove,
|
|
368
|
+
kingSquare: board.kings[us],
|
|
369
|
+
};
|
|
370
|
+
const themBase = (1 - us) * 6;
|
|
371
|
+
const dir = white ? 8 : -8;
|
|
372
|
+
//a pawn onto the en passant square takes the pawn behind it, not the empty square
|
|
373
|
+
let capturedSquare = move.to;
|
|
374
|
+
if (kind === 0 && move.to === board.enPassant)
|
|
375
|
+
capturedSquare = move.to - dir;
|
|
376
|
+
const capturedBit = bit(capturedSquare);
|
|
377
|
+
for (let k = 0; k < 6; k++) {
|
|
378
|
+
if (board.pieces[themBase + k] & capturedBit) {
|
|
379
|
+
undo.captured = { color: (1 - us), kind: k };
|
|
380
|
+
board.pieces[themBase + k] ^= capturedBit;
|
|
381
|
+
break;
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
//castling rights die with the king's first step, a rook's, or a captured rook's
|
|
385
|
+
const home = white ? 0 : 56;
|
|
386
|
+
const themHome = white ? 56 : 0;
|
|
387
|
+
if (kind === 5)
|
|
388
|
+
board.castling &= ~(rightBit(board.turn, true) | rightBit(board.turn, false));
|
|
389
|
+
if (kind === 3 && (move.from === home || move.from === home + 7)) {
|
|
390
|
+
board.castling &= ~rightBit(board.turn, move.from === home + 7);
|
|
391
|
+
}
|
|
392
|
+
if (undo.captured?.kind === 3 && (capturedSquare === themHome || capturedSquare === themHome + 7)) {
|
|
393
|
+
board.castling &= ~rightBit(white ? 'black' : 'white', capturedSquare === themHome + 7);
|
|
394
|
+
}
|
|
395
|
+
board.pieces[colorBase + kind] ^= fromBit;
|
|
396
|
+
if (move.promotion)
|
|
397
|
+
board.pieces[colorBase + KIND_INDEX[move.promotion]] |= toBit;
|
|
398
|
+
else
|
|
399
|
+
board.pieces[colorBase + kind] |= toBit;
|
|
400
|
+
if (kind === 5 && Math.abs(move.to - move.from) === 2) {
|
|
401
|
+
const rook = colorBase + 3;
|
|
402
|
+
if (move.to > move.from)
|
|
403
|
+
board.pieces[rook] ^= bit(home + 7) | bit(home + 5);
|
|
404
|
+
else
|
|
405
|
+
board.pieces[rook] ^= bit(home) | bit(home + 3);
|
|
406
|
+
}
|
|
407
|
+
board.enPassant = kind === 0 && Math.abs(move.to - move.from) === 16 ? (move.from + move.to) / 2 : null;
|
|
408
|
+
board.halfmove = kind === 0 || undo.captured ? 0 : board.halfmove + 1;
|
|
409
|
+
if (kind === 5)
|
|
410
|
+
board.kings[us] = move.to;
|
|
411
|
+
board.turn = white ? 'black' : 'white';
|
|
412
|
+
return undo;
|
|
413
|
+
}
|
|
414
|
+
/**
|
|
415
|
+
* Takes back exactly what `makeMove` played: the mover returns, the taken piece (or the
|
|
416
|
+
* en passant pawn behind the landing square) is restored, and rights, en passant
|
|
417
|
+
* square, halfmove clock and king square come back from the undo.
|
|
418
|
+
*
|
|
419
|
+
* @example
|
|
420
|
+
* ```ts
|
|
421
|
+
* import { bitboardMoves, makeMove, startingBitboard, unmakeMove } from '@datamoc/mw_games/board';
|
|
422
|
+
*
|
|
423
|
+
* const board = startingBitboard();
|
|
424
|
+
* const move = bitboardMoves(board)[0];
|
|
425
|
+
* const undo = makeMove(board, move);
|
|
426
|
+
* unmakeMove(board, move, undo);
|
|
427
|
+
* console.log(board.turn, bitboardMoves(board).length); // 'white' 20 - taken back whole
|
|
428
|
+
* ```
|
|
429
|
+
*/
|
|
430
|
+
export function unmakeMove(board, move, undo) {
|
|
431
|
+
board.turn = board.turn === 'white' ? 'black' : 'white';
|
|
432
|
+
const white = board.turn === 'white';
|
|
433
|
+
const us = white ? 0 : 1;
|
|
434
|
+
const colorBase = us * 6;
|
|
435
|
+
const toBit = bit(move.to);
|
|
436
|
+
//a promotion leaves a pawn to restore, anything else the piece standing on `to`
|
|
437
|
+
const kind = move.promotion
|
|
438
|
+
? 0
|
|
439
|
+
: (() => {
|
|
440
|
+
for (let k = 0; k < 6; k++) {
|
|
441
|
+
if (board.pieces[colorBase + k] & toBit)
|
|
442
|
+
return k;
|
|
443
|
+
}
|
|
444
|
+
throw new Error(`nothing on ${move.to} to take back`);
|
|
445
|
+
})();
|
|
446
|
+
if (move.promotion)
|
|
447
|
+
board.pieces[colorBase + KIND_INDEX[move.promotion]] ^= toBit;
|
|
448
|
+
else
|
|
449
|
+
board.pieces[colorBase + kind] ^= toBit;
|
|
450
|
+
board.pieces[colorBase + kind] |= bit(move.from);
|
|
451
|
+
if (kind === 5 && Math.abs(move.to - move.from) === 2) {
|
|
452
|
+
const home = white ? 0 : 56;
|
|
453
|
+
const rook = colorBase + 3;
|
|
454
|
+
if (move.to > move.from)
|
|
455
|
+
board.pieces[rook] ^= bit(home + 7) | bit(home + 5);
|
|
456
|
+
else
|
|
457
|
+
board.pieces[rook] ^= bit(home) | bit(home + 3);
|
|
458
|
+
}
|
|
459
|
+
if (undo.captured) {
|
|
460
|
+
const dir = white ? 8 : -8;
|
|
461
|
+
const square = kind === 0 && move.to === undo.enPassant ? move.to - dir : move.to;
|
|
462
|
+
board.pieces[(1 - us) * 6 + undo.captured.kind] |= bit(square);
|
|
463
|
+
}
|
|
464
|
+
board.castling = undo.castling;
|
|
465
|
+
board.enPassant = undo.enPassant;
|
|
466
|
+
board.halfmove = undo.halfmove;
|
|
467
|
+
board.kings[us] = undo.kingSquare;
|
|
468
|
+
}
|
|
469
|
+
/**
|
|
470
|
+
* Move-generation node count: 1 at depth 0, else the sum over every legal move. The
|
|
471
|
+
* position is played and taken back as it goes, so it reads identical afterwards.
|
|
472
|
+
* Counts match the published perft numbers, which is the whole point: a wrong move
|
|
473
|
+
* generator cannot hide from them.
|
|
474
|
+
*
|
|
475
|
+
* @example
|
|
476
|
+
* ```ts
|
|
477
|
+
* import { perft, startingBitboard } from '@datamoc/mw_games/board';
|
|
478
|
+
*
|
|
479
|
+
* console.log(perft(startingBitboard(), 2)); // 400 - the opening's two-ply count
|
|
480
|
+
* ```
|
|
481
|
+
*/
|
|
482
|
+
export function perft(board, depth) {
|
|
483
|
+
if (!Number.isInteger(depth) || depth < 0)
|
|
484
|
+
throw new RangeError('perft depth must be a non-negative integer');
|
|
485
|
+
if (depth === 0)
|
|
486
|
+
return 1;
|
|
487
|
+
let nodes = 0;
|
|
488
|
+
for (const move of bitboardMoves(board)) {
|
|
489
|
+
const undo = makeMove(board, move);
|
|
490
|
+
nodes += perft(board, depth - 1);
|
|
491
|
+
unmakeMove(board, move, undo);
|
|
492
|
+
}
|
|
493
|
+
return nodes;
|
|
494
|
+
}
|
|
495
|
+
//# sourceMappingURL=bitboard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bitboard.js","sourceRoot":"","sources":["../../src/board/bitboard.ts"],"names":[],"mappings":"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"}
|
package/dist/board/chess.d.ts
CHANGED
|
@@ -61,6 +61,22 @@ export declare function sq(name: string): ChessSquare;
|
|
|
61
61
|
* ```
|
|
62
62
|
*/
|
|
63
63
|
export declare function squareName(sq: ChessSquare): string;
|
|
64
|
+
/**
|
|
65
|
+
* The position half of FEN: placement, side to move, castling rights and en passant
|
|
66
|
+
* square, without either move clock. Two positions share a key exactly when the same
|
|
67
|
+
* moves are legal from both, which is what makes it the lookup key for an opening
|
|
68
|
+
* book (`board/openings.ts` builds and probes keys with this function on both sides,
|
|
69
|
+
* so the en passant square is taken as stored rather than re-derived).
|
|
70
|
+
*
|
|
71
|
+
* @example
|
|
72
|
+
* ```ts
|
|
73
|
+
* import { positionKey, startingChess } from '@datamoc/mw_games/board';
|
|
74
|
+
*
|
|
75
|
+
* console.log(positionKey(startingChess()));
|
|
76
|
+
* // 'rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq -'
|
|
77
|
+
* ```
|
|
78
|
+
*/
|
|
79
|
+
export declare function positionKey(state: ChessState): string;
|
|
64
80
|
/**
|
|
65
81
|
* Reads a position in Forsyth-Edwards Notation - the shape puzzles come in.
|
|
66
82
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chess.d.ts","sourceRoot":"","sources":["../../src/board/chess.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,MAAM,MAAM,SAAS,GAAG,OAAO,GAAG,OAAO,CAAC;AAC1C,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,QAAQ,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,CAAC;AAEjF,MAAM,WAAW,UAAU;IAC1B,IAAI,EAAE,SAAS,CAAC;IAChB,IAAI,EAAE,SAAS,CAAC;CAChB;AAED,0DAA0D;AAC1D,MAAM,MAAM,WAAW,GAAG,MAAM,CAAC;AAEjC,MAAM,MAAM,aAAa,GAAG,QAAQ,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,CAAC;AAEnE,MAAM,WAAW,SAAS;IACzB,IAAI,EAAE,WAAW,CAAC;IAClB,EAAE,EAAE,WAAW,CAAC;IAChB,SAAS,CAAC,EAAE,aAAa,CAAC;CAC1B;AAED,MAAM,WAAW,aAAa;IAC7B,aAAa,EAAE,OAAO,CAAC;IACvB,cAAc,EAAE,OAAO,CAAC;IACxB,aAAa,EAAE,OAAO,CAAC;IACvB,cAAc,EAAE,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,UAAU;IAC1B,KAAK,EAAE,KAAK,CAAC,UAAU,GAAG,IAAI,CAAC,CAAC;IAChC,IAAI,EAAE,SAAS,CAAC;IAChB,QAAQ,EAAE,aAAa,CAAC;IACxB,uEAAuE;IACvE,SAAS,EAAE,WAAW,GAAG,IAAI,CAAC;CAC9B;AAED,MAAM,MAAM,WAAW,GAAG,SAAS,GAAG,YAAY,GAAG,YAAY,GAAG,WAAW,CAAC;AAEhF;;;;;;;;;;;GAWG;AACH,wBAAgB,EAAE,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,CAO5C;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,UAAU,CAAC,EAAE,EAAE,WAAW,GAAG,MAAM,CAElD;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,CAqDhD;AAkBD;;;;;;;;;;;GAWG;AACH,wBAAgB,aAAa,IAAI,UAAU,CAe1C;AAED,mEAAmE;AACnE;;;;;;;;;;;;GAYG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,UAAU,GAAG,UAAU,CAOxD;AA6FD;;;;;;;GAOG;AACH,wBAAgB,OAAO,CAAC,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,SAAS,GAAG,OAAO,CAEnE;AA+LD;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,UAAU,GAAG,SAAS,EAAE,CAYzD;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,SAAS,GAAG,IAAI,CAelE;AAED;;;;;;;;GAQG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,UAAU,GAAG,WAAW,CAIzD"}
|
|
1
|
+
{"version":3,"file":"chess.d.ts","sourceRoot":"","sources":["../../src/board/chess.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,MAAM,MAAM,SAAS,GAAG,OAAO,GAAG,OAAO,CAAC;AAC1C,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,QAAQ,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,CAAC;AAEjF,MAAM,WAAW,UAAU;IAC1B,IAAI,EAAE,SAAS,CAAC;IAChB,IAAI,EAAE,SAAS,CAAC;CAChB;AAED,0DAA0D;AAC1D,MAAM,MAAM,WAAW,GAAG,MAAM,CAAC;AAEjC,MAAM,MAAM,aAAa,GAAG,QAAQ,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,CAAC;AAEnE,MAAM,WAAW,SAAS;IACzB,IAAI,EAAE,WAAW,CAAC;IAClB,EAAE,EAAE,WAAW,CAAC;IAChB,SAAS,CAAC,EAAE,aAAa,CAAC;CAC1B;AAED,MAAM,WAAW,aAAa;IAC7B,aAAa,EAAE,OAAO,CAAC;IACvB,cAAc,EAAE,OAAO,CAAC;IACxB,aAAa,EAAE,OAAO,CAAC;IACvB,cAAc,EAAE,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,UAAU;IAC1B,KAAK,EAAE,KAAK,CAAC,UAAU,GAAG,IAAI,CAAC,CAAC;IAChC,IAAI,EAAE,SAAS,CAAC;IAChB,QAAQ,EAAE,aAAa,CAAC;IACxB,uEAAuE;IACvE,SAAS,EAAE,WAAW,GAAG,IAAI,CAAC;CAC9B;AAED,MAAM,MAAM,WAAW,GAAG,SAAS,GAAG,YAAY,GAAG,YAAY,GAAG,WAAW,CAAC;AAEhF;;;;;;;;;;;GAWG;AACH,wBAAgB,EAAE,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,CAO5C;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,UAAU,CAAC,EAAE,EAAE,WAAW,GAAG,MAAM,CAElD;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CA2BrD;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,CAqDhD;AAkBD;;;;;;;;;;;GAWG;AACH,wBAAgB,aAAa,IAAI,UAAU,CAe1C;AAED,mEAAmE;AACnE;;;;;;;;;;;;GAYG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,UAAU,GAAG,UAAU,CAOxD;AA6FD;;;;;;;GAOG;AACH,wBAAgB,OAAO,CAAC,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,SAAS,GAAG,OAAO,CAEnE;AA+LD;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,UAAU,GAAG,SAAS,EAAE,CAYzD;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,SAAS,GAAG,IAAI,CAelE;AAED;;;;;;;;GAQG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,UAAU,GAAG,WAAW,CAIzD"}
|
package/dist/board/chess.js
CHANGED
|
@@ -42,6 +42,49 @@ export function sq(name) {
|
|
|
42
42
|
export function squareName(sq) {
|
|
43
43
|
return String.fromCharCode(97 + (sq & 7)) + String.fromCharCode(49 + (sq >> 3));
|
|
44
44
|
}
|
|
45
|
+
/**
|
|
46
|
+
* The position half of FEN: placement, side to move, castling rights and en passant
|
|
47
|
+
* square, without either move clock. Two positions share a key exactly when the same
|
|
48
|
+
* moves are legal from both, which is what makes it the lookup key for an opening
|
|
49
|
+
* book (`board/openings.ts` builds and probes keys with this function on both sides,
|
|
50
|
+
* so the en passant square is taken as stored rather than re-derived).
|
|
51
|
+
*
|
|
52
|
+
* @example
|
|
53
|
+
* ```ts
|
|
54
|
+
* import { positionKey, startingChess } from '@datamoc/mw_games/board';
|
|
55
|
+
*
|
|
56
|
+
* console.log(positionKey(startingChess()));
|
|
57
|
+
* // 'rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq -'
|
|
58
|
+
* ```
|
|
59
|
+
*/
|
|
60
|
+
export function positionKey(state) {
|
|
61
|
+
const rows = [];
|
|
62
|
+
for (let rank = 7; rank >= 0; rank--) {
|
|
63
|
+
let row = '';
|
|
64
|
+
let empty = 0;
|
|
65
|
+
for (let file = 0; file < 8; file++) {
|
|
66
|
+
const piece = state.board[rank * 8 + file];
|
|
67
|
+
if (!piece) {
|
|
68
|
+
empty++;
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
71
|
+
if (empty > 0) {
|
|
72
|
+
row += String(empty);
|
|
73
|
+
empty = 0;
|
|
74
|
+
}
|
|
75
|
+
const letter = { pawn: 'p', knight: 'n', bishop: 'b', rook: 'r', queen: 'q', king: 'k' }[piece.kind];
|
|
76
|
+
row += piece.side === 'white' ? letter.toUpperCase() : letter;
|
|
77
|
+
}
|
|
78
|
+
if (empty > 0)
|
|
79
|
+
row += String(empty);
|
|
80
|
+
rows.push(row);
|
|
81
|
+
}
|
|
82
|
+
const rights = (state.castling.whiteKingside ? 'K' : '') +
|
|
83
|
+
(state.castling.whiteQueenside ? 'Q' : '') +
|
|
84
|
+
(state.castling.blackKingside ? 'k' : '') +
|
|
85
|
+
(state.castling.blackQueenside ? 'q' : '');
|
|
86
|
+
return `${rows.join('/')} ${state.turn === 'white' ? 'w' : 'b'} ${rights || '-'} ${state.enPassant === null ? '-' : squareName(state.enPassant)}`;
|
|
87
|
+
}
|
|
45
88
|
/**
|
|
46
89
|
* Reads a position in Forsyth-Edwards Notation - the shape puzzles come in.
|
|
47
90
|
*
|