Skip to content

Commit

Permalink
Merge pull request #62 from emilio-zuniga/search
Browse files Browse the repository at this point in the history
Search
  • Loading branch information
ethanbarry authored Nov 29, 2024
2 parents 5e824a3 + 1478f13 commit 5f22b28
Show file tree
Hide file tree
Showing 5 changed files with 42 additions and 29 deletions.
8 changes: 4 additions & 4 deletions src/gamemanager/evaluation/heatmaps.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ pub struct Heatmap {
}

impl Default for Heatmap {
/// Returns the heatmaps for white.
/// Use .rev() to get the heatmaps for black.
/// Returns the heatmaps for black.
/// Use .rev() to get the heatmaps for white.
fn default() -> Self {
let pawns_start = [
0, 0, 0, 0, 0, 0, 0, 0, 50, 50, 50, 50, 50, 50, 50, 50, 10, 10, 20, 30, 30, 20, 10, 10,
Expand Down Expand Up @@ -79,8 +79,8 @@ impl Default for Heatmap {
}

impl Heatmap {
/// Returns the heatmap for black, if the provided
/// heatmap is for white, and vice versa.
/// Returns the heatmap for white, if the provided
/// heatmap is for black, and vice versa.
pub fn rev(&self) -> Self {
Self {
pawns_start: reverse_array(self.pawns_start),
Expand Down
17 changes: 9 additions & 8 deletions src/gamemanager/evaluation/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,26 +19,28 @@ impl GameManager {
pub fn evaluate(&self, movetype: MoveType) -> i32 {
if self.white_to_move {
// Evaluate for black; better or worse after its move?
let mass_score = self.bitboard.piece_mass(Color::Black) + movetype_weight(movetype);
let mass_score = self.bitboard.piece_mass(Color::Black);
let heatmap = heatmaps::Heatmap::default();

let endgame_weight = mass_score * 100 / START_MASS;
// endgame_weight shows how close we are to the endgame. The more pieces our side has, the further
// it is from the end of the game, and the fewer, the closer to the end of the game.
let endgame_weight = (mass_score / START_MASS) * 100;

let position_score =
eval_heatmaps(Color::Black, self.bitboard, heatmap, endgame_weight);

position_score + mass_score
position_score + mass_score + movetype_weight(movetype)
} else {
// Ditto for white.
let mass_score = self.bitboard.piece_mass(Color::White) + movetype_weight(movetype);
let mass_score = self.bitboard.piece_mass(Color::White);
let heatmap = heatmaps::Heatmap::default().rev();

let endgame_weight = mass_score * 100 / START_MASS;
let endgame_weight = (mass_score / START_MASS) * 100;

let position_score =
eval_heatmaps(Color::White, self.bitboard, heatmap, endgame_weight);

position_score + mass_score
position_score + mass_score + movetype_weight(movetype)
}
}
}
Expand All @@ -55,8 +57,7 @@ fn movetype_weight(mt: MoveType) -> i32 {
BPromoCapture => Bishop as i32 + 50,
NPromotion => Knight as i32,
NPromoCapture => Knight as i32 + 50,
EPCapture => Pawn as i32,
Capture => 400,
Capture => 500,
_ => 0,
}
}
Expand Down
35 changes: 19 additions & 16 deletions src/gamemanager/legal_moves/search.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,20 @@ pub fn root_negamax(depth: u16, gm: GameManager, tbl: &NoArc<MoveTable>) -> (Mov
.map(|(s, movetuple)| (s, (movetuple.0, movetuple.1)))
.collect();

scored_moves.sort_by(|a, b| a.0.cmp(&b.0));
if depth % 2 == 0 {
scored_moves.sort_by(|a, b| a.0.cmp(&b.0));
} else {
scored_moves.sort_by(|a, b| a.0.cmp(&b.0));
}

// Little bit of debugging code.
let _ = scored_moves
.iter()
.for_each(|m| println!("{}: {}{}", m.0, m.1 .0 .1.to_str(), m.1 .0 .2.to_str()));
let best = scored_moves
.into_iter()
.inspect(|m| println!("{}: {}{}", m.0, m.1 .0 .1.to_str(), m.1 .0 .2.to_str()))
.last()
.expect("Should be a move here!");

scored_moves.pop().expect("There'll be a move!").1
println!("Best score: {}", best.0);
best.1
}

fn negamax(
Expand All @@ -54,22 +60,19 @@ fn negamax(
let moves = gm.legal_moves(tbl);

if moves.len() == 0 {
return i32::MIN + 1; // It's a pretty bad outcome to have no moves,
// but stalemates shouldn't count so hard against us.
return i32::MIN + 1; // Return value of node.
}

let mut score = i32::MIN + 1;
for mv in moves {
// Call negamax and negate it's return value. Enemy's alpha is our -beta & v.v.
let score = -negamax(depth - 1, -beta, -alpha, mv.3, &mv.4, tbl);

if score >= beta {
return beta;
}
if score > alpha {
alpha = score;
score = score.max(-negamax(depth - 1, -beta, -alpha, mv.3, &mv.4, tbl));
alpha = alpha.max(score);
if alpha >= beta {
break;
}
}
alpha
score
}
}

Expand Down
9 changes: 9 additions & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,16 @@ mod ucimanager;
mod enginemanager;

fn main() {

let tbl = noarc::NoArc::new(MoveTable::default());

let gm =
GameManager::from_fen_str("rn1b1k1r/p4ppp/1pp5/8/2B5/3n4/PPP1N1PP/RNBQ1K1R w - - 0 11");
let bestmove = root_negamax(4, gm, &tbl).0;
println!("Best move: {}{}", bestmove.1.to_str(), bestmove.2.to_str())

ucimanager::communicate();

}

#[cfg(test)]
Expand Down
2 changes: 1 addition & 1 deletion src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use std::fmt::Display;
#[derive(Debug, Clone, Eq, Hash, PartialEq)]
pub enum PieceType {
King,
Queen = 900,
Queen = 1000,
Rook = 500,
Bishop = 320,
Knight = 300,
Expand Down

0 comments on commit 5f22b28

Please sign in to comment.