File size: 1,745 Bytes
3014f14
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
// movepick.rs
use crate::types::{Move, PieceType};
use crate::position::Position;

// MVV-LVA [Victim][Attacker]
const MVV_LVA: [[i32; 7]; 7] = [
    [0; 7],
    [0, 105, 205, 305, 405, 505, 605], // Victim Pawn
    [0, 104, 204, 304, 404, 504, 604], // Victim Knight
    [0, 103, 203, 303, 403, 503, 603], // Victim Bishop
    [0, 102, 202, 302, 402, 502, 602], // Victim Rook
    [0, 101, 201, 301, 401, 501, 601], // Victim Queen
    [0, 100, 200, 300, 400, 500, 600], // Victim King
];

pub fn score_moves(pos: &Position, moves: &mut [(Move, i32)], tt_move: Move, killer1: Move, killer2: Move) {
    for (m, score) in moves.iter_mut() {
        if *m == tt_move {
            *score = 2000000; // Best move from Transposition Table
            continue;
        }

        let captured = pos.get_piece_at(m.to());
        if captured != PieceType::None {
            let attacker = pos.get_piece_at(m.from());
            *score = 1000000 + MVV_LVA[captured as usize][attacker as usize];
        } else if *m == killer1 {
            *score = 900000;
        } else if *m == killer2 {
            *score = 800000;
        } else {
            if m.promotion() != PieceType::None {
                *score = 700000; // Promote to a piece
            } else {
                *score = 0; // Quiet moves will be ordered by history heuristic eventually
            }
        }
    }
}

pub fn pick_next_move(moves: &mut [(Move, i32)], start_idx: usize) -> Move {
    let mut best_idx = start_idx;
    let mut best_score = -1;

    for i in start_idx..moves.len() {
        if moves[i].1 > best_score {
            best_score = moves[i].1;
            best_idx = i;
        }
    }

    moves.swap(start_idx, best_idx);
    moves[start_idx].0
}