test WIP
This commit is contained in:
parent
0de67fd423
commit
1a8c339326
1 changed files with 187 additions and 0 deletions
|
|
@ -132,6 +132,42 @@ fn shift_in_direction(magnitude: i8, value: Board) -> Board {
|
|||
}
|
||||
|
||||
impl BitBoard {
|
||||
/// Convert from a JON (Jack Othello Notation) string into a usable board.
|
||||
pub fn from_jon(fen: &str) -> Result<Self, &'static str> {
|
||||
let mut boards: [Board; 2] = [0, 0];
|
||||
let mut line: u8 = 7;
|
||||
let mut rank_idx: u8 = 0;
|
||||
let mut rank_jump: u8 = 0;
|
||||
for c in fen.chars().into_iter() {
|
||||
match c.to_ascii_lowercase() {
|
||||
'/' => {
|
||||
line -= 1;
|
||||
rank_idx = 0;
|
||||
rank_jump = 0;
|
||||
}
|
||||
'b' => {
|
||||
boards[0] += 1 << (line * 8 + rank_idx + rank_jump);
|
||||
rank_idx += rank_jump + 1;
|
||||
rank_jump = 0;
|
||||
}
|
||||
'w' => {
|
||||
boards[1] += 1 << (line * 8 + rank_idx + rank_jump);
|
||||
rank_idx += rank_jump + 1;
|
||||
rank_jump = 0;
|
||||
}
|
||||
'0'..'9' => {
|
||||
rank_jump = c
|
||||
.to_digit(10u32)
|
||||
.ok_or("Failed to parse integer from character")?
|
||||
as u8;
|
||||
}
|
||||
_ => {
|
||||
return Err("Malformed FEN: Unexpected character encountered");
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(Self { boards })
|
||||
}
|
||||
/// Compute board with valid moves marked
|
||||
pub fn available(&self, current_team: Team) -> Board {
|
||||
// bitwise OR gives spots with either white OR black discs
|
||||
|
|
@ -360,4 +396,155 @@ mod tests {
|
|||
--------";
|
||||
assert_eq!(format!("{}", bb), expected_output);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn jon_works() {
|
||||
let bb = BitBoard::from_jon("///3wb/3bw///").expect("Starting board should be valid");
|
||||
println!("{}", bb);
|
||||
assert_eq!(bb.boards, BitBoard::default().boards);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_available_starting_position_black() {
|
||||
// Starting position
|
||||
let bb = BitBoard::from_jon("///3wb/3bw///").expect("Valid board");
|
||||
let available = bb.available(Team::Black);
|
||||
|
||||
// Black can move to: d3, c4, f5, e6
|
||||
let expected = BitBoard::from_jon("//4b/5b/2b/3b//").expect("Valid board");
|
||||
assert_eq!(available, expected.boards[Team::Black as usize]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_available_starting_position_white() {
|
||||
// Starting position
|
||||
let bb = BitBoard::from_jon("///3wb/3bw///").expect("Valid board");
|
||||
let available = bb.available(Team::White);
|
||||
|
||||
// White can move to: c5, d6, f4, e3
|
||||
let expected = BitBoard::from_jon("//3w/5w/2w/4w//").expect("Valid board");
|
||||
assert_eq!(available, expected.boards[Team::White as usize]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_available_empty_board() {
|
||||
// Empty board - no pieces
|
||||
let bb = BitBoard::from_jon("////////").expect("Valid board");
|
||||
let available_black = bb.available(Team::Black);
|
||||
let available_white = bb.available(Team::White);
|
||||
|
||||
// No moves available on empty board
|
||||
assert_eq!(available_black, 0);
|
||||
assert_eq!(available_white, 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_available_single_piece_no_moves() {
|
||||
// Single white piece, no black pieces
|
||||
let bb = BitBoard::from_jon("///3w////").expect("Valid board");
|
||||
let available = bb.available(Team::Black);
|
||||
|
||||
// Black has no valid moves (needs opponent pieces to capture)
|
||||
assert_eq!(available, 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_available_corner_move() {
|
||||
// Board with pieces set up for a corner capture
|
||||
// Black at b8, white at a8, black can play at a7 to capture
|
||||
let bb = BitBoard::from_jon("wb//////").expect("Valid board");
|
||||
println!("{}", bb);
|
||||
let available = bb.available(Team::Black);
|
||||
|
||||
// Black can move to a7 to capture white at a8
|
||||
let expected = BitBoard::from_jon("/b//////").expect("Valid board");
|
||||
assert_eq!(available, expected.boards[Team::Black as usize]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_available_edge_captures() {
|
||||
// Black pieces on edges with white pieces that can be captured
|
||||
let bb = BitBoard::from_jon("b6w/8/8/8/8/8/8/8").expect("Valid board");
|
||||
let available = bb.available(Team::Black);
|
||||
|
||||
// Black can capture by playing in between
|
||||
let expected = BitBoard::from_jon("1bbbbbb/").expect("Valid board");
|
||||
assert_eq!(available, expected.boards[Team::Black as usize]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_available_multiple_direction_capture() {
|
||||
// White surrounded by black - black can capture in multiple directions
|
||||
let bb = BitBoard::from_jon("///2bbb/2bwb/2bbb///").expect("Valid board");
|
||||
let available = bb.available(Team::Black);
|
||||
|
||||
// Black can play at d4 (where white is) - but this is invalid, let me reconsider
|
||||
// Actually, moves must be on empty squares
|
||||
// Let's set up where black can capture in multiple directions
|
||||
let bb = BitBoard::from_jon("///2b1b/2bwb/2bbb///").expect("Valid board");
|
||||
let available = bb.available(Team::Black);
|
||||
|
||||
// Black can move to d5 to capture white
|
||||
let expected = BitBoard::from_jon("///3b////").expect("Valid board");
|
||||
assert_eq!(available, expected.boards[Team::Black as usize]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_available_no_valid_moves() {
|
||||
// Position where current team has no valid moves
|
||||
// Black pieces isolated with no white pieces to capture
|
||||
let bb = BitBoard::from_jon("b///////w").expect("Valid board");
|
||||
let available_black = bb.available(Team::Black);
|
||||
let available_white = bb.available(Team::White);
|
||||
|
||||
// Neither player can capture anything
|
||||
assert_eq!(available_black, 0);
|
||||
assert_eq!(available_white, 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_available_full_row_capture() {
|
||||
// Black can capture an entire row of white pieces
|
||||
let bb = BitBoard::from_jon("///////bwwwwwwb").expect("Valid board");
|
||||
let available = bb.available(Team::Black);
|
||||
|
||||
// Black can play anywhere between the two black pieces on row 1
|
||||
let expected = BitBoard::from_jon("///////1bbbbbb").expect("Valid board");
|
||||
assert_eq!(available, expected.boards[Team::Black as usize]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_available_diagonal_capture() {
|
||||
// Test diagonal captures
|
||||
let bb = BitBoard::from_jon("b/1w/2w/3w////").expect("Valid board");
|
||||
let available = bb.available(Team::Black);
|
||||
|
||||
// Black can capture diagonally
|
||||
let expected = BitBoard::from_jon("////4b///").expect("Valid board");
|
||||
assert_eq!(available, expected.boards[Team::Black as usize]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_available_midgame_position() {
|
||||
// More complex mid-game position
|
||||
let bb = BitBoard::from_jon("//2bwb/2www/2bwb///").expect("Valid board");
|
||||
let available = bb.available(Team::Black);
|
||||
|
||||
// Black should have several valid moves
|
||||
// This would need to be calculated based on actual game rules
|
||||
// Adding moves that would flip white pieces
|
||||
let expected = BitBoard::from_jon("/3b/b1b1b/b3b/b1b1b/3b//").expect("Valid board");
|
||||
assert_eq!(available, expected.boards[Team::Black as usize]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_available_vertical_capture() {
|
||||
// Test vertical captures
|
||||
let bb = BitBoard::from_jon("b/w/w/w////").expect("Valid board");
|
||||
let available = bb.available(Team::Black);
|
||||
|
||||
// Black can capture vertically downward
|
||||
let expected = BitBoard::from_jon("////b///").expect("Valid board");
|
||||
assert_eq!(available, expected.boards[Team::Black as usize]);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue