UNPKG

cm-chessboard

Version:

A JavaScript chessboard which is lightweight, ES6 module based, responsive, SVG rendered and without dependencies.

152 lines (136 loc) 4.77 kB
/** * Author and copyright: Stefan Haack (https://shaack.com) * Repository: https://github.com/shaack/cm-chessboard * License: MIT, see file 'LICENSE' */ export const FEN = { start: "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1", empty: "8/8/8/8/8/8/8/8" } export class Position { constructor(fen = FEN.empty) { this.squares = new Array(64).fill(null) this.setFen(fen) } setFen(fen = FEN.empty) { const parts = fen.replace(/^\s*/, "").replace(/\s*$/, "").split(/\/|\s/) for (let part = 0; part < 8; part++) { const row = parts[7 - part].replace(/\d/g, (str) => { const numSpaces = parseInt(str) let ret = '' for (let i = 0; i < numSpaces; i++) { ret += '-' } return ret }) for (let c = 0; c < 8; c++) { const char = row.substring(c, c + 1) let piece = null if (char !== '-') { if (char.toUpperCase() === char) { piece = `w${char.toLowerCase()}` } else { piece = `b${char}` } } this.squares[part * 8 + c] = piece } } } getFen() { let parts = new Array(8).fill("") for (let part = 0; part < 8; part++) { let spaceCounter = 0 for (let i = 0; i < 8; i++) { const piece = this.squares[part * 8 + i] if (!piece) { spaceCounter++ } else { if (spaceCounter > 0) { parts[7 - part] += spaceCounter spaceCounter = 0 } const color = piece.substring(0, 1) const name = piece.substring(1, 2) if (color === "w") { parts[7 - part] += name.toUpperCase() } else { parts[7 - part] += name } } } if (spaceCounter > 0) { parts[7 - part] += spaceCounter spaceCounter = 0 } } return parts.join("/") } getPieces(pieceColor = undefined, pieceType = undefined, sortBy = ['k', 'q', 'r', 'b', 'n', 'p']) { const pieces = [] const sort = (a, b) => { return sortBy.indexOf(a.name) - sortBy.indexOf(b.name) } for (let i = 0; i < 64; i++) { const piece = this.squares[i] if (piece) { const type = piece.charAt(1) const color = piece.charAt(0) const square = Position.indexToSquare(i) if(pieceType && pieceType !== type || pieceColor && pieceColor !== color) { continue } pieces.push({ name: type, // deprecated, use type type: type, color: color, position: square, // deprecated, use square square: square }) } } if (sortBy) { pieces.sort(sort) } return pieces } movePiece(squareFrom, squareTo) { if (!this.squares[Position.squareToIndex(squareFrom)]) { console.warn("no piece on", squareFrom) return } this.squares[Position.squareToIndex(squareTo)] = this.squares[Position.squareToIndex(squareFrom)] this.squares[Position.squareToIndex(squareFrom)] = null } setPiece(square, piece) { this.squares[Position.squareToIndex(square)] = piece } getPiece(square) { return this.squares[Position.squareToIndex(square)] } static squareToIndex(square) { const coordinates = Position.squareToCoordinates(square) return coordinates[0] + coordinates[1] * 8 } static indexToSquare(index) { return this.coordinatesToSquare([Math.floor(index % 8), index / 8]) } static squareToCoordinates(square) { const file = square.charCodeAt(0) - 97 const rank = square.charCodeAt(1) - 49 return [file, rank] } static coordinatesToSquare(coordinates) { const file = String.fromCharCode(coordinates[0] + 97) const rank = String.fromCharCode(coordinates[1] + 49) return file + rank } toString() { return this.getFen() } clone() { const cloned = Object.create(Position.prototype) cloned.squares = this.squares.slice(0) return cloned } }