xchess
Version:
Chess Engine
335 lines (264 loc) • 5.38 kB
JavaScript
export {BoardView}
import {white, black} from './color.js'
import {King, Queen, Rook, Bishop, Knight, Pawn} from './piece.js'
import {PieceSet} from './piece-set.js'
import {inspect} from './inspect.js'
import {Weight, Advantage, PiecesStat} from './piece-stat.js'
import {InsertEvent, DeleteEvent, TransferEvent} from './events.js'
class BoardView {
#context;
constructor(context){
this.#context = context;
}
get #board(){
return this.#context.board;
}
// read
get size(){
return this.#board.size;
}
keys(){
return this.#board.keys();
}
values(){
return this.#board.values();
}
entries(){
return this.#board.entries();
}
at(x, y){
return this.#board.at(x, y);
}
has(square){
return this.#board.has(square);
}
get(square){
return this.#board.get(square);
}
find(piece){
return this.#board.find(piece);
}
contains(piece){
return this.#board.contains(piece);
}
byColor(color){
const pieces = new PieceSet();
for(const piece of this.values())
if(piece.color.eq(color))
pieces.add(piece);
return pieces;
}
white(){
return this.byColor(white);
}
black(){
return this.byColor(black);
}
// Stat
get weight(){
return Weight(this.values());
}
advantage(color){
return Advantage(this.values(), color);
}
stat(){
return PiecesStat(this.values());
}
// I/O
[inspect.custom](){
return `${this.constructor.name}(${this.size}) {}`;
}
* [Symbol.iterator](){
yield * this.#board;
}
toString(){
return this.fen;
}
hash(){
return this.#board.hash();
}
toJSON(){
return this.#board.toJSON();
}
text(opts){
return this.#board.text(opts);
}
log(opts){
this.#board.log(opts);
}
get fen(){
return this.#board.fen;
}
// write
#access(){
this.#context.access();
}
#onInsert(piece, square){
this.#context.dispatch(new InsertEvent(piece, square));
}
#onDelete(piece, square){
this.#context.dispatch(new DeleteEvent(piece, square));
}
#onTransfer(piece, from, to){
this.#context.dispatch(new TransferEvent(piece, from, to));
}
set fen(fen){
this.#access();
const deleted = new Map(this.#board);
this.#board.fen = fen;
for(const [square, piece] of deleted)
this.#onDelete(piece, square);
for(const [square, piece] of this)
this.#onInsert(piece, square);
}
setAll(board){
this.#access();
const deleted = new Map(this.#board);
this.#board.setAll(board);
for(const [square, piece] of deleted)
this.#onDelete(piece, square);
for(const [square, piece] of this)
this.#onInsert(piece, square);
}
set(square, piece){
this.#access();
const report = this.#board.set(square, piece);
if(report.deleted)
this.#onDelete(report.deleted, report.to);
if(report.inserted)
this.#onInsert(report.inserted, report.to);
if(report.moved)
this.#onTransfer(report.moved, report.from, report.to);
return report;
}
move(from, to){
this.#access();
const report = this.#board.move(from, to);
if(report.deleted)
this.#onDelete(report.deleted, report.to);
if(report.moved)
this.#onTransfer(report.moved, report.from, report.to);
return report;
}
delete(square){
this.#access();
const {change, from, deleted} = this.#board.delete(square);
if(change){
this.#onDelete(deleted, from);
return {change, from, deleted};
} return {change};
}
clear(){
this.#access();
const board = new Map(this.#board);
const count = this.#board.clear();
for(const [square, piece] of board)
this.#onDelete(piece, square);
return count;
}
// Piece
king(square, color){
const piece = new King(color);
this.set(square, piece);
return piece;
}
queen(square, color){
const piece = new Queen(color);
this.set(square, piece);
return piece;
}
rook(square, color){
const piece = new Rook(color);
this.set(square, piece);
return piece;
}
bishop(square, color){
const piece = new Bishop(color);
this.set(square, piece);
return piece;
}
knight(square, color){
const piece = new Knight(color);
this.set(square, piece);
return piece;
}
pawn(square, color){
const piece = new Pawn(color);
this.set(square, piece);
return piece;
}
k(square){
return this.king(square, black);
}
q(square){
return this.queen(square, black);
}
r(square){
return this.rook(square, black);
}
b(square){
return this.bishop(square, black);
}
n(square){
return this.knight(square, black);
}
p(square){
return this.pawn(square, black);
}
K(square){
return this.king(square, white);
}
Q(square){
return this.queen(square, white);
}
R(square){
return this.rook(square, white);
}
B(square){
return this.bishop(square, white);
}
N(square){
return this.knight(square, white);
}
P(square){
return this.pawn(square, white);
}
setup(){
this.clear();
// Black
this.r('a8');
this.n('b8');
this.b('c8');
this.q('d8');
this.k('e8');
this.b('f8');
this.n('g8');
this.r('h8');
this.p('a7');
this.p('b7');
this.p('c7');
this.p('d7');
this.p('e7');
this.p('f7');
this.p('g7');
this.p('h7');
// White
this.P('a2');
this.P('b2');
this.P('c2');
this.P('d2');
this.P('e2');
this.P('f2');
this.P('g2');
this.P('h2');
this.R('a1');
this.N('b1');
this.B('c1');
this.Q('d1');
this.K('e1');
this.B('f1');
this.N('g1');
this.R('h1');
return this;
}
}