#bindings #yare

yareio

轻量级的 yare.io Rust 绑定,提供丰富的文档和有用的常量

5 个版本

0.1.4 2021 年 8 月 28 日
0.1.3 2021 年 8 月 28 日
0.1.2 2021 年 8 月 22 日
0.1.1 2021 年 8 月 8 日
0.1.0 2021 年 8 月 7 日

WebAssembly 中排名第 604

GPL-2.0-or-later

87KB
2K SLoC

Rust 2K SLoC // 0.0% comments JavaScript 199 SLoC // 0.1% comments WebAssembly 12 SLoC

Yare-Rust

一个用于使用 Rust 为 yare 创建机器人的库。

工作原理

您创建一个 Rust 库并将其编译为 wasm。然后,您使用 wasm2yareio 脚本来生成一个 JavaScript yare 机器人。结果可以复制到游戏中。

设置

您需要 Rust 和一些额外的工具。

rustup toolchain add nightly
rustup target add wasm32-unknown-unknown
rustup component add llvm-tools-preview
rustup update

创建一个新的 Rust 库。

cargo new --lib my-yare-bot

将以下内容放入您的 Cargo.toml 中。

[lib]
crate-type = ["cdylib"]

[dependencies]
yareio = "0.1"

[profile.release]
opt-level = "s"
lto = true

然后从链接的子模块中复制 wasm2yareio.js 到您的项目中,并安装一个依赖项。确保您的 Node 是最新的。

npm i minify

示例

这是一个示例机器人。您需要定义一个名为 tick 的外部函数,它有一个参数。这将每帧被调用。

#[no_mangle]
pub extern "C" fn tick(_tick: u32) {
    unsafe {
        let me = player::me();
        let Position {x, y} = base::position(0);
        for index in 0..spirit::count() {
            if spirit::player_id(index) == me && spirit::hp(index) > 0 {
                spirit::goto(index, x, y);
            }
        }
    }
}

您应该为这些函数创建安全的包装器,这样您就不必在机器人代码中有 unsafe 块。例如,您可以这样做

use std::ffi::CString;
use yareio::spirit;
use yareio::player;

/// Your own Spirit struct with all the information you want.
struct Spirit {
    index: usize,
    alive: bool,
    friendly: bool,
}

impl Spirit {
    /// Safe wrapper for moving a spirit.
    fn goto(&self, x: f32, y: f32) {
        unsafe { spirit::goto(self.index, x, y) }
    }

    /// Safe wrapper for using shout.
    fn shout(&self, string: &str) {
        let c_string = CString::new(string).unwrap();
        unsafe { spirit::shout(self.index, c_string.as_ptr()) }
    }
}

/// Parse all spirits into your own Spirit structs.
fn get_spirits() -> Vec<Spirit> {
    unsafe {
        let me = player::me();
        let count = spirit::count();
        let mut spirits = Vec::with_capacity(count);
        for index in 0..count {
            spirits.push(Spirit {
                index,
                alive: spirit::hp(index) > 0,
                friendly: spirit::player_id(index) == me,
            });
        }
        spirits
    }
}

// No unsafe block needed here!
#[no_mangle]
pub extern "C" fn tick(_tick: u32) {
    let all_spirits = get_spirits();
    for spirit in all_spirits {
        if spirit.friendly && spirit.alive {
            spirit.goto(123., 456.);
            spirit.shout("Hello, world!");
        }
    }
}

查看这个 模板 以了解如何结构您的代码的示例!

构建

要构建您的 yare 机器人,您首先需要将其编译为 wasm。使用这个

cargo rustc --target wasm32-unknown-unknown --release -- -C target-feature=+multivalue

然后,您想要通过 wasm2yareio 传递它。

node wasm2yareio target/wasm32-unknown-unknown/release/my-yare-bot.wasm

还建议您安装 tampermonkey 脚本来自动将您的代码上传到 yare.io: 点击安装

无头

该库包含 dbenson24 对游戏的头无脑实现。它并不完整,但可用于回归测试或可能用于机器学习。

要使用它,您需要启用 "headless" 功能。您很可能想要在测试时这样做。命令可能看起来像这样

cargo test --features yareio/headless --release

测试应该看起来像这样

#[cfg(test)]
mod tests {
    use std::rc::Rc;
    use yareio::yare_impl::{Headless, Outcome, SimulationResult, Shape};

    #[test]
    fn win_against_rush() {
        let bots: &[Rc<dyn Fn(u32)>] = &[Rc::new(my_bot_func), Rc::new(rush)];
        let shapes = &[Shape::Circle, Shape::Square];
        let headless = Headless::init(bots, shapes, None);
        let SimulationResult(_tick, outcome) = headless.simulate();
        assert!(matches!(outcome, Outcome::Victory(0)));
    }
}

确保您的机器人在运行多个测试时是线程安全的。如果您与自己对战,请确保您没有写入相同的可变静态变量。

此外,还有未经文档记录的 ffi 绑定,可以从其他语言运行头无脑模拟。

依赖项

~0–340KB