@maxr0ssi/chaos-chess 0.1.6 → 0.2.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 +36 -0
- package/README.md +44 -60
- package/dist/chaos-chess.css +1 -1
- package/dist/chaos-chess.js +1016 -683
- package/dist/chaos-chess.js.map +1 -1
- package/dist/index.d.ts +18 -1
- package/package.json +3 -2
package/dist/chaos-chess.js
CHANGED
|
@@ -1,161 +1,413 @@
|
|
|
1
|
-
import { jsx as
|
|
2
|
-
import
|
|
3
|
-
import { Chess as
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
1
|
+
import { jsx as l, jsxs as M } from "react/jsx-runtime";
|
|
2
|
+
import Et, { useState as v, useRef as y, useCallback as C, useEffect as O, useLayoutEffect as ot } from "react";
|
|
3
|
+
import { Chess as fe } from "chess.js";
|
|
4
|
+
const It = {
|
|
5
|
+
p: 1,
|
|
6
|
+
n: 3,
|
|
7
|
+
b: 3,
|
|
8
|
+
r: 5,
|
|
9
|
+
q: 9,
|
|
10
|
+
k: 0
|
|
11
|
+
}, ye = {
|
|
12
|
+
wk: "♚︎",
|
|
13
|
+
wq: "♛︎",
|
|
14
|
+
wr: "♜︎",
|
|
15
|
+
wb: "♝︎",
|
|
16
|
+
wn: "♞︎",
|
|
17
|
+
wp: "♟︎",
|
|
18
|
+
bk: "♔︎",
|
|
19
|
+
bq: "♕︎",
|
|
20
|
+
br: "♖︎",
|
|
21
|
+
bb: "♗︎",
|
|
22
|
+
bn: "♘︎",
|
|
23
|
+
bp: "♙︎"
|
|
24
|
+
}, Te = "abcdefgh";
|
|
25
|
+
function K(t) {
|
|
26
|
+
const e = t.trim().split(/\s+/);
|
|
27
|
+
return {
|
|
28
|
+
position: e[0],
|
|
29
|
+
activeColor: e[1] ?? "w",
|
|
30
|
+
castling: e[2] ?? "-",
|
|
31
|
+
enPassant: e[3] ?? "-",
|
|
32
|
+
halfmove: e[4] ?? "0",
|
|
33
|
+
fullmove: e[5] ?? "1"
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
function z(t) {
|
|
37
|
+
const e = [], n = t.split("/");
|
|
38
|
+
for (const r of n) {
|
|
39
|
+
const s = [];
|
|
40
|
+
for (const i of r) {
|
|
41
|
+
const a = parseInt(i);
|
|
42
|
+
if (isNaN(a)) {
|
|
43
|
+
const o = i === i.toUpperCase() ? "w" : "b", c = i.toLowerCase();
|
|
44
|
+
s.push({ type: c, color: o });
|
|
45
|
+
} else
|
|
46
|
+
for (let o = 0; o < a; o++) s.push(null);
|
|
47
|
+
}
|
|
48
|
+
e.push(s);
|
|
49
|
+
}
|
|
50
|
+
return e;
|
|
51
|
+
}
|
|
52
|
+
function at(t) {
|
|
53
|
+
return t.map((e) => {
|
|
54
|
+
let n = "", r = 0;
|
|
55
|
+
for (const s of e)
|
|
56
|
+
if (s === null)
|
|
57
|
+
r++;
|
|
58
|
+
else {
|
|
59
|
+
r > 0 && (n += r, r = 0);
|
|
60
|
+
const i = s.color === "w" ? s.type.toUpperCase() : s.type;
|
|
61
|
+
n += i;
|
|
62
|
+
}
|
|
63
|
+
return r > 0 && (n += r), n;
|
|
64
|
+
}).join("/");
|
|
65
|
+
}
|
|
66
|
+
function qe(t) {
|
|
67
|
+
return `${t.position} ${t.activeColor} ${t.castling} ${t.enPassant} ${t.halfmove} ${t.fullmove}`;
|
|
68
|
+
}
|
|
69
|
+
function qt(t) {
|
|
70
|
+
const { position: e } = K(t), n = z(e);
|
|
71
|
+
let r = 0, s = 0;
|
|
72
|
+
for (const i of n)
|
|
73
|
+
for (const a of i)
|
|
74
|
+
if (a) {
|
|
75
|
+
const o = It[a.type];
|
|
76
|
+
a.color === "w" ? r += o : s += o;
|
|
77
|
+
}
|
|
78
|
+
return { white: r, black: s };
|
|
79
|
+
}
|
|
80
|
+
function Ft(t) {
|
|
81
|
+
const { position: e } = K(t), n = z(e), r = [];
|
|
82
|
+
for (let s = 0; s < 8; s++)
|
|
83
|
+
for (let i = 0; i < 8; i++)
|
|
84
|
+
n[s][i] === null && r.push(`${Te[i]}${8 - s}`);
|
|
85
|
+
return r;
|
|
86
|
+
}
|
|
87
|
+
function $t(t, e, n = !0) {
|
|
88
|
+
const { position: r } = K(t), s = z(r), i = [];
|
|
89
|
+
for (let a = 0; a < 8; a++)
|
|
90
|
+
for (let o = 0; o < 8; o++) {
|
|
91
|
+
const c = s[a][o];
|
|
92
|
+
if (c && c.color === e) {
|
|
93
|
+
if (n && c.type === "k") continue;
|
|
94
|
+
i.push(`${Te[o]}${8 - a}`);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
return i;
|
|
98
|
+
}
|
|
99
|
+
function Fe(t) {
|
|
100
|
+
const e = Te.indexOf(t[0]);
|
|
101
|
+
return [8 - parseInt(t[1]), e];
|
|
102
|
+
}
|
|
103
|
+
function At(t, e, n, r) {
|
|
104
|
+
const s = K(t), i = z(s.position), [a, o] = Fe(e);
|
|
105
|
+
return i[a][o] = { type: n, color: r }, s.position = at(i), Y(qe(s));
|
|
106
|
+
}
|
|
107
|
+
function Dt(t, e) {
|
|
108
|
+
const n = K(t), r = z(n.position), [s, i] = Fe(e);
|
|
109
|
+
return r[s][i] = null, n.position = at(r), Y(qe(n));
|
|
110
|
+
}
|
|
111
|
+
const Gt = {
|
|
112
|
+
K: ["e1", "h1", "w"],
|
|
113
|
+
Q: ["e1", "a1", "w"],
|
|
114
|
+
k: ["e8", "h8", "b"],
|
|
115
|
+
q: ["e8", "a8", "b"]
|
|
116
|
+
};
|
|
117
|
+
function le(t, e) {
|
|
118
|
+
const [n, r] = Fe(e);
|
|
119
|
+
return t[n]?.[r] ?? null;
|
|
120
|
+
}
|
|
121
|
+
function ct(t, e) {
|
|
122
|
+
return !t || t === "-" ? "-" : ["K", "Q", "k", "q"].filter((r) => {
|
|
123
|
+
if (!t.includes(r)) return !1;
|
|
124
|
+
const s = Gt[r], [i, a, o] = s, c = le(e, i), p = le(e, a);
|
|
125
|
+
return c?.type === "k" && c.color === o && p?.type === "r" && p.color === o;
|
|
126
|
+
}).join("") || "-";
|
|
127
|
+
}
|
|
128
|
+
function lt(t, e, n) {
|
|
129
|
+
if (!t || t === "-") return "-";
|
|
130
|
+
const r = t[0], s = parseInt(t[1]), i = e === "w" ? 6 : 3;
|
|
131
|
+
if (!Te.includes(r) || s !== i) return "-";
|
|
132
|
+
const a = e === "w" ? 5 : 4, o = e === "w" ? 7 : 2, c = le(n, `${r}${a}`), p = e === "w" ? "b" : "w";
|
|
133
|
+
return c?.type !== "p" || c.color !== p || le(n, t) !== null || le(n, `${r}${o}`) !== null ? "-" : t;
|
|
134
|
+
}
|
|
135
|
+
function Y(t) {
|
|
136
|
+
const e = K(t), n = z(e.position);
|
|
137
|
+
return e.castling = ct(e.castling, n), e.enPassant = lt(e.enPassant, e.activeColor, n), qe(e);
|
|
138
|
+
}
|
|
139
|
+
function ue(t) {
|
|
140
|
+
const e = t.findPiece({ type: "k", color: "w" }).length > 0, n = t.findPiece({ type: "k", color: "b" }).length > 0;
|
|
141
|
+
return !e || !n ? { isGameOver: !0, result: "king-captured", winner: e ? "w" : n ? "b" : null, inCheck: null } : t.isGameOver() ? t.isCheckmate() ? { isGameOver: !0, result: "checkmate", winner: t.turn() === "w" ? "b" : "w", inCheck: t.turn() } : t.isStalemate() ? { isGameOver: !0, result: "stalemate", winner: null, inCheck: null } : t.isInsufficientMaterial() ? { isGameOver: !0, result: "insufficient", winner: null, inCheck: null } : t.isThreefoldRepetition() ? { isGameOver: !0, result: "threefold", winner: null, inCheck: null } : t.isDrawByFiftyMoves() ? { isGameOver: !0, result: "fifty-move", winner: null, inCheck: null } : { isGameOver: !0, result: "draw", winner: null, inCheck: null } : { isGameOver: !1, result: null, winner: null, inCheck: t.inCheck() ? t.turn() : null };
|
|
142
|
+
}
|
|
143
|
+
function xt(t) {
|
|
144
|
+
if (t)
|
|
145
|
+
try {
|
|
146
|
+
return new fe(Y(t));
|
|
147
|
+
} catch {
|
|
148
|
+
}
|
|
149
|
+
return new fe();
|
|
150
|
+
}
|
|
151
|
+
function Ut(t) {
|
|
152
|
+
const [e] = v(() => xt(t)), n = y(e), [r, s] = v(() => e.fen()), [i, a] = v(() => e.turn()), [o, c] = v(null), [p, k] = v([]), [_, w] = v(() => ue(e)), [f, g] = v(null), [b, D] = v([]), [R, F] = v(null), [U, B] = v(null), [G, ne] = v(() => e.board()), m = C(() => {
|
|
153
|
+
c(null), k([]);
|
|
154
|
+
}, []), T = C(() => {
|
|
155
|
+
s(n.current.fen()), a(n.current.turn()), ne(n.current.board()), w(ue(n.current));
|
|
156
|
+
}, []), $ = C((d) => {
|
|
157
|
+
F({ from: d.from, to: d.to }), B({ captured: !!d.captured, check: d.san.includes("+") || d.san.includes("#") }), D((S) => [
|
|
158
|
+
...S,
|
|
159
|
+
{ san: d.san, fen: n.current.fen(), color: d.color }
|
|
160
|
+
]);
|
|
161
|
+
}, []), re = C((d) => {
|
|
162
|
+
const S = n.current, V = S.turn();
|
|
163
|
+
if (f || ue(S).isGameOver)
|
|
15
164
|
return;
|
|
16
|
-
if (
|
|
17
|
-
const
|
|
18
|
-
if (
|
|
19
|
-
|
|
165
|
+
if (o && p.includes(d)) {
|
|
166
|
+
const L = S.get(o);
|
|
167
|
+
if (L?.type === "p" && (L.color === "w" && d[1] === "8" || L.color === "b" && d[1] === "1")) {
|
|
168
|
+
g({ from: o, to: d }), m();
|
|
20
169
|
return;
|
|
21
170
|
}
|
|
22
171
|
try {
|
|
23
|
-
const
|
|
24
|
-
|
|
25
|
-
...P,
|
|
26
|
-
{ san: M.san, fen: m.fen(), color: M.color }
|
|
27
|
-
]));
|
|
172
|
+
const X = S.move({ from: o, to: d });
|
|
173
|
+
X && $(X);
|
|
28
174
|
} catch {
|
|
29
175
|
}
|
|
30
|
-
|
|
176
|
+
m(), T();
|
|
31
177
|
return;
|
|
32
178
|
}
|
|
33
|
-
const
|
|
34
|
-
if (
|
|
35
|
-
if (
|
|
36
|
-
|
|
179
|
+
const P = S.get(d);
|
|
180
|
+
if (P && P.color === V) {
|
|
181
|
+
if (d === o) {
|
|
182
|
+
m();
|
|
37
183
|
return;
|
|
38
184
|
}
|
|
39
|
-
c(
|
|
40
|
-
const
|
|
41
|
-
|
|
185
|
+
c(d);
|
|
186
|
+
const L = S.moves({ square: d, verbose: !0 });
|
|
187
|
+
k(L.map((X) => X.to));
|
|
42
188
|
return;
|
|
43
189
|
}
|
|
44
|
-
|
|
45
|
-
}, [
|
|
46
|
-
if (!
|
|
47
|
-
const
|
|
190
|
+
m();
|
|
191
|
+
}, [o, p, f, m, T, $]), I = C((d) => {
|
|
192
|
+
if (!f) return;
|
|
193
|
+
const S = n.current;
|
|
48
194
|
try {
|
|
49
|
-
const
|
|
50
|
-
from:
|
|
51
|
-
to:
|
|
52
|
-
promotion:
|
|
195
|
+
const V = S.move({
|
|
196
|
+
from: f.from,
|
|
197
|
+
to: f.to,
|
|
198
|
+
promotion: d
|
|
53
199
|
});
|
|
54
|
-
|
|
55
|
-
...H,
|
|
56
|
-
{ san: S.san, fen: m.fen(), color: S.color }
|
|
57
|
-
]));
|
|
200
|
+
V && $(V);
|
|
58
201
|
} catch {
|
|
59
202
|
}
|
|
60
|
-
|
|
61
|
-
}, [
|
|
62
|
-
const
|
|
203
|
+
g(null), m(), T();
|
|
204
|
+
}, [f, m, T, $]), de = C((d) => {
|
|
205
|
+
const S = n.current;
|
|
63
206
|
try {
|
|
64
|
-
|
|
207
|
+
S.load(Y(d)), m(), T();
|
|
65
208
|
} catch {
|
|
66
209
|
}
|
|
67
|
-
}, [
|
|
68
|
-
|
|
69
|
-
|
|
210
|
+
}, [m, T]), Ce = C((d, S) => {
|
|
211
|
+
const V = n.current;
|
|
212
|
+
if (S !== void 0 && V.fen() !== S) return !1;
|
|
213
|
+
let P;
|
|
214
|
+
try {
|
|
215
|
+
P = V.move(d);
|
|
216
|
+
} catch {
|
|
217
|
+
return !1;
|
|
218
|
+
}
|
|
219
|
+
return $(P), m(), T(), !0;
|
|
220
|
+
}, [$, m, T]), Me = C(() => {
|
|
221
|
+
n.current.reset(), m(), D([]), F(null), B(null), g(null), T();
|
|
222
|
+
}, [m, T]);
|
|
70
223
|
return {
|
|
71
|
-
fen:
|
|
72
|
-
turn:
|
|
73
|
-
selectedSquare:
|
|
74
|
-
legalMoves:
|
|
75
|
-
gameStatus:
|
|
76
|
-
promotionPending:
|
|
77
|
-
moveHistory:
|
|
78
|
-
lastMove:
|
|
79
|
-
lastMoveDetail:
|
|
80
|
-
board:
|
|
81
|
-
handleSquareClick:
|
|
82
|
-
handlePromotion:
|
|
83
|
-
applyFen:
|
|
84
|
-
|
|
224
|
+
fen: r,
|
|
225
|
+
turn: i,
|
|
226
|
+
selectedSquare: o,
|
|
227
|
+
legalMoves: p,
|
|
228
|
+
gameStatus: _,
|
|
229
|
+
promotionPending: f,
|
|
230
|
+
moveHistory: b,
|
|
231
|
+
lastMove: R,
|
|
232
|
+
lastMoveDetail: U,
|
|
233
|
+
board: G,
|
|
234
|
+
handleSquareClick: re,
|
|
235
|
+
handlePromotion: I,
|
|
236
|
+
applyFen: de,
|
|
237
|
+
applyMove: Ce,
|
|
238
|
+
handleRestart: Me
|
|
85
239
|
};
|
|
86
240
|
}
|
|
87
|
-
|
|
241
|
+
const Vt = 2e4, Wt = 8e3, ut = 3, Ht = 5e3, jt = 1e4, Ze = 2e3;
|
|
242
|
+
class ae extends Error {
|
|
243
|
+
constructor() {
|
|
244
|
+
super("Search cancelled"), this.name = "StockfishCancelledError";
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
class Ne extends Error {
|
|
248
|
+
constructor() {
|
|
249
|
+
super("Stockfish worker restarted"), this.name = "StockfishRestartedError";
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
class Ee extends Error {
|
|
253
|
+
constructor() {
|
|
254
|
+
super("Stockfish is unavailable"), this.name = "StockfishUnavailableError";
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
class Re extends Error {
|
|
258
|
+
constructor(e) {
|
|
259
|
+
super(`Stockfish timed out during ${e}`), this.name = "StockfishTimeoutError";
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
class Yt {
|
|
88
263
|
worker = null;
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
264
|
+
ready = null;
|
|
265
|
+
pending = null;
|
|
266
|
+
waiters = [];
|
|
267
|
+
/** True from `go` until its `bestmove`, including after `stop`. */
|
|
268
|
+
searching = !1;
|
|
93
269
|
searchId = 0;
|
|
270
|
+
destroyed = !1;
|
|
271
|
+
initFailures = 0;
|
|
272
|
+
hasStarted = !1;
|
|
94
273
|
workerPath;
|
|
95
274
|
constructor(e = "/stockfish/stockfish-18-lite-single.js") {
|
|
96
275
|
this.workerPath = e;
|
|
97
276
|
}
|
|
98
|
-
|
|
99
|
-
return
|
|
100
|
-
try {
|
|
101
|
-
this.worker = new Worker(this.workerPath);
|
|
102
|
-
const s = (o) => {
|
|
103
|
-
(typeof o.data == "string" ? o.data : "").includes("uciok") && (this.worker?.removeEventListener("message", s), e());
|
|
104
|
-
};
|
|
105
|
-
this.worker.addEventListener("message", s), this.worker.addEventListener("error", (o) => {
|
|
106
|
-
n(new Error(`Stockfish worker error: ${o.message}`));
|
|
107
|
-
}), this.worker.postMessage("uci");
|
|
108
|
-
} catch (s) {
|
|
109
|
-
n(s);
|
|
110
|
-
}
|
|
111
|
-
});
|
|
277
|
+
get isDestroyed() {
|
|
278
|
+
return this.destroyed;
|
|
112
279
|
}
|
|
113
|
-
/**
|
|
114
|
-
|
|
115
|
-
|
|
280
|
+
/** True after MAX_INIT_FAILURES failed starts in a row. */
|
|
281
|
+
get isUnavailable() {
|
|
282
|
+
return this.initFailures >= ut;
|
|
116
283
|
}
|
|
117
284
|
/**
|
|
118
|
-
*
|
|
119
|
-
*
|
|
120
|
-
*
|
|
285
|
+
* Start the worker and wait for `uciok`. Concurrent calls share one start.
|
|
286
|
+
* Rejects with StockfishUnavailableError once starting has failed
|
|
287
|
+
* MAX_INIT_FAILURES times in a row.
|
|
121
288
|
*/
|
|
122
|
-
|
|
123
|
-
return new
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
289
|
+
init(e) {
|
|
290
|
+
if (this.destroyed) return Promise.reject(new Error("Stockfish engine destroyed"));
|
|
291
|
+
if (this.isUnavailable) return Promise.reject(new Ee());
|
|
292
|
+
if (!this.ready) {
|
|
293
|
+
const n = e ?? (this.hasStarted ? Wt : Vt), r = this.spawn(n).then(
|
|
294
|
+
() => {
|
|
295
|
+
this.initFailures = 0, this.hasStarted = !0;
|
|
296
|
+
},
|
|
297
|
+
(s) => {
|
|
298
|
+
throw this.initFailures++, this.ready === r && (this.ready = null), this.isUnavailable ? new Ee() : s;
|
|
299
|
+
}
|
|
300
|
+
);
|
|
301
|
+
this.ready = r;
|
|
302
|
+
}
|
|
303
|
+
return this.ready;
|
|
304
|
+
}
|
|
305
|
+
async spawn(e) {
|
|
306
|
+
const n = new Worker(this.workerPath);
|
|
307
|
+
this.worker = n, this.searching = !1, n.addEventListener("message", (r) => this.handleMessage(n, r)), n.addEventListener("error", (r) => this.handleWorkerError(n, r)), n.postMessage("uci");
|
|
308
|
+
try {
|
|
309
|
+
await this.waitFor((r) => r.includes("uciok"), e, "init");
|
|
310
|
+
} catch (r) {
|
|
311
|
+
throw this.terminate(n), r;
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
handleMessage(e, n) {
|
|
315
|
+
if (e !== this.worker) return;
|
|
316
|
+
const r = typeof n.data == "string" ? n.data : "";
|
|
317
|
+
if (r.startsWith("bestmove")) {
|
|
318
|
+
this.searching = !1;
|
|
319
|
+
const s = this.pending;
|
|
320
|
+
if (s) {
|
|
321
|
+
this.pending = null, s.timer !== null && clearTimeout(s.timer);
|
|
322
|
+
const i = r.split(" ")[1];
|
|
323
|
+
s.resolve(i && i !== "(none)" ? i : null);
|
|
127
324
|
}
|
|
128
|
-
|
|
129
|
-
|
|
325
|
+
}
|
|
326
|
+
for (const s of [...this.waiters])
|
|
327
|
+
s.match(r) && (this.waiters = this.waiters.filter((i) => i !== s), s.resolve(r));
|
|
328
|
+
}
|
|
329
|
+
handleWorkerError(e, n) {
|
|
330
|
+
if (e !== this.worker) return;
|
|
331
|
+
const r = new Error(`Stockfish worker error: ${n.message}`);
|
|
332
|
+
console.warn("[ChaosChess] Stockfish worker error, restarting:", n.message), this.failPending(r), this.terminate(e, r);
|
|
333
|
+
}
|
|
334
|
+
/** Wait for a message from the current worker, with a timeout. */
|
|
335
|
+
waitFor(e, n, r) {
|
|
336
|
+
return new Promise((s, i) => {
|
|
337
|
+
const a = setTimeout(() => {
|
|
338
|
+
this.waiters = this.waiters.filter((c) => c !== o), i(new Re(r));
|
|
339
|
+
}, n), o = {
|
|
340
|
+
match: e,
|
|
341
|
+
resolve: (c) => {
|
|
342
|
+
clearTimeout(a), s(c);
|
|
343
|
+
},
|
|
344
|
+
// Called when the worker is terminated, so callers fail fast
|
|
345
|
+
reject: (c) => {
|
|
346
|
+
clearTimeout(a), i(c);
|
|
347
|
+
}
|
|
130
348
|
};
|
|
131
|
-
this.
|
|
349
|
+
this.waiters.push(o);
|
|
132
350
|
});
|
|
133
351
|
}
|
|
352
|
+
/** Terminate a worker. If it is the current one, the next search starts a new one. */
|
|
353
|
+
terminate(e, n = new Ne()) {
|
|
354
|
+
try {
|
|
355
|
+
e.terminate();
|
|
356
|
+
} catch {
|
|
357
|
+
}
|
|
358
|
+
if (e !== this.worker) return;
|
|
359
|
+
this.worker = null, this.ready = null, this.searching = !1;
|
|
360
|
+
const r = this.waiters;
|
|
361
|
+
this.waiters = [];
|
|
362
|
+
for (const s of r) s.reject(n);
|
|
363
|
+
}
|
|
364
|
+
/** Reject the in-flight search and clear its timer. */
|
|
365
|
+
failPending(e) {
|
|
366
|
+
const n = this.pending;
|
|
367
|
+
n && (this.pending = null, n.timer !== null && clearTimeout(n.timer), n.reject(e));
|
|
368
|
+
}
|
|
369
|
+
/** Cancel any in-flight search. Its bestmove is drained before the next search. */
|
|
370
|
+
cancelPending() {
|
|
371
|
+
this.failPending(new ae()), this.searching && this.stop();
|
|
372
|
+
}
|
|
373
|
+
/**
|
|
374
|
+
* Cancel whatever this engine is doing, including a search that is still
|
|
375
|
+
* waiting to start. The engine stays usable.
|
|
376
|
+
*/
|
|
377
|
+
cancel() {
|
|
378
|
+
this.searchId++, this.cancelPending();
|
|
379
|
+
}
|
|
134
380
|
/**
|
|
135
381
|
* Get the best move for a given FEN position at the specified depth.
|
|
136
|
-
* Returns a UCI move string like "e2e4"
|
|
137
|
-
*
|
|
382
|
+
* Returns a UCI move string like "e2e4", or null when Stockfish reports
|
|
383
|
+
* no move ("(none)").
|
|
384
|
+
*
|
|
385
|
+
* Calling this while a search is in-flight cancels the previous search,
|
|
386
|
+
* which rejects with StockfishCancelledError. A search that passes
|
|
387
|
+
* `timeoutMs` is stopped and resolves with the best move found so far. If
|
|
388
|
+
* the engine does not answer even then, the worker is replaced and the
|
|
389
|
+
* search rejects with StockfishTimeoutError.
|
|
138
390
|
*/
|
|
139
|
-
async getBestMove(e, n,
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
this.
|
|
391
|
+
async getBestMove(e, n, r = jt) {
|
|
392
|
+
const s = Number.isFinite(n) ? Math.min(20, Math.max(1, Math.round(n))) : 10, i = ++this.searchId;
|
|
393
|
+
this.cancelPending(), await this.init();
|
|
394
|
+
const a = this.worker;
|
|
395
|
+
if (!a) throw new Error("Stockfish not initialized");
|
|
396
|
+
if (i !== this.searchId) throw new ae();
|
|
397
|
+
try {
|
|
398
|
+
this.searching && await this.waitFor((o) => o.startsWith("bestmove"), Ze, "stop"), a.postMessage("isready"), await this.waitFor((o) => o === "readyok", Ht, "isready");
|
|
399
|
+
} catch (o) {
|
|
400
|
+
throw i !== this.searchId ? new ae() : (o instanceof Re && this.terminate(a), o);
|
|
401
|
+
}
|
|
402
|
+
if (i !== this.searchId) throw new ae();
|
|
403
|
+
if (a !== this.worker || this.searching) throw new Ne();
|
|
404
|
+
return new Promise((o, c) => {
|
|
405
|
+
const p = { resolve: o, reject: c, timer: null };
|
|
406
|
+
p.timer = setTimeout(() => {
|
|
407
|
+
this.pending === p && (a.postMessage("stop"), p.timer = setTimeout(() => {
|
|
408
|
+
this.pending === p && (this.failPending(new Re("search")), this.terminate(a));
|
|
409
|
+
}, Ze));
|
|
410
|
+
}, r), this.pending = p, this.searching = !0, a.postMessage("ucinewgame"), a.postMessage(`position fen ${Y(e)}`), a.postMessage(`go depth ${s}`);
|
|
159
411
|
});
|
|
160
412
|
}
|
|
161
413
|
/**
|
|
@@ -168,236 +420,205 @@ class tt {
|
|
|
168
420
|
* Terminate the worker.
|
|
169
421
|
*/
|
|
170
422
|
destroy() {
|
|
171
|
-
this.
|
|
423
|
+
this.destroyed = !0, this.cancel();
|
|
424
|
+
const e = this.worker;
|
|
425
|
+
e && (e.postMessage("quit"), this.terminate(e, new Error("Stockfish engine destroyed")));
|
|
172
426
|
}
|
|
173
427
|
}
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
428
|
+
const Kt = 300 * 1e3, ce = /* @__PURE__ */ new Map();
|
|
429
|
+
function ft(t) {
|
|
430
|
+
return t ?? "";
|
|
431
|
+
}
|
|
432
|
+
function zt(t) {
|
|
433
|
+
const e = ft(t), n = ce.get(e);
|
|
434
|
+
for (; n && n.length > 0; ) {
|
|
435
|
+
const r = n.pop();
|
|
436
|
+
if (clearTimeout(r.timer), !r.engine.isDestroyed && !r.engine.isUnavailable) return r.engine;
|
|
437
|
+
r.engine.destroy();
|
|
438
|
+
}
|
|
439
|
+
return new Yt(t);
|
|
440
|
+
}
|
|
441
|
+
function Xt(t, e) {
|
|
442
|
+
t.cancel();
|
|
443
|
+
const n = ft(e), r = ce.get(n) ?? [];
|
|
444
|
+
if (r.some((i) => i.engine === t)) return;
|
|
445
|
+
const s = {
|
|
446
|
+
engine: t,
|
|
447
|
+
timer: setTimeout(() => {
|
|
448
|
+
const i = ce.get(n);
|
|
449
|
+
i && ce.set(n, i.filter((a) => a !== s)), t.destroy();
|
|
450
|
+
}, Kt)
|
|
451
|
+
};
|
|
452
|
+
r.push(s), ce.set(n, r);
|
|
453
|
+
}
|
|
454
|
+
const Qt = 2e3, et = 45e3;
|
|
455
|
+
function Jt(t) {
|
|
456
|
+
const e = y(null), [n, r] = v("loading"), [s, i] = v(!1), a = y(0);
|
|
457
|
+
O(() => {
|
|
458
|
+
const k = zt(t);
|
|
459
|
+
e.current = k;
|
|
460
|
+
let _ = !1, w = null;
|
|
461
|
+
r("loading");
|
|
462
|
+
const f = (g) => {
|
|
463
|
+
k.init().then(() => {
|
|
464
|
+
_ || r("ready");
|
|
465
|
+
}).catch((b) => {
|
|
466
|
+
_ || (console.warn(`Stockfish failed to load (attempt ${g}/${ut}):`, b.message), k.isUnavailable ? r("failed") : w = setTimeout(() => f(g + 1), Qt));
|
|
467
|
+
});
|
|
182
468
|
};
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
469
|
+
return f(1), () => {
|
|
470
|
+
_ = !0, w && clearTimeout(w), Xt(k, t), e.current = null;
|
|
471
|
+
};
|
|
472
|
+
}, [t]);
|
|
473
|
+
const o = n === "ready", c = C(
|
|
474
|
+
async (k, _) => {
|
|
475
|
+
if (!e.current || !o) return null;
|
|
476
|
+
const w = ++a.current;
|
|
477
|
+
i(!0);
|
|
478
|
+
const f = setTimeout(() => {
|
|
479
|
+
a.current === w && (console.warn(`[ChaosChess] Safety timeout: clearing isThinking after ${et / 1e3}s`), i(!1));
|
|
480
|
+
}, et);
|
|
192
481
|
try {
|
|
193
|
-
return await e.current.getBestMove(
|
|
194
|
-
} catch (
|
|
195
|
-
|
|
482
|
+
return await e.current.getBestMove(k, _);
|
|
483
|
+
} catch (g) {
|
|
484
|
+
throw g instanceof Ee && r("failed"), g;
|
|
196
485
|
} finally {
|
|
197
|
-
clearTimeout(
|
|
486
|
+
clearTimeout(f), a.current === w && i(!1);
|
|
198
487
|
}
|
|
199
488
|
},
|
|
200
|
-
[
|
|
201
|
-
)
|
|
202
|
-
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
p: 1,
|
|
206
|
-
n: 3,
|
|
207
|
-
b: 3,
|
|
208
|
-
r: 5,
|
|
209
|
-
q: 9,
|
|
210
|
-
k: 0
|
|
211
|
-
}, ie = {
|
|
212
|
-
wk: "♚︎",
|
|
213
|
-
wq: "♛︎",
|
|
214
|
-
wr: "♜︎",
|
|
215
|
-
wb: "♝︎",
|
|
216
|
-
wn: "♞︎",
|
|
217
|
-
wp: "♟︎",
|
|
218
|
-
bk: "♔︎",
|
|
219
|
-
bq: "♕︎",
|
|
220
|
-
br: "♖︎",
|
|
221
|
-
bb: "♗︎",
|
|
222
|
-
bn: "♘︎",
|
|
223
|
-
bp: "♙︎"
|
|
224
|
-
}, fe = "abcdefgh";
|
|
225
|
-
function X(t) {
|
|
226
|
-
const e = t.split(" ");
|
|
227
|
-
return {
|
|
228
|
-
position: e[0],
|
|
229
|
-
activeColor: e[1],
|
|
230
|
-
castling: e[2],
|
|
231
|
-
enPassant: e[3],
|
|
232
|
-
halfmove: e[4],
|
|
233
|
-
fullmove: e[5]
|
|
234
|
-
};
|
|
235
|
-
}
|
|
236
|
-
function J(t) {
|
|
237
|
-
const e = [], n = t.split("/");
|
|
238
|
-
for (const s of n) {
|
|
239
|
-
const o = [];
|
|
240
|
-
for (const r of s) {
|
|
241
|
-
const c = parseInt(r);
|
|
242
|
-
if (isNaN(c)) {
|
|
243
|
-
const i = r === r.toUpperCase() ? "w" : "b", l = r.toLowerCase();
|
|
244
|
-
o.push({ type: l, color: i });
|
|
245
|
-
} else
|
|
246
|
-
for (let i = 0; i < c; i++) o.push(null);
|
|
247
|
-
}
|
|
248
|
-
e.push(o);
|
|
249
|
-
}
|
|
250
|
-
return e;
|
|
251
|
-
}
|
|
252
|
-
function Ne(t) {
|
|
253
|
-
return t.map((e) => {
|
|
254
|
-
let n = "", s = 0;
|
|
255
|
-
for (const o of e)
|
|
256
|
-
if (o === null)
|
|
257
|
-
s++;
|
|
258
|
-
else {
|
|
259
|
-
s > 0 && (n += s, s = 0);
|
|
260
|
-
const r = o.color === "w" ? o.type.toUpperCase() : o.type;
|
|
261
|
-
n += r;
|
|
262
|
-
}
|
|
263
|
-
return s > 0 && (n += s), n;
|
|
264
|
-
}).join("/");
|
|
265
|
-
}
|
|
266
|
-
function Re(t) {
|
|
267
|
-
return `${t.position} ${t.activeColor} ${t.castling} ${t.enPassant} ${t.halfmove} ${t.fullmove}`;
|
|
489
|
+
[o]
|
|
490
|
+
), p = C(() => {
|
|
491
|
+
e.current?.cancel();
|
|
492
|
+
}, []);
|
|
493
|
+
return { status: n, isReady: o, isThinking: s, getBestMove: c, cancel: p };
|
|
268
494
|
}
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
for (const r of n)
|
|
273
|
-
for (const c of r)
|
|
274
|
-
if (c) {
|
|
275
|
-
const i = st[c.type];
|
|
276
|
-
c.color === "w" ? s += i : o += i;
|
|
277
|
-
}
|
|
278
|
-
return { white: s, black: o };
|
|
279
|
-
}
|
|
280
|
-
function ot(t) {
|
|
281
|
-
const { position: e } = X(t), n = J(e), s = [];
|
|
282
|
-
for (let o = 0; o < 8; o++)
|
|
283
|
-
for (let r = 0; r < 8; r++)
|
|
284
|
-
n[o][r] === null && s.push(`${fe[r]}${8 - o}`);
|
|
285
|
-
return s;
|
|
286
|
-
}
|
|
287
|
-
function it(t, e, n = !0) {
|
|
288
|
-
const { position: s } = X(t), o = J(s), r = [];
|
|
289
|
-
for (let c = 0; c < 8; c++)
|
|
290
|
-
for (let i = 0; i < 8; i++) {
|
|
291
|
-
const l = o[c][i];
|
|
292
|
-
if (l && l.color === e) {
|
|
293
|
-
if (n && l.type === "k") continue;
|
|
294
|
-
r.push(`${fe[i]}${8 - c}`);
|
|
295
|
-
}
|
|
296
|
-
}
|
|
297
|
-
return r;
|
|
495
|
+
const Zt = ["p", "n", "b", "r", "q"], ht = 10, dt = 16, mt = 8;
|
|
496
|
+
function en(t, e) {
|
|
497
|
+
return t > e ? Math.random() < 0.7 ? "help_black" : "help_white" : e > t ? Math.random() < 0.7 ? "help_white" : "help_black" : Math.random() < 0.5 ? "help_white" : "help_black";
|
|
298
498
|
}
|
|
299
499
|
function Ie(t) {
|
|
300
|
-
|
|
301
|
-
return [8 - parseInt(t[1]), e];
|
|
302
|
-
}
|
|
303
|
-
function at(t, e, n, s) {
|
|
304
|
-
const o = X(t), r = J(o.position), [c, i] = Ie(e);
|
|
305
|
-
return r[c][i] = { type: n, color: s }, o.position = Ne(r), Re(o);
|
|
306
|
-
}
|
|
307
|
-
function ct(t, e) {
|
|
308
|
-
const n = X(t), s = J(n.position), [o, r] = Ie(e);
|
|
309
|
-
return s[o][r] = null, n.position = Ne(s), Re(n);
|
|
500
|
+
return t[Math.floor(Math.random() * t.length)];
|
|
310
501
|
}
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
502
|
+
function tn(t) {
|
|
503
|
+
const e = [...t];
|
|
504
|
+
for (let n = e.length - 1; n > 0; n--) {
|
|
505
|
+
const r = Math.floor(Math.random() * (n + 1));
|
|
506
|
+
[e[n], e[r]] = [e[r], e[n]];
|
|
507
|
+
}
|
|
508
|
+
return e;
|
|
314
509
|
}
|
|
315
|
-
function
|
|
316
|
-
|
|
510
|
+
function nn(t, e) {
|
|
511
|
+
const n = parseInt(t[1]);
|
|
512
|
+
return Ie(!e || n === 1 || n === 8 ? ["n", "b", "r", "q"] : Zt);
|
|
317
513
|
}
|
|
318
|
-
function
|
|
319
|
-
const
|
|
320
|
-
|
|
514
|
+
function rn(t, e) {
|
|
515
|
+
const n = z(K(t).position);
|
|
516
|
+
let r = 0, s = 0;
|
|
517
|
+
for (const i of n)
|
|
518
|
+
for (const a of i)
|
|
519
|
+
a && a.color === e && (r++, a.type === "p" && s++);
|
|
520
|
+
return { total: r, pawns: s };
|
|
321
521
|
}
|
|
322
|
-
function
|
|
522
|
+
function he(t) {
|
|
523
|
+
let e;
|
|
323
524
|
try {
|
|
324
|
-
|
|
525
|
+
e = new fe(t);
|
|
325
526
|
} catch {
|
|
326
527
|
return !1;
|
|
327
528
|
}
|
|
529
|
+
const { position: n, activeColor: r, castling: s, enPassant: i } = K(t), a = z(n), o = { w: 0, b: 0 }, c = { w: 0, b: 0 }, p = { w: [], b: [] };
|
|
530
|
+
for (let _ = 0; _ < 8; _++)
|
|
531
|
+
for (let w = 0; w < 8; w++) {
|
|
532
|
+
const f = a[_][w];
|
|
533
|
+
if (f) {
|
|
534
|
+
if (o[f.color]++, f.type === "p") {
|
|
535
|
+
if (_ === 0 || _ === 7) return !1;
|
|
536
|
+
c[f.color]++;
|
|
537
|
+
}
|
|
538
|
+
f.type === "k" && p[f.color].push(`${"abcdefgh"[w]}${8 - _}`);
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
for (const _ of ["w", "b"])
|
|
542
|
+
if (p[_].length !== 1 || o[_] > dt || c[_] > mt) return !1;
|
|
543
|
+
if (ct(s, a) !== s || lt(i, r, a) !== i) return !1;
|
|
544
|
+
const k = e.turn() === "w" ? "b" : "w";
|
|
545
|
+
return !e.isAttacked(p[k][0], e.turn());
|
|
328
546
|
}
|
|
329
|
-
function
|
|
330
|
-
const n =
|
|
547
|
+
function tt(t, e) {
|
|
548
|
+
const n = Ft(t);
|
|
331
549
|
if (n.length === 0) return null;
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
550
|
+
const { total: r, pawns: s } = rn(t, e);
|
|
551
|
+
if (r >= dt) return null;
|
|
552
|
+
const i = s < mt;
|
|
553
|
+
for (let a = 0; a < ht; a++) {
|
|
554
|
+
const o = Ie(n), c = nn(o, i), p = At(t, o, c, e);
|
|
555
|
+
if (he(p))
|
|
556
|
+
return { newFen: p, square: o, piece: c };
|
|
336
557
|
}
|
|
337
558
|
return null;
|
|
338
559
|
}
|
|
339
|
-
function
|
|
340
|
-
const n =
|
|
560
|
+
function nt(t, e) {
|
|
561
|
+
const n = $t(t, e, !0);
|
|
341
562
|
if (n.length === 0) return null;
|
|
342
|
-
for (
|
|
343
|
-
const
|
|
344
|
-
if (
|
|
345
|
-
return { newFen:
|
|
563
|
+
for (const r of tn(n).slice(0, ht)) {
|
|
564
|
+
const s = Dt(t, r);
|
|
565
|
+
if (he(s))
|
|
566
|
+
return { newFen: s, square: r };
|
|
346
567
|
}
|
|
347
568
|
return null;
|
|
348
569
|
}
|
|
349
|
-
function
|
|
350
|
-
const { white: e, black: n } =
|
|
351
|
-
if (
|
|
352
|
-
const
|
|
353
|
-
if (
|
|
570
|
+
function sn(t) {
|
|
571
|
+
const { white: e, black: n } = qt(t), r = en(e, n), s = Math.random() < 0.5 ? "add" : "remove", i = r === "help_white" ? "w" : "b", a = r === "help_white" ? "b" : "w";
|
|
572
|
+
if (s === "add") {
|
|
573
|
+
const o = tt(t, i);
|
|
574
|
+
if (o)
|
|
354
575
|
return {
|
|
355
|
-
newFen:
|
|
576
|
+
newFen: o.newFen,
|
|
356
577
|
action: {
|
|
357
578
|
type: "add",
|
|
358
|
-
target:
|
|
359
|
-
square:
|
|
360
|
-
piece:
|
|
361
|
-
color:
|
|
579
|
+
target: r,
|
|
580
|
+
square: o.square,
|
|
581
|
+
piece: o.piece,
|
|
582
|
+
color: i,
|
|
362
583
|
whiteMaterial: e,
|
|
363
584
|
blackMaterial: n
|
|
364
585
|
}
|
|
365
586
|
};
|
|
366
|
-
const
|
|
367
|
-
if (
|
|
587
|
+
const c = nt(t, a);
|
|
588
|
+
if (c)
|
|
368
589
|
return {
|
|
369
|
-
newFen:
|
|
590
|
+
newFen: c.newFen,
|
|
370
591
|
action: {
|
|
371
592
|
type: "remove",
|
|
372
|
-
target:
|
|
373
|
-
square:
|
|
593
|
+
target: r,
|
|
594
|
+
square: c.square,
|
|
374
595
|
whiteMaterial: e,
|
|
375
596
|
blackMaterial: n
|
|
376
597
|
}
|
|
377
598
|
};
|
|
378
599
|
} else {
|
|
379
|
-
const
|
|
380
|
-
if (
|
|
600
|
+
const o = nt(t, a);
|
|
601
|
+
if (o)
|
|
381
602
|
return {
|
|
382
|
-
newFen:
|
|
603
|
+
newFen: o.newFen,
|
|
383
604
|
action: {
|
|
384
605
|
type: "remove",
|
|
385
|
-
target:
|
|
386
|
-
square:
|
|
606
|
+
target: r,
|
|
607
|
+
square: o.square,
|
|
387
608
|
whiteMaterial: e,
|
|
388
609
|
blackMaterial: n
|
|
389
610
|
}
|
|
390
611
|
};
|
|
391
|
-
const
|
|
392
|
-
if (
|
|
612
|
+
const c = tt(t, i);
|
|
613
|
+
if (c)
|
|
393
614
|
return {
|
|
394
|
-
newFen:
|
|
615
|
+
newFen: c.newFen,
|
|
395
616
|
action: {
|
|
396
617
|
type: "add",
|
|
397
|
-
target:
|
|
398
|
-
square:
|
|
399
|
-
piece:
|
|
400
|
-
color:
|
|
618
|
+
target: r,
|
|
619
|
+
square: c.square,
|
|
620
|
+
piece: c.piece,
|
|
621
|
+
color: i,
|
|
401
622
|
whiteMaterial: e,
|
|
402
623
|
blackMaterial: n
|
|
403
624
|
}
|
|
@@ -405,7 +626,7 @@ function ht(t) {
|
|
|
405
626
|
}
|
|
406
627
|
return null;
|
|
407
628
|
}
|
|
408
|
-
const
|
|
629
|
+
const on = [
|
|
409
630
|
[12, 20],
|
|
410
631
|
// level 1
|
|
411
632
|
[8, 15],
|
|
@@ -417,267 +638,289 @@ const mt = [
|
|
|
417
638
|
[1, 4]
|
|
418
639
|
// level 5
|
|
419
640
|
];
|
|
420
|
-
function
|
|
421
|
-
const e = Math.max(0, Math.min(4,
|
|
422
|
-
return (
|
|
641
|
+
function an(t = 3) {
|
|
642
|
+
const e = Number.isFinite(t) ? Math.round(t) : 3, n = Math.max(0, Math.min(4, e - 1)), [r, s] = on[n];
|
|
643
|
+
return (r + Math.random() * (s - r)) * 1e3;
|
|
644
|
+
}
|
|
645
|
+
const cn = 200, ln = 1e3;
|
|
646
|
+
function rt() {
|
|
647
|
+
return typeof document < "u" && document.visibilityState === "hidden";
|
|
423
648
|
}
|
|
424
|
-
function
|
|
649
|
+
function un({
|
|
425
650
|
fen: t,
|
|
426
651
|
isPaused: e,
|
|
427
652
|
stupidLevel: n,
|
|
428
|
-
onChaosAction:
|
|
653
|
+
onChaosAction: r,
|
|
654
|
+
resetKey: s = 0
|
|
429
655
|
}) {
|
|
430
|
-
const [
|
|
431
|
-
|
|
432
|
-
const
|
|
433
|
-
const
|
|
434
|
-
|
|
656
|
+
const [i, a] = v(0), [o, c] = v(0), [p, k] = v(null), [_, w] = v(null), f = y(t), g = y(e), b = y(n), D = y(r), R = y(0), F = y(0), U = y(!1), B = y(!1);
|
|
657
|
+
f.current = t, g.current = e, b.current = n, D.current = r;
|
|
658
|
+
const G = C(() => {
|
|
659
|
+
const m = an(b.current), T = Math.ceil(m / 1e3);
|
|
660
|
+
c(T), a(T), R.current = m;
|
|
435
661
|
}, []);
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
662
|
+
ot(() => {
|
|
663
|
+
e && (U.current = !0);
|
|
664
|
+
}, [e]), O(() => {
|
|
665
|
+
G();
|
|
666
|
+
}, [n, G]);
|
|
667
|
+
const ne = y(!0);
|
|
668
|
+
return O(() => {
|
|
669
|
+
if (ne.current) {
|
|
670
|
+
ne.current = !1;
|
|
671
|
+
return;
|
|
672
|
+
}
|
|
673
|
+
k(null), w(null), G();
|
|
674
|
+
}, [s, G]), O(() => {
|
|
675
|
+
B.current = rt();
|
|
676
|
+
const m = () => {
|
|
677
|
+
B.current = rt(), F.current = Date.now(), B.current && (U.current = !0);
|
|
678
|
+
};
|
|
679
|
+
return document.addEventListener("visibilitychange", m), () => document.removeEventListener("visibilitychange", m);
|
|
680
|
+
}, []), O(() => {
|
|
681
|
+
F.current = Date.now();
|
|
682
|
+
let m = null;
|
|
683
|
+
const T = setInterval(() => {
|
|
684
|
+
const $ = Date.now(), re = $ - F.current;
|
|
685
|
+
if (F.current = $, g.current || B.current) {
|
|
686
|
+
U.current = !0;
|
|
442
687
|
return;
|
|
443
688
|
}
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
piece: Pt,
|
|
472
|
-
pieceWhite: St,
|
|
473
|
-
pieceBlack: Mt
|
|
689
|
+
if (U.current) {
|
|
690
|
+
U.current = !1, R.current = Math.max(R.current, ln), a(Math.ceil(R.current / 1e3));
|
|
691
|
+
return;
|
|
692
|
+
}
|
|
693
|
+
if (R.current -= re, a(Math.max(0, Math.ceil(R.current / 1e3))), R.current > 0) return;
|
|
694
|
+
const I = sn(f.current);
|
|
695
|
+
I && D.current(I.newFen) !== !1 && (k(I.action), w(I.action.square), m && clearTimeout(m), m = setTimeout(() => w(null), 600)), G();
|
|
696
|
+
}, cn);
|
|
697
|
+
return () => {
|
|
698
|
+
clearInterval(T), m && clearTimeout(m);
|
|
699
|
+
};
|
|
700
|
+
}, [G]), { countdown: i, maxCountdown: o, lastAction: p, chaosSquare: _ };
|
|
701
|
+
}
|
|
702
|
+
const fn = "_square_1tsnw_1", hn = "_light_1tsnw_14", dn = "_dark_1tsnw_18", mn = "_selected_1tsnw_22", pn = "_legalMove_1tsnw_26", gn = "_legalCapture_1tsnw_39", vn = "_check_1tsnw_54", _n = "_lastMoveFrom_1tsnw_58", kn = "_lastMoveTo_1tsnw_62", wn = "_chaosFlash_1tsnw_66", yn = "_piece_1tsnw_70", bn = "_pieceWhite_1tsnw_78", Sn = "_pieceBlack_1tsnw_83", q = {
|
|
703
|
+
square: fn,
|
|
704
|
+
light: hn,
|
|
705
|
+
dark: dn,
|
|
706
|
+
selected: mn,
|
|
707
|
+
legalMove: pn,
|
|
708
|
+
legalCapture: gn,
|
|
709
|
+
check: vn,
|
|
710
|
+
lastMoveFrom: _n,
|
|
711
|
+
lastMoveTo: kn,
|
|
712
|
+
chaosFlash: wn,
|
|
713
|
+
piece: yn,
|
|
714
|
+
pieceWhite: bn,
|
|
715
|
+
pieceBlack: Sn
|
|
474
716
|
};
|
|
475
|
-
function
|
|
476
|
-
const
|
|
477
|
-
if (!
|
|
478
|
-
const
|
|
479
|
-
return /* @__PURE__ */
|
|
480
|
-
}
|
|
481
|
-
const
|
|
482
|
-
board:
|
|
483
|
-
rankLabel:
|
|
484
|
-
fileLabel:
|
|
485
|
-
boardLocked:
|
|
717
|
+
function pt({ type: t, color: e, className: n }) {
|
|
718
|
+
const r = `${e}${t}`, s = ye[r];
|
|
719
|
+
if (!s) return null;
|
|
720
|
+
const i = e === "w" ? q.pieceWhite : q.pieceBlack;
|
|
721
|
+
return /* @__PURE__ */ l("span", { className: `${n ?? ""} ${i}`, children: s });
|
|
722
|
+
}
|
|
723
|
+
const Tn = "_board_119uf_1", Cn = "_rankLabel_119uf_15", Mn = "_fileLabel_119uf_26", Ln = "_boardLocked_119uf_37", be = {
|
|
724
|
+
board: Tn,
|
|
725
|
+
rankLabel: Cn,
|
|
726
|
+
fileLabel: Mn,
|
|
727
|
+
boardLocked: Ln
|
|
486
728
|
};
|
|
487
|
-
function
|
|
729
|
+
function Pn({
|
|
488
730
|
square: t,
|
|
489
731
|
piece: e,
|
|
490
732
|
isLight: n,
|
|
491
|
-
isSelected:
|
|
492
|
-
isLegalMove:
|
|
493
|
-
isCheck:
|
|
494
|
-
isLastMoveFrom:
|
|
495
|
-
isLastMoveTo:
|
|
496
|
-
isChaosFlash:
|
|
497
|
-
rankLabel:
|
|
498
|
-
fileLabel:
|
|
733
|
+
isSelected: r,
|
|
734
|
+
isLegalMove: s,
|
|
735
|
+
isCheck: i,
|
|
736
|
+
isLastMoveFrom: a,
|
|
737
|
+
isLastMoveTo: o,
|
|
738
|
+
isChaosFlash: c,
|
|
739
|
+
rankLabel: p,
|
|
740
|
+
fileLabel: k,
|
|
499
741
|
onClick: _
|
|
500
742
|
}) {
|
|
501
|
-
const
|
|
502
|
-
|
|
503
|
-
n ?
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
!
|
|
508
|
-
!
|
|
509
|
-
|
|
743
|
+
const w = [
|
|
744
|
+
q.square,
|
|
745
|
+
n ? q.light : q.dark,
|
|
746
|
+
r && q.selected,
|
|
747
|
+
s && (e ? q.legalCapture : q.legalMove),
|
|
748
|
+
i && q.check,
|
|
749
|
+
!r && !i && a && q.lastMoveFrom,
|
|
750
|
+
!r && !i && o && q.lastMoveTo,
|
|
751
|
+
c && q.chaosFlash
|
|
510
752
|
].filter(Boolean).join(" ");
|
|
511
|
-
return /* @__PURE__ */
|
|
512
|
-
e && /* @__PURE__ */
|
|
513
|
-
|
|
753
|
+
return /* @__PURE__ */ M("div", { className: w, onClick: () => _(t), children: [
|
|
754
|
+
e && /* @__PURE__ */ l(
|
|
755
|
+
pt,
|
|
514
756
|
{
|
|
515
757
|
type: e.type,
|
|
516
758
|
color: e.color,
|
|
517
|
-
className:
|
|
759
|
+
className: q.piece
|
|
518
760
|
}
|
|
519
761
|
),
|
|
520
|
-
|
|
521
|
-
|
|
762
|
+
p != null && /* @__PURE__ */ l("span", { className: be.rankLabel, children: p }),
|
|
763
|
+
k != null && /* @__PURE__ */ l("span", { className: be.fileLabel, children: k })
|
|
522
764
|
] });
|
|
523
765
|
}
|
|
524
|
-
const
|
|
525
|
-
function
|
|
526
|
-
return `${
|
|
766
|
+
const gt = "abcdefgh";
|
|
767
|
+
function st(t, e) {
|
|
768
|
+
return `${gt[e]}${8 - t}`;
|
|
527
769
|
}
|
|
528
|
-
function
|
|
770
|
+
function Bn(t, e) {
|
|
529
771
|
return (t + e) % 2 === 0;
|
|
530
772
|
}
|
|
531
|
-
const
|
|
773
|
+
const On = Et.memo(function({
|
|
532
774
|
board: e,
|
|
533
775
|
selectedSquare: n,
|
|
534
|
-
legalMoves:
|
|
535
|
-
inCheck:
|
|
536
|
-
lastMove:
|
|
537
|
-
chaosSquare:
|
|
538
|
-
flipped:
|
|
539
|
-
locked:
|
|
540
|
-
onSquareClick:
|
|
776
|
+
legalMoves: r,
|
|
777
|
+
inCheck: s,
|
|
778
|
+
lastMove: i,
|
|
779
|
+
chaosSquare: a,
|
|
780
|
+
flipped: o,
|
|
781
|
+
locked: c,
|
|
782
|
+
onSquareClick: p
|
|
541
783
|
}) {
|
|
542
|
-
let
|
|
543
|
-
if (
|
|
544
|
-
for (let
|
|
545
|
-
for (let
|
|
546
|
-
const
|
|
547
|
-
|
|
784
|
+
let k = null;
|
|
785
|
+
if (s)
|
|
786
|
+
for (let f = 0; f < 8; f++)
|
|
787
|
+
for (let g = 0; g < 8; g++) {
|
|
788
|
+
const b = e[f][g];
|
|
789
|
+
b?.type === "k" && b.color === s && (k = st(f, g));
|
|
548
790
|
}
|
|
549
|
-
const _ =
|
|
550
|
-
return /* @__PURE__ */
|
|
551
|
-
(
|
|
552
|
-
const
|
|
553
|
-
return /* @__PURE__ */
|
|
554
|
-
|
|
791
|
+
const _ = o ? [7, 6, 5, 4, 3, 2, 1, 0] : [0, 1, 2, 3, 4, 5, 6, 7], w = o ? [7, 6, 5, 4, 3, 2, 1, 0] : [0, 1, 2, 3, 4, 5, 6, 7];
|
|
792
|
+
return /* @__PURE__ */ l("div", { className: `${be.board}${c ? ` ${be.boardLocked}` : ""}`, children: _.map(
|
|
793
|
+
(f) => w.map((g) => {
|
|
794
|
+
const b = st(f, g), D = e[f][g], R = _.indexOf(f), F = w.indexOf(g);
|
|
795
|
+
return /* @__PURE__ */ l(
|
|
796
|
+
Pn,
|
|
555
797
|
{
|
|
556
|
-
square:
|
|
557
|
-
piece:
|
|
558
|
-
isLight:
|
|
559
|
-
isSelected:
|
|
560
|
-
isLegalMove:
|
|
561
|
-
isCheck:
|
|
562
|
-
isLastMoveFrom:
|
|
563
|
-
isLastMoveTo:
|
|
564
|
-
isChaosFlash:
|
|
565
|
-
rankLabel:
|
|
566
|
-
fileLabel:
|
|
567
|
-
onClick:
|
|
798
|
+
square: b,
|
|
799
|
+
piece: D,
|
|
800
|
+
isLight: Bn(f, g),
|
|
801
|
+
isSelected: b === n,
|
|
802
|
+
isLegalMove: r.includes(b),
|
|
803
|
+
isCheck: b === k,
|
|
804
|
+
isLastMoveFrom: i?.from === b,
|
|
805
|
+
isLastMoveTo: i?.to === b,
|
|
806
|
+
isChaosFlash: a === b,
|
|
807
|
+
rankLabel: F === 0 ? 8 - f : void 0,
|
|
808
|
+
fileLabel: R === 7 ? gt[g] : void 0,
|
|
809
|
+
onClick: p
|
|
568
810
|
},
|
|
569
|
-
|
|
811
|
+
b
|
|
570
812
|
);
|
|
571
813
|
})
|
|
572
814
|
) });
|
|
573
|
-
}),
|
|
574
|
-
promotionOverlay:
|
|
575
|
-
promotionDialog:
|
|
576
|
-
promotionTitle:
|
|
577
|
-
promotionOptions:
|
|
578
|
-
promotionBtn:
|
|
579
|
-
gameOverOverlay:
|
|
580
|
-
gameOverBanner:
|
|
581
|
-
gameOverResult:
|
|
582
|
-
gameOverDetail:
|
|
583
|
-
restartBtn:
|
|
584
|
-
chaosBar:
|
|
585
|
-
chaosBarLabel:
|
|
586
|
-
chaosBarTrack:
|
|
587
|
-
chaosBarFill:
|
|
588
|
-
difficultySelector:
|
|
589
|
-
difficultyLabel:
|
|
590
|
-
difficultySlider:
|
|
591
|
-
difficultyValue:
|
|
592
|
-
sidePickerOverlay:
|
|
593
|
-
sidePickerCard:
|
|
594
|
-
sidePickerTitle:
|
|
595
|
-
sidePickerOptions:
|
|
596
|
-
sidePickerBtn:
|
|
597
|
-
sidePickerIcon:
|
|
598
|
-
sidePickerWhite:
|
|
599
|
-
sidePickerBlack:
|
|
600
|
-
sidePickerLabel:
|
|
601
|
-
sidePickerSettings:
|
|
602
|
-
stupidLevel:
|
|
603
|
-
stupidLevelHeader:
|
|
604
|
-
stupidLevelLabel:
|
|
605
|
-
stupidLevelValue:
|
|
606
|
-
stupidLevelSlider:
|
|
607
|
-
muteBtn:
|
|
608
|
-
muteBtnMuted:
|
|
609
|
-
chaosToast:
|
|
610
|
-
chaosToastFading:
|
|
611
|
-
},
|
|
815
|
+
}), Rn = "_promotionOverlay_lr711_2", Nn = "_promotionDialog_lr711_14", En = "_promotionTitle_lr711_27", In = "_promotionOptions_lr711_34", qn = "_promotionBtn_lr711_39", Fn = "_gameOverOverlay_lr711_61", $n = "_gameOverBanner_lr711_73", An = "_gameOverResult_lr711_86", Dn = "_gameOverDetail_lr711_95", Gn = "_restartBtn_lr711_102", xn = "_chaosBar_lr711_121", Un = "_chaosBarLabel_lr711_129", Vn = "_chaosBarTrack_lr711_138", Wn = "_chaosBarFill_lr711_146", Hn = "_difficultySelector_lr711_155", jn = "_difficultyLabel_lr711_162", Yn = "_difficultySlider_lr711_168", Kn = "_difficultyValue_lr711_199", zn = "_sidePickerOverlay_lr711_206", Xn = "_sidePickerCard_lr711_214", Qn = "_sidePickerTitle_lr711_227", Jn = "_sidePickerOptions_lr711_235", Zn = "_sidePickerBtn_lr711_240", er = "_sidePickerIcon_lr711_260", tr = "_sidePickerWhite_lr711_265", nr = "_sidePickerBlack_lr711_270", rr = "_sidePickerLabel_lr711_275", sr = "_sidePickerSettings_lr711_282", ir = "_stupidLevel_lr711_291", or = "_stupidLevelHeader_lr711_298", ar = "_stupidLevelLabel_lr711_304", cr = "_stupidLevelValue_lr711_312", lr = "_stupidLevelSlider_lr711_319", ur = "_muteBtn_lr711_351", fr = "_muteBtnMuted_lr711_376", hr = "_chaosToast_lr711_386", dr = "_chaosToastFading_lr711_406", u = {
|
|
816
|
+
promotionOverlay: Rn,
|
|
817
|
+
promotionDialog: Nn,
|
|
818
|
+
promotionTitle: En,
|
|
819
|
+
promotionOptions: In,
|
|
820
|
+
promotionBtn: qn,
|
|
821
|
+
gameOverOverlay: Fn,
|
|
822
|
+
gameOverBanner: $n,
|
|
823
|
+
gameOverResult: An,
|
|
824
|
+
gameOverDetail: Dn,
|
|
825
|
+
restartBtn: Gn,
|
|
826
|
+
chaosBar: xn,
|
|
827
|
+
chaosBarLabel: Un,
|
|
828
|
+
chaosBarTrack: Vn,
|
|
829
|
+
chaosBarFill: Wn,
|
|
830
|
+
difficultySelector: Hn,
|
|
831
|
+
difficultyLabel: jn,
|
|
832
|
+
difficultySlider: Yn,
|
|
833
|
+
difficultyValue: Kn,
|
|
834
|
+
sidePickerOverlay: zn,
|
|
835
|
+
sidePickerCard: Xn,
|
|
836
|
+
sidePickerTitle: Qn,
|
|
837
|
+
sidePickerOptions: Jn,
|
|
838
|
+
sidePickerBtn: Zn,
|
|
839
|
+
sidePickerIcon: er,
|
|
840
|
+
sidePickerWhite: tr,
|
|
841
|
+
sidePickerBlack: nr,
|
|
842
|
+
sidePickerLabel: rr,
|
|
843
|
+
sidePickerSettings: sr,
|
|
844
|
+
stupidLevel: ir,
|
|
845
|
+
stupidLevelHeader: or,
|
|
846
|
+
stupidLevelLabel: ar,
|
|
847
|
+
stupidLevelValue: cr,
|
|
848
|
+
stupidLevelSlider: lr,
|
|
849
|
+
muteBtn: ur,
|
|
850
|
+
muteBtnMuted: fr,
|
|
851
|
+
chaosToast: hr,
|
|
852
|
+
chaosToastFading: dr
|
|
853
|
+
}, mr = [
|
|
612
854
|
{ type: "q", label: "Queen" },
|
|
613
855
|
{ type: "r", label: "Rook" },
|
|
614
856
|
{ type: "b", label: "Bishop" },
|
|
615
857
|
{ type: "n", label: "Knight" }
|
|
616
858
|
];
|
|
617
|
-
function
|
|
618
|
-
return /* @__PURE__ */
|
|
619
|
-
/* @__PURE__ */
|
|
620
|
-
/* @__PURE__ */
|
|
859
|
+
function pr({ color: t, onSelect: e }) {
|
|
860
|
+
return /* @__PURE__ */ l("div", { className: u.promotionOverlay, children: /* @__PURE__ */ M("div", { className: u.promotionDialog, children: [
|
|
861
|
+
/* @__PURE__ */ l("h3", { className: u.promotionTitle, children: "Promote pawn" }),
|
|
862
|
+
/* @__PURE__ */ l("div", { className: u.promotionOptions, children: mr.map(({ type: n, label: r }) => /* @__PURE__ */ l(
|
|
621
863
|
"button",
|
|
622
864
|
{
|
|
865
|
+
type: "button",
|
|
623
866
|
className: u.promotionBtn,
|
|
624
867
|
onClick: () => e(n),
|
|
625
|
-
title:
|
|
626
|
-
children: /* @__PURE__ */
|
|
868
|
+
title: r,
|
|
869
|
+
children: /* @__PURE__ */ l(pt, { type: n, color: t })
|
|
627
870
|
},
|
|
628
871
|
n
|
|
629
872
|
)) })
|
|
630
873
|
] }) });
|
|
631
874
|
}
|
|
632
|
-
function
|
|
633
|
-
return t.result === "checkmate" ? t.winner === e ? { title: "You Win!", detail: "Checkmate" } : { title: "You Lose", detail: "Checkmate" } : t.result === "stalemate" ? { title: "Draw", detail: "Stalemate" } : t.result === "insufficient" ? { title: "Draw", detail: "Insufficient material" } : t.result === "threefold" ? { title: "Draw", detail: "Threefold repetition" } : { title: "Draw", detail: "Game over" };
|
|
875
|
+
function gr(t, e) {
|
|
876
|
+
return t.result === "checkmate" ? t.winner === e ? { title: "You Win!", detail: "Checkmate" } : { title: "You Lose", detail: "Checkmate" } : t.result === "stalemate" ? { title: "Draw", detail: "Stalemate" } : t.result === "insufficient" ? { title: "Draw", detail: "Insufficient material" } : t.result === "threefold" ? { title: "Draw", detail: "Threefold repetition" } : t.result === "fifty-move" ? { title: "Draw", detail: "Fifty-move rule" } : t.result === "king-captured" ? { title: t.winner === e ? "You Win!" : "You Lose", detail: "King captured" } : { title: "Draw", detail: "Game over" };
|
|
634
877
|
}
|
|
635
|
-
function
|
|
636
|
-
const { title:
|
|
637
|
-
return /* @__PURE__ */
|
|
638
|
-
/* @__PURE__ */
|
|
639
|
-
/* @__PURE__ */
|
|
640
|
-
/* @__PURE__ */
|
|
878
|
+
function vr({ status: t, humanColor: e, onRestart: n }) {
|
|
879
|
+
const { title: r, detail: s } = gr(t, e);
|
|
880
|
+
return /* @__PURE__ */ l("div", { className: u.gameOverOverlay, children: /* @__PURE__ */ M("div", { className: u.gameOverBanner, children: [
|
|
881
|
+
/* @__PURE__ */ l("h2", { className: u.gameOverResult, children: r }),
|
|
882
|
+
/* @__PURE__ */ l("p", { className: u.gameOverDetail, children: s }),
|
|
883
|
+
/* @__PURE__ */ l("button", { type: "button", className: u.restartBtn, onClick: n, children: "Play Again" })
|
|
641
884
|
] }) });
|
|
642
885
|
}
|
|
643
|
-
function
|
|
644
|
-
const n = e > 0 ? (e - t) / e * 100 : 0,
|
|
645
|
-
return /* @__PURE__ */
|
|
646
|
-
/* @__PURE__ */
|
|
647
|
-
/* @__PURE__ */
|
|
886
|
+
function _r({ countdown: t, maxCountdown: e }) {
|
|
887
|
+
const n = e > 0 ? (e - t) / e * 100 : 0, r = 1 - (t / e || 0);
|
|
888
|
+
return /* @__PURE__ */ M("div", { className: u.chaosBar, children: [
|
|
889
|
+
/* @__PURE__ */ l("span", { className: u.chaosBarLabel, children: "STUPIDITY" }),
|
|
890
|
+
/* @__PURE__ */ l("div", { className: u.chaosBarTrack, children: /* @__PURE__ */ l(
|
|
648
891
|
"div",
|
|
649
892
|
{
|
|
650
893
|
className: u.chaosBarFill,
|
|
651
894
|
style: {
|
|
652
895
|
width: `${n}%`,
|
|
653
|
-
"--glow":
|
|
896
|
+
"--glow": r
|
|
654
897
|
}
|
|
655
898
|
}
|
|
656
899
|
) })
|
|
657
900
|
] });
|
|
658
901
|
}
|
|
659
|
-
function
|
|
660
|
-
const [e, n] =
|
|
661
|
-
if (
|
|
902
|
+
function kr({ action: t }) {
|
|
903
|
+
const [e, n] = v(!1), [r, s] = v(!1), [i, a] = v(null), o = y(void 0);
|
|
904
|
+
if (O(() => {
|
|
662
905
|
if (t)
|
|
663
|
-
return
|
|
664
|
-
|
|
665
|
-
n(!1),
|
|
906
|
+
return o.current && clearTimeout(o.current), a(t), s(!1), n(!0), o.current = setTimeout(() => {
|
|
907
|
+
s(!0), o.current = setTimeout(() => {
|
|
908
|
+
n(!1), s(!1);
|
|
666
909
|
}, 400);
|
|
667
910
|
}, 1600), () => {
|
|
668
|
-
|
|
911
|
+
o.current && clearTimeout(o.current);
|
|
669
912
|
};
|
|
670
|
-
}, [t]), !e || !
|
|
671
|
-
const
|
|
672
|
-
return /* @__PURE__ */
|
|
913
|
+
}, [t]), !e || !i) return null;
|
|
914
|
+
const c = i.type === "add" && i.piece && i.color ? `A ${ye[`${i.color}${i.piece}`]} appeared on ${i.square}!` : `The piece on ${i.square} vanished!`;
|
|
915
|
+
return /* @__PURE__ */ l("div", { className: `${u.chaosToast} ${r ? u.chaosToastFading : ""}`, children: c });
|
|
673
916
|
}
|
|
674
|
-
function
|
|
675
|
-
return /* @__PURE__ */
|
|
676
|
-
/* @__PURE__ */
|
|
917
|
+
function vt({ depth: t, onChange: e }) {
|
|
918
|
+
return /* @__PURE__ */ M("div", { className: u.difficultySelector, children: [
|
|
919
|
+
/* @__PURE__ */ M("span", { className: u.difficultyLabel, children: [
|
|
677
920
|
"AI Depth: ",
|
|
678
|
-
/* @__PURE__ */
|
|
921
|
+
/* @__PURE__ */ l("span", { className: u.difficultyValue, children: t })
|
|
679
922
|
] }),
|
|
680
|
-
/* @__PURE__ */
|
|
923
|
+
/* @__PURE__ */ l(
|
|
681
924
|
"input",
|
|
682
925
|
{
|
|
683
926
|
className: u.difficultySlider,
|
|
@@ -690,14 +933,14 @@ function xe({ depth: t, onChange: e }) {
|
|
|
690
933
|
)
|
|
691
934
|
] });
|
|
692
935
|
}
|
|
693
|
-
const
|
|
694
|
-
function
|
|
695
|
-
return /* @__PURE__ */
|
|
696
|
-
/* @__PURE__ */
|
|
697
|
-
/* @__PURE__ */
|
|
698
|
-
/* @__PURE__ */
|
|
936
|
+
const wr = ["OFF", "CHILL", "MID", "STUPID", "CHAOS", "LOL"];
|
|
937
|
+
function _t({ level: t, onChange: e }) {
|
|
938
|
+
return /* @__PURE__ */ M("div", { className: u.stupidLevel, children: [
|
|
939
|
+
/* @__PURE__ */ M("div", { className: u.stupidLevelHeader, children: [
|
|
940
|
+
/* @__PURE__ */ l("span", { className: u.stupidLevelLabel, children: "STUPID" }),
|
|
941
|
+
/* @__PURE__ */ l("span", { className: u.stupidLevelValue, children: wr[t] })
|
|
699
942
|
] }),
|
|
700
|
-
/* @__PURE__ */
|
|
943
|
+
/* @__PURE__ */ l(
|
|
701
944
|
"input",
|
|
702
945
|
{
|
|
703
946
|
type: "range",
|
|
@@ -711,43 +954,46 @@ function Ge({ level: t, onChange: e }) {
|
|
|
711
954
|
)
|
|
712
955
|
] });
|
|
713
956
|
}
|
|
714
|
-
function
|
|
715
|
-
return /* @__PURE__ */
|
|
716
|
-
/* @__PURE__ */
|
|
717
|
-
/* @__PURE__ */
|
|
718
|
-
/* @__PURE__ */
|
|
957
|
+
function yr({ depth: t, onDepthChange: e, stupidLevel: n, onStupidLevelChange: r, onSelectSide: s }) {
|
|
958
|
+
return /* @__PURE__ */ l("div", { className: u.sidePickerOverlay, children: /* @__PURE__ */ M("div", { className: u.sidePickerCard, children: [
|
|
959
|
+
/* @__PURE__ */ l("h2", { className: u.sidePickerTitle, children: "Choose Your Side" }),
|
|
960
|
+
/* @__PURE__ */ M("div", { className: u.sidePickerOptions, children: [
|
|
961
|
+
/* @__PURE__ */ M(
|
|
719
962
|
"button",
|
|
720
963
|
{
|
|
964
|
+
type: "button",
|
|
721
965
|
className: u.sidePickerBtn,
|
|
722
|
-
onClick: () =>
|
|
966
|
+
onClick: () => s("w"),
|
|
723
967
|
children: [
|
|
724
|
-
/* @__PURE__ */
|
|
725
|
-
/* @__PURE__ */
|
|
968
|
+
/* @__PURE__ */ l("span", { className: `${u.sidePickerIcon} ${u.sidePickerWhite}`, children: ye.wk }),
|
|
969
|
+
/* @__PURE__ */ l("span", { className: u.sidePickerLabel, children: "White" })
|
|
726
970
|
]
|
|
727
971
|
}
|
|
728
972
|
),
|
|
729
|
-
/* @__PURE__ */
|
|
973
|
+
/* @__PURE__ */ M(
|
|
730
974
|
"button",
|
|
731
975
|
{
|
|
976
|
+
type: "button",
|
|
732
977
|
className: u.sidePickerBtn,
|
|
733
|
-
onClick: () =>
|
|
978
|
+
onClick: () => s("b"),
|
|
734
979
|
children: [
|
|
735
|
-
/* @__PURE__ */
|
|
736
|
-
/* @__PURE__ */
|
|
980
|
+
/* @__PURE__ */ l("span", { className: `${u.sidePickerIcon} ${u.sidePickerBlack}`, children: ye.bk }),
|
|
981
|
+
/* @__PURE__ */ l("span", { className: u.sidePickerLabel, children: "Black" })
|
|
737
982
|
]
|
|
738
983
|
}
|
|
739
984
|
)
|
|
740
985
|
] }),
|
|
741
|
-
/* @__PURE__ */
|
|
742
|
-
/* @__PURE__ */
|
|
743
|
-
/* @__PURE__ */
|
|
986
|
+
/* @__PURE__ */ M("div", { className: u.sidePickerSettings, children: [
|
|
987
|
+
/* @__PURE__ */ l(vt, { depth: t, onChange: e }),
|
|
988
|
+
/* @__PURE__ */ l(_t, { level: n, onChange: r })
|
|
744
989
|
] })
|
|
745
990
|
] }) });
|
|
746
991
|
}
|
|
747
|
-
function
|
|
748
|
-
return /* @__PURE__ */
|
|
992
|
+
function br({ muted: t, onToggle: e }) {
|
|
993
|
+
return /* @__PURE__ */ l(
|
|
749
994
|
"button",
|
|
750
995
|
{
|
|
996
|
+
type: "button",
|
|
751
997
|
className: `${u.muteBtn} ${t ? u.muteBtnMuted : ""}`,
|
|
752
998
|
onClick: e,
|
|
753
999
|
title: t ? "Unmute" : "Mute",
|
|
@@ -755,228 +1001,315 @@ function Mn({ muted: t, onToggle: e }) {
|
|
|
755
1001
|
}
|
|
756
1002
|
);
|
|
757
1003
|
}
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
muted
|
|
1004
|
+
let oe = null;
|
|
1005
|
+
class Sr {
|
|
1006
|
+
muted;
|
|
1007
|
+
constructor(e = !1) {
|
|
1008
|
+
this.muted = e;
|
|
1009
|
+
}
|
|
761
1010
|
getCtx() {
|
|
762
1011
|
if (this.muted) return null;
|
|
763
|
-
if (!
|
|
1012
|
+
if (!oe)
|
|
764
1013
|
try {
|
|
765
|
-
|
|
1014
|
+
oe = new AudioContext();
|
|
766
1015
|
} catch {
|
|
767
1016
|
return null;
|
|
768
1017
|
}
|
|
769
|
-
return
|
|
1018
|
+
return oe.state === "suspended" && oe.resume(), oe;
|
|
770
1019
|
}
|
|
771
1020
|
setMuted(e) {
|
|
772
1021
|
this.muted = e;
|
|
773
1022
|
}
|
|
1023
|
+
get isMuted() {
|
|
1024
|
+
return this.muted;
|
|
1025
|
+
}
|
|
774
1026
|
playMove() {
|
|
775
1027
|
const e = this.getCtx();
|
|
776
1028
|
if (!e) return;
|
|
777
|
-
const n = e.createOscillator(),
|
|
778
|
-
n.type = "sine", n.frequency.value = 200,
|
|
1029
|
+
const n = e.createOscillator(), r = e.createGain();
|
|
1030
|
+
n.type = "sine", n.frequency.value = 200, r.gain.setValueAtTime(0.15, e.currentTime), r.gain.exponentialRampToValueAtTime(1e-3, e.currentTime + 0.08), n.connect(r).connect(e.destination), n.start(), n.stop(e.currentTime + 0.08);
|
|
779
1031
|
}
|
|
780
1032
|
playCapture() {
|
|
781
1033
|
const e = this.getCtx();
|
|
782
1034
|
if (!e) return;
|
|
783
|
-
const n = e.sampleRate * 0.1,
|
|
784
|
-
for (let
|
|
785
|
-
|
|
786
|
-
const
|
|
787
|
-
|
|
788
|
-
const
|
|
789
|
-
|
|
790
|
-
const
|
|
791
|
-
|
|
1035
|
+
const n = e.sampleRate * 0.1, r = e.createBuffer(1, n, e.sampleRate), s = r.getChannelData(0);
|
|
1036
|
+
for (let c = 0; c < n; c++)
|
|
1037
|
+
s[c] = (Math.random() * 2 - 1) * Math.exp(-c / (e.sampleRate * 0.015));
|
|
1038
|
+
const i = e.createBufferSource();
|
|
1039
|
+
i.buffer = r;
|
|
1040
|
+
const a = e.createBiquadFilter();
|
|
1041
|
+
a.type = "bandpass", a.frequency.value = 3e3, a.Q.value = 2;
|
|
1042
|
+
const o = e.createGain();
|
|
1043
|
+
o.gain.setValueAtTime(0.35, e.currentTime), o.gain.exponentialRampToValueAtTime(1e-3, e.currentTime + 0.1), i.connect(a).connect(o).connect(e.destination), i.start(), i.stop(e.currentTime + 0.1);
|
|
792
1044
|
}
|
|
793
1045
|
playCheck() {
|
|
794
1046
|
const e = this.getCtx();
|
|
795
1047
|
if (!e) return;
|
|
796
|
-
const n = e.createOscillator(),
|
|
797
|
-
n.type = "triangle", n.frequency.value = 800,
|
|
1048
|
+
const n = e.createOscillator(), r = e.createGain();
|
|
1049
|
+
n.type = "triangle", n.frequency.value = 800, r.gain.setValueAtTime(0.18, e.currentTime), r.gain.exponentialRampToValueAtTime(1e-3, e.currentTime + 0.12), n.connect(r).connect(e.destination), n.start(), n.stop(e.currentTime + 0.12);
|
|
798
1050
|
}
|
|
799
1051
|
playChaos() {
|
|
800
1052
|
const e = this.getCtx();
|
|
801
1053
|
if (!e) return;
|
|
802
|
-
const n = e.createOscillator(),
|
|
803
|
-
n.type = "sine", n.frequency.setValueAtTime(520, e.currentTime), n.frequency.exponentialRampToValueAtTime(320, e.currentTime + 0.18),
|
|
1054
|
+
const n = e.createOscillator(), r = e.createGain();
|
|
1055
|
+
n.type = "sine", n.frequency.setValueAtTime(520, e.currentTime), n.frequency.exponentialRampToValueAtTime(320, e.currentTime + 0.18), r.gain.setValueAtTime(0.07, e.currentTime), r.gain.exponentialRampToValueAtTime(1e-3, e.currentTime + 0.18), n.connect(r).connect(e.destination), n.start(), n.stop(e.currentTime + 0.18);
|
|
804
1056
|
}
|
|
805
1057
|
playGameOver() {
|
|
806
1058
|
const e = this.getCtx();
|
|
807
1059
|
if (!e) return;
|
|
808
1060
|
const n = [261.63, 329.63, 392];
|
|
809
|
-
for (const
|
|
810
|
-
const
|
|
811
|
-
|
|
1061
|
+
for (const r of n) {
|
|
1062
|
+
const s = e.createOscillator(), i = e.createGain();
|
|
1063
|
+
s.type = "sine", s.frequency.value = r, i.gain.setValueAtTime(0.1, e.currentTime), i.gain.exponentialRampToValueAtTime(1e-3, e.currentTime + 0.4), s.connect(i).connect(e.destination), s.start(), s.stop(e.currentTime + 0.4);
|
|
812
1064
|
}
|
|
813
1065
|
}
|
|
814
1066
|
}
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
1067
|
+
function Se(t) {
|
|
1068
|
+
return typeof t == "number" && Number.isFinite(t);
|
|
1069
|
+
}
|
|
1070
|
+
function Tr(t) {
|
|
1071
|
+
return Se(t) ? Math.min(20, Math.max(1, Math.round(t))) : 10;
|
|
1072
|
+
}
|
|
1073
|
+
function Cr(t) {
|
|
1074
|
+
return Se(t) ? Math.min(5, Math.max(0, Math.round(t))) : 3;
|
|
1075
|
+
}
|
|
1076
|
+
function Mr(t) {
|
|
1077
|
+
if (!t || typeof t != "object") return null;
|
|
1078
|
+
const e = t;
|
|
1079
|
+
if (e.version !== 1 || e.phase !== "setup" && e.phase !== "playing" || e.humanColor !== "w" && e.humanColor !== "b" || !Se(e.depth) || !Se(e.stupidLevel) || typeof e.fen != "string") return null;
|
|
1080
|
+
let n;
|
|
1081
|
+
try {
|
|
1082
|
+
n = Y(e.fen);
|
|
1083
|
+
} catch {
|
|
1084
|
+
return null;
|
|
1085
|
+
}
|
|
1086
|
+
return he(n) ? {
|
|
1087
|
+
version: 1,
|
|
1088
|
+
phase: e.phase,
|
|
1089
|
+
fen: n,
|
|
1090
|
+
humanColor: e.humanColor,
|
|
1091
|
+
depth: Tr(e.depth),
|
|
1092
|
+
stupidLevel: Cr(e.stupidLevel),
|
|
1093
|
+
muted: e.muted === !0
|
|
1094
|
+
} : null;
|
|
1095
|
+
}
|
|
1096
|
+
const Lr = "_container_1lkfq_1", Pr = "_topBar_1lkfq_11", Br = "_topBarLeft_1lkfq_23", Or = "_topBarRight_1lkfq_29", Rr = "_newGameBtn_1lkfq_35", Nr = "_aiUnavailable_1lkfq_59", Er = "_statusText_1lkfq_65", Ir = "_thinking_1lkfq_71", qr = "_bottomBar_1lkfq_81", j = {
|
|
1097
|
+
container: Lr,
|
|
1098
|
+
topBar: Pr,
|
|
1099
|
+
topBarLeft: Br,
|
|
1100
|
+
topBarRight: Or,
|
|
1101
|
+
newGameBtn: Rr,
|
|
1102
|
+
aiUnavailable: Nr,
|
|
1103
|
+
statusText: Er,
|
|
1104
|
+
thinking: Ir,
|
|
1105
|
+
bottomBar: qr
|
|
1106
|
+
}, it = 2;
|
|
1107
|
+
function Dr(t) {
|
|
824
1108
|
const {
|
|
825
1109
|
defaultDepth: e = 10,
|
|
826
1110
|
defaultStupidLevel: n = 3,
|
|
827
|
-
defaultHumanColor:
|
|
828
|
-
defaultMuted:
|
|
829
|
-
depth:
|
|
830
|
-
onDepthChange:
|
|
831
|
-
stupidLevel:
|
|
832
|
-
onStupidLevelChange:
|
|
833
|
-
stockfishWorkerPath:
|
|
834
|
-
skipSetup:
|
|
1111
|
+
defaultHumanColor: r,
|
|
1112
|
+
defaultMuted: s = !1,
|
|
1113
|
+
depth: i,
|
|
1114
|
+
onDepthChange: a,
|
|
1115
|
+
stupidLevel: o,
|
|
1116
|
+
onStupidLevelChange: c,
|
|
1117
|
+
stockfishWorkerPath: p,
|
|
1118
|
+
skipSetup: k = !1,
|
|
835
1119
|
showControls: _ = !0,
|
|
836
|
-
showMuteButton:
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
1120
|
+
showMuteButton: w = !0,
|
|
1121
|
+
initialState: f,
|
|
1122
|
+
onStateChange: g,
|
|
1123
|
+
onGameOver: b,
|
|
1124
|
+
onMove: D,
|
|
1125
|
+
onChaosAction: R,
|
|
1126
|
+
onRestart: F,
|
|
1127
|
+
className: U
|
|
1128
|
+
} = t, [B] = v(() => {
|
|
1129
|
+
if (!f) return null;
|
|
1130
|
+
const h = Mr(f);
|
|
1131
|
+
return h || console.warn("[ChaosChess] Ignoring invalid initialState"), h;
|
|
1132
|
+
}), [G, ne] = v(B?.depth ?? e), m = i ?? G, T = a ?? ne, [$, re] = v(B?.stupidLevel ?? n), I = o ?? $, de = c ?? re, [Ce, Me] = v(
|
|
1133
|
+
B?.humanColor ?? r ?? "w"
|
|
1134
|
+
), d = Ce, [S, V] = v(B?.muted ?? s), [P] = v(() => new Sr(B?.muted ?? s)), [L, X] = v(
|
|
1135
|
+
B?.phase ?? (k || r ? "playing" : "setup")
|
|
1136
|
+
), [kt, wt] = v(0), {
|
|
1137
|
+
fen: N,
|
|
1138
|
+
turn: se,
|
|
1139
|
+
selectedSquare: yt,
|
|
1140
|
+
legalMoves: bt,
|
|
1141
|
+
gameStatus: E,
|
|
1142
|
+
promotionPending: $e,
|
|
1143
|
+
lastMove: St,
|
|
1144
|
+
lastMoveDetail: me,
|
|
1145
|
+
moveHistory: Q,
|
|
1146
|
+
board: Tt,
|
|
1147
|
+
handleSquareClick: Ae,
|
|
1148
|
+
handlePromotion: Ct,
|
|
1149
|
+
applyFen: De,
|
|
1150
|
+
applyMove: Ge,
|
|
1151
|
+
handleRestart: xe
|
|
1152
|
+
} = Ut(B?.fen), {
|
|
1153
|
+
status: Le,
|
|
1154
|
+
isReady: pe,
|
|
1155
|
+
isThinking: J,
|
|
1156
|
+
getBestMove: Ue,
|
|
1157
|
+
cancel: Ve
|
|
1158
|
+
} = Jt(p), ge = Le !== "failed", Z = se === d, ve = y(N), We = y(d), Pe = y(L);
|
|
1159
|
+
ot(() => {
|
|
1160
|
+
ve.current = N, We.current = d, Pe.current = L;
|
|
1161
|
+
}, [N, d, L]);
|
|
1162
|
+
const Be = y(0), He = I > 0, Mt = L !== "playing" || !He || !Z || J || !!$e || E.isGameOver, { countdown: Lt, maxCountdown: Pt, lastAction: ee, chaosSquare: Oe } = un({
|
|
1163
|
+
fen: N,
|
|
1164
|
+
isPaused: Mt,
|
|
1165
|
+
stupidLevel: Math.max(1, I),
|
|
1166
|
+
resetKey: kt,
|
|
1167
|
+
onChaosAction: C((h) => {
|
|
1168
|
+
const A = new fe(ve.current);
|
|
1169
|
+
if (A.turn() !== We.current || ue(A).isGameOver) return !1;
|
|
1170
|
+
const W = Y(h);
|
|
1171
|
+
return he(W) ? (De(W), !0) : !1;
|
|
1172
|
+
}, [De])
|
|
1173
|
+
}), je = y(ee);
|
|
1174
|
+
O(() => {
|
|
1175
|
+
ee && ee !== je.current && R?.(ee, N), je.current = ee;
|
|
1176
|
+
}, [ee, N, R]);
|
|
1177
|
+
const Ye = y(g);
|
|
1178
|
+
O(() => {
|
|
1179
|
+
Ye.current = g;
|
|
1180
|
+
}, [g]), O(() => {
|
|
1181
|
+
const h = {
|
|
1182
|
+
version: 1,
|
|
1183
|
+
phase: L,
|
|
1184
|
+
fen: N,
|
|
1185
|
+
humanColor: d,
|
|
1186
|
+
depth: m,
|
|
1187
|
+
stupidLevel: I,
|
|
1188
|
+
muted: S
|
|
1189
|
+
};
|
|
1190
|
+
Ye.current?.(h);
|
|
1191
|
+
}, [L, N, d, m, I, S]);
|
|
1192
|
+
const ie = y(null), _e = y({ fen: "", count: 0 }), ke = C((h, A) => Ge(
|
|
1193
|
+
{
|
|
1194
|
+
from: A.slice(0, 2),
|
|
1195
|
+
to: A.slice(2, 4),
|
|
1196
|
+
promotion: A.length > 4 ? A[4] : void 0
|
|
1197
|
+
},
|
|
1198
|
+
h
|
|
1199
|
+
), [Ge]), Ke = C((h, A) => {
|
|
1200
|
+
if (ve.current !== h || Pe.current !== "playing") return !0;
|
|
1201
|
+
const W = new fe(h);
|
|
1202
|
+
if (ue(W).isGameOver) return !1;
|
|
1203
|
+
const H = W.moves({ verbose: !0 });
|
|
1204
|
+
if (H.length === 0) return !1;
|
|
1205
|
+
const te = H[Math.floor(Math.random() * H.length)];
|
|
1206
|
+
return console.warn(`[ChaosChess] ${A}; playing random move ${te.lan}`), ke(h, te.lan);
|
|
1207
|
+
}, [ke]), we = C((h) => {
|
|
1208
|
+
const A = Be.current, W = () => Be.current !== A || Pe.current !== "playing", H = (x) => {
|
|
1209
|
+
W() || Ke(h, x) || (ie.current = h);
|
|
1210
|
+
};
|
|
1211
|
+
if (!he(Y(h))) {
|
|
1212
|
+
H("Position not supported by Stockfish");
|
|
1213
|
+
return;
|
|
897
1214
|
}
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
}, [de]);
|
|
902
|
-
const be = y(!1);
|
|
903
|
-
F(() => {
|
|
904
|
-
B.isGameOver && !be.current && (Y.playGameOver(), g?.(B)), be.current = B.isGameOver;
|
|
905
|
-
}, [B, g]);
|
|
906
|
-
const me = y(!1);
|
|
907
|
-
F(() => {
|
|
908
|
-
if (q !== "playing") {
|
|
909
|
-
me.current = !1;
|
|
1215
|
+
const te = _e.current.fen === h ? _e.current.count : 0;
|
|
1216
|
+
if (te >= it) {
|
|
1217
|
+
H("Stockfish keeps failing on this position");
|
|
910
1218
|
return;
|
|
911
1219
|
}
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
U.current = null, re(p);
|
|
918
|
-
}));
|
|
919
|
-
}, [q, P, E, B.isGameOver, K, A, m, ne, T, re]), F(() => {
|
|
920
|
-
if (q !== "playing" || E || A || B.isGameOver || !K || U.current === P) return;
|
|
921
|
-
const p = setTimeout(() => {
|
|
922
|
-
ne(P, T).then((j) => {
|
|
923
|
-
if (!j) {
|
|
924
|
-
U.current = P;
|
|
1220
|
+
const Nt = te > 0 ? Math.max(1, Math.floor(m / 2)) : m;
|
|
1221
|
+
Ue(h, Nt).then((x) => {
|
|
1222
|
+
if (!W() && ve.current === h) {
|
|
1223
|
+
if (!x) {
|
|
1224
|
+
H("Stockfish returned no move");
|
|
925
1225
|
return;
|
|
926
1226
|
}
|
|
927
|
-
|
|
928
|
-
}
|
|
929
|
-
}
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
(
|
|
934
|
-
|
|
1227
|
+
ie.current = null, ke(h, x) || H(`Stockfish move ${x} is not legal here`);
|
|
1228
|
+
}
|
|
1229
|
+
}).catch((x) => {
|
|
1230
|
+
W() || x instanceof ae || x instanceof Ne || (_e.current = { fen: h, count: te + 1 }, te + 1 >= it && H(`Stockfish failed (${x?.message ?? x})`));
|
|
1231
|
+
});
|
|
1232
|
+
}, [Ue, m, ke, Ke]), Bt = C((h) => {
|
|
1233
|
+
Me(h), X("playing");
|
|
1234
|
+
}, []), ze = C(() => {
|
|
1235
|
+
Be.current++, Ve(), xe(), ie.current = null, _e.current = { fen: "", count: 0 }, wt((h) => h + 1), X(k || r ? "playing" : "setup"), F?.();
|
|
1236
|
+
}, [xe, Ve, k, r, F]);
|
|
1237
|
+
O(() => {
|
|
1238
|
+
P.setMuted(S);
|
|
1239
|
+
}, [P, S]);
|
|
1240
|
+
const Xe = y(Q.length);
|
|
1241
|
+
O(() => {
|
|
1242
|
+
if (Q.length > Xe.current) {
|
|
1243
|
+
me && (me.check ? P.playCheck() : me.captured ? P.playCapture() : P.playMove());
|
|
1244
|
+
const h = Q[Q.length - 1];
|
|
1245
|
+
h && D?.(h.fen, h.san, h.color);
|
|
1246
|
+
}
|
|
1247
|
+
Xe.current = Q.length;
|
|
1248
|
+
}, [Q.length, me, Q, D, P]), O(() => {
|
|
1249
|
+
Oe && P.playChaos();
|
|
1250
|
+
}, [Oe, P]);
|
|
1251
|
+
const Qe = y(E.isGameOver);
|
|
1252
|
+
O(() => {
|
|
1253
|
+
E.isGameOver && !Qe.current && (P.playGameOver(), b?.(E)), Qe.current = E.isGameOver;
|
|
1254
|
+
}, [E, b, P]), O(() => {
|
|
1255
|
+
L === "playing" && (Z || E.isGameOver || !pe || J || ie.current !== N && we(N));
|
|
1256
|
+
}, [L, N, Z, E.isGameOver, pe, J, we]), O(() => {
|
|
1257
|
+
if (L !== "playing" || Z || J || E.isGameOver || !pe || ie.current === N) return;
|
|
1258
|
+
const h = setTimeout(() => we(N), 3e3);
|
|
1259
|
+
return () => clearTimeout(h);
|
|
1260
|
+
}, [L, Z, J, E.isGameOver, pe, N, we]);
|
|
1261
|
+
const Ot = C(
|
|
1262
|
+
(h) => {
|
|
1263
|
+
ge && se !== d || Ae(h);
|
|
935
1264
|
},
|
|
936
|
-
[
|
|
937
|
-
),
|
|
938
|
-
return
|
|
939
|
-
|
|
1265
|
+
[ge, se, d, Ae]
|
|
1266
|
+
), Rt = E.isGameOver ? "Game Over" : J ? "" : ge ? Z ? "Your turn" : Le === "loading" ? "Loading engine..." : "Opponent thinking..." : `${se === "w" ? "White" : "Black"} to move`, Je = [j.container, U].filter(Boolean).join(" ");
|
|
1267
|
+
return L === "setup" ? /* @__PURE__ */ l("div", { className: Je, "data-chaos-chess": "", children: /* @__PURE__ */ l(
|
|
1268
|
+
yr,
|
|
940
1269
|
{
|
|
941
|
-
depth:
|
|
942
|
-
onDepthChange:
|
|
943
|
-
stupidLevel:
|
|
944
|
-
onStupidLevelChange:
|
|
945
|
-
onSelectSide:
|
|
1270
|
+
depth: m,
|
|
1271
|
+
onDepthChange: T,
|
|
1272
|
+
stupidLevel: I,
|
|
1273
|
+
onStupidLevelChange: de,
|
|
1274
|
+
onSelectSide: Bt
|
|
946
1275
|
}
|
|
947
|
-
) }) : /* @__PURE__ */
|
|
948
|
-
/* @__PURE__ */
|
|
949
|
-
/* @__PURE__ */
|
|
950
|
-
/* @__PURE__ */
|
|
951
|
-
|
|
1276
|
+
) }) : /* @__PURE__ */ M("div", { className: Je, "data-chaos-chess": "", children: [
|
|
1277
|
+
/* @__PURE__ */ M("div", { className: j.topBar, children: [
|
|
1278
|
+
/* @__PURE__ */ M("div", { className: j.topBarLeft, children: [
|
|
1279
|
+
/* @__PURE__ */ l("span", { className: j.statusText, children: Rt }),
|
|
1280
|
+
J && /* @__PURE__ */ l("span", { className: j.thinking, children: "AI thinking..." }),
|
|
1281
|
+
Le === "failed" && /* @__PURE__ */ l("span", { className: j.aiUnavailable, role: "status", children: "AI unavailable" })
|
|
952
1282
|
] }),
|
|
953
|
-
|
|
1283
|
+
/* @__PURE__ */ M("div", { className: j.topBarRight, children: [
|
|
1284
|
+
/* @__PURE__ */ l("button", { type: "button", className: j.newGameBtn, onClick: ze, title: "Start a new game", children: "New game" }),
|
|
1285
|
+
w && /* @__PURE__ */ l(br, { muted: S, onToggle: () => V((h) => !h) })
|
|
1286
|
+
] })
|
|
954
1287
|
] }),
|
|
955
|
-
|
|
956
|
-
/* @__PURE__ */
|
|
957
|
-
|
|
1288
|
+
He && /* @__PURE__ */ l(_r, { countdown: Lt, maxCountdown: Pt }),
|
|
1289
|
+
/* @__PURE__ */ l(
|
|
1290
|
+
On,
|
|
958
1291
|
{
|
|
959
|
-
board:
|
|
960
|
-
selectedSquare:
|
|
961
|
-
legalMoves:
|
|
962
|
-
inCheck:
|
|
963
|
-
lastMove:
|
|
964
|
-
chaosSquare:
|
|
965
|
-
flipped:
|
|
966
|
-
locked:
|
|
967
|
-
onSquareClick:
|
|
1292
|
+
board: Tt,
|
|
1293
|
+
selectedSquare: yt,
|
|
1294
|
+
legalMoves: bt,
|
|
1295
|
+
inCheck: E.inCheck,
|
|
1296
|
+
lastMove: St,
|
|
1297
|
+
chaosSquare: Oe,
|
|
1298
|
+
flipped: d === "b",
|
|
1299
|
+
locked: ge && !Z,
|
|
1300
|
+
onSquareClick: Ot
|
|
968
1301
|
}
|
|
969
1302
|
),
|
|
970
|
-
_ && /* @__PURE__ */
|
|
971
|
-
/* @__PURE__ */
|
|
972
|
-
/* @__PURE__ */
|
|
1303
|
+
_ && /* @__PURE__ */ M("div", { className: j.bottomBar, children: [
|
|
1304
|
+
/* @__PURE__ */ l(vt, { depth: m, onChange: T }),
|
|
1305
|
+
/* @__PURE__ */ l(_t, { level: I, onChange: de })
|
|
973
1306
|
] }),
|
|
974
|
-
/* @__PURE__ */
|
|
975
|
-
|
|
976
|
-
|
|
1307
|
+
/* @__PURE__ */ l(kr, { action: ee }),
|
|
1308
|
+
$e && /* @__PURE__ */ l(pr, { color: se, onSelect: Ct }),
|
|
1309
|
+
E.isGameOver && /* @__PURE__ */ l(vr, { status: E, humanColor: d, onRestart: ze })
|
|
977
1310
|
] });
|
|
978
1311
|
}
|
|
979
1312
|
export {
|
|
980
|
-
|
|
1313
|
+
Dr as ChaosChess
|
|
981
1314
|
};
|
|
982
1315
|
//# sourceMappingURL=chaos-chess.js.map
|