|  | @@ -1,4 +1,3 @@
 | 
	
		
			
				|  |  | -use bitboard::*;
 | 
	
		
			
				|  |  |  use movegen::*;
 | 
	
		
			
				|  |  |  use game::Game;
 | 
	
		
			
				|  |  |  use evaluate::*;
 | 
	
	
		
			
				|  | @@ -266,6 +265,12 @@ fn quiescence_search(game: &mut Game, sc: &mut SearchControl, hash: &mut Cache,
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          let (mut val, ret) = quiescence_search(game, sc, hash, -beta, -alpha, depth - 1);
 | 
	
		
			
				|  |  |          val = -val;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        if ret {
 | 
	
		
			
				|  |  | +            game.undo_move(undo);
 | 
	
		
			
				|  |  | +            return (alpha, ret)
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |          if val >= beta {
 | 
	
		
			
				|  |  |              game.undo_move(undo);
 | 
	
		
			
				|  |  |              return (beta, false);
 | 
	
	
		
			
				|  | @@ -279,111 +284,6 @@ fn quiescence_search(game: &mut Game, sc: &mut SearchControl, hash: &mut Cache,
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -pub fn apply_move(game: &Game, mov: Move) -> Game {
 | 
	
		
			
				|  |  | -    let mut new_game = game.clone();
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    let side = game.turn;
 | 
	
		
			
				|  |  | -    let friends = game.get_all_side(side);
 | 
	
		
			
				|  |  | -    let others = game.get_all_side(!side);
 | 
	
		
			
				|  |  | -    match mov {
 | 
	
		
			
				|  |  | -        Move::Default{ mov, piece_type: pt, captured: _ } => {
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -            if pt == KING {
 | 
	
		
			
				|  |  | -                // invalidate castling rights
 | 
	
		
			
				|  |  | -                new_game.castling_rights[if game.turn == BLACK { 2 } else { 0 }] = false;
 | 
	
		
			
				|  |  | -                new_game.castling_rights[if game.turn == BLACK { 3 } else { 1 }] = false;
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -            // invalidate castling rights
 | 
	
		
			
				|  |  | -            if mov.from == square_from_indices(7, 0) || mov.to == square_from_indices(7, 0) {
 | 
	
		
			
				|  |  | -                new_game.castling_rights[0] = false;
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -            if mov.from == square_from_indices(0, 0) || mov.to == square_from_indices(0, 0) {
 | 
	
		
			
				|  |  | -                new_game.castling_rights[1] = false;
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -            if mov.from == square_from_indices(7, 7) || mov.to == square_from_indices(7, 7) {
 | 
	
		
			
				|  |  | -                new_game.castling_rights[2] = false;
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -            if mov.from == square_from_indices(0, 7) || mov.to == square_from_indices(0, 7) {
 | 
	
		
			
				|  |  | -                new_game.castling_rights[3] = false;
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -            // if it is a capture
 | 
	
		
			
				|  |  | -            if from_square(mov.to) & others != 0 {
 | 
	
		
			
				|  |  | -                let (other_piece, other_side) = game.get_square(mov.to);
 | 
	
		
			
				|  |  | -                if let Some((ref zt, ref _zv)) = game.zobrist {
 | 
	
		
			
				|  |  | -                    let hup = zt.piece_hash(other_piece, other_side, mov.to);
 | 
	
		
			
				|  |  | -                    new_game.update_zobrist(hup);
 | 
	
		
			
				|  |  | -                }
 | 
	
		
			
				|  |  | -                new_game.apply_mask(!from_square(mov.to));
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -            let moved_piece = mov.apply_to(new_game.get_piece(pt, side));
 | 
	
		
			
				|  |  | -            new_game.set_piece(pt, side, moved_piece);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -            if let Some((ref zt, ref _zv)) = game.zobrist {
 | 
	
		
			
				|  |  | -                let hup = zt.piece_hash(pt, side, mov.from) ^ zt.piece_hash(pt, side, mov.to);
 | 
	
		
			
				|  |  | -                new_game.update_zobrist(hup);
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -        },
 | 
	
		
			
				|  |  | -        Move::Castling { side, left } => {
 | 
	
		
			
				|  |  | -            // invalidate future castling rights
 | 
	
		
			
				|  |  | -            new_game.castling_rights[if game.turn == BLACK { 2 } else { 0 }] = false;
 | 
	
		
			
				|  |  | -            new_game.castling_rights[if game.turn == BLACK { 3 } else { 1 }] = false;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -            let king = game.get_piece(KING, side);
 | 
	
		
			
				|  |  | -            let rook = if left {
 | 
	
		
			
				|  |  | -                game.get_piece(ROOK, side) & (king << 4)
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -            else {
 | 
	
		
			
				|  |  | -                game.get_piece(ROOK, side) & (king >> 3)
 | 
	
		
			
				|  |  | -            };
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -            let new_king = if left { king << 2 } else { king >> 2 };
 | 
	
		
			
				|  |  | -            let new_rook = if left { rook >> 3 } else { rook << 2 };
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -            new_game.set_piece(KING, side, new_king);
 | 
	
		
			
				|  |  | -            *new_game.get_piece_mut(ROOK, side) |= new_rook;
 | 
	
		
			
				|  |  | -            *new_game.get_piece_mut(ROOK, side) &= !rook;
 | 
	
		
			
				|  |  | -        },
 | 
	
		
			
				|  |  | -        Move::EnPassant { mov, beaten } => {
 | 
	
		
			
				|  |  | -            let pawns = game.pawns(side);
 | 
	
		
			
				|  |  | -            if let Some(ep) = game.en_passant {
 | 
	
		
			
				|  |  | -                *new_game.get_piece_mut(PAWN, side) &= !from_square(mov.from);
 | 
	
		
			
				|  |  | -                *new_game.get_piece_mut(PAWN, side) |= from_square(mov.to);
 | 
	
		
			
				|  |  | -                *new_game.get_piece_mut(PAWN, !side) &= !from_square(beaten);
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -        },
 | 
	
		
			
				|  |  | -        Move::Promotion { mov, promote_to, captured } => {
 | 
	
		
			
				|  |  | -            //if from_square(mov.to) & others != 0 {
 | 
	
		
			
				|  |  | -            if let Some(pt) = captured {
 | 
	
		
			
				|  |  | -                *new_game.get_piece_mut(pt, !side) &= !from_square(mov.to);
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -            new_game.apply_mask(!from_square(mov.from));
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -            match promote_to {
 | 
	
		
			
				|  |  | -                QUEEN => { *new_game.queens_mut(side) |= from_square(mov.to); }
 | 
	
		
			
				|  |  | -                ROOK => { *new_game.rooks_mut(side) |= from_square(mov.to); }
 | 
	
		
			
				|  |  | -                BISHOP => { *new_game.bishops_mut(side) |= from_square(mov.to); }
 | 
	
		
			
				|  |  | -                KNIGHT => { *new_game.knights_mut(side) |= from_square(mov.to); }
 | 
	
		
			
				|  |  | -                _ => {
 | 
	
		
			
				|  |  | -                    info!("internal error");
 | 
	
		
			
				|  |  | -                }
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -        },
 | 
	
		
			
				|  |  | -        Move::Nullmove => {}
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    new_game.turn = !new_game.turn;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    if let Some((ref zt, ref zv)) = new_game.zobrist {
 | 
	
		
			
				|  |  | -        //info!("applied {}, zobrist now {}", mov.to_string(), *zv);
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    return new_game;
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |  pub fn perft(game: &mut Game, sc: &mut SearchControl, depth: i32) -> bool {
 | 
	
		
			
				|  |  |      let moves = generate_legal_moves(game, game.turn);
 | 
	
		
			
				|  |  |  
 |