Spaces:
Sleeping
Sleeping
File size: 4,146 Bytes
e83ab43 6139d24 e83ab43 3339781 6139d24 e83ab43 3339781 e83ab43 a3f099e e83ab43 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 |
(() => {
const { roomId, basePath } = window.__ROOM_CONFIG__ || {};
const boardEl = document.getElementById('boardUI');
let board, chess;
async function getJSON(path, options) {
const res = await fetch(path, options);
if (!res.ok) throw new Error(await res.text());
return res.json();
}
async function refreshSideInfo() {
const s = await getJSON(`${basePath}/room/${roomId}/status`);
document.getElementById('turn').textContent = s.turn + (s.is_check ? ' (check)' : '');
document.getElementById('result').textContent = s.is_game_over ? (s.result || 'game over') : '-';
const legal = await getJSON(`${basePath}/room/${roomId}/legal_moves`);
document.getElementById('legal').textContent = legal.join(', ');
}
async function syncFromServer() {
const st = await getJSON(`${basePath}/room/${roomId}/board`);
// chess.js v0.13 uses load(fen)
chess.load(st.fen);
board.position(chess.fen());
await refreshSideInfo();
}
function onDragStart(source, piece) {
// Disallow moves if game over or trying to move wrong color
if (chess.game_over()) return false;
const turn = chess.turn() === 'w' ? 'white' : 'black';
if ((turn === 'white' && piece.search(/^b/) !== -1) || (turn === 'black' && piece.search(/^w/) !== -1)) {
return false;
}
return true;
}
async function onDrop(source, target) {
let moveObj = chess.move({ from: source, to: target, promotion: 'q' });
if (moveObj == null) return 'snapback';
// Send move to server in UCI
const uci = `${source}${target}${moveObj.promotion ? moveObj.promotion : ''}`;
try {
await getJSON(`${basePath}/room/${roomId}/player_move`, {
method: 'POST', headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ move: uci })
});
await syncFromServer();
} catch (e) {
console.error(e);
chess.undo();
return 'snapback';
}
}
function onSnapEnd() {
board.position(chess.fen());
}
async function init() {
if (typeof Chess === 'undefined' || typeof Chessboard === 'undefined') {
console.error('Required libraries not loaded: Chess and/or Chessboard');
return;
}
chess = new Chess();
const pieceSvg = (piece) => {
const glyphs = { wK:'โ', wQ:'โ', wR:'โ', wB:'โ', wN:'โ', wP:'โ', bK:'โ', bQ:'โ', bR:'โ', bB:'โ', bN:'โ', bP:'โ' };
const isWhite = piece && piece[0] === 'w';
const glyph = glyphs[piece] || '?';
const fill = isWhite ? '#ffffff' : '#111827';
const stroke = isWhite ? '#e5e7eb' : '#0b0f19';
const svg = `<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns='http://www.w3.org/2000/svg' width='64' height='64'>
<rect x='0' y='0' width='64' height='64' fill='transparent'/>
<text x='50%' y='62%' font-size='48' text-anchor='middle' fill='${fill}' stroke='${stroke}' stroke-width='1.5' font-family='Segoe UI Symbol, DejaVu Sans, Noto Sans Symbols, Arial, sans-serif'>${glyph}</text>
</svg>`;
return 'data:image/svg+xml;utf8,' + encodeURIComponent(svg);
};
board = Chessboard('boardUI', {
position: 'start', draggable: true, dropOffBoard: 'snapback',
pieceTheme: (p) => pieceSvg(p),
onDragStart, onDrop, onSnapEnd
});
await syncFromServer();
}
document.getElementById('startBtn').addEventListener('click', async () => {
const color = document.getElementById('color').value;
await getJSON(`${basePath}/room/${roomId}/start`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ player_color: color })});
board.orientation(color);
await syncFromServer();
});
document.getElementById('aiBtn').addEventListener('click', async () => {
await getJSON(`${basePath}/room/${roomId}/ai_move`, { method: 'POST' });
await syncFromServer();
});
document.getElementById('copyPgnBtn').addEventListener('click', async () => {
const data = await getJSON(`${basePath}/room/${roomId}/pgn`);
await navigator.clipboard.writeText(data.pgn || '');
alert('PGN copied to clipboard');
});
init();
})();
|