summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ai/src/lib.rs92
-rw-r--r--model/src/possible_moves.rs19
-rw-r--r--ui/src/main.rs7
3 files changed, 74 insertions, 44 deletions
diff --git a/ai/src/lib.rs b/ai/src/lib.rs
index 21fcf1e..8c49ba7 100644
--- a/ai/src/lib.rs
+++ b/ai/src/lib.rs
@@ -55,16 +55,7 @@ pub fn eval_singlethreaded(
let moves = PossibleMoves::moves(board);
if moves.is_empty() {
- let pos_eval = if board.turn() == PieceColor::Dark {
- eval_position(board)
- } else {
- 1.0 - eval_position(board)
- };
- return if pos_eval < f32::EPSILON || pos_eval > 1.0 - f32::EPSILON {
- pos_eval
- } else {
- 0.5
- };
+ return 0.0;
}
for current_move in PossibleMoves::moves(board) {
@@ -96,7 +87,11 @@ pub fn eval_singlethreaded(
pub fn eval_multithreaded(depth: usize, alpha: f32, beta: f32, board: CheckersBitBoard) -> f32 {
if depth <= 1 {
- eval_position(board)
+ if board.turn() == PieceColor::Dark {
+ eval_position(board)
+ } else {
+ 1.0 - eval_position(board)
+ }
} else {
let turn = board.turn();
let best_eval = Mutex::new(f32::NEG_INFINITY);
@@ -105,34 +100,47 @@ pub fn eval_multithreaded(depth: usize, alpha: f32, beta: f32, board: CheckersBi
let is_still_going = || *keep_going.read();
let get_alpha = || *alpha.read();
- PossibleMoves::moves(board)
- .into_iter()
- .par_bridge()
- .for_each(|current_move| {
- if is_still_going() {
- let board = unsafe { current_move.apply_to(board) };
- let current_eval = if board.turn() != turn {
- 1.0 - eval_singlethreaded(depth - 1, 1.0 - beta, 1.0 - get_alpha(), board)
- } else {
- eval_singlethreaded(depth - 1, get_alpha(), beta, board)
- };
-
- let mut best = best_eval.lock();
- if current_eval >= beta {
- *best = beta;
- let mut going_val = keep_going.write();
- *going_val = false;
- }
-
- if *best < current_eval {
- *best = current_eval;
- }
- if get_alpha() < *best {
- let mut alpha = alpha.write();
- *alpha = *best;
- }
+
+ let moves = PossibleMoves::moves(board);
+
+ if moves.is_empty() {
+ let pos_eval = if board.turn() == PieceColor::Dark {
+ eval_position(board)
+ } else {
+ 1.0 - eval_position(board)
+ };
+ return if pos_eval < f32::EPSILON || pos_eval > 1.0 - f32::EPSILON {
+ pos_eval
+ } else {
+ 0.5
+ };
+ }
+
+ moves.into_iter().par_bridge().for_each(|current_move| {
+ if is_still_going() {
+ let board = unsafe { current_move.apply_to(board) };
+ let current_eval = if board.turn() != turn {
+ 1.0 - eval_singlethreaded(depth - 1, 1.0 - beta, 1.0 - get_alpha(), board)
+ } else {
+ eval_singlethreaded(depth - 1, get_alpha(), beta, board)
+ };
+
+ let mut best = best_eval.lock();
+ if current_eval >= beta {
+ *best = beta;
+ let mut going_val = keep_going.write();
+ *going_val = false;
}
- });
+
+ if *best < current_eval {
+ *best = current_eval;
+ }
+ if get_alpha() < *best {
+ let mut alpha = alpha.write();
+ *alpha = *best;
+ }
+ }
+ });
best_eval.into_inner()
}
@@ -141,6 +149,12 @@ pub fn eval_multithreaded(depth: usize, alpha: f32, beta: f32, board: CheckersBi
pub fn best_move(depth: usize, board: CheckersBitBoard) -> Move {
let mut best_eval = 0.0;
let mut best_move = MaybeUninit::uninit();
+ let moves = PossibleMoves::moves(board);
+
+ if moves.is_empty() {
+ panic!("No moves are available")
+ }
+
for current_move in PossibleMoves::moves(board) {
let new_board = unsafe { current_move.apply_to(board) };
let mut current_eval = eval_multithreaded(depth - 1, best_eval, 1.0, new_board);
@@ -149,7 +163,7 @@ pub fn best_move(depth: usize, board: CheckersBitBoard) -> Move {
}
if current_eval > best_eval {
best_eval = current_eval;
- best_move = MaybeUninit::new(current_move);
+ best_move.write(current_move);
}
}
diff --git a/model/src/possible_moves.rs b/model/src/possible_moves.rs
index 2b8d9f3..0feee6e 100644
--- a/model/src/possible_moves.rs
+++ b/model/src/possible_moves.rs
@@ -32,6 +32,7 @@ pub struct PossibleMovesIter {
impl PossibleMovesIter {
fn add_slide_forward_left<const SQUARE: usize>(&mut self, possible_moves: PossibleMoves) {
if (possible_moves.forward_left_movers >> SQUARE) & 1 != 0 {
+ debug_assert!(self.length < POSSIBLE_MOVES_ITER_SIZE);
let ptr = unsafe { self.moves.as_mut().get_unchecked_mut(self.length) };
*ptr = MaybeUninit::new(Move::new(SQUARE, MoveDirection::ForwardLeft, false));
self.length += 1;
@@ -40,6 +41,7 @@ impl PossibleMovesIter {
fn add_slide_forward_right<const SQUARE: usize>(&mut self, possible_moves: PossibleMoves) {
if (possible_moves.forward_right_movers >> SQUARE) & 1 != 0 {
+ debug_assert!(self.length < POSSIBLE_MOVES_ITER_SIZE);
let ptr = unsafe { self.moves.as_mut().get_unchecked_mut(self.length) };
*ptr = MaybeUninit::new(Move::new(SQUARE, MoveDirection::ForwardRight, false));
self.length += 1;
@@ -48,6 +50,7 @@ impl PossibleMovesIter {
fn add_slide_backward_left<const SQUARE: usize>(&mut self, possible_moves: PossibleMoves) {
if (possible_moves.backward_left_movers >> SQUARE) & 1 != 0 {
+ debug_assert!(self.length < POSSIBLE_MOVES_ITER_SIZE);
let ptr = unsafe { self.moves.as_mut().get_unchecked_mut(self.length) };
*ptr = MaybeUninit::new(Move::new(SQUARE, MoveDirection::BackwardLeft, false));
self.length += 1;
@@ -56,6 +59,7 @@ impl PossibleMovesIter {
fn add_slide_backward_right<const SQUARE: usize>(&mut self, possible_moves: PossibleMoves) {
if (possible_moves.backward_right_movers >> SQUARE) & 1 != 0 {
+ debug_assert!(self.length < POSSIBLE_MOVES_ITER_SIZE);
let ptr = unsafe { self.moves.as_mut().get_unchecked_mut(self.length) };
*ptr = MaybeUninit::new(Move::new(SQUARE, MoveDirection::BackwardRight, false));
self.length += 1;
@@ -64,6 +68,7 @@ impl PossibleMovesIter {
fn add_jump_forward_left<const SQUARE: usize>(&mut self, possible_moves: PossibleMoves) {
if (possible_moves.forward_left_movers >> SQUARE) & 1 != 0 {
+ debug_assert!(self.length < POSSIBLE_MOVES_ITER_SIZE);
let ptr = unsafe { self.moves.as_mut().get_unchecked_mut(self.length) };
*ptr = MaybeUninit::new(Move::new(SQUARE, MoveDirection::ForwardLeft, true));
self.length += 1;
@@ -72,6 +77,7 @@ impl PossibleMovesIter {
fn add_jump_forward_right<const SQUARE: usize>(&mut self, possible_moves: PossibleMoves) {
if (possible_moves.forward_right_movers >> SQUARE) & 1 != 0 {
+ debug_assert!(self.length < POSSIBLE_MOVES_ITER_SIZE);
let ptr = unsafe { self.moves.as_mut().get_unchecked_mut(self.length) };
*ptr = MaybeUninit::new(Move::new(SQUARE, MoveDirection::ForwardRight, true));
self.length += 1;
@@ -80,6 +86,7 @@ impl PossibleMovesIter {
fn add_jump_backward_left<const SQUARE: usize>(&mut self, possible_moves: PossibleMoves) {
if (possible_moves.backward_left_movers >> SQUARE) & 1 != 0 {
+ debug_assert!(self.length < POSSIBLE_MOVES_ITER_SIZE);
let ptr = unsafe { self.moves.as_mut().get_unchecked_mut(self.length) };
*ptr = MaybeUninit::new(Move::new(SQUARE, MoveDirection::BackwardLeft, true));
self.length += 1;
@@ -88,6 +95,7 @@ impl PossibleMovesIter {
fn add_jump_backward_right<const SQUARE: usize>(&mut self, possible_moves: PossibleMoves) {
if (possible_moves.backward_right_movers >> SQUARE) & 1 != 0 {
+ debug_assert!(self.length < POSSIBLE_MOVES_ITER_SIZE);
let ptr = unsafe { self.moves.as_mut().get_unchecked_mut(self.length) };
*ptr = MaybeUninit::new(Move::new(SQUARE, MoveDirection::BackwardRight, true));
self.length += 1;
@@ -101,7 +109,7 @@ impl Iterator for PossibleMovesIter {
type Item = Move;
fn next(&mut self) -> Option<Self::Item> {
- if self.length != self.index {
+ if self.length > self.index {
let next_move = unsafe { self.moves.as_ref().get_unchecked(self.index).assume_init() };
self.index += 1;
Some(next_move)
@@ -129,7 +137,12 @@ impl Iterator for PossibleMovesIter {
where
Self: Sized,
{
- Some(unsafe { self.moves.as_ref().get_unchecked(self.length).assume_init() })
+ Some(unsafe {
+ self.moves
+ .as_ref()
+ .get_unchecked(self.length - 1)
+ .assume_init()
+ })
}
// TODO test
@@ -139,7 +152,7 @@ impl Iterator for PossibleMovesIter {
} else {
self.index += n;
let current_move =
- unsafe { self.moves.as_ref().get_unchecked(self.length).assume_init() };
+ unsafe { self.moves.as_ref().get_unchecked(self.index).assume_init() };
self.index += 1;
Some(current_move)
}
diff --git a/ui/src/main.rs b/ui/src/main.rs
index c25c0d7..37d1732 100644
--- a/ui/src/main.rs
+++ b/ui/src/main.rs
@@ -77,17 +77,20 @@ impl State for GameState {
// safety: this was determined to be in the list of possible moves
self.bit_board = unsafe { selected_move.apply_to(self.bit_board) };
+ self.evaluation = ai::eval_multithreaded(15, 0.0, 1.0, self.bit_board);
+ println!("{}", self.evaluation);
+
// ai makes a move
while self.bit_board.turn() == PieceColor::Light
&& !PossibleMoves::moves(self.bit_board).is_empty()
{
- let best_move = ai::best_move(12, self.bit_board);
+ let best_move = ai::best_move(15, self.bit_board);
self.bit_board = unsafe { best_move.apply_to(self.bit_board) };
}
self.selected_square = None;
self.possible_moves.clear();
- self.evaluation = ai::eval_multithreaded(12, 0.0, 1.0, self.bit_board);
+ self.evaluation = ai::eval_multithreaded(15, 0.0, 1.0, self.bit_board);
println!("{}", self.evaluation);
} else {
self.selected_square = Some(square);