Skip to content

whompyjaw/rust-sc2

 
 

Repository files navigation

rust-sc2

crates.io Documentation

Rust implementation of StarCraft II API

The library aims to be simple and easy to use, being very fast and functional at the same time. However, it provides both high and low level abstractions. This lib is inspired by python-sc2 lib, so people might find it easy to switch to rust-sc2. It was originally created because other rust libs were old, not functional and low level.

Feel free to ask questions in #rust channel of these Discord servers:

Getting started

Rust

Install Rust >= 1.42.0

Create your project

cargo add <name_of_project>

Warning: Compilation is broken in rustc 1.45.0 - 1.46.0, you'll get following error:

thread 'rustc' has overflowed its stack
error: could not compile `rust-sc2`.

Add to dependencies in Cargo.toml:

[dependencies]
rust-sc2 = "1.1.0"

Or if you want developer version directly from github:

[dependencies]
rust-sc2 = { git = "https://github.com/UltraMachine/rust-sc2" }

StarCraft II

Windows and macOS

Install SC2 through Battle.net.

Linux

Lutris and Wine

  1. Install Lutris from your package manager
  2. Install Battle.net dependencies. (Wine and Vulkan drivers)
  3. Install SC2 through Lutris

Headless (no graphics)

  1. Download most recent Linux Package (Maps will come with the zip)

  2. Unzip to ~/StarCraftII (you'll need the End User License Agreement Password above the Linux Packages link)

Bug Workarounds (as of 7/31/22)

These solutions will (hopefully) help you run the bot example...

  1. The current solution of expanding ~ doesn't work. I guess it's not that easy. So export SC2PATH=/home/<user>/StarCraftII is required before running your bot.

  2. rust-sc2 doesn't recurse down Maps child directories, so you will need to copy whatever .SC2Map from the season's to the parent Maps directory. (Make sure you update your map in the bot example below)

  3. Create an empty directory mkdir ~/StarCraftII/Support64.

  4. When you run the example (and I guess any bot), it will crash. See this Discord thread for more context

Example

The simplest competetive bot in less than 30 lines. Copy this into your /path/to/project/main.rs

use rust_sc2::prelude::*;

#[bot]
#[derive(Default)]
struct WorkerRush;
impl Player for WorkerRush {
	fn get_player_settings(&self) -> PlayerSettings {
	PlayerSettings::new(Race::Protoss)
	}
	fn on_start(&mut self) -> SC2Result<()> {
	for worker in &self.units.my.workers {
		worker.attack(Target::Pos(self.enemy_start), false);
	}
	Ok(())
	}
}

fn main() -> SC2Result<()> {
	let mut bot = WorkerRush::default();
	run_vs_computer(
	&mut bot,
	Computer::new(Race::Random, Difficulty::Medium, None),
	"EternalEmpireLE",
	Default::default(),
	)
}

Running Example

Lutris

As of 7/31/22, neither of these options have been tested, but hopefully one of them will work.

  1. You can try burnysc2's solution.
  2. Or, try this from @ccapitalK discord

Headless

In your project directory: cargo run

For more advanced examples see examples folder.

Optional features

  • "rayon" - enables parallelism and makes all types threadsafe
  • "serde" - adds implementation of Serialize, Deserialize to ids, Race, GameResult, ...

Making bot step by step

First of all, import rust-sc2 lib:

use rust_sc2::prelude::*;

Create your bot's struct (Can be Unit or C-like):

#[bot]
struct MyBot;
#[bot]
struct MyBot {
	/* fields here */
}

Then implement Player trait for your bot:

// You mustn't call any of these methods by hands, they're for API only
impl Player for MyBot {
	// Must be implemented
	fn get_player_settings(&self) -> PlayerSettings {
	// Race can be Terran, Zerg, Protoss or Random
	PlayerSettings::new(Race::Random)
	}

	// Methods below aren't necessary to implement (Empty by default)

	// Called once on first step
	fn on_start(&mut self) -> SC2Result<()> {
	/* your awesome code here */
	}

	// Called on every game step
	fn on_step(&mut self, iteration: usize) -> SC2Result<()> {
	/* your awesome code here */
	}

	// Called once on last step
	// "result" says if your bot won or lost game
	fn on_end(&self, result: GameResult) -> SC2Result<()> {
	/* your awesome code here */
	}

	// Called on different events, see more in `examples/events.rs`
	fn on_event(&mut self, event: Event) -> SC2Result<()> {
	/* your awesome code here */
	}
}

Also you might want to add method to construct it:

impl MyBot {
	// It's necessary to have #[bot_new] here
	#[bot_new]
	fn new() -> Self {
	Self {
		/* initializing fields */
	}
	}
}

If your bot implements Default you can simply call MyBot::default(), but if you want more control over initializer:

impl MyBot {
	// You don't need #[bot_new] here, because of "..Default::default()"
	fn new() -> Self {
	Self {
		/* initializing fields */
		..Default::default()
	}
	}
}

The rest is to run it:

fn main() -> SC2Result<()> {
	let mut bot = MyBot::new();
	run_vs_computer(
	&mut bot,
	Computer::new(
		Race::Random,
		Difficulty::VeryEasy,
		None,              // AI Build (random here)
	),
	"EternalEmpireLE", // Map name
	LaunchOptions::default(),
	)
}

About

SC2 API for Rust

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • Rust 98.9%
  • Python 1.1%