basic bot

This commit is contained in:
2026-01-21 20:37:17 -07:00
commit ae7f57d3df
21 changed files with 1354 additions and 0 deletions

View File

@@ -0,0 +1,14 @@
[build]
# Target 64-bit Windows for modern tournament compatibility
target = "x86_64-pc-windows-gnu"
[target.x86_64-pc-windows-gnu]
# Linker and rustflags will be set by Nix flake via environment variables:
# - CARGO_TARGET_X86_64_PC_WINDOWS_GNU_LINKER
# - CARGO_TARGET_X86_64_PC_WINDOWS_GNU_RUSTFLAGS
# Falls back to system linker if not in Nix shell
linker = "x86_64-w64-mingw32-gcc"
[env]
# TARGET environment variable helps bindgen know we're cross-compiling
TARGET = "x86_64-pc-windows-gnu"

16
protossbot/.gitignore vendored Normal file
View File

@@ -0,0 +1,16 @@
# Rust
/target/
**/*.rs.bk
*.pdb
Cargo.lock
# IDE
.vscode/
.idea/
*.swp
*.swo
*~
# OS
.DS_Store
Thumbs.db

20
protossbot/Cargo.toml Normal file
View File

@@ -0,0 +1,20 @@
[package]
name = "rustbot"
version = "0.1.0"
edition = "2021"
[dependencies]
rsbwapi = "3.6.3"
axum = { version = "0.7", features = ["ws"] }
tokio = { version = "1", features = ["full"] }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
serde_yaml = "0.9"
tokio-tungstenite = "0.24"
futures-util = "0.3"
tower-http = { version = "0.6", features = ["fs", "cors"] }
rand = "0.8"
[profile.release]
opt-level = 3
lto = true

23
protossbot/build.sh Executable file
View File

@@ -0,0 +1,23 @@
#!/usr/bin/env bash
set -e
# Set up environment for cross-compilation
export CARGO_TARGET_X86_64_PC_WINDOWS_GNU_LINKER=x86_64-w64-mingw32-gcc
export CC_x86_64_pc_windows_gnu=x86_64-w64-mingw32-gcc
export CXX_x86_64_pc_windows_gnu=x86_64-w64-mingw32-g++
export AR_x86_64_pc_windows_gnu=x86_64-w64-mingw32-ar
# Set include path for bindgen - add C++ standard library and GCC include paths
export BINDGEN_EXTRA_CLANG_ARGS="-I/usr/lib/gcc/x86_64-w64-mingw32/13-posix/include/c++ -I/usr/lib/gcc/x86_64-w64-mingw32/13-posix/include/c++/x86_64-w64-mingw32 -I/usr/lib/gcc/x86_64-w64-mingw32/13-posix/include -I/usr/x86_64-w64-mingw32/include"
# Build for Windows target
echo "Building..."
cargo build --target x86_64-pc-windows-gnu
# Check if build was successful
if [ -f "target/x86_64-pc-windows-gnu/debug/rustbot.exe" ]; then
echo "Build successful: target/x86_64-pc-windows-gnu/debug/rustbot.exe"
else
echo "Build failed!"
exit 1
fi

69
protossbot/src/bot.rs Normal file
View File

@@ -0,0 +1,69 @@
use std::sync::{Arc, Mutex};
use rsbwapi::*;
use crate::game_state::GameState;
impl AiModule for RustBot {
fn on_start(&mut self, game: &Game) {
// SAFETY: rsbwapi uses interior mutability (RefCell) for the command queue.
// enable_flag only adds a command to the queue.
// This cast is safe in the single-threaded BWAPI callback context.
unsafe {
let game_ptr = game as *const Game as *mut Game;
(*game_ptr).enable_flag(Flag::UserInput as i32);
}
println!("Game started on map: {}", game.map_file_name());
}
fn on_frame(&mut self, game: &Game) {
// println!("Frame {}", game.get_frame_count());
let Ok(mut locked_state) = self.game_state.lock() else {
return;
};
}
fn on_unit_create(&mut self, game: &Game, unit: Unit) {
if game.get_frame_count() < 1 {
return;
}
println!("unit created: {:?}", unit.get_type());
}
fn on_unit_morph(&mut self, game: &Game, unit: Unit) {
}
fn on_unit_destroy(&mut self, _game: &Game, unit: Unit) {
}
fn on_unit_complete(&mut self, game: &Game, unit: Unit) {
let Some(player) = game.self_() else {
return;
};
}
fn on_end(&mut self, _game: &Game, is_winner: bool) {
if is_winner {
println!("Victory!");
} else {
println!("Defeat!");
}
}
}
pub struct RustBot {
game_state: Arc<Mutex<GameState>>,
}
impl RustBot {
pub fn new(game_state: Arc<Mutex<GameState>>) -> Self {
Self {
game_state,
}
}
}

View File

@@ -0,0 +1,14 @@
pub struct GameState {
}
impl Default for GameState {
fn default() -> Self {
Self {
}
}
}

15
protossbot/src/main.rs Normal file
View File

@@ -0,0 +1,15 @@
mod bot;
pub mod game_state;
use bot::RustBot;
use std::sync::{Arc, Mutex};
use game_state::GameState;
fn main() {
println!("Starting RustBot...");
let game_state = Arc::new(Mutex::new(GameState::default()));
rsbwapi::start(move |_game| RustBot::new(game_state.clone() ));
}