some work (prep for NN training)
This commit is contained in:
parent
0483f4ce86
commit
4e78de70d7
|
@ -1,5 +1,10 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="CPP_MODULE" version="4">
|
||||
<component name="FacetManager">
|
||||
<facet type="Python" name="Python facet">
|
||||
<configuration sdkName="Python 3.10" />
|
||||
</facet>
|
||||
</component>
|
||||
<component name="NewModuleRootManager">
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||
|
@ -7,5 +12,6 @@
|
|||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="library" name="Python 3.10 interpreter library" level="application" />
|
||||
</component>
|
||||
</module>
|
|
@ -12,9 +12,16 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
|||
name = "bamboo"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"hex",
|
||||
"spin",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hex"
|
||||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
|
||||
|
||||
[[package]]
|
||||
name = "lock_api"
|
||||
version = "0.4.9"
|
||||
|
|
|
@ -6,4 +6,5 @@ edition = "2021"
|
|||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
spin = "0.9.5"
|
||||
spin = "0.9.5"
|
||||
hex = "0.4.3"
|
|
@ -0,0 +1 @@
|
|||
1,1,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,1,1,1,0,1,1,0,1,0,0,0,0,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,1,1,1,0,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,1,0,0,1,0,0,0,1,0,0,1,0,0,0,1,1,0,0,0,0,0,1,1,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,1,0,0,1,0,1,0,1,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,-,0,-2801
|
|
100
src/board.rs
100
src/board.rs
|
@ -5,7 +5,7 @@ use crate::boardfield::{Boardfield, BoardfieldOps};
|
|||
use crate::piece::{PieceColor, PieceOnBoard, PieceType};
|
||||
use crate::utils::{algebraic_to_boardloc, AlgebraicNotationError, boardloc_to_algebraic};
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub struct Board {
|
||||
bitfield: Boardfield,
|
||||
// While this is a less efficient memory layout, having an array of where all the pieces are will make move generation significantly faster.
|
||||
|
@ -48,6 +48,66 @@ impl Display for FENParseError {
|
|||
}
|
||||
|
||||
impl Board {
|
||||
pub fn to_board_id(&self) -> [u8; 41] {
|
||||
// 0-31 BOARDFILED
|
||||
// 32 FLAGS
|
||||
// 33-36 EN_PASSANT_TARGET
|
||||
// 37-38 HALFMOVE_COUNTER
|
||||
// 39-40 FULLMOVE_COUNTER
|
||||
|
||||
let mut res = [0u8; 41];
|
||||
|
||||
res[0..32].copy_from_slice(&self.bitfield.get_field());
|
||||
|
||||
let mut flags_byte = res[32];
|
||||
// FLAGS BYTE:
|
||||
//
|
||||
// / unused
|
||||
// |
|
||||
// 000 0 0 0 0 0
|
||||
// | | | | \
|
||||
// | | | | turn to move (1 white, 0 black)
|
||||
// | | | \
|
||||
// | | | white kingside castling
|
||||
// | | \
|
||||
// | | white queenside castling
|
||||
// | \
|
||||
// | black kingside castling
|
||||
// \
|
||||
// black queenside castling
|
||||
if self.turn == PieceColor::White {
|
||||
flags_byte |= 0b1;
|
||||
}
|
||||
if self.castle_white_kingside {
|
||||
flags_byte |= 0b1 << 1;
|
||||
}
|
||||
if self.castle_white_queenside {
|
||||
flags_byte |= 0b1 << 2;
|
||||
}
|
||||
if self.castle_black_kingside {
|
||||
flags_byte |= 0b1 << 3;
|
||||
}
|
||||
if self.castle_black_queenside {
|
||||
flags_byte |= 0b1 << 4;
|
||||
}
|
||||
res[32] = flags_byte;
|
||||
|
||||
let en_passant_target: [u8; 4] = match self.en_passant_target {
|
||||
Some(target) => {
|
||||
(target as u32).to_le_bytes()
|
||||
},
|
||||
None => {
|
||||
u32::MAX.to_le_bytes()
|
||||
}
|
||||
};
|
||||
res[33..37].copy_from_slice(&en_passant_target);
|
||||
|
||||
res[37..39].copy_from_slice(&(self.halfmove_counter as u16).to_le_bytes());
|
||||
res[39..41].copy_from_slice(&(self.move_counter as u16).to_le_bytes());
|
||||
|
||||
res
|
||||
}
|
||||
|
||||
pub fn from_fen(fen: &str) -> Result<Self, FENParseError> {
|
||||
let components = fen.split(' ').collect::<Vec<&str>>();
|
||||
if components.len() != 6 {
|
||||
|
@ -115,7 +175,7 @@ impl Board {
|
|||
file += num;
|
||||
},
|
||||
'/' => {
|
||||
if rank == 8 {
|
||||
if rank == 7 {
|
||||
return Err(FENParseError::CannotSkipToOutsideOfBoard { got: 1, which_is: file + 1 })
|
||||
}
|
||||
|
||||
|
@ -142,7 +202,6 @@ impl Board {
|
|||
}
|
||||
|
||||
fn create_fen_piece(c: char, rank: usize, file: usize) -> Result<PieceOnBoard, FENParseError> {
|
||||
println!("playing {} at {} ({}, {})", c, rank + file * 8, file, rank);
|
||||
Ok(PieceOnBoard {
|
||||
loc: rank + file * 8,
|
||||
value: match c {
|
||||
|
@ -189,6 +248,41 @@ mod tests {
|
|||
use crate::boardloc;
|
||||
use crate::piece::{PieceColor, PieceType};
|
||||
|
||||
#[test]
|
||||
pub fn test_serialization() {
|
||||
assert_eq!(Board::from_fen("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w - - 0 1").unwrap().to_board_id(), [156, 0, 0, 65, 154, 0, 0, 33, 155, 0, 0, 49, 157, 0, 0, 81, 158, 0, 0, 97, 155, 0, 0, 49, 154, 0, 0, 33, 156, 0, 0, 65, 1, 255, 255, 255, 255, 0, 0, 1, 0]);
|
||||
assert_eq!(Board::from_fen("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w q - 0 1").unwrap().to_board_id(), [156, 0, 0, 65, 154, 0, 0, 33, 155, 0, 0, 49, 157, 0, 0, 81, 158, 0, 0, 97, 155, 0, 0, 49, 154, 0, 0, 33, 156, 0, 0, 65, 17, 255, 255, 255, 255, 0, 0, 1, 0]);
|
||||
assert_eq!(Board::from_fen("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w k - 0 1").unwrap().to_board_id(), [156, 0, 0, 65, 154, 0, 0, 33, 155, 0, 0, 49, 157, 0, 0, 81, 158, 0, 0, 97, 155, 0, 0, 49, 154, 0, 0, 33, 156, 0, 0, 65, 9, 255, 255, 255, 255, 0, 0, 1, 0]);
|
||||
assert_eq!(Board::from_fen("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w kq - 0 1").unwrap().to_board_id(), [156, 0, 0, 65, 154, 0, 0, 33, 155, 0, 0, 49, 157, 0, 0, 81, 158, 0, 0, 97, 155, 0, 0, 49, 154, 0, 0, 33, 156, 0, 0, 65, 25, 255, 255, 255, 255, 0, 0, 1, 0]);
|
||||
assert_eq!(Board::from_fen("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w Q - 0 1").unwrap().to_board_id(), [156, 0, 0, 65, 154, 0, 0, 33, 155, 0, 0, 49, 157, 0, 0, 81, 158, 0, 0, 97, 155, 0, 0, 49, 154, 0, 0, 33, 156, 0, 0, 65, 5, 255, 255, 255, 255, 0, 0, 1, 0]);
|
||||
assert_eq!(Board::from_fen("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w Qq - 0 1").unwrap().to_board_id(), [156, 0, 0, 65, 154, 0, 0, 33, 155, 0, 0, 49, 157, 0, 0, 81, 158, 0, 0, 97, 155, 0, 0, 49, 154, 0, 0, 33, 156, 0, 0, 65, 21, 255, 255, 255, 255, 0, 0, 1, 0]);
|
||||
assert_eq!(Board::from_fen("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w Qk - 0 1").unwrap().to_board_id(), [156, 0, 0, 65, 154, 0, 0, 33, 155, 0, 0, 49, 157, 0, 0, 81, 158, 0, 0, 97, 155, 0, 0, 49, 154, 0, 0, 33, 156, 0, 0, 65, 13, 255, 255, 255, 255, 0, 0, 1, 0]);
|
||||
assert_eq!(Board::from_fen("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w Qkq - 0 1").unwrap().to_board_id(), [156, 0, 0, 65, 154, 0, 0, 33, 155, 0, 0, 49, 157, 0, 0, 81, 158, 0, 0, 97, 155, 0, 0, 49, 154, 0, 0, 33, 156, 0, 0, 65, 29, 255, 255, 255, 255, 0, 0, 1, 0]);
|
||||
assert_eq!(Board::from_fen("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w K - 0 1").unwrap().to_board_id(), [156, 0, 0, 65, 154, 0, 0, 33, 155, 0, 0, 49, 157, 0, 0, 81, 158, 0, 0, 97, 155, 0, 0, 49, 154, 0, 0, 33, 156, 0, 0, 65, 3, 255, 255, 255, 255, 0, 0, 1, 0]);
|
||||
assert_eq!(Board::from_fen("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w Kq - 0 1").unwrap().to_board_id(), [156, 0, 0, 65, 154, 0, 0, 33, 155, 0, 0, 49, 157, 0, 0, 81, 158, 0, 0, 97, 155, 0, 0, 49, 154, 0, 0, 33, 156, 0, 0, 65, 19, 255, 255, 255, 255, 0, 0, 1, 0]);
|
||||
assert_eq!(Board::from_fen("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w Kk - 0 1").unwrap().to_board_id(), [156, 0, 0, 65, 154, 0, 0, 33, 155, 0, 0, 49, 157, 0, 0, 81, 158, 0, 0, 97, 155, 0, 0, 49, 154, 0, 0, 33, 156, 0, 0, 65, 11, 255, 255, 255, 255, 0, 0, 1, 0]);
|
||||
assert_eq!(Board::from_fen("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQ - 0 1").unwrap().to_board_id(), [156, 0, 0, 65, 154, 0, 0, 33, 155, 0, 0, 49, 157, 0, 0, 81, 158, 0, 0, 97, 155, 0, 0, 49, 154, 0, 0, 33, 156, 0, 0, 65, 7, 255, 255, 255, 255, 0, 0, 1, 0]);
|
||||
assert_eq!(Board::from_fen("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQq - 0 1").unwrap().to_board_id(), [156, 0, 0, 65, 154, 0, 0, 33, 155, 0, 0, 49, 157, 0, 0, 81, 158, 0, 0, 97, 155, 0, 0, 49, 154, 0, 0, 33, 156, 0, 0, 65, 23, 255, 255, 255, 255, 0, 0, 1, 0]);
|
||||
assert_eq!(Board::from_fen("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQk - 0 1").unwrap().to_board_id(), [156, 0, 0, 65, 154, 0, 0, 33, 155, 0, 0, 49, 157, 0, 0, 81, 158, 0, 0, 97, 155, 0, 0, 49, 154, 0, 0, 33, 156, 0, 0, 65, 15, 255, 255, 255, 255, 0, 0, 1, 0]);
|
||||
assert_eq!(Board::from_fen("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1").unwrap().to_board_id(), [156, 0, 0, 65, 154, 0, 0, 33, 155, 0, 0, 49, 157, 0, 0, 81, 158, 0, 0, 97, 155, 0, 0, 49, 154, 0, 0, 33, 156, 0, 0, 65, 31, 255, 255, 255, 255, 0, 0, 1, 0]);
|
||||
|
||||
assert_eq!(Board::from_fen("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR b KQkq a4 0 1").unwrap().to_board_id(), [156, 0, 0, 65, 154, 0, 0, 33, 155, 0, 0, 49, 157, 0, 0, 81, 158, 0, 0, 97, 155, 0, 0, 49, 154, 0, 0, 33, 156, 0, 0, 65, 30, 3, 0, 0, 0, 0, 0, 1, 0]);
|
||||
|
||||
assert!(Board::from_fen("d").is_err());
|
||||
assert!(Board::from_fen("8/8/8/8/8/8/8/8 h - - 0 1").is_err());
|
||||
assert!(Board::from_fen("8/8/8/8/8/8/8 w KQkq j4 0 1").is_err());
|
||||
|
||||
assert!(Board::from_fen("9/8/8/8/8/8/8 w KQkq a4 0 1").is_err());
|
||||
assert!(Board::from_fen("18/8/8/8/8/8/8 w KQkq a4 0 1").is_err());
|
||||
assert!(Board::from_fen("8/8/8/8/8/8/8/8/8 w KQkq a4 0 1").is_err());
|
||||
assert!(Board::from_fen("8/8/8/8/8/8/8/8 w KQkq a4 a 1").is_err());
|
||||
assert!(Board::from_fen("8/8/8/8/8/8/8/8 w KQkq a4 0 a").is_err());
|
||||
|
||||
assert!(Board::from_fen("s w KQkq a4 0 1").is_err());
|
||||
|
||||
assert_eq!(Board::from_fen("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1").unwrap().to_board_id(), [156, 0, 0, 65, 154, 0, 0, 33, 155, 0, 0, 49, 157, 0, 0, 81, 158, 0, 0, 97, 155, 0, 0, 49, 154, 0, 0, 33, 156, 0, 0, 65, 31, 255, 255, 255, 255, 0, 0, 1, 0]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn fen_parse_testing() {
|
||||
let board = Board::from_fen("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1").unwrap();
|
||||
|
|
|
@ -33,6 +33,7 @@ pub trait BoardfieldOps {
|
|||
fn startpos() -> Self where Self: Sized;
|
||||
fn get_pos(&self, boardloc: usize) -> u8;
|
||||
fn set_pos(&mut self, boardloc: usize, piece: u8);
|
||||
fn get_field(&self) -> [u8; 32];
|
||||
}
|
||||
impl BoardfieldOps for Boardfield {
|
||||
fn new() -> Self where Self: Sized {
|
||||
|
@ -117,6 +118,12 @@ impl BoardfieldOps for Boardfield {
|
|||
|
||||
self[boardloc / 2] = bf_new;
|
||||
}
|
||||
|
||||
fn get_field(&self) -> [u8; 32] {
|
||||
*self
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
|
24
src/main.rs
24
src/main.rs
|
@ -3,6 +3,7 @@ use std::path::Path;
|
|||
use std::sync::{Arc};
|
||||
use crate::uci::{uci_handle_command, UCIState};
|
||||
use spin::Mutex;
|
||||
use crate::board::Board;
|
||||
|
||||
#[cfg(not(tarpaulin_include))] // UCI parse engine is not tested with tarpaulin, outer test harness is planned
|
||||
pub mod uci;
|
||||
|
@ -19,6 +20,29 @@ pub const ENGINE_AUTHOR: &str = "c0repwn3r";
|
|||
|
||||
#[cfg(not(tarpaulin_include))]
|
||||
fn main() {
|
||||
if std::env::args().len() > 1 {
|
||||
let args = std::env::args().collect::<Vec<String>>();
|
||||
|
||||
if args[1] == "--serBoard" && args.len() != 3 {
|
||||
println!("usage: bamboo [--serBoard <fenString>]");
|
||||
std::process::exit(1);
|
||||
} else if args[1] == "--serBoard" {
|
||||
match Board::from_fen(args[2].as_str()) {
|
||||
Ok(b) => {
|
||||
println!("{}", hex::encode(b.to_board_id()));
|
||||
std::process::exit(0);
|
||||
},
|
||||
Err(e) => {
|
||||
println!("Error decoding FEN string: {}", e);
|
||||
std::process::exit(1);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
println!("usage: bamboo [--serBoard <fenString>]");
|
||||
std::process::exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
println!("{} {} by {}", ENGINE_NAME, ENGINE_VERSION, ENGINE_AUTHOR);
|
||||
|
||||
let mut uci_state = UCIState::new();
|
||||
|
|
13
src/piece.rs
13
src/piece.rs
|
@ -1,4 +1,4 @@
|
|||
#[derive(Debug)]
|
||||
#[derive(Debug, Ord, PartialOrd, Eq, PartialEq)]
|
||||
pub struct PieceOnBoard {
|
||||
pub loc: usize,
|
||||
pub value: Piece
|
||||
|
@ -12,7 +12,7 @@ impl PieceOnBoard {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Ord, PartialOrd, Eq, PartialEq)]
|
||||
#[repr(u8)]
|
||||
pub enum PieceType {
|
||||
Pawn = 1,
|
||||
|
@ -23,7 +23,7 @@ pub enum PieceType {
|
|||
King = 6
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Ord, PartialOrd, Eq, PartialEq)]
|
||||
#[repr(u8)]
|
||||
pub enum PieceColor {
|
||||
White = 8,
|
||||
|
@ -52,10 +52,15 @@ impl PieceOps for Piece {
|
|||
|
||||
#[cfg(test)]
|
||||
mod piece_tests {
|
||||
use crate::piece::{Piece, PieceColor, PieceOps, PieceType};
|
||||
use crate::piece::{Piece, PieceColor, PieceOnBoard, PieceOps, PieceType};
|
||||
|
||||
#[test]
|
||||
fn piece_serialization() {
|
||||
assert_eq!(PieceOnBoard::new(0, 0), PieceOnBoard {
|
||||
loc: 0,
|
||||
value: 0,
|
||||
});
|
||||
|
||||
assert_eq!(PieceType::Pawn as u8 | PieceColor::White as u8, 0b1001);
|
||||
assert_eq!(PieceType::Pawn as u8 | PieceColor::Black as u8, 0b0001);
|
||||
|
||||
|
|
Loading…
Reference in New Issue