Exemplo n.º 1
0
void move_eval(const board_t * board, int eval) {

   int index;
   int best_value, value;
   int move;

   ASSERT(board!=NULL);
   ASSERT(value_is_ok(eval));

   move = board->move;
   ASSERT(move_is_ok(move));

   // exceptions

   if ((move & (1 << 15)) != 0)        return;
   if (MOVE_TO(move) == board->cap_sq) return;
   if (MOVE_IS_CASTLE(move))           return;

   ASSERT(!MOVE_IS_PROMOTE(move));
   ASSERT(!MOVE_IS_EN_PASSANT(move));
   ASSERT(board->cap_sq==Empty);
   ASSERT(!board_is_check(board));

   index = PIECE_TO_12(board->square[MOVE_TO(move)]) * 64 + SQUARE_TO_64(MOVE_TO(move));
   ASSERT(index>=0&&index<HistorySize);

   if (eval > ValueQueen) {
      value = ValueQueen;
   } else if (eval < -ValueQueen) {
      value = -ValueQueen;
   } else {
      value = eval;
   }

   best_value = HistEval[index];

   ASSERT(best_value<=HistoryEvalMax);
   ASSERT(best_value>=-HistoryEvalMax);

   if (value >= best_value) {

      if (value == HistoryEvalValue) value++;
      HistEval[index] = value;

   } else {

      if (HistEval[index] > -ValueQueen) {

         if (best_value == HistoryEvalValue+1) {
            HistEval[index] -= 2;
         } else {
            HistEval[index]--;
         }
      }
   }

   ASSERT(HistEval[index]!=HistoryEvalValue);
   ASSERT(HistEval[index]<=HistoryEvalMax);
   ASSERT(HistEval[index]>=-HistoryEvalMax);
}
Exemplo n.º 2
0
static bool capture_is_dangerous(int move, const board_t * board) {

   int piece, capture;

   ASSERT(move_is_ok(move));
   ASSERT(board!=NULL);

   ASSERT(move_is_tactical(move,board));

   piece = MOVE_PIECE(move,board);

   if (PIECE_IS_PAWN(piece)
    && PAWN_RANK(MOVE_TO(move),board->turn) >= Rank7) {
      return true;
   }

   capture = move_capture(move,board);

   if (PIECE_IS_QUEEN(capture)) return true;

   if (PIECE_IS_PAWN(capture)
    && PAWN_RANK(MOVE_TO(move),board->turn) <= Rank2) {
      return true;
   }

   return false;
}
Exemplo n.º 3
0
/**
extend_move():
Calculates the search extension to be awarded to the given move. This is based
on various information such as whether the move checks, if it is a threat or
not, etc. This also determines whether a move should be reduced or not.
Created 072007; last modified 081808
**/
int extend_move(SEARCH_BLOCK *sb)
{
	int extension;
	int lmr_moves;

	/* First, determine if the move should be extended (rather than reduced). */
	extension = 0;
	if (!(sb->move & MOVE_NOEXTEND))
	{
		/* check extension */
		if (in_check())
		{
			extension += zct->check_extension;
			zct->check_extensions_done++;
		}
		/* one-reply extension */
		if (sb->check && sb->last_move - sb->first_move == 1)
		{
			extension += zct->one_rep_extension;
			zct->one_rep_extensions_done++;
		}
		/* pawn to 7th extension */
		if (board.piece[MOVE_TO(sb->move)] == PAWN &&
			RANK_OF(SQ_FLIP_COLOR(MOVE_TO(sb->move), board.side_ntm)) == RANK_7)
		{
			extension += zct->passed_pawn_extension;
			zct->passed_pawn_extensions_done++;
		}
		extension = MIN(PLY, extension);
	}

	/* Now try to reduce the move. If the move is marked as not reducible, or
		if the depth is too low, don't bother reducing it. */
	if (extension > 0 || sb->depth < 2 * PLY || (sb->move & MOVE_NOREDUCE))
		return extension;

	lmr_moves = 0;
	switch (sb->node_type)
	{
		case NODE_PV:
			lmr_moves = 5;
			break;
		case NODE_CUT:
			lmr_moves = 2;
			break;
		case NODE_ALL:
			lmr_moves = 3;
			break;
	}

	/* Most LMR conditions are already covered in the move scoring routines.
		The only "dynamic" factor is the count of moves. */
	if (sb->moves > lmr_moves)
	{
		sb->move |= MOVE_ISREDUCED;
		extension -= PLY;
	}

	return extension;
}
Exemplo n.º 4
0
/**
moves_are_connected():
This function is used for LMR, testing if a reduced move actually contained a
threat. The function tests if the move that refuted null move was connected to
the first move. This idea is from Tord Romstad.
Created 101707; last modified 101807
**/
BOOL moves_are_connected(MOVE move_1, MOVE move_2)
{
	if (move_1 == NULL_MOVE || move_2 == NULL_MOVE)
		return FALSE;
	if (MOVE_TO(move_1) == MOVE_FROM(move_2))
		return TRUE;
	if (MOVE_FROM(move_1) == MOVE_TO(move_2))
		return TRUE;
	if (MASK(MOVE_FROM(move_1)) & in_between_bb[MOVE_FROM(move_2)]
		[MOVE_TO(move_2)])
		return TRUE;
	return FALSE;
}
Exemplo n.º 5
0
static int full_new_depth(int depth, int move, board_t * board, bool single_reply, bool in_pv, int height, bool extended, bool * cap_extended, int ThreadId) {

   int new_depth;

   ASSERT(depth_is_ok(depth));
   ASSERT(move_is_ok(move));
   ASSERT(board!=NULL);
   ASSERT(single_reply==true||single_reply==false);
   ASSERT(in_pv==true||in_pv==false);

   ASSERT(depth>0);

   new_depth = depth - 1;
   *cap_extended = false;
   
   if (in_pv && board->square[MOVE_TO(move)] != Empty && !PIECE_IS_PAWN(board->square[MOVE_TO(move)])){
	   if ((board->piece_size[White] + board->piece_size[Black]) == 3){
			return new_depth+1;
	   }
	   else if ((board->piece_size[White] == 3 && board->piece_size[Black] == 2) 
		   || (board->piece_size[White] == 2 && board->piece_size[Black] == 3))
		   return new_depth+1; 
   }
   if ((single_reply && ExtendSingleReply)
		//|| (in_pv && MOVE_TO(move) == board->cap_sq // recapture
		//	&& see_move(move,board) >= -100 /*|| ABS(VALUE_PIECE(board->square[MOVE_TO(move)])-VALUE_PIECE(board->square[MOVE_FROM(move)])) <= 250 )*/)  
		//|| (in_pv && PIECE_IS_PAWN(MOVE_PIECE(move,board))
		//	  && (PAWN_RANK(MOVE_TO(move),board->turn) == Rank7 || PAWN_RANK(MOVE_TO(move),board->turn) == Rank6))
		//|| (in_pv &&  board->square[MOVE_TO(move)] != PieceNone256 && SearchCurrent[ThreadId]->act_iteration-height >= 6 && see_move(move,board) >= -100) 
		//|| (in_pv &&  board->square[MOVE_TO(move)] != PieceNone256 && !extended && see_move(move,board) >= -100)
		//|| (in_pv && mate_threat == true)
		|| move_is_check(move,board) && (in_pv || see_move(move,board) >= -100)) {
        // @tried no check extension in endgame (~ -5 elo)
        // @tried no bad SEE check extension in PV (~ -5 elo)
		return new_depth+1;
   }
   if (in_pv && PIECE_IS_PAWN(MOVE_PIECE(move,board))){
			if (is_passed(board,MOVE_TO(move)))
				return new_depth+1;
   }

  if (in_pv &&  board->square[MOVE_TO(move)] != PieceNone256 
	   && !extended && see_move(move,board) >= -100){
		   *cap_extended = true;
		   return new_depth+1;
   }
  
   ASSERT(new_depth>=0&&new_depth<=depth);

   return new_depth;
}
Exemplo n.º 6
0
static bool capture_is_good(int move, const board_t * board) {

   int piece, capture;

   ASSERT(move_is_ok(move));
   ASSERT(board!=NULL);

   ASSERT(MOVE_IS_TACTICAL(move,board));

   // special cases

   if (MOVE_IS_EN_PASSANT(move)) return true;
   if (MOVE_IS_UNDER_PROMOTE(move)) return false; // REMOVE ME?

   // captures and queen promotes

   capture = board->square[MOVE_TO(move)];

   if (capture != Empty) {

      // capture

      ASSERT(move_is_capture(move,board));

      if (MOVE_IS_PROMOTE(move)) return true; // promote-capture

      piece = board->square[MOVE_FROM(move)];
      if (VALUE_PIECE(capture) >= VALUE_PIECE(piece)) return true;
   }

   return see_move(move,board,0) >= 0;
}
Exemplo n.º 7
0
static int mvv_lva(int move, const board_t * board) {

   int piece, capture, promote;
   int value;

   ASSERT(move_is_ok(move));
   ASSERT(board!=NULL);

   ASSERT(move_is_tactical(move,board));

   if (MOVE_IS_EN_PASSANT(move)) { // en-passant capture

      value = 5; // PxP

   } else if ((capture = board->square[MOVE_TO(move)]) != Empty) { // normal capture

      piece = board->square[MOVE_FROM(move)];

      value = PIECE_ORDER(capture) * 6 - PIECE_ORDER(piece) + 5;
      ASSERT(value>=0&&value<30);

   } else { // promote

      ASSERT(MOVE_IS_PROMOTE(move));

      promote = move_promote(move);

      value = PIECE_ORDER(promote) - 5;
      ASSERT(value>=-4&&value<0);
   }

   ASSERT(value>=-4&&value<+30);

   return value;
}
Exemplo n.º 8
0
void str_CSA_move( char *str, unsigned int move )
{
  int type_c = MOVE_TYPE( move );
  int type   = type_c & ~mask_piece_color;
  int from   = MOVE_FROM( move );
  int to     = MOVE_TO( move );
  int prom   = MOVE_PROMOTE( move );

  if( from == move_drop )
    {
      snprintf( str, 7, "%d%d%d%d%s",
                0, 0,
                5-( to%5),    ( to/5   +1 ),
                ch_piece_csa[ type ] );
    }
  else if( prom )
    {
      snprintf( str, 7, "%d%d%d%d%s",
                5-( from%5 ), ( from/5 +1 ),
                5-( to%5),    ( to/5   +1 ),
                ch_piece_csa[ type + m_promote ] );
    }
  else
    {
      snprintf( str, 7, "%d%d%d%d%s",
                5-( from%5 ), ( from/5 +1 ),
                5-( to%5),    ( to/5   +1 ),
                ch_piece_csa[ type ] );    
    }
  return;
}
Exemplo n.º 9
0
/**
heuristic():
Updates history, killer, and counter tables based on a move that failed high.
Created 092906; last modified 081007
**/
void heuristic(MOVE best_move, SEARCH_BLOCK *sb)
{
	int x;

	/* Update the history table. */
	zct->history_table[board.side_tm][MOVE_KEY(best_move)] +=
		sb->depth * sb->depth;
	zct->history_counter = MAX(zct->history_table[board.side_tm]
		[MOVE_KEY(best_move)], zct->history_counter);
	/* Check for an "overflow" of the history table, in which case we scale
		back all of the values. */
	if (zct->history_counter > 1 << 20)
	{
		for (x = 0; x < 2 * 4096; x++) /* This is not recommended ;) */
			zct->history_table[0][x] >>= 4;
		zct->history_counter >>= 4;
	}
	/* Update killer moves. */
	if (board.color[MOVE_TO(best_move)] == EMPTY)
	{
		zct->killer_move[sb->ply][1] = MOVE_COMPARE(best_move);
		zct->counter_move[board.side_tm][MOVE_KEY((sb - 1)->move)][1] =
			MOVE_COMPARE(best_move);
	}
}
Exemplo n.º 10
0
/**
move_is_futile():
This function tests whether a move should be pruned using Ernst Heinz's Futility
Pruning. The idea is that, at horizon nodes, if a move cannot bring the material
score (plus a margin) to alpha, there is no point in even making it, because
the next ply in quiescence will have a stand-pat fail high.
Created 101707; last modified 101707
**/
BOOL move_is_futile(SEARCH_BLOCK *sb, MOVE move)
{
	return FALSE;
	return (sb->moves > 0 && sb->extension == 0 && sb->depth <= PLY &&
		material_balance() + piece_value[board.piece[MOVE_TO(sb->move)]] +
		100 < sb->alpha);
}
Exemplo n.º 11
0
static void note_quiet_moves(list_t * list, const board_t * board, bool in_pv, int ThreadId) {

   int size;
   int i, move;
   int move_piece;

   ASSERT(list_is_ok(list));
   ASSERT(board!=NULL);

   size = LIST_SIZE(list);

   if (size >= 2) {
      for (i = 0; i < size; i++) {
         move = LIST_MOVE(list,i);
         list->value[i] = quiet_move_value(move,board,ThreadId);
         if (TryQuietKingAttacks && in_pv) {
            move_piece = MOVE_PIECE(move,board);
            if (!(PIECE_IS_PAWN(move_piece) || PIECE_IS_KING(move_piece))) {
               if (narrow_piece_attack_king(board,move_piece,MOVE_TO(move),KING_POS(board,COLOUR_OPP(board->turn)))) {
                  if (see_move(move,board) >= 0) {
//                   if (1 == NumberThreadsInternal) print_board(board);
                     list->value[i] += 16;
                  }
               }
            }
         }
      }
   }
}
Exemplo n.º 12
0
static int full_new_depth(int depth, int move, board_t * board, bool single_reply, bool mate_threat, bool in_pv, int height) {

   int new_depth;

   ASSERT(depth_is_ok(depth));
   ASSERT(move_is_ok(move));
   ASSERT(board!=NULL);
   ASSERT(single_reply==true||single_reply==false);
   ASSERT(in_pv==true||in_pv==false);

   ASSERT(depth>0);

   new_depth = depth - 1;
   
   if (in_pv && board->square[MOVE_TO(move)] != Empty && !PIECE_IS_PAWN(board->square[MOVE_TO(move)])){
	   if ((board->piece_size[White] + board->piece_size[Black]) == 3){
			return new_depth+1;
	   }
	   else if ((board->piece_size[White] == 3 && board->piece_size[Black] == 2) 
		   || (board->piece_size[White] == 2 && board->piece_size[Black] == 3))
		   return new_depth+1; 
   }
   //else{ 
		if ((single_reply && ExtendSingleReply)
			|| (in_pv && MOVE_TO(move) == board->cap_sq // recapture
		/*		&& (see_move(move,board) > 0 || ABS(VALUE_PIECE(board->square[MOVE_TO(move)])-VALUE_PIECE(board->square[MOVE_FROM(move)])) <= 250 ) */)  
			|| (in_pv && PIECE_IS_PAWN(MOVE_PIECE(move,board))
				  && (PAWN_RANK(MOVE_TO(move),board->turn) == Rank7 || PAWN_RANK(MOVE_TO(move),board->turn) == Rank6)
				  /* && see_move(move,board) >= 0 */)
			|| (in_pv &&  board->square[MOVE_TO(move)] != PieceNone256 && SearchCurrent->max_extensions-height >= 6) 
			//|| (in_pv &&  depth <= 1 && height <= SearchCurrent->max_extensions)
			//|| (in_pv && mate_threat == true)
			|| move_is_check(move,board)) {
			return new_depth+1;
		}
	//	else{
			if (in_pv && PIECE_IS_PAWN(MOVE_PIECE(move,board))){
				if (passed_pawn_move(move,board))
					return new_depth+1;
			}
	//	}
//   }
  
   ASSERT(new_depth>=0&&new_depth<=depth);

   return new_depth;
}
Exemplo n.º 13
0
bool pseudo_is_legal(int move, board_t * board) {

    int me, opp;
    int from, to;
    int piece;
    bool legal;
    int king;
    undo_t undo[1];

    ASSERT(move_is_ok(move));
    ASSERT(board!=NULL);

    // init

    me = board->turn;
    opp = COLOUR_OPP(me);

    from = MOVE_FROM(move);
    to = MOVE_TO(move);

    piece = board->square[from];
    ASSERT(COLOUR_IS(piece,me));

    // slow test for en-passant captures

    if (MOVE_IS_EN_PASSANT(move)) {

        move_do(board,move,undo);
        legal = !IS_IN_CHECK(board,me);
        move_undo(board,move,undo);

        return legal;
    }

    // king moves (including castle)

    if (PIECE_IS_KING(piece)) {

        legal = !is_attacked(board,to,opp);

        if (DEBUG) {
            ASSERT(board->square[from]==piece);
            board->square[from] = Empty;
            ASSERT(legal==!is_attacked(board,to,opp));
            board->square[from] = piece;
        }

        return legal;
    }

    // pins

    if (is_pinned(board,from,me)) {
        king = KING_POS(board,me);
        return DELTA_INC_LINE(king-to) == DELTA_INC_LINE(king-from); // does not discover the line
    }

    return true;
}
Exemplo n.º 14
0
/*
    Undoes a move on a board.
*/
void undo_move(board_t* board, move_t move) {
    #define UNDO_CASTLE(color, king_side_from, king_side_to, queen_side_from, queen_side_to) \
        if (to_square > from_square) { UPDATE_CASTLE_BITBOARDS(color, color##_ROOK, king_side_from, king_side_to); } \
        else { UPDATE_CASTLE_BITBOARDS(color, color##_ROOK, queen_side_from, queen_side_to); }

    #define UNDO_CAPTURE(other_color, square_offset) int captured_square = to_square; \
                if (IS_ENPASSANT(move)) { \
                    captured_square += square_offset; \
                } \
                board->color_bitboard[other_color] |= SQUARE_MASK[captured_square]; \
                board->piece_bitboard[captured_piece] |= SQUARE_MASK[captured_square]; \
                board->pieces[captured_square] = captured_piece;

    #define UNDO_PROMOTION(pawn) board->piece_bitboard[promotion_piece] ^= SQUARE_MASK[to_square]; \
                board->piece_bitboard[pawn] |= SQUARE_MASK[to_square];

    board->state_index--;
    board->can_castle = board->state[board->state_index].can_castle;
    board->passed_square = board->state[board->state_index].passed_square;
    board->fifty_move_rule_counter = board->state[board->state_index].fifty_move_rule_counter;
    board->material[WHITE] = board->state[board->state_index].material[WHITE];
    board->material[BLACK] = board->state[board->state_index].material[BLACK];
    board->hash_key = board->state[board->state_index].hash_key;

    int from_square = MOVE_FROM(move), to_square = MOVE_TO(move), moving_piece = MOVING_PIECE(move), 
        captured_piece = CAPTURED_PIECE(move), promotion_piece = PROMOTION_PIECE(move);
    bitboard_t from_to_bitboard = SQUARE_MASK[from_square] | SQUARE_MASK[to_square];

    board->pieces[from_square] = moving_piece;
    board->pieces[to_square] = EMPTY;

    if (board->to_move == BLACK) {
        board->color_bitboard[WHITE] ^= from_to_bitboard;

        if (IS_CASTLE(move)) { UNDO_CASTLE(WHITE, H1, F1, A1, D1); }
        if (IS_PROMOTION(move)) { UNDO_PROMOTION(WHITE_PAWN); }
        if (captured_piece) {  UNDO_CAPTURE(BLACK, -8); }

        if (moving_piece == WHITE_KING) board->king_position[WHITE] = from_square;
        else board->piece_bitboard[moving_piece] ^= from_to_bitboard;

        board->to_move = WHITE;
    } else {
        board->color_bitboard[BLACK] ^= from_to_bitboard;

        if (IS_CASTLE(move)) { UNDO_CASTLE(BLACK, H8, F8, A8, D8); }
        if (IS_PROMOTION(move)) { UNDO_PROMOTION(BLACK_PAWN); }
        if (captured_piece) {  UNDO_CAPTURE(WHITE, 8); }

        if (moving_piece == BLACK_KING) board->king_position[BLACK] = from_square;
        else board->piece_bitboard[moving_piece] ^= from_to_bitboard;

        board->to_move = BLACK;
    }

    board->all_pieces_bitboard = board->color_bitboard[WHITE] | board->color_bitboard[BLACK];
}
Exemplo n.º 15
0
/**
heuristic_pv():
Updates killer tables when the pv changes at a pv node.
Created 110606; last modified 081007
**/
void heuristic_pv(MOVE best_move, SEARCH_BLOCK *sb)
{
	if (board.color[MOVE_TO(best_move)] == EMPTY)
	{
		zct->killer_move[sb->ply][0] = MOVE_COMPARE(best_move);
		zct->counter_move[board.side_tm][MOVE_KEY((sb - 1)->move)][0] =
			MOVE_COMPARE(best_move);
	}
}
Exemplo n.º 16
0
void move_undo(int move, const undo_t * undo) {

   int me;
   int from, to;
   int piece,pos;

   
   ASSERT(move_is_ok(move));
   ASSERT(undo!=NULL);

   // init

   me = undo->turn;

   from = MOVE_FROM(move);
   to = MOVE_TO(move);

   piece = Square[to];
   pos=piece & 31;


   ASSERT(COLOUR_IS(piece,me));
   
   Square[from]=piece;
   Piece[pos]=from;

   BitRanks[from>>4] ^= g_BitRankMask[from];
   BitFiles[from & 0xf]^= g_BitFileMask[from];
 
  
   if(undo->capture)//吃子更新
   {
	   Square[to]=undo->capture_piece;
	   Piece[undo->capture_piece & 31]=to;
       
	   Piece_size[PIECE_COLOUR(undo->capture_piece)]++;
	   Number[PieceTo32[undo->capture_piece & 31]]++;
        
   }else
   { 
	   Square[to]=Empty;

	   BitRanks[to>>4] ^= g_BitRankMask[to];
	   BitFiles[to&0xf]^= g_BitFileMask[to];
   }
   
   Turn = undo->turn;

   Opening = undo->opening;
   Endgame = undo->endgame;

   Key = undo->key;
   Lock = undo->lock;

   Sp--;
}
Exemplo n.º 17
0
void add_promote(list_t * list, int move) {

   ASSERT(list!=NULL);
   ASSERT(move_is_ok(move));

   ASSERT((move&~07777)==0); // HACK
   ASSERT(SQUARE_IS_PROMOTE(MOVE_TO(move)));

   LIST_ADD(list,move|MovePromoteQueen);
   LIST_ADD(list,move|MovePromoteKnight);
   LIST_ADD(list,move|MovePromoteRook);
   LIST_ADD(list,move|MovePromoteBishop);
}
Exemplo n.º 18
0
void history_very_bad(int move, const board_t * board) {

   int index;

   ASSERT(move_is_ok(move));
   ASSERT(board!=NULL);

   //if (move_is_tactical(move,board)) return;

   // history

   index = PIECE_TO_12(board->square[MOVE_TO(move)]) * 64 + SQUARE_TO_64(MOVE_TO(move));

   HistTot[index] += 100;

   if (HistTot[index] >= HistoryMax) {
      HistHit[index] = (HistHit[index] + 1) / 2;
      HistTot[index] = (HistTot[index] + 1) / 2;
   }

   ASSERT(HistHit[index]<=HistTot[index]);
   ASSERT(HistTot[index]<HistoryMax);
}
Exemplo n.º 19
0
static int history_index(int move, const board_t * board) {

   int index;

   ASSERT(move_is_ok(move));
   ASSERT(board!=NULL);

   ASSERT(!MOVE_IS_TACTICAL(move,board));

   index = PIECE_TO_12(board->square[MOVE_FROM(move)]) * 64 + SQUARE_TO_64(MOVE_TO(move));

   ASSERT(index>=0&&index<HistorySize);

   return index;
}
Exemplo n.º 20
0
int see(Move_t move, Board_t *board) {
    Board_t temp_board = *global_board();
    Board_t *ptr = &temp_board;
    
    int attacking_piece = MOVE_PIECE(move);
    int captured_piece;
    int gain[32];
    int depth = 0;
    int from = MOVE_FROM(move);
    int to = MOVE_TO(move);
    
    if (ENEMY_PAWNS(ptr) & SQ_MASK(to))
        captured_piece = PAWN;
    else if (ENEMY_KNIGHTS(ptr) & SQ_MASK(to))
        captured_piece = KNIGHT;
    else if (ENEMY_BISHOPS(ptr) & SQ_MASK(to))
        captured_piece = BISHOP;
    else if (ENEMY_ROOKS(ptr) & SQ_MASK(to))
        captured_piece = ROOK;
    else if (ENEMY_QUEENS(ptr) & SQ_MASK(to))
        captured_piece = QUEEN;
    else
        captured_piece = 0;
        
    gain[0] = Piece_Values[captured_piece];
    
    if (MOVE_IS_EN_PASSANT(move))
        gain[0] = Piece_Values[PAWN];
    
    do {
        make_quick_move_on_board(ptr, from, to, captured_piece, attacking_piece);
        
        captured_piece = attacking_piece;
        depth++;
        gain[depth] = Piece_Values[captured_piece] - gain[depth-1];
        
        if (MAX(-gain[depth-1], gain[depth]) < 0)
            break;
        
        attacking_piece = get_least_valuable_attacker(ptr, to, &from);
        
    } while (attacking_piece);
    
    while (--depth)
        gain[depth-1] = -MAX(-gain[depth-1], gain[depth]);
    
    return gain[0];
}
Exemplo n.º 21
0
bool quiet_is_pseudo( int move, board_t *board )
{
	int to;

	ASSERT(move_is_ok(move));
	ASSERT(board != NULL);

	ASSERT(!board_is_check(board));

	to = MOVE_TO(move);
	ASSERT(SQUARE_IS_OK(to));

	if( board->square[to] != Empty )
		return false; // capture

	return move_is_pseudo(move, board );
}
Exemplo n.º 22
0
bool move_is_check(int move, board_t * board) {

    undo_t undo[1];
    bool check;
    int me, opp, king;
    int from, to, piece;

    ASSERT(move_is_ok(move));
    ASSERT(board!=NULL);

    // slow test for complex moves

    if (MOVE_IS_SPECIAL(move)) {

        move_do(board,move,undo);
        check = IS_IN_CHECK(board,board->turn);
        move_undo(board,move,undo);

        return check;
    }

    // init

    me = board->turn;
    opp = COLOUR_OPP(me);
    king = KING_POS(board,opp);

    from = MOVE_FROM(move);
    to = MOVE_TO(move);
    piece = board->square[from];
    ASSERT(COLOUR_IS(piece,me));

    // direct check

    if (PIECE_ATTACK(board,piece,to,king)) return true;

    // indirect check

    if (is_pinned(board,from,opp)
            && DELTA_INC_LINE(king-to) != DELTA_INC_LINE(king-from)) {
        return true;
    }

    return false;
}
Exemplo n.º 23
0
static bool move_is_dangerous(int move, const board_t * board) {

   int piece;

   ASSERT(move_is_ok(move));
   ASSERT(board!=NULL);

   ASSERT(!move_is_tactical(move,board));

   piece = MOVE_PIECE(move,board);

   if (PIECE_IS_PAWN(piece)
    && is_passed(board,MOVE_TO(move)) /*PAWN_RANK(MOVE_TO(move),board->turn) >= Rank7*/) {
      return true;
   }

   return false;
}
Exemplo n.º 24
0
static bool passed_pawn_move(int move, const board_t * board) {

   int piece, delta, to;

   ASSERT(board!=NULL);

   if (board->turn == Black){
	   piece = WhitePawn256;
	   delta = -16;
   }
   else {
	   piece = BlackPawn256;
	   delta = 16;
   }

   for (to = MOVE_TO(move) + delta; PAWN_RANK(to,board->turn) <= Rank7; to = to + delta) {
	   if (board->square[to] == piece || board->square[to-1] == piece || board->square[to+1] == piece)
		   return false;
   }
   return true;
}
Exemplo n.º 25
0
static unsigned int history_index(int move, const board_t * board) {

   unsigned int index;
   
   int move_from = MOVE_FROM(move);
   int piece_12  = PIECE_TO_12(board->square[move_from]);
   
   ASSERT(move_is_ok(move));
   ASSERT(board!=NULL);
   
   ASSERT(!move_is_tactical(move,board));
   
// index = PIECE_TO_12(board->square[MOVE_FROM(move)]) *     64                                       + SQUARE_TO_64(MOVE_TO(move)); fruit 2.1
// index = PIECE_TO_12(board->square[MOVE_FROM(move)]) * (64*64) + SQUARE_TO_64(MOVE_FROM(move)) * 64 + SQUARE_TO_64(MOVE_TO(move)); Toga II 1.2.1 (corrected?).  
   
   index = 64 * piece_12  +  SQUARE_TO_64(MOVE_TO(move)); // fruit 2.1 and Toga II 1.4beta5c
   
   
   ASSERT(index >= 0 && index < HistorySize);
   
   return index;
}
Exemplo n.º 26
0
void move_undo(board_t * board, int move, const undo_t * undo) {

   int me;
   int from, to;
   int piece, pos;
   int rook;

   ASSERT(board!=NULL);
   ASSERT(move_is_ok(move));
   ASSERT(undo!=NULL);

   // init

   me = undo->turn;

   from = MOVE_FROM(move);
   to = MOVE_TO(move);

   piece = board->square[to];
   ASSERT(COLOUR_IS(piece,me));

   // castle

   if (MOVE_IS_CASTLE(move)) {

      rook = Rook64 | COLOUR_FLAG(me); // HACK

      if (to == G1) {
         square_move(board,F1,H1,rook,false);
      } else if (to == C1) {
         square_move(board,D1,A1,rook,false);
      } else if (to == G8) {
         square_move(board,F8,H8,rook,false);
      } else if (to == C8) {
         square_move(board,D8,A8,rook,false);
      } else {
         ASSERT(false);
      }
   }

   // move the piece backward

   if (MOVE_IS_PROMOTE(move)) {

      // promote

      ASSERT(piece==move_promote(move));
      square_clear(board,to,piece,false);

      piece = PAWN_MAKE(me);
      pos = undo->pawn_pos;

      square_set(board,from,piece,pos,false);

   } else {

      // normal move

      square_move(board,to,from,piece,false);
   }

   // put the captured piece back

   if (undo->capture) {
      square_set(board,undo->capture_square,undo->capture_piece,undo->capture_pos,false);
   }

   // update board info

   board->turn = undo->turn;
   board->flags = undo->flags;
   board->ep_square = undo->ep_square;
   board->ply_nb = undo->ply_nb;

   board->cap_sq = undo->cap_sq;

   board->opening = undo->opening;
   board->endgame = undo->endgame;

   board->key = undo->key;
   board->pawn_key = undo->pawn_key;
   board->material_key = undo->material_key;

   // update key stack

   ASSERT(board->sp>0);
   board->sp--;

   // debug

   ASSERT(board_is_ok(board));
   ASSERT(board_is_legal(board));
}
Exemplo n.º 27
0
void move_do(board_t * board, int move, undo_t * undo) {

   int me, opp;
   int from, to;
   int piece, pos, capture;
   int old_flags, new_flags;
   int delta;
   int sq;
   int pawn, rook;

   ASSERT(board!=NULL);
   ASSERT(move_is_ok(move));
   ASSERT(undo!=NULL);

   ASSERT(board_is_legal(board));

   // initialise undo

   undo->capture = false;

   undo->turn = board->turn;
   undo->flags = board->flags;
   undo->ep_square = board->ep_square;
   undo->ply_nb = board->ply_nb;

   undo->cap_sq = board->cap_sq;

   undo->opening = board->opening;
   undo->endgame = board->endgame;

   undo->key = board->key;
   undo->pawn_key = board->pawn_key;
   undo->material_key = board->material_key;

   // init

   me = board->turn;
   opp = COLOUR_OPP(me);

   from = MOVE_FROM(move);
   to = MOVE_TO(move);

   piece = board->square[from];
   ASSERT(COLOUR_IS(piece,me));

   // update key stack

   ASSERT(board->sp<StackSize);
   board->stack[board->sp++] = board->key;

   // update turn

   board->turn = opp;
   board->key ^= RANDOM_64(RandomTurn);

   // update castling rights

   old_flags = board->flags;
   new_flags = old_flags & CastleMask[from] & CastleMask[to];

   board->flags = new_flags;
   board->key ^= Castle64[new_flags^old_flags]; // HACK

   // update en-passant square

   if ((sq=board->ep_square) != SquareNone) {
      board->key ^= RANDOM_64(RandomEnPassant+SQUARE_FILE(sq)-FileA);
      board->ep_square = SquareNone;
   }

   if (PIECE_IS_PAWN(piece)) {

      delta = to - from;

      if (delta == +32 || delta == -32) {
         pawn = PAWN_MAKE(opp);
         if (board->square[to-1] == pawn || board->square[to+1] == pawn) {
            board->ep_square = (from + to) / 2;
            board->key ^= RANDOM_64(RandomEnPassant+SQUARE_FILE(to)-FileA);
         }
      }
   }

   // update move number (captures are handled later)

   board->ply_nb++;
   if (PIECE_IS_PAWN(piece)) board->ply_nb = 0; // conversion

   // update last square

   board->cap_sq = SquareNone;

   // remove the captured piece

   sq = to;
   if (MOVE_IS_EN_PASSANT(move)) sq = SQUARE_EP_DUAL(sq);

   if ((capture=board->square[sq]) != Empty) {

      ASSERT(COLOUR_IS(capture,opp));
      ASSERT(!PIECE_IS_KING(capture));

      undo->capture = true;
      undo->capture_square = sq;
      undo->capture_piece = capture;
      undo->capture_pos = board->pos[sq];

      square_clear(board,sq,capture,true);

      board->ply_nb = 0; // conversion
      board->cap_sq = to;
   }

   // move the piece

   if (MOVE_IS_PROMOTE(move)) {

      // promote

      undo->pawn_pos = board->pos[from];

      square_clear(board,from,piece,true);

      piece = move_promote(move);

      // insert the promote piece in MV order

      for (pos = board->piece_size[me]; pos > 0 && piece > board->square[board->piece[me][pos-1]]; pos--) // HACK
         ;

      square_set(board,to,piece,pos,true);

      board->cap_sq = to;

   } else {

      // normal move

      square_move(board,from,to,piece,true);
   }

   // move the rook in case of castling

   if (MOVE_IS_CASTLE(move)) {

      rook = Rook64 | COLOUR_FLAG(me); // HACK

      if (to == G1) {
         square_move(board,H1,F1,rook,true);
      } else if (to == C1) {
         square_move(board,A1,D1,rook,true);
      } else if (to == G8) {
         square_move(board,H8,F8,rook,true);
      } else if (to == C8) {
         square_move(board,A8,D8,rook,true);
      } else {
         ASSERT(false);
      }
   }

   // debug

   ASSERT(board_is_ok(board));
}
Exemplo n.º 28
0
       bool capture_is_good(int move, const board_t * board, bool in_pv) {
#else
static bool capture_is_good(int move, const board_t * board, bool in_pv) {
#endif

   int piece, capture;
   int see_value; // WHM 11/22/08

   ASSERT(move_is_ok(move));
   ASSERT(board!=NULL);

   ASSERT(move_is_tactical(move,board));

   // special cases

   if (MOVE_IS_EN_PASSANT(move)) return true;
   if (move_is_under_promote(move)) return false; // REMOVE ME?  Keep, looks good to me.  WHM;
// if (MOVE_IS_PROMOTE(move)) return true; // WHM; promote-to-queen, measures a little weaker
//                                                 too many garbage lines going nuts.
   
   // captures and queen promotes
   capture = board->square[MOVE_TO(move)];
   piece = board->square[MOVE_FROM(move)];

   if (capture != Empty) {

      // capture

      ASSERT(move_is_capture(move,board));

      if (MOVE_IS_PROMOTE(move)) return true; // capture a piece on Rank8 and promote to queen
      
      if (VALUE_PIECE(capture) >= VALUE_PIECE(piece)) return true;
   }


// return see_move(move,board) >= 0; WHM 11/22/08

// WHM 11/22/08 START

   see_value = see_move(move,board);
   if (see_value >= 0) return true;

   if (TryNodePVQueenPromotes) {
      if (in_pv && MOVE_IS_PROMOTE(move)) {
          ASSERT(!move_is_under_promote(move));
          return true; // WHM:
      }
   }
   
   if (TryKingAttackSacs || TryKingBoxSacs || TryPasserSacs) {
      if (in_pv  &&  see_value > -ValueBishop  &&  capture != Empty) {
         ASSERT(COLOUR_IS(capture,COLOUR_OPP(board->turn)));
         // king attack sacs.  
         if (TryKingAttackSacs) {
            if (narrow_piece_attack_king(board, piece, MOVE_TO(move), KING_POS(board,COLOUR_OPP(board->turn)))) {
               return true;
            }
         }
         // sacrifice attacks around the narrow/close king box can be examined more fully.  Rybka lessons.  
         if (TryKingBoxSacs) {
            if (DISTANCE(MOVE_TO(move),KING_POS(board,COLOUR_OPP(board->turn))) <= 1) {
               return true;
            }
         }
         // passer sacrifices...
         if (TryPasserSacs) {
            if (PIECE_IS_PAWN(capture) && PAWN_RANK(MOVE_TO(move),COLOUR_OPP(board->turn)) >= Rank6) {
               return true;
            }
         }
      }
   } // WHM 11/22/08 END
   
   
   return false;
}
Exemplo n.º 29
0
bool move_is_pseudo( int move, board_t *board )
{

	int me, opp;
	int from, to;
	int piece, capture;

	ASSERT(move_is_ok(move));
	ASSERT(board != NULL);
	// init

	me = board->turn;
	opp = COLOUR_OPP(board->turn);

	// from

	from = MOVE_FROM(move);
	ASSERT(SQUARE_IS_OK(from));

	piece = board->square[from];	
	if(INDEX_TO_COLOUR(piece) != me)
		return false;

	// to
	to = MOVE_TO(move);
	ASSERT(SQUARE_IS_OK(to));

	capture = board->square[to];	
	if( INDEX_TO_COLOUR(capture) == me )
		return false;

	// move 
	switch(INDEX_TO_PIECE(piece))
	{
	case RedKing:
		if(KING_IN_CITY(to) && KLegalDt[to - from + 256]) return true;
		if(EQUAL_FILE(from, to) && INDEX_TO_PIECE(capture) == BlackKing)
		{
			int row=SQUARE_RANK(from) - 3;
			int col=SQUARE_FILE(from) - 3;
			if(FileCapMin[row][board->file[col]] + col == to) return true;
		}

		return false;

	case BlackKing:
		if(KING_IN_CITY(to) && KLegalDt[to - from + 256]) return true;
		if(EQUAL_FILE(from, to) && INDEX_TO_PIECE(capture) ==RedKing)
		{
			int row=SQUARE_RANK(from) - 3;
			int col=SQUARE_FILE(from) - 3;
			if(FileCapMax[row][board->file[col]] + col == to) return true;
		}

		return false;

	case RedAdvisor:
	case BlackAdvisor:
		if(ADVISOR_IN_CITY(to) && ALegalDt[to - from + 256]) return true;
		return false;

	case RedBishop:
	case BlackBishop:
		if(BISHOP_IN_CITY(to) &&
			BLegalDt[to - from + 256] &&
			board->square[(to + from) >> 1] == PieceNone)//
			return true;
		return false;

	case RedKnight:
	case BlackKnight:
		if(NLegalDt[to - from + 256] && board->square[from + NLegalDt[to - from + 256]] == PieceNone)//
			return true;
		return false;

	case RedRook:
	case BlackRook:
		if(capture)
		{
			if(EQUAL_FILE(from, to))
			{
				int row=SQUARE_RANK(from) - 3;
				int col=SQUARE_FILE(from) - 3;
				if(FileCapMax[row][board->file[col]] + col == to || FileCapMin[row][board->file[col]] + col == to)
					return true;
			}
			else if(EQUAL_RANK(from, to))
			{
				int row=SQUARE_RANK(from) - 3;
				int col=SQUARE_FILE(from) - 3;
				if(RankCapMax[col][board->rank[row]] + (row << 4) == to ||
					RankCapMin[col][board->rank[row]] + (row << 4) == to)
					return true;
			}

		}
		else
		{
			int row=SQUARE_RANK(from) - 3;
			int col=SQUARE_FILE(from) - 3;
			int to_row = SQUARE_RANK(to) - 3;
			int to_col = SQUARE_FILE(to) - 3;
			int rowbit = board->rank[row];
			int colbit = board->file[col];
			if(EQUAL_FILE(from, to))
			{
				//if(FileNonCapMin[row][board->file[col]] + col <= to && to <= FileNonCapMax[row][board->file[col]] + col)
                if(PinNb[row][to_row][colbit] == 0)
					return true;
			}
			else if(EQUAL_RANK(from, to))
			{
				//if(RankNonCapMin[col][board->rank[row]] + (row << 4) <= to && to <= RankNonCapMax[col][board->rank[row]] + (row << 4))
				 if(PinNb[col][to_col][rowbit] == 0)
				    return true;
			}

		}

		return false;

	case RedCannon:
	case BlackCannon:
		if(capture)
		{
			if(EQUAL_RANK(from, to))
			{
				int row=SQUARE_RANK(from) - 3;
				int col=SQUARE_FILE(from) - 3;
				if(CannonRankCapMax[col][board->rank[row]] + (row << 4) == to ||
					CannonRankCapMin[col][board->rank[row]] + (row << 4) == to)
					return true;
			}
			else if(EQUAL_FILE(from, to))
			{
				int row=SQUARE_RANK(from) - 3;
				int col=SQUARE_FILE(from) - 3;
				if(CannonFileCapMax[row][board->file[col]] + col == to ||
					CannonFileCapMin[row][board->file[col]] + col == to)
					return true;
			}
		}
		else
		{
			int row=SQUARE_RANK(from) - 3;
			int col=SQUARE_FILE(from) - 3;
			int to_row = SQUARE_RANK(to) - 3;
			int to_col = SQUARE_FILE(to) - 3;
			int rowbit = board->rank[row];
			int colbit = board->file[col];

			if(EQUAL_RANK(from, to))
			{
				//if(RankNonCapMin[col][board->rank[row]] + (row << 4) <= to && to <= RankNonCapMax[col][board->rank[row]] + (row << 4))
				if(PinNb[col][to_col][rowbit] == 0)
					return true;
			}
			else if(EQUAL_FILE(from, to))
			{
				//if(FileNonCapMin[row][board->file[col]] + col <= to&& to <= FileNonCapMax[row][board->file[col]] + col)
				if(PinNb[row][to_row][colbit] == 0)
					return true;
			}
		}

		return false;

	case BlackPawn:

		if((from + 16) == to) return true;
		if(SQUARE_COLOUR(from) == Red)
		{
			if((from - 1) == to || (from + 1) == to)
				return true;
		}

		return false;

	case RedPawn:

		if((from - 16) == to) return true;
		if(SQUARE_COLOUR(from) == Black)
		{
			if((from - 1) == to || (from + 1) == to)
				return true;
		}

	default:
		return false;
	}


	return false;
}
Exemplo n.º 30
0
int see_move(int move, const board_t * board) {

   int att, def;
   int from, to;
   alists_t alists[1];
   int value, piece_value;
   int piece, capture;
   alist_t * alist;
   int pos;

   ASSERT(move_is_ok(move));
   ASSERT(board!=NULL);

   // init

   from = MOVE_FROM(move);
   to = MOVE_TO(move);

   // move the piece

   piece_value = 0;

   piece = board->square[from];
   ASSERT(piece_is_ok(piece));

   att = PIECE_COLOUR(piece);
   def = COLOUR_OPP(att);

   // promote

   if (MOVE_IS_PROMOTE(move)) {
      ASSERT(PIECE_IS_PAWN(piece));
      piece = move_promote(move);
      ASSERT(piece_is_ok(piece));
      ASSERT(COLOUR_IS(piece,att));
   }

   piece_value += VALUE_PIECE(piece);

   // clear attacker lists

   ALIST_CLEAR(alists->alist[Black]);
   ALIST_CLEAR(alists->alist[White]);

   // find hidden attackers

   alists_hidden(alists,board,from,to);

   // capture the piece

   value = 0;

   capture = board->square[to];

   if (capture != Empty) {

      ASSERT(piece_is_ok(capture));
      ASSERT(COLOUR_IS(capture,def));

      value += VALUE_PIECE(capture);
   }

   // promote

   if (MOVE_IS_PROMOTE(move)) {
      value += VALUE_PIECE(piece) - ValuePawn;
   }

   // en-passant

   if (MOVE_IS_EN_PASSANT(move)) {
      ASSERT(value==0);
      ASSERT(PIECE_IS_PAWN(board->square[SQUARE_EP_DUAL(to)]));
      value += ValuePawn;
      alists_hidden(alists,board,SQUARE_EP_DUAL(to),to);
   }

   // build defender list

   alist = alists->alist[def];

   alist_build(alist,board,to,def);
   if (alist->size == 0) return value; // no defender => stop SEE

   // build attacker list

   alist = alists->alist[att];

   alist_build(alist,board,to,att);

   // remove the moved piece (if it's an attacker)

   for (pos = 0; pos < alist->size && alist->square[pos] != from; pos++)
      ;

   if (pos < alist->size) alist_remove(alist,pos);

   // SEE search

   value -= see_rec(alists,board,def,to,piece_value);

   return value;
}