Skip to content

Commit 2815d21

Browse files
authored
Merge pull request #13 from eboatwright/dev
v3.0.7
2 parents c688b35 + 7e90546 commit 2815d21

File tree

7 files changed

+52
-49
lines changed

7 files changed

+52
-49
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "maxwell"
3-
version = "3.0.5"
3+
version = "3.0.7"
44
edition = "2021"
55

66
[dependencies]

README.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@
2828
- History heuristic
2929
- Castling
3030
- Promotions
31-
- Boost for moving a piece to a square a friendly piece attacks
3231
- Penalty for moving a piece to a square an opponent's piece attacks
3332
#### Search
3433
- Iterative deepening

src/board.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -436,7 +436,7 @@ impl Board {
436436

437437
pub fn king_in_check(&mut self, king_is_white: bool) -> bool {
438438
self.calculate_attacked_squares_for_color((!king_is_white) as usize);
439-
self.piece_bitboards[if king_is_white { WHITE_KING } else { BLACK_KING }] & self.attacked_squares_bitboards[(!king_is_white) as usize] != 0
439+
self.piece_bitboards[build_piece(king_is_white, KING)] & self.attacked_squares_bitboards[(!king_is_white) as usize] != 0
440440
}
441441

442442
pub fn get_legal_moves_for_color(&mut self, white_pieces: bool, only_captures: bool) -> Vec<MoveData> {

src/bot.rs

Lines changed: 36 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ pub struct Bot {
3333
positions_searched: u128,
3434
quiescence_searched: u128,
3535
transposition_hits: u128,
36-
null_move_prunes: u128,
3736
}
3837

3938
impl Bot {
@@ -60,7 +59,6 @@ impl Bot {
6059
positions_searched: 0,
6160
quiescence_searched: 0,
6261
transposition_hits: 0,
63-
null_move_prunes: 0,
6462
}
6563
}
6664

@@ -93,18 +91,18 @@ impl Bot {
9391
self.positions_searched = 0;
9492
self.quiescence_searched = 0;
9593
self.transposition_hits = 0;
96-
self.null_move_prunes = 0;
9794

9895
self.move_sorter.clear();
9996

97+
let mut window = 40;
98+
10099
self.think_timer = Instant::now();
101100
for depth in 1..=(255 - MAX_SEARCH_EXTENSIONS) {
102101
self.searched_one_move = false;
103102
self.best_move_this_iteration = NULL_MOVE;
104103
self.evaluation_this_iteration = 0;
105104

106105

107-
let mut window = 40;
108106
loop {
109107
let (alpha, beta) = (last_evaluation - window, last_evaluation + window);
110108

@@ -124,7 +122,7 @@ impl Bot {
124122
self.evaluation = self.evaluation_this_iteration;
125123
}
126124

127-
println!("Depth: {}, Window: {}, Evaluation: {}, Best move: {}, Positions searched: {}, Quiescence positions searched: {}, Total: {}, Transposition Hits: {}, Null move prunes: {}",
125+
println!("Depth: {}, Window: {}, Evaluation: {}, Best move: {}, Positions searched: {} + Quiescence positions searched: {} = {}, Transposition Hits: {}",
128126
depth,
129127
window,
130128
self.evaluation * board.perspective(),
@@ -133,7 +131,6 @@ impl Bot {
133131
self.quiescence_searched,
134132
self.positions_searched + self.quiescence_searched,
135133
self.transposition_hits,
136-
self.null_move_prunes,
137134
);
138135

139136
if evaluation_is_mate(self.evaluation) {
@@ -196,37 +193,45 @@ impl Bot {
196193
return data.evaluation;
197194
}
198195

199-
// Razoring
200-
if depth_left == 3
196+
let is_pv = alpha != beta - 1;
197+
198+
if !is_pv
201199
&& depth > 0
202-
&& board.get_last_move().capture == NO_PIECE as u8
200+
&& depth_left > 0
203201
&& !board.king_in_check(board.white_to_move) {
204-
let evaluation = board.evaluate();
205-
if evaluation + QUEEN_WORTH < alpha {
206-
depth_left -= 1;
207-
}
208-
}
202+
// Null Move Pruning
203+
if depth_left >= 3
204+
&& board.try_null_move() {
205+
// let reduction = 3 - (depth_left - 3) / 2;
206+
let evaluation = -self.alpha_beta_search(board, depth + 1, depth_left - 3, -beta, -beta + 1, number_of_extensions);
209207

210-
if depth_left == 0 {
211-
return self.quiescence_search(board, alpha, beta);
212-
}
208+
board.undo_null_move();
213209

214-
let is_pv = alpha != beta - 1;
210+
if evaluation >= beta {
211+
return evaluation;
212+
}
213+
}
215214

216-
if !is_pv
217-
&& depth > 0
218-
&& depth_left >= 3
219-
&& board.try_null_move() {
220-
let evaluation = -self.alpha_beta_search(board, depth + 1, depth_left - 3, -beta, -beta + 1, number_of_extensions);
215+
let static_eval = board.evaluate();
221216

222-
board.undo_null_move();
217+
// Reverse Futility Pruning
218+
if depth_left <= 4
219+
&& static_eval - (70 * depth_left as i32) >= beta {
220+
return static_eval;
221+
}
223222

224-
if evaluation >= beta {
225-
self.null_move_prunes += 1;
226-
return evaluation;
223+
// Razoring
224+
if depth_left <= 3
225+
&& board.get_last_move().capture == NO_PIECE as u8
226+
&& static_eval + QUEEN_WORTH < alpha {
227+
depth_left -= 1;
227228
}
228229
}
229230

231+
if depth_left == 0 {
232+
return self.quiescence_search(board, alpha, beta);
233+
}
234+
230235
let mut best_move_this_search = NULL_MOVE;
231236
let mut node_type = NodeType::UpperBound;
232237

@@ -270,6 +275,7 @@ impl Bot {
270275

271276

272277

278+
// Late Move Reduction / (Kind of) Principal Variation Search
273279
let mut evaluation = 0;
274280
let mut needs_full_search = true;
275281

@@ -346,7 +352,9 @@ impl Bot {
346352
return evaluation;
347353
}
348354

349-
let sorted_moves = self.move_sorter.sort_moves(board, legal_moves, NULL_MOVE, 0);
355+
// Depth is set to u8::MAX because it's only used for killer moves, and we don't need that here
356+
let sorted_moves = self.move_sorter.sort_moves(board, legal_moves, NULL_MOVE, u8::MAX);
357+
350358
for m in sorted_moves {
351359
board.make_move(m);
352360
let evaluation = -self.quiescence_search(board, -beta, -alpha);

src/main.rs

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,27 @@
11
/* TODO
2-
try to stop Bot from getting it's queen kicked around
32
calculate my own magic numbers; currently "borrowing" Sebastian Lague's ^^
4-
check out pin detection for checks?
3+
check out pin detection to speed up check detection?
54
try to write a neural network to evaluate positions? :o
5+
figure out how to implement "pondering" to think on opponent's time
66
7-
Ideas I've tried but they made no impact (Or I implemented them wrong :P)
7+
Ideas I've tried, but they didn't help, or made it play worse (Or I implemented them wrong :P)
88
https://www.chessprogramming.org/Futility_Pruning
9-
https://www.chessprogramming.org/Reverse_Futility_Pruning
109
https://www.chessprogramming.org/Principal_Variation_Search
10+
https://www.chessprogramming.org/Internal_Iterative_Deepening
1111
1212
Random ideas to try (from other engines and chessprogramming.org)
13-
History reduction?
13+
History reduction
1414
https://www.chessprogramming.org/History_Leaf_Pruning
1515
https://www.chessprogramming.org/Futility_Pruning#MoveCountBasedPruning
1616
https://www.chessprogramming.org/Delta_Pruning
17-
https://www.chessprogramming.org/Internal_Iterative_Deepening
1817
https://www.chessprogramming.org/Triangular_PV-Table
1918
https://www.chessprogramming.org/Razoring (look into a better implementation)
2019
2120
Some random resources I found:
2221
https://analog-hors.github.io/site/magic-bitboards/ (didn't use this for my initial implementation, but that might change ;))
2322
https://web.archive.org/web/20071030220825/http://www.brucemo.com/compchess/programming/pvs.htm
24-
https://github.com/lynx-chess/Lynx
23+
https://github.com/lynx-chess/Lynx/
2524
https://github.com/Heiaha/Weiawaga/
26-
27-
v3.0.5 vs v3.0.4
28-
v1: 10 - 15 - (11 draws)
29-
v2: 12 - 14 - (10 draws)
30-
current: 13 - 9 - (14 draws)
3125
*/
3226

3327
#![allow(dead_code)]

src/move_sorter.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,10 @@ impl MoveSorter {
4040

4141
let endgame = board.endgame_multiplier();
4242

43-
// Mental note that this is here
44-
board.calculate_attacked_squares();
43+
// board.calculate_attacked_squares();
44+
board.calculate_attacked_squares_for_color((!board.white_to_move) as usize);
4545

46-
let squares_i_attack = board.attacked_squares_bitboards[board.white_to_move as usize];
46+
// let squares_i_attack = board.attacked_squares_bitboards[board.white_to_move as usize];
4747
let squares_opponent_attacks = board.attacked_squares_bitboards[!board.white_to_move as usize];
4848

4949
for i in 0..num_of_moves {
@@ -70,9 +70,9 @@ impl MoveSorter {
7070
score += 2000;
7171
}
7272

73-
if squares_i_attack & (1 << m.to) != 0 {
74-
score += get_full_worth_of_piece(m.piece as usize, m.to as usize, endgame);
75-
}
73+
// if squares_i_attack & (1 << m.to) != 0 {
74+
// score += get_full_worth_of_piece(m.piece as usize, m.to as usize, endgame);
75+
// }
7676

7777
if squares_opponent_attacks & (1 << m.to) != 0 {
7878
score -= 2 * get_full_worth_of_piece(m.piece as usize, m.to as usize, endgame);

src/opening_book.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ impl OpeningBook {
4343

4444
"Xc2c4 e7e5 b1c3 g8f6",
4545
"e2e4 c7c5 Xb1c3 b8c6 f1b5 c6d4 b5c4 a7a6 g1f3 b7b5 c4e2 c8b7 e1g1 e7e6 d2d3 d4e2 d1e2",
46+
47+
"e2e4 Xg7g6 d2d4 f8g7 b1c3 d7d6 c1e3",
4648
],
4749
}
4850
}

0 commit comments

Comments
 (0)