webworker runs fish bot for suggestions
This commit is contained in:
parent
c6a20e2bcd
commit
74028e8efe
|
@ -61,6 +61,7 @@ name = "fish-webworker"
|
|||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"fish",
|
||||
"mino",
|
||||
"wasm-bindgen",
|
||||
"wasm-bindgen-macro",
|
||||
"wee_alloc",
|
||||
|
|
|
@ -9,6 +9,7 @@ crate-type = ["cdylib"]
|
|||
|
||||
[dependencies]
|
||||
fish = { path = "../fish" }
|
||||
mino = { path = "../mino" }
|
||||
|
||||
wasm-bindgen = "0.2"
|
||||
wasm-bindgen-macro = "0.2"
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
use std::{cell::RefCell, mem::MaybeUninit};
|
||||
use wasm_bindgen_macro::wasm_bindgen;
|
||||
|
||||
use fish::Weights;
|
||||
use fish::{Bot, Weights};
|
||||
use mino::srs::{PieceType, Queue};
|
||||
use mino::{MatBuf, Rot};
|
||||
|
||||
#[global_allocator]
|
||||
static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT;
|
||||
|
@ -13,18 +15,22 @@ struct State {
|
|||
|
||||
static mut STATE: MaybeUninit<RefCell<State>> = MaybeUninit::uninit();
|
||||
|
||||
fn state() -> &'static RefCell<State> {
|
||||
unsafe { STATE.assume_init_ref() }
|
||||
impl State {
|
||||
fn new() -> RefCell<State> {
|
||||
RefCell::new(State {
|
||||
weights: Weights::default(),
|
||||
max_iters: 10_000,
|
||||
})
|
||||
}
|
||||
|
||||
fn get() -> &'static RefCell<State> {
|
||||
unsafe { STATE.assume_init_ref() }
|
||||
}
|
||||
}
|
||||
|
||||
#[wasm_bindgen(start)]
|
||||
fn start() {
|
||||
let init_state = State {
|
||||
weights: Weights::default(),
|
||||
max_iters: 10_000,
|
||||
};
|
||||
|
||||
unsafe { STATE.write(RefCell::new(init_state)) };
|
||||
unsafe { STATE.write(State::new()) };
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
|
@ -34,8 +40,71 @@ pub fn get_version() -> String {
|
|||
|
||||
#[wasm_bindgen]
|
||||
pub fn get_config() -> Vec<i32> {
|
||||
let state = state().borrow();
|
||||
let state = State::get().borrow();
|
||||
let mut config = Vec::from(state.weights.0);
|
||||
config.push(state.max_iters as i32);
|
||||
config
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn suggest(matrix: String, hold: String, next: String) -> Result<String, String> {
|
||||
let matrix = parse_matrix(&matrix);
|
||||
let hold = parse_hold(&hold)?;
|
||||
let next = parse_queue(&next)?;
|
||||
let queue = Queue::new(hold, &next);
|
||||
|
||||
let state = State::get().borrow();
|
||||
|
||||
let res = {
|
||||
let mut bot = Bot::new(&state.weights, &matrix, queue);
|
||||
bot.think(state.max_iters);
|
||||
bot.suggest().ok_or("No suggestion found")?
|
||||
};
|
||||
|
||||
Ok(format!(
|
||||
"{x},{y},{r},{ty}",
|
||||
x = res.loc.x,
|
||||
y = res.loc.y,
|
||||
r = rot(res.loc.r),
|
||||
ty = res.ty
|
||||
))
|
||||
}
|
||||
|
||||
fn rot(r: Rot) -> &'static str {
|
||||
match r {
|
||||
Rot::N => "spawn",
|
||||
Rot::E => "right",
|
||||
Rot::S => "reverse",
|
||||
Rot::W => "left",
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_matrix(s: &str) -> MatBuf {
|
||||
s.bytes()
|
||||
.take(400)
|
||||
.enumerate()
|
||||
.filter(|(_, c)| *c != b' ')
|
||||
.map(|(i, _)| ((i % 10) as i16, (i / 10) as i16))
|
||||
.fold(MatBuf::new(), |mut mat, (x, y)| {
|
||||
mat.set(x, y);
|
||||
mat
|
||||
})
|
||||
}
|
||||
|
||||
fn parse_hold(s: &str) -> Result<Option<PieceType>, &'static str> {
|
||||
match s.len() {
|
||||
0 => Ok(None),
|
||||
1 => {
|
||||
let c = s.as_bytes()[0];
|
||||
let ty = PieceType::try_from(c as char).map_err(|_| "Unrecognized hold piece")?;
|
||||
Ok(Some(ty))
|
||||
}
|
||||
_ => Err("Expected hold piece to be a single character"),
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_queue(s: &str) -> Result<Vec<PieceType>, &'static str> {
|
||||
s.bytes()
|
||||
.map(|c| PieceType::try_from(c as char).map_err(|_| "Unrecognized next piece"))
|
||||
.collect()
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ import {
|
|||
default as init,
|
||||
get_version as getVersion,
|
||||
get_config as getConfig,
|
||||
suggest,
|
||||
} from '../build/fish_webworker.js'
|
||||
|
||||
let initPromise = init('/blockfish.wasm');
|
||||
|
@ -16,6 +17,14 @@ async function handle(msg) {
|
|||
return { version, config: { weights, maxIters } };
|
||||
}
|
||||
|
||||
case 'suggest':
|
||||
{
|
||||
let res = suggest(msg.state.matrix, msg.state.hold, msg.state.next);
|
||||
let [x, y, r, type] = res.split(',');
|
||||
x = +x, y = +y;
|
||||
return { moves: [{ x, y, r, type }] };
|
||||
}
|
||||
|
||||
default:
|
||||
throw `Unrecognized message "${msg.type}"`;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue