// use std::num::Int;

pub type Bitboard = u32;

pub trait BitMove {
    fn up_left(&self) -> Self;
    fn up_right(&self) -> Self;
    fn down_left(&self) -> Self;
    fn down_right(&self) -> Self;
    fn is(&self) -> bool;
}

pub const S: [Bitboard; 32] = [
                 1 << 18, 1 << 12, 1 << 6, 1 << 0,
                 1 << 19, 1 << 13, 1 << 7, 1 << 1,
                 1 << 26, 1 << 20, 1 << 14, 1 << 8,
                 1 << 27, 1 << 21, 1 << 15, 1 << 9,
                 1 << 2, 1 << 28, 1 << 22, 1 << 16,
                 1 << 3, 1 << 29, 1 << 23, 1 << 17,
                 1 << 10, 1 << 4, 1 << 30, 1 << 24,
                 1 << 11, 1 << 05, 1 << 31, 1 << 25];

pub const BP_INIT: Bitboard = S[0] | S[1] | S[2] | S[3] | S[4] | S[5] | S[6] | S[7]
                | S[8] | S[9] | S[10] | S[11];

pub const WP_INIT: Bitboard = S[20] | S[21] | S[22] | S[23] | S[24] | S[25] | S[26]
                | S[27] | S[28] | S[29] | S[30] | S[31];

pub const  ROW_1: Bitboard = S[0] | S[1] | S[2] | S[3];
pub const  ROW_2: Bitboard = S[4] | S[5] | S[6] | S[7];
pub const  ROW_7: Bitboard = S[24] | S[25] | S[26] | S[27];
pub const  ROW_8: Bitboard = S[28] | S[29] | S[30] | S[31];

pub const  CAN_UPLEFT: Bitboard = !(S[0] | S[8] | S[16] | S[24] | ROW_8);
pub const  CAN_UPRIGHT: Bitboard = !(S[7] | S[15] | S[23] | S[31] | ROW_8);
pub const  CAN_DOWNLEFT: Bitboard = !(S[0] | S[8] | S[16] | S[24] | ROW_1);
pub const  CAN_DOWNRIGHT: Bitboard = !(S[7] | S[15] | S[23] | S[31] | ROW_1);

#[derive(Clone, PartialEq, Show, Copy)]
pub struct Move {
    pub src: u16,
    pub dst: u16,
    pub jump: bool,
    __dummy: ()
}

#[derive(Clone, PartialEq, Show, Copy)]
pub enum Direction{
    UpLeft,
    UpRight,
    DownLeft,
    DownRight
}

impl Move {
    pub fn 
(src: u16, dst: u16, jump: bool) -> Move {
        assert!(src < 32);
        assert!(dst < 32);

        Move {
            src: src, dst: dst, jump: jump, __dummy: ()
        }
    }

    pub fn calc_direction(&self) -> Option<Direction> {
        let (src, dst) = (S[self.src as usize], S[self.dst as usize]);

        if src.up_left() ^ dst == 0 {
            Some(Direction::UpLeft)
        } else if src.up_right() ^ dst == 0 {
            Some(Direction::UpRight)
        } else if src.down_right() ^ dst == 0 {
            Some(Direction::DownRight)
        } else if src.down_left() ^ dst == 0 {
            Some(Direction::DownLeft)
        } else {
            None
        }
    }
}


#[derive(Clone, Copy)]
pub enum Cell {
    Empty = 0,
    Pw,
    Pb,
    Kw,
    Kb
}

pub const CELLTABLE: [&'static str; 5] = [ "---", "WHI", "BLK", "KWH", "KBK" ];

#[derive(Show, Clone, Copy, PartialEq)]
pub enum MoveCode {
    Success,
    VoidPiece,
    IllegalMove,
    WrongPiece,
    Quit,
    InputFail
}

impl BitMove for Bitboard {
    #[inline]
    fn up_left(&self) -> Bitboard {
        self.rotate_left(7)
    }

    #[inline]
    fn up_right(&self) -> Bitboard {
        self.rotate_left(1)
    }

    #[inline]
    fn down_left(&self) -> Bitboard {
        self.rotate_right(1)
    }

    #[inline]
    fn down_right(&self) -> Bitboard {
        self.rotate_right(7)
    }

    #[inline]
    fn is(&self) -> bool {
        *self != 0
    }
}

// Maps from Bitboard indicating a position to the number
// of that position itself
pub fn bbumap(b: Bitboard) -> Bitboard {
    S.iter().position(|&x| x == b).unwrap() as u32
}

#[inline]
pub fn high_bit(mut board: Bitboard) -> Bitboard {
    board |= board >> 1;
    board |= board >> 2;
    board |= board >> 4;
    board |= board >> 8;
    board |= board >> 16;
    board - (board >> 1)
}

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

    #[test]
    #[should_panic(expected = "assertion failed")]
    fn test_move_validation() {
        let _ = Move::new(0, 100, false);
    }

    #[test]
    fn test_move_validation2() {
        let _ = Move::new(1,2,false);
        let _ = Move::new(31,0,false);
    }

    #[test]
    fn test_direction_calculation() {
        let m = Move::new(9, 12, true);
        assert_eq!(m.calc_direction(), Some(Direction::UpLeft));

        let m = Move::new(9, 13, false);
        assert_eq!(m.calc_direction(), Some(Direction::UpRight));

        let m = Move::new(21, 17, false);
        assert_eq!(m.calc_direction(), Some(Direction::DownLeft));

        let m = Move::new(21, 18, false);
        assert_eq!(m.calc_direction(), Some(Direction::DownRight));

        let m = Move::new(21, 12, false);
        assert_eq!(m.calc_direction(), None);
    }
}
new