UNPKG

xchess

Version:

Chess Engine

264 lines (211 loc) 4.74 kB
export {table} import {File, files} from './file.js' import {Rank, ranks} from './rank.js' import {Color} from './color.js' import {TableWhiteCell, TableBlackCell, TableBorder} from './ansi-style.js' // styles const white = TableWhiteCell; const black = TableBlackCell; const style = {white, black}; const StyleMap = new Map(); // config const EOL = '\n'; const INDENT = 4; const cellPaddingLeft = 3; const cellPaddingRight = 3; const indexPadding = 2; const cellWidth = cellPaddingLeft + cellPaddingRight + 1; const indexColumnWidth = indexPadding * 2 + 1; const tableWidth = cellWidth * files.length + indexColumnWidth * 2; const indexRowSpace = TableBorder(space(tableWidth)); const indexColumnSpace = space(indexColumnWidth); const cellSpaceLeft = space(cellPaddingLeft); const cellSpaceRight = space(cellPaddingRight); const cellSpace = space(cellWidth); const indexColumnBg = TableBorder(indexColumnSpace); const indexPaddingSpace = space(indexPadding); function table(board, opts){ return Table.render(board, opts); } function space(length){ return ' '.repeat(length); } function cell(value){ return cellSpaceLeft + String(value) + cellSpaceRight; } function indexRowCells(files){ const cells = []; for(const file of files) cells.push(cell(file.name)); return cells.join(''); } function indexRow(files){ return TableBorder(indexColumnSpace + indexRowCells(files) + indexColumnSpace); } function resizeCell(value){ value = String(value); if(value.length > cellWidth) return value.substring(0, cellWidth); if(value.length < cellWidth) return value.padEnd(cellWidth); return value; } function styleCell(square, piece, table){ return table.flags.get(square); } function formatCell(square, piece, table){ if(piece) return cell(piece); return cellSpace; } class Table { static render(board, opts){ const table = new this(board, opts); return table.render(); } // Config #board; #indent; #format; #style; #styleMap; #color; #flags; // Runtime #text = []; #cells = []; constructor(board, { indent = INDENT, format = formatCell, style = styleCell, styleMap = StyleMap, color = Color.white, flags = new Map(), } = {}){ this.#board = board; this.#indent = indent; this.#format = format; this.#style = style; this.#styleMap = styleMap; this.#color = Color.from(color); this.#flags = flags; } // config get board(){ return this.#board; } get indent(){ return this.#indent; } get format(){ return this.#format; } get style(){ return this.#style; } get styleMap(){ return this.#styleMap; } get color(){ return this.#color; } get flags(){ return this.#flags; } get ranks(){ if(this.color === Color.white) return ranks; return Rank.reverse(); } get files(){ if(this.color === Color.white) return files; return File.reverse(); } // Runtime get text(){ return this.#text; } push(value){ this.#cells.push(value); } releaseRow(){ this.line(this.#cells.join('')); this.#cells = []; } line(line){ this.#text.push(space(this.indent) + line); } release(){ const text = this.text; this.#text = []; return text.join(EOL); } styleCell(square){ const piece = this.board.get(square); const styleCell = this.style(square, piece, this); return this.styleMap.get(styleCell) ?? styleCell ?? style; } colorStyleCell(square){ const {color} = square; const styleCell = this.styleCell(square); return Object(styleCell)[color] ?? style[color]; } // Render indexRow(){ this.line(indexRowSpace); this.line(indexRow(this.files)); this.line(indexRowSpace); } cellSpace(square){ const style = this.colorStyleCell(square); this.push(style(cellSpace)); } cellsSpace(rank){ for(const file of this.files) this.cellSpace(file.squares[rank.y]); } indexCell(rank){ this.push(TableBorder(indexPaddingSpace + rank.name + indexPaddingSpace)); } cell(square){ const piece = this.board.get(square); const style = this.colorStyleCell(square); const value = this.format(square, piece, this); const cell = resizeCell(value); this.push(style(cell)); } cells(rank){ for(const file of this.files) this.cell(file.squares[rank.y]); } rowSpace(rank){ this.push(indexColumnBg); this.cellsSpace(rank); this.push(indexColumnBg); this.releaseRow(rank); } rowCells(rank){ this.indexCell(rank); this.cells(rank); this.indexCell(rank); this.releaseRow(); } row(rank){ this.rowSpace(rank); this.rowCells(rank); this.rowSpace(rank); } rows(){ for(const rank of this.ranks) this.row(rank); } table(){ this.indexRow(); this.rows(); this.indexRow(); } render(){ this.table(); return this.release(); } }