chess-tools
Version:
A collection of tools / libraries for programming chess applications.
118 lines (115 loc) • 3.81 kB
JavaScript
"use strict";
//see https://chessprogramming.wikispaces.com/ABK
//http://www.talkchess.com/forum/viewtopic.php?topic_view=threads&p=184321&t=20661
const debug = require('debug')('ABK');
const utils = require('../../utils.js');
const Transform = require('stream').Transform;
const EventEmitter = require('events');
const ENTRY_SIZE= 28; //bytes
const START_ADDRESS = ENTRY_SIZE * 900;
const Chess = require('chess.js').Chess;
//var chess = new Chess();
const files = utils.board.FILES;
const ABKEntry = require("./entry.js");
class ABKStream extends Transform {
constructor() {
super({readableObjectMode: true});
this.start = 900 * ENTRY_SIZE;
this.last_read = this.start;
this.entry_num = 0;
this.current_depth = 0;
this.current_address = 900;
this.read_to_start = false;
this.received_bytes = 0;
this.can_read = true;
this.current_path = [];
}
_flush(callback) {
callback();
}
_transform(chunk, encoding, callback) {
this.received_bytes += chunk.length;
if (this._data) {
this._data = Buffer.concat([this._data, chunk]);
} else {
this._data = chunk;
}
if (this.received_bytes > this.start + ENTRY_SIZE) {
this.read_to_start = true;
}
if (this.read_to_start) {
let t0 = new Date().getTime();
while(this.can_read == true) {
this.read_record();
}
let t3 = new Date().getTime();
}
callback();
}
read_record() {
let offset = ENTRY_SIZE * this.entry_num;
let record = this._data.slice(START_ADDRESS + offset, START_ADDRESS + ENTRY_SIZE + offset);
this.last_read = START_ADDRESS + offset;
let entry = ABKEntry.fromBuffer(record, this.entry_num + 900);
if (this.current_path.length > 0 ) {
this.current_path[this.current_path.length-1].children.push(entry);
for (let p of this.current_path) {
entry.path.push(p);
}
if (entry.first_child > -1 ) {
this.current_path.push(entry);
} else if (entry.first_child === -1 && entry.next_sibling === -1) {
let remove = 0;
for (let p of this.current_path) {
if (p.next_sibling === -1) {
remove++;
}
}
this.current_path = this.current_path.slice(0, this.current_path.length - remove);
} else {
}
} else {
this.current_path = [entry];
}
this.entry_num++;
entry.entry_num = this.entry_num;
this.push(entry);
this.can_read = (this._data.length > START_ADDRESS + ENTRY_SIZE + offset + ENTRY_SIZE);
}
push(e) {
super.push(e);
}
}
class ABK extends EventEmitter {
constructor() {
super();
this.entries = {};
this.stream = new ABKStream();
}
load_book(stream) {
this.entries = [];
this.loaded = false;
this.stream.on("data", (entry)=>{
let key = utils.key_from_fen(entry.fen);
if (this.entries[key]) {
this.entries[key].push(entry);
} else {
this.entries[key] = [ entry ];
}
});
this.stream.on('finish', ()=>{
this.loaded= true;
this.emit("loaded");
});
this.stream.on('error', (error)=>{
console.log("error", error);
this.emit("error", error);
});
stream.pipe(this.stream);
}
find(fen) {
let key = utils.key_from_fen(fen);
return this.entries[key];
}
}
module.exports=ABK;