pleco 0.5.0

A blazingly-fast chess library.
Documentation
use {Player,SQ,File,Piece};
use core::masks::*;
use core::score::*;

const BONUS: [[[Score; (FILE_CNT / 2)]; RANK_CNT]; PIECE_TYPE_CNT] = [
    [    // NO PIECE
        [ Score(0, 0), Score(0, 0), Score(0, 0), Score(0, 0)],
        [ Score(0, 0), Score(0, 0), Score(0, 0), Score(0, 0)],
        [ Score(0, 0), Score(0, 0), Score(0, 0), Score(0, 0)],
        [ Score(0, 0), Score(0, 0), Score(0, 0), Score(0, 0)],
        [ Score(0, 0), Score(0, 0), Score(0, 0), Score(0, 0)],
        [ Score(0, 0), Score(0, 0), Score(0, 0), Score(0, 0)],
        [ Score(0, 0), Score(0, 0), Score(0, 0), Score(0, 0)],
        [ Score(0, 0), Score(0, 0), Score(0, 0), Score(0, 0)],
    ],
    [ // Pawn
        [ Score(  0, 0), Score(  0, 0), Score(  0, 0), Score( 0, 0) ],
        [ Score(-11, 7), Score(  6,-4), Score(  7, 8), Score( 3,-2) ],
        [ Score(-18,-4), Score( -2,-5), Score( 19, 5), Score(24, 4) ],
        [ Score(-17, 3), Score( -9, 3), Score( 20,-8), Score(35,-3) ],
        [ Score( -6, 8), Score(  5, 9), Score(  3, 7), Score(21,-6) ],
        [ Score( -6, 8), Score( -8,-5), Score( -6, 2), Score(-2, 4) ],
        [ Score( -4, 3), Score( 20,-9), Score( -8, 1), Score(-4,18) ],
        [ Score(  0, 0), Score(  0, 0), Score(  0, 0), Score( 0, 0) ]
    ],
    [ // Knight
        [ Score(-161,-105), Score(-96,-82), Score(-80,-46), Score(-73,-14) ],
        [ Score( -83, -69), Score(-43,-54), Score(-21,-17), Score(-10,  9) ],
        [ Score( -71, -50), Score(-22,-39), Score(  0, -7), Score(  9, 28) ],
        [ Score( -25, -41), Score( 18,-25), Score( 43,  6), Score( 47, 38) ],
        [ Score( -26, -46), Score( 16,-25), Score( 38,  3), Score( 50, 40) ],
        [ Score( -11, -54), Score( 37,-38), Score( 56, -7), Score( 65, 27) ],
        [ Score( -63, -65), Score(-19,-50), Score(  5,-24), Score( 14, 13) ],
        [ Score(-195,-109), Score(-67,-89), Score(-42,-50), Score(-29,-13) ]
    ],
    [ // Bishop
        [ Score(-44,-58), Score(-13,-31), Score(-25,-37), Score(-34,-19) ],
        [ Score(-20,-34), Score( 20, -9), Score( 12,-14), Score(  1,  4) ],
        [ Score( -9,-23), Score( 27,  0), Score( 21, -3), Score( 11, 16) ],
        [ Score(-11,-26), Score( 28, -3), Score( 21, -5), Score( 10, 16) ],
        [ Score(-11,-26), Score( 27, -4), Score( 16, -7), Score(  9, 14) ],
        [ Score(-17,-24), Score( 16, -2), Score( 12,  0), Score(  2, 13) ],
        [ Score(-23,-34), Score( 17,-10), Score(  6,-12), Score( -2,  6) ],
        [ Score(-35,-55), Score(-11,-32), Score(-19,-36), Score(-29,-17) ]
    ],
    [ // Rook
        [ Score(-25, 0), Score(-16, 0), Score(-16, 0), Score(-9, 0) ],
        [ Score(-21, 0), Score( -8, 0), Score( -3, 0), Score( 0, 0) ],
        [ Score(-21, 0), Score( -9, 0), Score( -4, 0), Score( 2, 0) ],
        [ Score(-22, 0), Score( -6, 0), Score( -1, 0), Score( 2, 0) ],
        [ Score(-22, 0), Score( -7, 0), Score(  0, 0), Score( 1, 0) ],
        [ Score(-21, 0), Score( -7, 0), Score(  0, 0), Score( 2, 0) ],
        [ Score(-12, 0), Score(  4, 0), Score(  8, 0), Score(12, 0) ],
        [ Score(-23, 0), Score(-15, 0), Score(-11, 0), Score(-5, 0) ]
    ],
    [ // Queen
        [ Score( 0,-71), Score(-4,-56), Score(-3,-42), Score(-1,-29) ],
        [ Score(-4,-56), Score( 6,-30), Score( 9,-21), Score( 8, -5) ],
        [ Score(-2,-39), Score( 6,-17), Score( 9, -8), Score( 9,  5) ],
        [ Score(-1,-29), Score( 8, -5), Score(10,  9), Score( 7, 19) ],
        [ Score(-3,-27), Score( 9, -5), Score( 8, 10), Score( 7, 21) ],
        [ Score(-2,-40), Score( 6,-16), Score( 8,-10), Score(10,  3) ],
        [ Score(-2,-55), Score( 7,-30), Score( 7,-21), Score( 6, -6) ],
        [ Score(-1,-74), Score(-4,-55), Score(-1,-43), Score( 0,-30) ]
    ],
    [ // King
        [ Score(267,  0), Score(320, 48), Score(270, 75), Score(195, 84) ],
        [ Score(264, 43), Score(304, 92), Score(238,143), Score(180,132) ],
        [ Score(200, 83), Score(245,138), Score(176,167), Score(110,165) ],
        [ Score(177,106), Score(185,169), Score(148,169), Score(110,179) ],
        [ Score(149,108), Score(177,163), Score(115,200), Score( 66,203) ],
        [ Score(118, 95), Score(159,155), Score( 84,176), Score( 41,174) ],
        [ Score( 87, 50), Score(128, 99), Score( 63,122), Score( 20,139) ],
        [ Score( 63,  9), Score( 88, 55), Score( 47, 80), Score(  0, 90) ]
    ],
    [    // ALL PIECE
        [ Score(0, 0), Score(0, 0), Score(0, 0), Score(0, 0)],
        [ Score(0, 0), Score(0, 0), Score(0, 0), Score(0, 0)],
        [ Score(0, 0), Score(0, 0), Score(0, 0), Score(0, 0)],
        [ Score(0, 0), Score(0, 0), Score(0, 0), Score(0, 0)],
        [ Score(0, 0), Score(0, 0), Score(0, 0), Score(0, 0)],
        [ Score(0, 0), Score(0, 0), Score(0, 0), Score(0, 0)],
        [ Score(0, 0), Score(0, 0), Score(0, 0), Score(0, 0)],
        [ Score(0, 0), Score(0, 0), Score(0, 0), Score(0, 0)],
    ]
];

