Files
chess/frontend/main.js
Pavel Lutskov b5c252bd4d Implement basic frontend-engine interaction
Use a Flask-based Python server as an adapter to the engine's
stdin-stdout inferface.
2021-12-11 14:58:16 +01:00

132 lines
3.0 KiB
JavaScript

import * as visuals from "./visuals.js";
function get_json(url) {
var request = new XMLHttpRequest();
request.open("get", url, false);
request.send(null);
return JSON.parse(request.responseText);
}
class Backend {
constructor() {
this.config = this.getConfig();
}
getConfig() {
return new Configuration(
get_json("http://localhost:3000/get_state/").map((p) => {
let piece = new Piece();
Object.assign(piece, p);
return piece;
})
);
}
makeMove(move) {
this.config = this.config.makeMove(move);
return this.config.clone();
}
getAvailableMoves(position) {
return [];
}
}
class Chess {
constructor() {
this.backend = new Backend();
this.configVis = null;
this.canvas = new visuals.Canvas();
this.moveSource = null;
this.canMoveTo = [];
this.syncBackend();
document.onclick = (ev) => this.click(ev);
}
syncBackend() {
let config = this.backend.getConfig();
if (this.configVis !== null) {
this.configVis.undraw();
}
this.configVis = new visuals.ConfigVis(config.pieces);
this.configVis.draw(this.canvas);
}
showAvailableMoves(canMoveTo) {}
click(ev) {
if (this.moveSource === null) {
this._firstClick(ev);
} else {
this._secondClick(ev);
}
}
_firstClick(ev) {
let rcA = this.canvas.screenCoordsToRowCol(ev.clientX, ev.clientY);
if (rcA === null) return;
let positionA = visuals.rowColToBoardIndex(...rcA);
this.showAvailableMoves(this.backend.getAvailableMoves(positionA));
this.moveSource = positionA;
}
_secondClick(ev) {
let rcB = this.canvas.screenCoordsToRowCol(ev.clientX, ev.clientY);
if (rcB !== null) {
let move = {
from: this.moveSource,
to: visuals.rowColToBoardIndex(...rcB),
};
this.backend.makeMove(move);
this.syncBackend();
}
this.moveSource = null;
}
}
class Move {
constructor(kind, from, to) {
this.kind = kind;
this.from = from;
this.to = to;
}
}
class Piece {
constructor(who, color, position) {
this.who = who;
this.color = color;
this.position = position;
}
clone() {
return new Piece(this.who, this.color, this.position);
}
moveTo(position) {
return new Piece(this.who, this.color, position);
}
}
class Configuration {
constructor(pieces) {
this.pieces = pieces;
}
clone() {
let pieces = [];
for (let piece of this.pieces) {
pieces.push(piece.clone());
}
return new Configuration(pieces);
}
getAt(position) {
return this.pieces.find((piece) => piece.position === position) || null;
}
dropAt(position) {
return new Configuration(
this.pieces.filter((piece) => piece.position !== position)
);
}
makeMove(move) {
const pieceToMove = this.getAt(move.from);
if (pieceToMove === null) return this;
else
return new Configuration([
...this.dropAt(move.from).dropAt(move.to).pieces,
pieceToMove.moveTo(move.to),
]);
}
}
new Chess();