14 unstable releases (4 breaking)
0.8.2 | Jul 1, 2023 |
---|---|
0.8.1 | Jun 7, 2023 |
0.6.0 | Nov 7, 2022 |
0.5.0 | Apr 25, 2022 |
0.3.6 | Sep 11, 2021 |
#394 in Algorithms
325KB
8K
SLoC
board-game-rs
A Board abstraction for deterministic two player games. This allows for code to be generic over the actual game, so it only needs to written once.
Features
Currently, the implemented games are:
- Chess as ChessBoard, implemented as a simple wrapper around the chess crate.
- Go/Baduk as GoBoard.
- Super/Ultimate tic-tac-toe as STTTBoard.
- Ataxx as AtaxxBoard.
- Oware as OwareBoard.
- Connect4 as Connect4.
- Tic Tac Toe as TTTBoard.
Most game implementations are heavily optimized, using bitboards or other techniques where appropriate.
There are also some utility boards:
- MaxMovesBoard wraps another board and sets the outcome to a draw after move limit has been reached.
- DummyGame is a board that is constructed from an explicit game tree, useful for debugging.
Utilities in this crate that work for any Board:
- Game-playing algorithms, specifically:
- RandomBot, which simply picks a random move.
- RolloutBot, which simulates a fixed number of random games for each possible move and picks the one with the best win probability.
- MinimaxBot, which picks the best move as evaluated by a customizable heuristic at a fixed depth. (implemented as alpha-beta negamax).
- MCTSBot, which picks the best move as found by Monte Carlo Tree Search.
- Random board generation functions, see board_gen.
- A bot vs bot game runner to compare playing strength, see bot_game.
- Simple game statistics (perft, random game length) which can be used to test board implementations.
This crate is also used as the foundation for kZero, a general AlphaZero implementation.
Examples
List the available moves on a board and play a random one.
let mut board = AtaxxBoard::default();
println!("{}", board);
board.available_moves().unwrap().for_each(|mv| {
println!("{:?}", mv)
});
let mv = board.random_available_move(&mut rng).unwrap();
println!("Picked move {:?}", mv);
board.play(mv).unwrap();
println!("{}", board);
Get the best move according to MCTS
let board = AtaxxBoard::default();
println!("{}", board);
let mut bot = MCTSBot::new(1000, 2.0, thread_rng());
println!("{:?}", bot.select_move(&board))
Dependencies
~8MB
~139K SLoC