|
@@ -262,7 +262,8 @@ enum SortingState {
|
|
Captures,
|
|
Captures,
|
|
Killers,
|
|
Killers,
|
|
Counter,
|
|
Counter,
|
|
- Quiets
|
|
|
|
|
|
+ Quiets,
|
|
|
|
+ LosingCaptures,
|
|
}
|
|
}
|
|
|
|
|
|
///
|
|
///
|
|
@@ -276,6 +277,7 @@ pub struct MoveGenerator {
|
|
captures: Vec<(Move, i32)>,
|
|
captures: Vec<(Move, i32)>,
|
|
counters: Vec<(Move, i16)>,
|
|
counters: Vec<(Move, i16)>,
|
|
quiets: Vec<Move>,
|
|
quiets: Vec<Move>,
|
|
|
|
+ losing_captures: Vec<(Move, i32)>,
|
|
|
|
|
|
state: SortingState,
|
|
state: SortingState,
|
|
|
|
|
|
@@ -296,6 +298,7 @@ impl MoveGenerator {
|
|
captures: Vec::with_capacity(32),
|
|
captures: Vec::with_capacity(32),
|
|
counters: Vec::with_capacity(32),
|
|
counters: Vec::with_capacity(32),
|
|
quiets: Vec::with_capacity(32),
|
|
quiets: Vec::with_capacity(32),
|
|
|
|
+ losing_captures: Vec::with_capacity(32),
|
|
state: if ce.is_some() { SortingState::PvMove } else { SortingState::Captures },
|
|
state: if ce.is_some() { SortingState::PvMove } else { SortingState::Captures },
|
|
pv_move: ce.map(|e| e.mov),
|
|
pv_move: ce.map(|e| e.mov),
|
|
killers: killers.to_vec(),
|
|
killers: killers.to_vec(),
|
|
@@ -310,8 +313,7 @@ impl MoveGenerator {
|
|
}
|
|
}
|
|
|
|
|
|
pub fn is_late(&self) -> bool {
|
|
pub fn is_late(&self) -> bool {
|
|
- //self.is_late
|
|
|
|
- self.state == SortingState::Quiets
|
|
|
|
|
|
+ self.is_late
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -335,7 +337,13 @@ impl Iterator for MoveGenerator {
|
|
if self.captures.is_empty() {
|
|
if self.captures.is_empty() {
|
|
for m in &self.moves {
|
|
for m in &self.moves {
|
|
if m.is_capture() {
|
|
if m.is_capture() {
|
|
- self.captures.push((*m, calculate_see(self.board.clone(), *m, self.board.turn)));
|
|
|
|
|
|
+ let see = calculate_see(self.board.clone(), *m, self.board.turn);
|
|
|
|
+ if see >= 0 {
|
|
|
|
+ self.captures.push((*m, see));
|
|
|
|
+ }
|
|
|
|
+ else {
|
|
|
|
+ self.losing_captures.push((*m, see));
|
|
|
|
+ }
|
|
}
|
|
}
|
|
else {
|
|
else {
|
|
self.quiets.push(*m);
|
|
self.quiets.push(*m);
|
|
@@ -416,12 +424,34 @@ impl Iterator for MoveGenerator {
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
+ self.is_late = true;
|
|
if let Some(p) = promo {
|
|
if let Some(p) = promo {
|
|
self.quiets.retain(|m| *m != p);
|
|
self.quiets.retain(|m| *m != p);
|
|
return Some(p);
|
|
return Some(p);
|
|
}
|
|
}
|
|
- return self.quiets.pop();
|
|
|
|
|
|
+
|
|
|
|
+ if let Some(last) = self.quiets.pop() {
|
|
|
|
+ return Some(last);
|
|
|
|
+ }
|
|
|
|
+ else {
|
|
|
|
+ self.state = SortingState::LosingCaptures;
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
},
|
|
},
|
|
|
|
+ SortingState::LosingCaptures => {
|
|
|
|
+ let mut best_score = crate::evaluate::MIN_VALUE;
|
|
|
|
+ let mut best_move: Option<Move> = None;
|
|
|
|
+
|
|
|
|
+ for (c, score) in &self.losing_captures {
|
|
|
|
+ if *score > best_score {
|
|
|
|
+ best_move = Some(*c);
|
|
|
|
+ best_score = *score;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ self.losing_captures.retain(|(m, _s)| Some(*m) != best_move);
|
|
|
|
+ return best_move;
|
|
|
|
+ }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -631,7 +661,7 @@ pub fn sort_moves(game: &mut Board, hash: &mut Cache, killers: &[Move], move_lis
|
|
/// assigns a score to capture moves lower the more valuable the captured piece. Secondly
|
|
/// assigns a score to capture moves lower the more valuable the captured piece. Secondly
|
|
/// also higher the more the attacking piece is worth.
|
|
/// also higher the more the attacking piece is worth.
|
|
///
|
|
///
|
|
-fn mvv_lva_score(mov: &Move) -> i32 {
|
|
|
|
|
|
+pub fn mvv_lva_score(mov: &Move) -> i32 {
|
|
const PIECE_VALUES: [i32; 6] = [
|
|
const PIECE_VALUES: [i32; 6] = [
|
|
100, // Pawn
|
|
100, // Pawn
|
|
220, // Knight
|
|
220, // Knight
|