removed chess.js to build my own engine now

This commit is contained in:
Didictateur 2025-11-09 18:33:02 +01:00
parent 09f50e2477
commit fa9c28df05
5 changed files with 62 additions and 44 deletions

7
package-lock.json generated
View file

@ -9,7 +9,6 @@
"version": "0.1.0",
"license": "MIT",
"dependencies": {
"chess.js": "^1.1.2",
"express": "^4.18.2",
"socket.io": "^4.7.2",
"uuid": "^9.0.0"
@ -129,12 +128,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/chess.js": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/chess.js/-/chess.js-1.4.0.tgz",
"integrity": "sha512-BBJgrrtKQOzFLonR0l+k64A98NLemPwNsCskwb+29bRwobUa4iTm51E1kwGPbWXAcfdDa18nad6vpPPKPWarqw==",
"license": "BSD-2-Clause"
},
"node_modules/content-disposition": {
"version": "0.5.4",
"resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz",

View file

@ -11,7 +11,6 @@
"author": "Didictateur",
"license": "MIT",
"dependencies": {
"chess.js": "^1.1.2",
"express": "^4.18.2",
"socket.io": "^4.7.2",
"uuid": "^9.0.0"

View file

@ -111,7 +111,28 @@
connectAndJoin();
// allow clicking on the board to request legal moves for a square
// show markers for legal moves when clicking any square (any piece color)
function clearLegalMarkers(){
const prev = boardEl.querySelectorAll('.move-marker');
prev.forEach(p=>p.remove());
}
function showLegalMoves(moves){
clearLegalMarkers();
(moves||[]).forEach(m => {
const to = m.to || (m.move && m.move.to);
if(!to) return;
const target = boardEl.querySelector(`.square[data-square="${to}"]`);
if(!target) return;
const marker = document.createElement('div');
marker.className = 'move-marker';
// store metadata if needed later
marker.dataset.from = m.from || '';
marker.dataset.to = to;
target.appendChild(marker);
});
}
if(boardEl){
boardEl.addEventListener('click', (ev)=>{
const sqEl = ev.target.closest && ev.target.closest('.square');
@ -120,8 +141,9 @@
if(!square) return;
if(socket){
socket.emit('game:legalMoves', { roomId, square }, (resp)=>{
if(resp && resp.error){ log('legalMoves error', resp); return; }
if(resp && resp.error){ log('legalMoves error', resp); clearLegalMarkers(); return; }
log('legalMoves for', square, resp.moves || resp);
showLegalMoves(resp.moves || []);
});
}
});

View file

@ -47,6 +47,15 @@ a:hover{text-decoration:underline}
.square{width:100%;height:100%;display:flex;align-items:center;justify-content:center}
.square img, .piece{max-width:78%;max-height:78%;user-select:none}
/* marker shown on target squares for legal moves */
.square{position:relative}
.square .move-marker{
position:absolute;
left:50%;top:50%;transform:translate(-50%,-50%);
width:18%;height:18%;border-radius:50%;pointer-events:none;background:rgba(96,165,250,0.95);
box-shadow:0 2px 6px rgba(2,6,23,0.6);z-index:3
}
/* basic checkerboard coloring */
.square.light{background: linear-gradient(180deg, rgba(255,255,255,0.02), rgba(255,255,255,0.01));}
.square.dark{background: linear-gradient(180deg, rgba(0,0,0,0.18), rgba(0,0,0,0.12));}

View file

@ -1,7 +1,6 @@
const express = require('express');
const http = require('http');
const { Server } = require('socket.io');
const { Chess } = require('chess.js');
const { v4: uuidv4 } = require('uuid');
const app = express();
@ -15,24 +14,36 @@ app.use(express.static('public'));
app.use('/assets', express.static(path.join(__dirname, 'assets')));
// In-memory rooms store. For production replace with persistent store.
// room = { id, chess: Chess, players: [{id, socketId, color}], status }
// room = { id, boardFEN: string|null, turn: 'w'|'b'|null, players: [{id, socketId, color}], status }
const rooms = new Map();
// Placeholder: compute legal moves for a square in the given room.
// This is intentionally a stub — you will implement the full rules engine.
// (fields like { from, to, piece, color, flags, captured, san } are typical).
function computeLegalMoves(room, square){
// TODO: implement rule engine. For now return empty array so client shows nothing.
return [];
}
app.post('/rooms', (req, res) => {
const id = uuidv4().slice(0, 8);
// allow optional board size in request body (default 8)
const size = (req.body && parseInt(req.body.size, 10)) || 8;
// For standard 8x8 chess we use chess.js. For other sizes we keep a placeholder state
const chess = size === 8 ? new Chess() : null;
// For standard 8x8 we initialize a FEN string as the canonical board state.
// manually (or by a separate engine). This server stores the board FEN and
// the active turn so custom logic can operate on them.
const startingFEN = 'rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1';
const boardFEN = size === 8 ? startingFEN : null;
const turn = size === 8 ? 'w' : null; // 'w' or 'b'
// hostId will be set when the first player joins
rooms.set(id, { id, chess, players: [], status: 'waiting', hostId: null, size, cards: {}, playedCards: [], removalTimers: new Map() });
rooms.set(id, { id, boardFEN, turn, players: [], status: 'waiting', hostId: null, size, cards: {}, playedCards: [], removalTimers: new Map() });
res.json({ roomId: id, size });
});
app.get('/rooms/:id', (req, res) => {
const room = rooms.get(req.params.id);
if (!room) return res.status(404).json({ error: 'room not found' });
const fen = room.chess ? room.chess.fen() : null;
const fen = room.boardFEN || null;
res.json({ id: room.id, fen, size: room.size, players: room.players.map(p => ({ id: p.id, color: p.color })), status: room.status, hostId: room.hostId, cards: Object.keys(room.cards || {}) });
});
@ -70,7 +81,7 @@ io.on('connection', (socket) => {
io.to(roomId).emit('room:update', {
fen: room.chess ? room.chess.fen() : null,
fen: room.boardFEN || null,
players: room.players.map(p => ({ id: p.id, color: p.color })),
status: room.status,
hostId: room.hostId,
@ -85,26 +96,10 @@ io.on('connection', (socket) => {
const room = rooms.get(roomId);
if (!room) return cb && cb({ error: 'room not found' });
const chess = room.chess;
// If we have a chess.js instance (standard 8x8) use it for validation
if (!chess) return cb && cb({ error: 'custom board sizes not yet supported for moves' });
// Validate move
const move = chess.move({ from, to, promotion });
if (!move) return cb && cb({ error: 'invalid move' });
io.to(roomId).emit('move:moved', { move, fen: chess.fen() });
if (chess.isGameOver()) {
room.status = 'finished';
let result = 'draw';
if (chess.isCheckmate()) result = 'checkmate';
else if (chess.isStalemate()) result = 'stalemate';
io.to(roomId).emit('game:over', { result, fen: chess.fen() });
}
cb && cb({ ok: true, move, fen: chess.fen() });
// Move handling/validation is intentionally not implemented here because
// Implement a function to validate & apply moves on the room state and
// then emit 'move:moved' with move details and updated room.boardFEN.
return cb && cb({ error: 'move handling not implemented on server; implement custom engine' });
});
// Host can start the game explicitly
@ -120,9 +115,9 @@ io.on('connection', (socket) => {
if (!room.hostId || room.hostId !== senderId) return cb && cb({ error: 'only host can start' });
room.status = 'playing';
io.to(roomId).emit('game:started', { roomId, fen: room.chess.fen() });
io.to(roomId).emit('game:started', { roomId, fen: room.boardFEN });
io.to(roomId).emit('room:update', {
fen: room.chess ? room.chess.fen() : null,
fen: room.boardFEN || null,
players: room.players.map(p => ({ id: p.id, color: p.color })),
status: room.status,
hostId: room.hostId,
@ -149,7 +144,7 @@ io.on('connection', (socket) => {
}
if (room.players.length < 2 && room.status === 'playing') room.status = 'waiting';
io.to(roomId).emit('room:update', {
fen: room.chess ? room.chess.fen() : null,
fen: room.boardFEN || null,
players: room.players.map(p => ({ id: p.id, color: p.color })),
status: room.status,
hostId: room.hostId,
@ -167,7 +162,7 @@ io.on('connection', (socket) => {
room.hostId = room.players[0] ? room.players[0].id : null;
}
io.to(roomId).emit('room:update', {
fen: room.chess ? room.chess.fen() : null,
fen: room.boardFEN || null,
players: room.players.map(p => ({ id: p.id, color: p.color })),
status: room.status,
hostId: room.hostId,
@ -177,15 +172,15 @@ io.on('connection', (socket) => {
}
});
// Provide legal moves for a given square (for standard 8x8 via chess.js)
// delegates to `computeLegalMoves` which is a stub you should implement.
socket.on('game:legalMoves', ({ roomId, square }, cb) => {
const room = rooms.get(roomId);
if (!room) return cb && cb({ error: 'room not found' });
if (!room.chess) return cb && cb({ error: 'legal moves not supported for custom board sizes yet', moves: [] });
try{
const moves = room.chess.moves({ square, verbose: true }) || [];
const moves = computeLegalMoves(room, square) || [];
return cb && cb({ ok: true, moves });
}catch(e){
console.error('game:legalMoves error', e);
return cb && cb({ error: 'invalid square', moves: [] });
}
});