const std = @import("std"); const Chess = @import("Chess.zig"); const BitMove = @import("Board.zig").BitMove; const BitMoveType = @import("Board.zig").BitMoveType; const Search = @import("Search.zig").Search; const Square = @import("Board.zig").Square; const MoveList = @import("Board.zig").MoveList; // These values are arbitrary, but only decreasing makes sense. const CAPTURE_BOOST = 10_000; const KILLER_FIRST = 9_000; const KILLER_SECOND = 8_000; // PV value score pub const PV_SCORE = 20_000; // Best move score const BEST_MOVE_SCORE = 30_000; // Killer moves [first/second][MAX_PLY] pub var killer_moves: [2][64]BitMove = undefined; // History moves [piece][square] pub var history_moves: [@typeInfo(Chess.PE).Enum.fields.len - 1][@typeInfo(Square).Enum.fields.len]usize = undefined; pub fn moves(search: *const Search, ml: *MoveList, best: BitMove) void { for (ml.slice()) |*mp| { mp.score = scoreMove(search, mp.move, best); } } fn scoreMove(search: *const Search, move: BitMove, best: BitMove) isize { if (@as(BitMoveType, @bitCast(move)) == @as(BitMoveType, @bitCast(best))) { return BEST_MOVE_SCORE; } if (move.capture) { var target_piece = Chess.PE.P; // this could be p as well const pieces = switch (search.state.side) { .white => &[_]Chess.PE{ .p, .n, .b, .r, .q, .k }, .black => &[_]Chess.PE{ .P, .N, .B, .R, .Q, .K }, }; for (pieces) |piece| { if (search.state.bitboards[@intFromEnum(piece)].isSet(move.target)) { target_piece = piece; break; } } return MVV_LVA[@intFromEnum(move.piece)][@intFromEnum(target_piece)] + CAPTURE_BOOST; } else { // score 1st killer move if (@as(BitMoveType, @bitCast(killer_moves[0][search.ply])) == @as(BitMoveType, @bitCast(move))) { return KILLER_FIRST; } // score 2nd killer move else if (@as(BitMoveType, @bitCast(killer_moves[1][search.ply])) == @as(BitMoveType, @bitCast(move))) { return KILLER_SECOND; } // score history moves else { return @as( isize, @intCast(history_moves[@intFromEnum(move.piece)][@intFromEnum(move.target)]), ); } return 0; } return 0; } // most valuable victim & less valuable attacker // (Victims) Pawn Knight Bishop Rook Queen King // (Attackers) // Pawn 105 205 305 405 505 605 // Knight 104 204 304 404 504 604 // Bishop 103 203 303 403 503 603 // Rook 102 202 302 402 502 602 // Queen 101 201 301 401 501 601 // King 100 200 300 400 500 600 // MVV LVA [attacker][victim] const MVV_LVA: [12][12]isize = .{ .{ 105, 205, 305, 405, 505, 605, 105, 205, 305, 405, 505, 605 }, .{ 104, 204, 304, 404, 504, 604, 104, 204, 304, 404, 504, 604 }, .{ 103, 203, 303, 403, 503, 603, 103, 203, 303, 403, 503, 603 }, .{ 102, 202, 302, 402, 502, 602, 102, 202, 302, 402, 502, 602 }, .{ 101, 201, 301, 401, 501, 601, 101, 201, 301, 401, 501, 601 }, .{ 100, 200, 300, 400, 500, 600, 100, 200, 300, 400, 500, 600 }, .{ 105, 205, 305, 405, 505, 605, 105, 205, 305, 405, 505, 605 }, .{ 104, 204, 304, 404, 504, 604, 104, 204, 304, 404, 504, 604 }, .{ 103, 203, 303, 403, 503, 603, 103, 203, 303, 403, 503, 603 }, .{ 102, 202, 302, 402, 502, 602, 102, 202, 302, 402, 502, 602 }, .{ 101, 201, 301, 401, 501, 601, 101, 201, 301, 401, 501, 601 }, .{ 100, 200, 300, 400, 500, 600, 100, 200, 300, 400, 500, 600 }, };