xchess
Version:
Chess Engine
130 lines (111 loc) • 2.55 kB
JavaScript
export {MoveMap, EmptyMoveMap}
import {ParseMove} from './move-parser.js'
import {ComputeDisambiguationLevels} from './move-disambiguator.js'
import {IS_INTEGER, IS_STRING} from './types.js'
import {INVALID_MOVE_VALUE, AMBIGUOUS_MOVE} from './errors.js'
class MoveMap {
#list;
constructor(moves){
this.#list = new Set(moves);
this.#computeDisambiguationLevels();
}
[Symbol.iterator](){
return this.#list.values();
}
get size(){
return this.#list.size;
}
stat(){
const count = this.size;
const pieces = new Set();
const squares = new Set();
const captures = new Set();
let captureCount = 0;
for(const move of this){
pieces.add(move.target);
squares.add(move.to);
if(move.capture){
captures.add(move.capture);
captureCount ++;
}
}
const fatality = captureCount / count;
return {count, captureCount, fatality, pieces, squares, captures};
}
#computeDisambiguationLevels(){
ComputeDisambiguationLevels(this);
}
#search(moveArg){
const all = [];
const MoveCond = ParseMove(moveArg);
for(const move of this){
const fixMove = move.resolve(MoveCond);
if(fixMove) all.push(fixMove);
}
return all;
}
#test(moveArg){
const MoveCond = ParseMove(moveArg);
for(const move of this)
if(move.match(MoveCond))
return true;
return false;
}
#fromCode(code){
for(const move of this)
if(move.code === code)
return move;
return null;
}
#filterByCode(code){
const all = [];
for(const move of this)
if(move.code === code)
all.push(move);
return all;
}
#hasCode(code){
for(const move of this)
if(move.code === code)
return true;
return false;
}
of(piece){
const moves = [];
for(const move of this)
if(move.target === piece)
moves.push(move);
return moves;
}
has(moveArg){
if(this.#list.has(moveArg))
return true;
if(IS_INTEGER(moveArg))
return this.#hasCode(moveArg);
if(IS_STRING(moveArg))
return this.#test(moveArg);
return false;
}
get(moveArg){
if(this.#list.has(moveArg))
return moveArg;
if(IS_INTEGER(moveArg))
return this.#fromCode(moveArg);
const [move, ... rest] = this.#search(String(moveArg));
if(move){
if(rest.length > 0)
throw AMBIGUOUS_MOVE(moveArg);
return move;
} return null;
throw INVALID_MOVE_VALUE(moveArg);
}
getAll(moveArg){
if(this.#list.has(moveArg))
return [moveArg];
if(IS_INTEGER(moveArg))
return this.#filterByCode(moveArg);
if(IS_STRING(moveArg))
return this.#search(moveArg);
}
}
const EmptyMoveMap = new MoveMap();