Implement basic frontend-engine interaction

Use a Flask-based Python server as an adapter to the engine's
stdin-stdout inferface.
This commit is contained in:
2021-12-11 14:58:16 +01:00
parent 57931b29de
commit b5c252bd4d
4 changed files with 80 additions and 38 deletions

46
adapter/adapter.py Normal file
View File

@@ -0,0 +1,46 @@
import os
import subprocess
import flask
from flask_cors import CORS
PIECE_TYPE = [("P", "pawn")]
COLOR = [
("W", "white"),
("B", "black"),
]
HERE = os.path.abspath(os.path.dirname(__file__))
app = flask.Flask(__name__)
CORS(app)
engine = subprocess.Popen(
[os.path.join(HERE, "../rs/target/debug/schach")],
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
)
def make_piece(piece_str):
piece_type, color, file, rank = piece_str
return {
"who": dict(PIECE_TYPE)[piece_type],
"color": dict(COLOR)[color],
"position": f"{file}{rank}",
}
@app.route("/get_state/")
def get_state():
engine.stdin.write(b"get_state\n")
engine.stdin.flush()
position_str = engine.stdout.readline().decode("ascii").strip()
position = [
make_piece(position_str[i : i + 4])
for i in range(0, len(position_str), 4)
]
return flask.jsonify(position)
if __name__ == "__main__":
app.run(debug=True, host="127.0.0.1", port=3000)

View File

@@ -1,42 +1,24 @@
import * as visuals from "./visuals.js"; import * as visuals from "./visuals.js";
function setupBoard() { function get_json(url) {
let pawns = []; var request = new XMLHttpRequest();
for (let x of "abcdefgh") { request.open("get", url, false);
pawns.push( request.send(null);
new Piece("pawn", "black", `${x}7`), return JSON.parse(request.responseText);
new Piece("pawn", "white", `${x}2`)
);
}
return new Configuration([
new Piece("rook", "black", "a8"),
new Piece("rook", "black", "h8"),
new Piece("knight", "black", "b8"),
new Piece("knight", "black", "g8"),
new Piece("bishop", "black", "c8"),
new Piece("bishop", "black", "f8"),
new Piece("queen", "black", "d8"),
new Piece("king", "black", "e8"),
...pawns,
new Piece("rook", "white", "a1"),
new Piece("rook", "white", "h1"),
new Piece("knight", "white", "b1"),
new Piece("knight", "white", "g1"),
new Piece("bishop", "white", "c1"),
new Piece("bishop", "white", "f1"),
new Piece("queen", "white", "d1"),
new Piece("king", "white", "e1"),
]);
} }
class Backend { class Backend {
constructor() { constructor() {
this.config = setupBoard(); this.config = this.getConfig();
} }
getConfig() { getConfig() {
return this.config.clone(); return new Configuration(
get_json("http://localhost:3000/get_state/").map((p) => {
let piece = new Piece();
Object.assign(piece, p);
return piece;
})
);
} }
makeMove(move) { makeMove(move) {
this.config = this.config.makeMove(move); this.config = this.config.makeMove(move);

View File

@@ -224,15 +224,17 @@ impl Board {
}; };
} }
pub fn new() -> Board { pub fn new() -> Board {
let mut board = Board { Board {
state: Default::default(), state: Default::default(),
}; }
}
pub fn reset(&mut self) {
self.state.clear();
for piece_type in &[PieceType::Pawn] { for piece_type in &[PieceType::Pawn] {
for (piece, position) in piece_type.initial_setup() { for (piece, position) in piece_type.initial_setup() {
board.set_at(position, Some(piece)); self.set_at(position, Some(piece));
} }
} }
board
} }
pub fn iter(&self) -> impl Iterator<Item = (&Position, &Piece)> { pub fn iter(&self) -> impl Iterator<Item = (&Position, &Piece)> {
self.state.iter() self.state.iter()

View File

@@ -1,7 +1,19 @@
use std::io::BufRead;
mod board; mod board;
mod ui; mod ui;
fn main() { fn main() -> Result<(), ()> {
let board = board::Board::new(); let mut board = board::Board::new();
println!("{}", board.to_string()); board.reset();
let stdin = std::io::stdin();
let mut input_lines = stdin.lock().lines();
loop {
match input_lines.next() {
None => break Ok(()),
Some(line) => match &line.unwrap()[..] {
"get_state" => println!("{}", board.to_string()),
_ => break Err(()),
},
}
}
} }