static mut PSQ: [[Score; SQ_CNT]; PIECE_CNT] =
    [[Score(0,0); SQ_CNT]; PIECE_CNT];

static PIECE_VALUE: [[Value; PHASE_CNT]; PIECE_CNT] =
    [[0, 0],                 // Empty
    [ PAWN_MG,    PAWN_EG],  // White Pawn
    [ KNIGHT_MG,  KNIGHT_EG],// White Knight
    [ BISHOP_MG,  BISHOP_EG],// White Bishop
    [ ROOK_MG,    ROOK_EG],  // White Rook
    [ QUEEN_MG,   QUEEN_MG], // White Queen
    [ ZERO,       ZERO],     // White King
    [0, 0],
    [0, 0],                 // Empty
    [ PAWN_MG,    PAWN_EG],  // Black Pawn
    [ KNIGHT_MG,  KNIGHT_EG],// Black Knight
    [ BISHOP_MG,  BISHOP_EG],// Black Bishop
    [ ROOK_MG,    ROOK_EG],  // Black Rook
    [ QUEEN_MG,   QUEEN_MG], // Black Queen
    [ ZERO,       ZERO],     // Black King
    [0, 0],
    ];

#[cold]
pub fn init_psqt() {
    for piece in 0..PIECE_TYPE_CNT {
        let v: Score = Score(PIECE_VALUE[piece][0], PIECE_VALUE[piece][1]);
        for s in 0..SQ_CNT {
            let sq: SQ = SQ(s as u8);
            let f: File = sq.file().min(!sq.file());
            let score = v + BONUS[piece][sq.rank() as usize][f as usize];
            unsafe {
                PSQ[(Player::White as usize) << 3 | piece][s] = score;
                PSQ[(Player::Black as usize) << 3 | piece][sq.flip().0 as usize] = -score;
            }
        }
    }
}

/// Returns the score for a player's piece being at a particular square.
#[inline(always)]
pub fn psq(piece: Piece, sq: SQ) -> Score{
    debug_assert!(sq.is_okay());
    unsafe {
        *(PSQ.get_unchecked(piece as usize)).get_unchecked(sq.0 as usize)
    }
}

/// Returns the value of a piece for a player. If `eg` is true, it returns the end game value. Otherwise,
/// it'll return the midgame value.
#[inline(always)]
pub fn piece_value(piece: Piece, eg: bool) -> Value {
    unsafe {
        (*(PIECE_VALUE.get_unchecked(piece as usize)).get_unchecked(eg as usize))
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn psq_tes() {
        init_psqt();
        assert_eq!(psq(Piece::WhiteQueen, SQ::A1), -psq(Piece::BlackQueen, SQ::A8));
        assert_eq!(psq(Piece::WhiteRook, SQ::A1), -psq( Piece::BlackRook, SQ::A8));
        assert_eq!(psq(Piece::WhitePawn, SQ::B1), -psq( Piece::BlackPawn, SQ::B8));
        assert_eq!(psq(Piece::BlackKnight,  SQ::B4), -psq(Piece::WhiteKnight,SQ::B5));
    }

}