-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #61 from emilio-zuniga/uci-testing
Add UCI
- Loading branch information
Showing
16 changed files
with
1,690 additions
and
1,256 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
use vampirc_uci::UciMove; | ||
|
||
use crate::{gamemanager::GameManager, movetable::{noarc::NoArc, MoveTable}}; | ||
|
||
pub struct Engine { | ||
pub tbl: NoArc<MoveTable>, | ||
pub move_history: Vec<UciMove>, | ||
pub board: GameManager, | ||
//pub set_new_game: bool, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
pub struct Heatmap { | ||
pub pawns_start: [i32; 64], | ||
pub pawns_end: [i32; 64], | ||
pub knights: [i32; 64], | ||
pub bishops: [i32; 64], | ||
pub rooks: [i32; 64], | ||
pub queens: [i32; 64], | ||
pub kings_start: [i32; 64], | ||
pub kings_end: [i32; 64], | ||
} | ||
|
||
impl Default for Heatmap { | ||
/// Returns the heatmaps for white. | ||
/// Use .rev() to get the heatmaps for black. | ||
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, | ||
5, 5, 10, 25, 25, 10, 5, 5, 0, 0, 0, 20, 20, 0, 0, 0, 5, -5, -10, 0, 0, -10, -5, 5, 5, | ||
10, 10, -20, -20, 10, 10, 5, 0, 0, 0, 0, 0, 0, 0, 0, | ||
]; | ||
|
||
let pawns_end = [ | ||
0, 0, 0, 0, 0, 0, 0, 0, 80, 80, 80, 80, 80, 80, 80, 80, 50, 50, 50, 50, 50, 50, 50, 50, | ||
30, 30, 30, 30, 30, 30, 30, 30, 20, 20, 20, 20, 20, 20, 20, 20, 10, 10, 10, 10, 10, 10, | ||
10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, | ||
]; | ||
|
||
let knights = [ | ||
-50, -40, -30, -30, -30, -30, -40, -50, -40, -20, 0, 0, 0, 0, -20, -40, -30, 0, 10, 15, | ||
15, 10, 0, -30, -30, 5, 15, 20, 20, 15, 5, -30, -30, 0, 15, 20, 20, 15, 0, -30, -30, 5, | ||
10, 15, 15, 10, 5, -30, -40, -20, 0, 5, 5, 0, -20, -40, -50, -40, -30, -30, -30, -30, | ||
-40, -50, | ||
]; | ||
|
||
let bishops = [ | ||
-20, -10, -10, -10, -10, -10, -10, -20, -10, 0, 0, 0, 0, 0, 0, -10, -10, 0, 5, 10, 10, | ||
5, 0, -10, -10, 5, 5, 10, 10, 5, 5, -10, -10, 0, 10, 10, 10, 10, 0, -10, -10, 10, 10, | ||
10, 10, 10, 10, -10, -10, 5, 0, 0, 0, 0, 5, -10, -20, -10, -10, -10, -10, -10, -10, | ||
-20, | ||
]; | ||
|
||
let rooks = [ | ||
0, 0, 0, 0, 0, 0, 0, 0, 5, 10, 10, 10, 10, 10, 10, 5, -5, 0, 0, 0, 0, 0, 0, -5, -5, 0, | ||
0, 0, 0, 0, 0, -5, -5, 0, 0, 0, 0, 0, 0, -5, -5, 0, 0, 0, 0, 0, 0, -5, -5, 0, 0, 0, 0, | ||
0, 0, -5, 0, 0, 0, 5, 5, 0, 0, 0, | ||
]; | ||
|
||
let queens = [ | ||
-20, -10, -10, -5, -5, -10, -10, -20, -10, 0, 0, 0, 0, 0, 0, -10, -10, 0, 5, 5, 5, 5, | ||
0, -10, -5, 0, 5, 5, 5, 5, 0, -5, 0, 0, 5, 5, 5, 5, 0, -5, -10, 5, 5, 5, 5, 5, 0, -10, | ||
-10, 0, 5, 0, 0, 0, 0, -10, -20, -10, -10, -5, -5, -10, -10, -20, | ||
]; | ||
|
||
let kings_start = [ | ||
-80, -70, -70, -70, -70, -70, -70, -80, -60, -60, -60, -60, -60, -60, -60, -60, -40, | ||
-50, -50, -60, -60, -50, -50, -40, -30, -40, -40, -50, -50, -40, -40, -30, -20, -30, | ||
-30, -40, -40, -30, -30, -20, -10, -20, -20, -20, -20, -20, -20, -10, 20, 20, -5, -5, | ||
-5, -5, 20, 20, 20, 30, 10, 0, 0, 10, 30, 20, | ||
]; | ||
|
||
let kings_end = [ | ||
-20, -10, -10, -10, -10, -10, -10, -20, -5, 0, 5, 5, 5, 5, 0, -5, -10, -5, 20, 30, 30, | ||
20, -5, -10, -15, -10, 35, 45, 45, 35, -10, -15, -20, -15, 30, 40, 40, 30, -15, -20, | ||
-25, -20, 20, 25, 25, 20, -20, -25, -30, -25, 0, 0, 0, 0, -25, -30, -50, -30, -30, -30, | ||
-30, -30, -30, -50, | ||
]; | ||
|
||
Self { | ||
pawns_start, | ||
pawns_end, | ||
knights, | ||
bishops, | ||
rooks, | ||
queens, | ||
kings_start, | ||
kings_end, | ||
} | ||
} | ||
} | ||
|
||
impl Heatmap { | ||
/// Returns the heatmap for black, if the provided | ||
/// heatmap is for white, and vice versa. | ||
pub fn rev(&self) -> Self { | ||
Self { | ||
pawns_start: reverse_array(self.pawns_start), | ||
pawns_end: reverse_array(self.pawns_end), | ||
knights: reverse_array(self.knights), | ||
bishops: reverse_array(self.bishops), | ||
rooks: reverse_array(self.rooks), | ||
queens: reverse_array(self.queens), | ||
kings_start: reverse_array(self.kings_start), | ||
kings_end: reverse_array(self.kings_end), | ||
} | ||
} | ||
} | ||
|
||
fn reverse_array(arr: [i32; 64]) -> [i32; 64] { | ||
let mut ret = [0; 64]; | ||
|
||
// All heatmaps are symmetric about the central vertical axis. | ||
for (idx, v) in arr.into_iter().rev().enumerate() { | ||
ret[idx] = v; | ||
} | ||
ret | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
use heatmaps::Heatmap; | ||
|
||
use crate::{ | ||
bitboard::BitBoard, | ||
types::{Color, MoveType, PieceType}, | ||
}; | ||
|
||
use super::GameManager; | ||
|
||
mod heatmaps; | ||
|
||
const START_MASS: i32 = PieceType::Queen as i32 | ||
+ PieceType::Rook as i32 * 2 | ||
+ PieceType::Bishop as i32 * 2 | ||
+ PieceType::Knight as i32 * 2 | ||
+ PieceType::Pawn as i32 * 8; | ||
|
||
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 heatmap = heatmaps::Heatmap::default(); | ||
|
||
let endgame_weight = mass_score * 100 / START_MASS; | ||
|
||
let position_score = | ||
eval_heatmaps(Color::Black, self.bitboard, heatmap, endgame_weight); | ||
|
||
position_score + mass_score | ||
} else { | ||
// Ditto for white. | ||
let mass_score = self.bitboard.piece_mass(Color::White) + movetype_weight(movetype); | ||
let heatmap = heatmaps::Heatmap::default().rev(); | ||
|
||
let endgame_weight = mass_score * 100 / START_MASS; | ||
|
||
let position_score = | ||
eval_heatmaps(Color::White, self.bitboard, heatmap, endgame_weight); | ||
|
||
position_score + mass_score | ||
} | ||
} | ||
} | ||
|
||
fn movetype_weight(mt: MoveType) -> i32 { | ||
use MoveType::*; | ||
use PieceType::*; | ||
match mt { | ||
QPromotion => Queen as i32, | ||
QPromoCapture => Queen as i32 + 50, | ||
RPromotion => Rook as i32, | ||
RPromoCapture => Rook as i32 + 50, | ||
BPromotion => Bishop as i32, | ||
BPromoCapture => Bishop as i32 + 50, | ||
NPromotion => Knight as i32, | ||
NPromoCapture => Knight as i32 + 50, | ||
EPCapture => Pawn as i32, | ||
Capture => 400, | ||
_ => 0, | ||
} | ||
} | ||
|
||
fn eval_heatmaps(color: Color, board: BitBoard, map: Heatmap, endgame_weight: i32) -> i32 { | ||
let base_value = match color { | ||
Color::Black => { | ||
eval_heatmap(map.knights, board.knights_black) | ||
+ eval_heatmap(map.bishops, board.bishops_black) | ||
+ eval_heatmap(map.rooks, board.rooks_black) | ||
+ eval_heatmap(map.queens, board.queens_black) | ||
} | ||
Color::White => { | ||
eval_heatmap(map.knights, board.knights_white) | ||
+ eval_heatmap(map.bishops, board.bishops_white) | ||
+ eval_heatmap(map.rooks, board.rooks_white) | ||
+ eval_heatmap(map.queens, board.queens_white) | ||
} | ||
}; | ||
|
||
let weighted_value = match color { | ||
Color::Black => { | ||
eval_heatmap(map.pawns_start, board.pawns_black) * (100 - endgame_weight) | ||
+ eval_heatmap(map.pawns_end, board.pawns_black) * endgame_weight | ||
+ eval_heatmap(map.kings_start, board.king_black) * (100 - endgame_weight) | ||
+ eval_heatmap(map.kings_end, board.king_black) * endgame_weight | ||
} | ||
Color::White => { | ||
eval_heatmap(map.pawns_start, board.pawns_white) * (100 - endgame_weight) | ||
+ eval_heatmap(map.pawns_end, board.pawns_white) * endgame_weight | ||
+ eval_heatmap(map.kings_start, board.king_white) * (100 - endgame_weight) | ||
+ eval_heatmap(map.kings_end, board.king_white) * endgame_weight | ||
} | ||
}; | ||
|
||
base_value + weighted_value | ||
} | ||
|
||
fn eval_heatmap(table: [i32; 64], bits: u64) -> i32 { | ||
let mut score = 0; | ||
let split_bits = split_bits(bits); | ||
for idx in 0..64 { | ||
score += table[idx] * split_bits[idx] as i32; | ||
} | ||
score | ||
} | ||
|
||
fn split_bits(int: u64) -> [u8; 64] { | ||
let mut bits = [0u8; 64]; | ||
for idx in 0..64 { | ||
bits[idx] = ((int >> idx) & 1) as u8; | ||
} | ||
bits | ||
} |
Oops, something went wrong.