xchess
Version:
Chess Engine
468 lines (371 loc) • 7.14 kB
JavaScript
export {GameContext}
import {Emitter} from './emitter.js'
import {RestoreEvent} from './events.js'
import {Board} from './board.js'
import {all} from './piece-index.js'
import {PieceSet} from './piece-set.js'
import {PieceCreator} from './piece-creator.js'
import {SetupState} from './setup-state.js'
import {StateCounter} from './state-counter.js'
class GameContext extends Emitter {
#game;
#board = new Board(this);
#captureList = new PieceSet();
#stateCounter = new StateCounter();
#pieces = all;
first = null;
state = new SetupState(this);
constructor(game){
super();
this.#game = game;
}
get game(){
return this.#game;
}
get prev(){
return this.state.prev;
}
get next(){
return this.state.next;
}
get board(){
return this.#board;
}
get captureList(){
return this.#captureList;
}
get stateCounter(){
return this.#stateCounter;
}
get pieces(){
return this.#pieces;
}
get current(){
return this.state.handler;
}
get time(){
return this.state.time;
}
get count(){
return this.state.count;
}
get fullmoveNumber(){
return this.state.fullmoveNumber;
}
get halfmoveClock(){
return this.state.halfmoveClock;
}
get color(){
return this.state.color;
}
get gameColor(){
return this.state.gameColor;
}
get doubleMovePawn(){
return this.state.doubleMovePawn;
}
get enPassantTarget(){
return this.state.enPassantTarget;
}
get castling(){
return this.state.castling;
}
get prevCastling(){
return this.state.prevCastling;
}
get wk(){
return this.state.wk;
}
get wq(){
return this.state.wq;
}
get bk(){
return this.state.bk;
}
get bq(){
return this.state.bq;
}
get lastMove(){
return this.state.lastMove;
}
get moves(){
return this.state.moves;
}
get isCheck(){
return this.state.isCheck;
}
get checkKing(){
return this.state.checkKing;
}
get checkKingTarget(){
return this.state.checkKingTarget;
}
get hash(){
return this.state.hash;
}
get repetition(){
return this.state.repetition;
}
get newRepetition(){
return this.state.newRepetition;
}
get ownRepetition(){
return this.state.ownRepetition;
}
get drawOffer(){
return this.state.drawOffer;
}
set drawOffer(drawOffer){
this.state.setDrawOffer(drawOffer);
}
// Setup
access(){
this.state.access();
}
change(){
this.emit('change');
}
setPieceList(pieces){
this.#pieces = PieceCreator.from(pieces);
}
setAll(config){
this.state.setAll(config);
}
set board(board){
this.state.setBoard(board);
this.change();
}
set captureList(pieceList){
this.state.setCaptureList(pieceList);
this.change();
}
set count(count){
this.state.setCount(count);
this.change();
}
set fullmoveNumber(value){
this.state.setFullmoveNumber(value);
this.change();
}
set halfmoveClock(value){
this.state.setHalfmoveClock(value);
this.change();
}
set color(color){
this.state.setColor(color);
this.change();
}
set doubleMovePawn(pawn){
this.state.setDoubleMovePawn(pawn);
this.change();
}
set enPassantTarget(square){
this.state.setEnPassantTarget(square);
this.change();
}
set wk(value){
this.state.setWK(value);
this.change();
}
set wq(value){
this.state.setWQ(value);
this.change();
}
set bk(value){
this.state.setBK(value);
this.change();
}
set bq(value){
this.state.setBQ(value);
this.change();
}
// Stat
stat(){
return {
state: this.state,
prev: this.prev,
next: this.next,
target: this.state.target,
status: this.status,
time: this.time,
board: this.board,
captureList: this.captureList,
stateCounter: this.stateCounter,
hash: this.hash,
color: this.color,
count: this.count,
fullmoveNumber: this.fullmoveNumber,
halfmoveClock: this.halfmoveClock,
repetition: this.repetition,
ownRepetition: this.ownRepetition,
newRepetition: this.newRepetition,
doubleMovePawn: this.doubleMovePawn,
castling: this.castling,
prevCastling: this.prevCastling,
drawOffer: this.drawOffer,
lastMove: this.lastMove,
moves: this.moves,
isCheck: this.isCheck,
result: this.result,
winner: this.winner,
loser: this.loser,
subject: this.subject,
};
}
get status(){
return this.state.status;
}
get isSetup(){
return this.state.isSetup;
}
get isMovement(){
return this.state.isMovement;
}
get isPromotion(){
return this.state.isPromotion;
}
get isDrawOffer(){
return this.state.isDrawOffer;
}
get isEnd(){
return this.state.isEnd;
}
get isWin(){
return this.state.isWin;
}
get isDraw(){
return this.state.isDraw;
}
get isImmediate(){
return this.state.isImmediate;
}
get isCheckmate(){
return this.state.isCheckmate;
}
get isStalemate(){
return this.state.isStalemate;
}
get winner(){
return this.state.winner;
}
get loser(){
return this.state.loser;
}
get subject(){
return this.state.subject;
}
get result(){
return this.state.result;
}
// I/O
get fen(){
return this.state.fen;
}
set fen(fen){
this.state.setFEN(fen);
this.change();
}
// Events
dispatch(event){
this.game.dispatchEvent(event);
}
emit(type){
this.dispatch(new Event(type));
}
// Rules
isDeadPosition(){
return this.board.isDeadPosition();
}
isCheckmateChance(color){
return this.board.isCheckmateChance(color);
}
// Game Events
play(){
return this.state.play();
}
forfeit(color){
return this.state.forfeit(color);
}
resign(color){
return this.state.resign(color);
}
draw(color){
return this.state.draw(color);
}
toDraw(color){
return this.state.toDraw(color);
}
flagFall(){
return this.state.flagFall();
}
move(move){
return this.state.move(move);
}
promote(piece){
return this.state.promote(piece);
}
// Log Events
restore(count){
this.dispatch(new RestoreEvent(count));
}
undo(){
const prev = this.prev;
if(prev){
this.state.undo();
this.state = prev;
this.emit('undo');
this.restore(-1);
return true;
} return false;
}
redo(){
const next = this.next;
if(next){
this.state = next;
this.state.redo();
this.emit('redo');
this.restore(1);
return true;
} return false;
}
go(countVal){
const count = Math.trunc(countVal);
if(count){
let cursor = 0, state = this.state;
while(cursor < count && (state = state.next)){
this.state = state;
this.state.redo();
cursor ++;
}
while(cursor > count && (state = state.prev)){
this.state.undo();
this.state = state;
cursor --;
}
if(cursor){
this.restore(cursor);
return cursor;
}
} return 0;
}
goto(offsetVal){
const offset = Math.trunc(offsetVal);
if(offset != this.count){
let state = this.state;
const beginCount = this.count;
while(this.count < offset && (state = state.next)){
this.state = state;
this.state.redo();
}
while(this.count > offset && (state = state.prev)){
this.state.undo();
this.state = state;
}
if(this.count !== beginCount){
const result = this.count - beginCount;
this.restore(result);
return result;
}
} return 0;
}
}