Exemplo n.º 1
0
void move_undo_null(board_t * board, const undo_t * undo) {

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

   ASSERT(board_is_legal(board));
   ASSERT(!board_is_check(board));

   // update board info

   board->turn = undo->turn;
   board->ep_square = undo->ep_square;
   board->ply_nb = undo->ply_nb;
   board->cap_sq = undo->cap_sq;
   board->key = undo->key;

   // update key stack

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

   // debug

   ASSERT(board_is_ok(board));
}
Exemplo n.º 2
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.º 3
0
bool board_is_stalemate(const board_t * board) {

   ASSERT(board_is_ok(board));

   if (board_is_check(board)) return false;
   if (board_can_play(board)) return false;

   return true;
}
Exemplo n.º 4
0
static bool move_is_pseudo_debug(int move, board_t * board) {

    list_t list[1];

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

    ASSERT(!board_is_check(board));

    gen_moves(list,board);

    return list_contain(list,move);
}
Exemplo n.º 5
0
void move_do_null(board_t * board, undo_t * undo) {

   int sq;

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

   ASSERT(board_is_legal(board));
   ASSERT(!board_is_check(board));

   // initialise undo

   undo->turn = board->turn;
   undo->ep_square = board->ep_square;
   undo->ply_nb = board->ply_nb;
   undo->cap_sq = board->cap_sq;
	undo->moving_piece = board->moving_piece;
   undo->key = board->key;

   // update key stack

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

   // update turn

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

   // update en-passant square

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

   // update move number

   board->ply_nb = 0; // HACK: null move is considered as a conversion

   // update last square

   board->cap_sq = SquareNone;
	board->moving_piece = PieceNone256;

   // debug

   ASSERT(board_is_ok(board));
}
Exemplo n.º 6
0
static bool simple_stalemate(const board_t * board) {

   int me, opp;
   int king;
   int opp_flag;
   int from, to;
   int capture;
   const inc_t * inc_ptr;
   int inc;

   ASSERT(board!=NULL);

   ASSERT(board_is_legal(board));
   ASSERT(!board_is_check(board));

   // lone king?

   me = board->turn;
   if (board->piece_size[me] != 1 || board->pawn_size[me] != 0) return false; // no

   // king in a corner?

   king = KING_POS(board,me);
   if (king != A1 && king != H1 && king != A8 && king != H8) return false; // no

   // init

   opp = COLOUR_OPP(me);
   opp_flag = COLOUR_FLAG(opp);

   // king can move?

   from = king;

   for (inc_ptr = KingInc; (inc=*inc_ptr) != IncNone; inc_ptr++) {
      to = from + inc;
      capture = board->square[to];
      if (capture == Empty || FLAG_IS(capture,opp_flag)) {
         if (!is_attacked(board,to,opp)) return false; // legal king move
      }
   }

   // no legal move

   ASSERT(board_is_stalemate((board_t*)board));

   return true;
}
Exemplo n.º 7
0
void gen_quiet_moves(list_t * list, const board_t * board) {

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

   ASSERT(!board_is_check(board));

   LIST_CLEAR(list);

   add_quiet_moves(list,board);
   add_castle_moves(list,board);

   // debug

   ASSERT(list_is_ok(list));
}
Exemplo n.º 8
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.º 9
0
static void add_castle_moves(list_t * list, const board_t * board) {

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

   ASSERT(!board_is_check(board));

   if (COLOUR_IS_WHITE(board->turn)) {

      if ((board->flags & FlagsWhiteKingCastle) != 0
       && board->square[F1] == Empty
       && board->square[G1] == Empty
       && !is_attacked(board,F1,Black)) {
         LIST_ADD(list,MOVE_MAKE_FLAGS(E1,G1,MoveCastle));
      }

      if ((board->flags & FlagsWhiteQueenCastle) != 0
       && board->square[D1] == Empty
       && board->square[C1] == Empty
       && board->square[B1] == Empty
       && !is_attacked(board,D1,Black)) {
         LIST_ADD(list,MOVE_MAKE_FLAGS(E1,C1,MoveCastle));
      }

   } else { // black

      if ((board->flags & FlagsBlackKingCastle) != 0
       && board->square[F8] == Empty
       && board->square[G8] == Empty
       && !is_attacked(board,F8,White)) {
         LIST_ADD(list,MOVE_MAKE_FLAGS(E8,G8,MoveCastle));
      }

      if ((board->flags & FlagsBlackQueenCastle) != 0
       && board->square[D8] == Empty
       && board->square[C8] == Empty
       && board->square[B8] == Empty
       && !is_attacked(board,D8,White)) {
         LIST_ADD(list,MOVE_MAKE_FLAGS(E8,C8,MoveCastle));
      }
   }
}
Exemplo n.º 10
0
static bool gen_evasions(list_t * list, const board_t * board, const attack_t * attack, bool legal, bool stop) {

   int me, opp;
   int opp_flag;
   int king;
   const inc_t * inc_ptr;
   int inc;
   int to;
   int piece;

   ASSERT(list!=NULL);
   ASSERT(board!=NULL);
   ASSERT(attack!=NULL);
   ASSERT(legal==true||legal==false);
   ASSERT(stop==true||stop==false);

   ASSERT(board_is_check(board));
   ASSERT(ATTACK_IN_CHECK(attack));

   // init

   LIST_CLEAR(list);

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

   opp_flag = COLOUR_FLAG(opp);

   king = KING_POS(board,me);

   for (inc_ptr = KingInc; (inc=*inc_ptr) != IncNone; inc_ptr++) {
      if (inc != -attack->di[0] && inc != -attack->di[1]) { // avoid escaping along a check line
         to = king + inc;
         piece = board->square[to];
         if (piece == Empty || FLAG_IS(piece,opp_flag)) {
            if (!legal || !is_attacked(board,to,opp)) {
               if (stop) return true;
               LIST_ADD(list,MOVE_MAKE(king,to));
            }
         }
      }
   }

   if (attack->dn >= 2) return false; // double check, we are done

   // single check

   ASSERT(attack->dn==1);

   // capture the checking piece

   if (add_pawn_captures(list,board,attack->ds[0],legal,stop) && stop) return true;
   if (add_piece_moves(list,board,attack->ds[0],legal,stop) && stop) return true;

   // interpose a piece

   inc = attack->di[0];

   if (inc != IncNone) { // line
      for (to = king+inc; to != attack->ds[0]; to += inc) {
         ASSERT(SQUARE_IS_OK(to));
         ASSERT(board->square[to]==Empty);
         if (add_pawn_moves(list,board,to,legal,stop) && stop) return true;
         if (add_piece_moves(list,board,to,legal,stop) && stop) return true;
      }
   }

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

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

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

    ASSERT(!board_is_check(board));

    // special cases

    if (MOVE_IS_SPECIAL(move)) {
        return move_is_pseudo_debug(move,board);
    }

    ASSERT((move&~07777)==0);

    // init

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

    // from

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

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

    ASSERT(piece_is_ok(piece));

    // to

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

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

    // move

    if (PIECE_IS_PAWN(piece)) {

        if (SQUARE_IS_PROMOTE(to)) return false;

        inc = PAWN_MOVE_INC(me);
        delta = to - from;
        ASSERT(delta_is_ok(delta));

        if (capture == Empty) {

            // pawn push

            if (delta == inc) return true;

            if (delta == (2*inc)
                    && PAWN_RANK(from,me) == Rank2
                    && board->square[from+inc] == Empty) {
                return true;
            }

        } else {

            // pawn capture

            if (delta == (inc-1) || delta == (inc+1)) return true;
        }

    } else {

        if (PIECE_ATTACK(board,piece,from,to)) return true;
    }

    return false;
}
Exemplo n.º 12
0
static int full_no_null(board_t * board, int alpha, int beta, int depth, int height, mv_t pv[], int node_type, int trans_move, int * best_move) {

   int value, best_value;
   int move;
   int new_depth;
   attack_t attack[1];
   sort_t sort[1];
   undo_t undo[1];
   mv_t new_pv[HeightMax];

   ASSERT(board!=NULL);
   ASSERT(range_is_ok(alpha,beta));
   ASSERT(depth_is_ok(depth));
   ASSERT(height_is_ok(height));
   ASSERT(pv!=NULL);
   ASSERT(node_type==NodePV||node_type==NodeCut||node_type==NodeAll);
   ASSERT(trans_move==MoveNone||move_is_ok(trans_move));
   ASSERT(best_move!=NULL);

   ASSERT(board_is_legal(board));
   ASSERT(!board_is_check(board));
   ASSERT(depth>=1);

   // init

   SearchStack[height].best_move = MoveNone;
   SearchStack[height].move = MoveNone;
   SearchStack[height].threat_move = MoveNone;
   SearchStack[height].reduced = false;

   SearchCurrent->node_nb++;
   SearchInfo->check_nb--;
   PV_CLEAR(pv);

   if (height > SearchCurrent->max_depth) SearchCurrent->max_depth = height;

   if (SearchInfo->check_nb <= 0) {
      SearchInfo->check_nb += SearchInfo->check_inc;
      search_check();
   }

   attack_set(attack,board);
   ASSERT(!ATTACK_IN_CHECK(attack));

   *best_move = MoveNone;
   best_value = ValueNone;

   // move loop

   sort_init(sort,board,attack,depth,height,trans_move);

   while ((move=sort_next(sort)) != MoveNone) {

	  SearchStack[height].move = move;

      new_depth = full_new_depth(depth,move,board,false,false,false,height);

      move_do(board,move,undo);
      value = -full_search(board,-beta,-alpha,new_depth,height+1,new_pv,NODE_OPP(node_type));
      move_undo(board,move,undo);

      if (value > best_value) {
         best_value = value;
         pv_cat(pv,new_pv,move);
         if (value > alpha) {
            alpha = value;
            *best_move = move;
			SearchStack[height].best_move = move;
            if (value >= beta) goto cut;
         }
      }
   }

   // ALL node

   if (best_value == ValueNone) { // no legal move => stalemate
      ASSERT(board_is_stalemate(board));
      best_value = ValueDraw;
   }

cut:

   ASSERT(value_is_ok(best_value));

   return best_value;
}
Exemplo n.º 13
0
static int full_root(list_t * list, board_t * board, int alpha, int beta, int depth, int height, int search_type) {

   int old_alpha;
   int value, best_value[MultiPVMax];
   int i, move, j;
   int new_depth;
   undo_t undo[1];
   mv_t new_pv[HeightMax];
   bool found;

   ASSERT(list_is_ok(list));
   ASSERT(board_is_ok(board));
   ASSERT(range_is_ok(alpha,beta));
   ASSERT(depth_is_ok(depth));
   ASSERT(height_is_ok(height));
   ASSERT(search_type==SearchNormal||search_type==SearchShort);

   ASSERT(list==SearchRoot->list);
   ASSERT(!LIST_IS_EMPTY(list));
   ASSERT(board==SearchCurrent->board);
   ASSERT(board_is_legal(board));
   ASSERT(depth>=1);

   // init

   SearchStack[height].best_move = MoveNone;
   SearchStack[height].move = MoveNone;
   SearchStack[height].threat_move = MoveNone;
   SearchStack[height].reduced = false;

   SearchCurrent->node_nb++;
   SearchInfo->check_nb--;

   if (SearchCurrent->multipv == 0)
	  for (i = 0; i < LIST_SIZE(list); i++) list->value[i] = ValueNone;

   old_alpha = alpha;
   best_value[SearchCurrent->multipv] = ValueNone;

   // move loop

   for (i = 0; i < LIST_SIZE(list); i++) {

      move = LIST_MOVE(list,i);

	  if (SearchCurrent->multipv > 0){
		  found = false;
		  for (j = 0; j < SearchCurrent->multipv; j++){
			  if (SearchBest[j].pv[0] == move){
				  found = true;
				  break;
			  }
		  }
		  if (found == true)
				continue;
	  }
	  SearchStack[height].move = move;

      SearchRoot->depth = depth;
      SearchRoot->move = move;
      SearchRoot->move_pos = i;
      SearchRoot->move_nb = LIST_SIZE(list);

      search_update_root();

      new_depth = full_new_depth(depth,move,board,board_is_check(board)&&LIST_SIZE(list)==1,false,true, height);

      move_do(board,move,undo);

      if (search_type == SearchShort || best_value[SearchCurrent->multipv] == ValueNone) { // first move
         value = -full_search(board,-beta,-alpha,new_depth,height+1,new_pv,NodePV);
		 if (value <= alpha){ // research
			 old_alpha = -ValueInf;
			 value = -full_search(board,-beta,ValueInf,new_depth,height+1,new_pv,NodePV);
		 }
		 else if (value >= beta){ // research
			 value = -full_search(board,-ValueInf,-alpha,new_depth,height+1,new_pv,NodePV);
		 }
			  
      } else { // other moves
         value = -full_search(board,-alpha-1,-alpha,new_depth,height+1,new_pv,NodeCut);
         if (value > alpha) { // && value < beta
            SearchRoot->change = true;
            SearchRoot->easy = false;
            SearchRoot->flag = false;
            search_update_root();
            value = -full_search(board,-beta,-alpha,new_depth,height+1,new_pv,NodePV);
         }
      }

      move_undo(board,move,undo);

      if (value <= alpha) { // upper bound
         list->value[i] = old_alpha;
      } else if (value >= beta) { // lower bound
         list->value[i] = beta;
      } else { // alpha < value < beta => exact value
         list->value[i] = value;
      }

      if (value > best_value[SearchCurrent->multipv] && (best_value[SearchCurrent->multipv] == ValueNone || value > alpha)) {

         SearchBest[SearchCurrent->multipv].move = move;
		 SearchStack[height].best_move = move;
         SearchBest[SearchCurrent->multipv].value = value;
         if (value <= alpha) { // upper bound
            SearchBest[SearchCurrent->multipv].flags = SearchUpper;
         } else if (value >= beta) { // lower bound
            SearchBest[SearchCurrent->multipv].flags = SearchLower;
         } else { // alpha < value < beta => exact value
            SearchBest[SearchCurrent->multipv].flags = SearchExact;
         }
         SearchBest[SearchCurrent->multipv].depth = depth;
         pv_cat(SearchBest[SearchCurrent->multipv].pv,new_pv,move);

         search_update_best();
      }

      if (value > best_value[SearchCurrent->multipv]) {
         best_value[SearchCurrent->multipv] = value;
         if (value > alpha) {
            if (search_type == SearchNormal) alpha = value;
            if (value >= beta) break;
         }
      }
   }

   ASSERT(value_is_ok(best_value));

   list_sort(list);

   ASSERT(SearchBest->move==LIST_MOVE(list,0));
   ASSERT(SearchBest->value==best_value);

   if (UseTrans && best_value[SearchCurrent->multipv] > old_alpha && best_value[SearchCurrent->multipv] < beta) {
      pv_fill(SearchBest[SearchCurrent->multipv].pv,board);
   }

   return best_value[SearchCurrent->multipv];
}
Exemplo n.º 14
0
bool egbb_probe(const board_t * board, int * value) {

   int i;
   int sq;
   int piece;
   int colour, me;
   const sq_t * ptr;
   int counter;
   int white_king, black_king;
   int piece_list[4], square_list[4];

   ASSERT(board!=NULL);
   ASSERT(value!=NULL);

   ASSERT(board_is_ok(board));
   ASSERT(!board_is_check(board));

   // init

   if (Egbb->init == 0) return false;
   if (Egbb->load == 0) return false;

   ASSERT(board->piece_nb<=Egbb->piece_nb);

   // init

   for (i = 0; i < 4; i++) {
      piece_list[i] = 0;
      square_list[i] = 0;
   }

   Egbb->read_nb++;

   // king

   white_king = SQUARE_TO_64(KING_POS(board,White));
   black_king = SQUARE_TO_64(KING_POS(board,Black));

   counter = 0;

   for (colour = 0; colour < ColourNb; colour++) {

      me = colour;

      // pieces

      for (ptr = &board->piece[me][1]; (sq=*ptr) != SquareNone; ptr++) { // HACK: no king

         piece = board->square[sq];

         // index

         ASSERT(counter>=0&&counter<4);

         piece_list[counter] = TbPiece[PIECE_TO_12(piece)];
         square_list[counter] = SQUARE_TO_64(sq);

         counter++;
      }

      // pawns

      for (ptr = &board->pawn[me][0]; (sq=*ptr) != SquareNone; ptr++) {

         piece = board->square[sq];

         // index

         ASSERT(counter>=0&&counter<4);

         piece_list[counter] = TbPiece[PIECE_TO_12(piece)];
         square_list[counter] = SQUARE_TO_64(sq);

         counter++;
      }
   }

   // probe

   *value = probe_egbb_ptr(board->turn,white_king,black_king,piece_list[0],square_list[0],piece_list[1],square_list[1],piece_list[2],square_list[2]);

   // score

   if (*value != ValueError) {
      Egbb->read_hit++;
      ASSERT(!value_is_mate(*value));
      return true;
   }

   return false;
}