Beispiel #1
0
bool is_pinned(const board_t * board, int from, int to, int colour) {

    int king;
    int inc;
    int sq, piece;

    ASSERT(board!=NULL);
    ASSERT(square_is_ok(from));
    ASSERT(square_is_ok(to));
    ASSERT(colour_is_ok(colour));

    king = king_pos(board,colour);

    inc = DELTA_INC(king-from);
    if (inc == IncNone) return false; // not a line

    sq = from;
    do sq += inc;
    while (board->square[sq] == Empty);

    if (sq != king) return false; // blocker

    sq = from;
    do sq -= inc;
    while ((piece=board->square[sq]) == Empty);

    return square_is_ok(sq)
           && (piece & DELTA_MASK(king-sq)) != 0
           && piece_colour(piece) == colour_opp(colour)
           && DELTA_INC(king-to) != inc;
}
Beispiel #2
0
static void square_clear(board_t * board, int square, int piece) {

   int pos, piece_12, colour;
   int sq, size;

   ASSERT(board!=NULL);
   ASSERT(square_is_ok(square));
   ASSERT(piece_is_ok(piece));

   // init

   pos = board->pos[square];
   ASSERT(pos>=0);

   colour = piece_colour(piece);
   piece_12 = piece_to_12(piece);

   // square

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

   ASSERT(board->pos[square]==pos);
   board->pos[square] = -1; // not needed

   // piece list

   ASSERT(board->variant==Horde?board->list_size[colour]>=1:board->list_size[colour]>=2);
   size = --board->list_size[colour];
   ASSERT(pos<=size);

   if (pos != size) {

      sq = board->list[colour][size];
      ASSERT(square_is_ok(sq));
      ASSERT(sq!=square);

      ASSERT(board->pos[sq]==size);
      board->pos[sq] = pos;

      ASSERT(board->list[colour][pos]==square);
      board->list[colour][pos] = sq;
   }

   board->list[colour][size] = SquareNone;

   // material

   ASSERT(board->number[piece_12]>=1);
   board->number[piece_12]--;

   // hash key

   board->key ^= random_64(RandomPiece+piece_12*64+square_to_64(square));
}
Beispiel #3
0
static void square_set(board_t * board, int square, int piece, int pos) {

   int piece_12, colour;
   int sq, size;

   ASSERT(board!=NULL);
   ASSERT(square_is_ok(square));
   ASSERT(piece_is_ok(piece));
   ASSERT(pos>=0);

   // init

   colour = piece_colour(piece);
   piece_12 = piece_to_12(piece);

   // square

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

   ASSERT(board->pos[square]==-1);
   board->pos[square] = pos;

   // piece list

   size = board->list_size[colour]++;
   ASSERT(board->list[colour][size]==SquareNone);
   ASSERT(pos<=size);

   if (pos != size) {

      sq = board->list[colour][pos];
      ASSERT(square_is_ok(sq));
      ASSERT(sq!=square);

      ASSERT(board->pos[sq]==pos);
      board->pos[sq] = size;

      ASSERT(board->list[colour][size]==SquareNone);
      board->list[colour][size] = sq;
   }

   board->list[colour][pos] = square;

   // material

   ASSERT(board->number[piece_12]<=8);
   board->number[piece_12]++;

   // hash key

   board->key ^= random_64(RandomPiece+piece_12*64+square_to_64(square));
}
Beispiel #4
0
static void square_move(board_t * board, int from, int to, int piece) {

   int colour, pos;
   int piece_index;

   ASSERT(board!=NULL);
   ASSERT(square_is_ok(from));
   ASSERT(square_is_ok(to));
   ASSERT(piece_is_ok(piece));

   // init

   colour = piece_colour(piece);

   pos = board->pos[from];
   ASSERT(pos>=0);

   // from

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

   ASSERT(board->pos[from]==pos);
   board->pos[from] = -1; // not needed

   // to

   ASSERT(board->square[to]==Empty);
   board->square[to] = piece;

   ASSERT(board->pos[to]==-1);
   board->pos[to] = pos;

   // piece list

   ASSERT(board->list[colour][pos]==from);
   board->list[colour][pos] = to;

   // hash key

   piece_index = RandomPiece + piece_to_12(piece) * 64;

   board->key ^= random_64(piece_index+square_to_64(from))
               ^ random_64(piece_index+square_to_64(to));
}
bool board_is_ok(const board_t * board) {

   int sq, piece;
   int colour, pos;
   int king, rook;

   if (board == NULL) return false;

   // optional heavy DEBUG mode

   if (!UseSlowDebug) return true;

   // squares

   for (sq = 0; sq < SquareNb; sq++) {
      piece = board->square[sq];
      if (square_is_ok(sq)) {
         pos = board->pos[sq];
         if (piece == Empty) {
            if (pos != -1) return false;
         } else {
            if (pos < 0) return false;
            if (board->list[piece_colour(piece)][pos] != sq) return false;
         }
      } else {
         if (piece != Knight64) return false;
      }
   }

   // white piece list

   colour = White;
   pos = 0;

   if (board->list_size[colour] <= 0 || board->list_size[colour] > 16) return false;

   sq = board->list[colour][pos];
   if (sq == SquareNone) return false;
   if (board->pos[sq] != pos) return false;
   piece = board->square[sq];
   if (!colour_equal(piece,colour) || !piece_is_king(piece)) return false;

   for (pos++; pos < board->list_size[colour]; pos++) {
      sq = board->list[colour][pos];
      if (sq == SquareNone) return false;
      if (board->pos[sq] != pos) return false;
      if (!colour_equal(board->square[sq],colour)) return false;
   }

   sq = board->list[colour][pos];
   if (sq != SquareNone) return false;

   // black piece list

   colour = Black;
   pos = 0;

   if (board->list_size[colour] <= 0 || board->list_size[colour] > 16) return false;

   sq = board->list[colour][pos];
   if (sq == SquareNone) return false;
   if (board->pos[sq] != pos) return false;
   piece = board->square[sq];
   if (!colour_equal(piece,colour) || !piece_is_king(piece)) return false;

   for (pos++; pos < board->list_size[colour]; pos++) {
      sq = board->list[colour][pos];
      if (sq == SquareNone) return false;
      if (board->pos[sq] != pos) return false;
      if (!colour_equal(board->square[sq],colour)) return false;
   }

   sq = board->list[colour][pos];
   if (sq != SquareNone) return false;

   // TODO: material

   if (board->number[WhiteKing12] != 1) return false;
   if (board->number[BlackKing12] != 1) return false;

   if (!colour_is_ok(board->turn)) return false;

   // castling status

   if (board->castle[White][SideH] != SquareNone) {

      king = board->list[White][0];
      if (king < A1 || king > H1) return false;
      if (board->square[king] != WhiteKing256) return false;

      rook = board->castle[White][SideH];
      if (rook < A1 || rook > H1) return false;
      if (board->square[rook] != WhiteRook256) return false;

      if (rook <= king) return false;
   }

   if (board->castle[White][SideA] != SquareNone) {

      king = board->list[White][0];
      if (king < A1 || king > H1) return false;
      if (board->square[king] != WhiteKing256) return false;

      rook = board->castle[White][SideA];
      if (rook < A1 || rook > H1) return false;
      if (board->square[rook] != WhiteRook256) return false;

      if (rook >= king) return false;
   }

   if (board->castle[Black][SideH] != SquareNone) {

      king = board->list[Black][0];
      if (king < A8 || king > H8) return false;
      if (board->square[king] != BlackKing256) return false;

      rook = board->castle[Black][SideH];
      if (rook < A8 || rook > H8) return false;
      if (board->square[rook] != BlackRook256) return false;

      if (rook <= king) return false;
   }

   if (board->castle[Black][SideA] != SquareNone) {

      king = board->list[Black][0];
      if (king < A8 || king > H8) return false;
      if (board->square[king] != BlackKing256) return false;

      rook = board->castle[Black][SideA];
      if (rook < A8 || rook > H8) return false;
      if (board->square[rook] != BlackRook256) return false;

      if (rook >= king) return false;
   }

   return true;
}
Beispiel #6
0
bool board_from_fen(board_t * board, const char string[]) {

   int pos;
   int file, rank, sq;
   int c;
   int i, len;
   int piece;
   int king_pos[ColourNb];

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

   board_clear(board);

   king_pos[White] = SquareNone;
   king_pos[Black] = SquareNone;

   pos = 0;
   c = string[pos];

   // piece placement

   for (rank = 7; rank >= 0; rank--) {

      for (file = 0; file < 8;) {

         sq = square_make(file,rank);

         if (c >= '1' && c <= '8') { // empty square(s)

            len = c - '0';
            if (file + len > 8) my_fatal("board_from_fen(): bad FEN (pos=%d)\n",pos);

            for (i = 0; i < len; i++) {
               board->square[sq++] = Empty;
               file++;
            }

         } else { // piece

            piece = piece_from_char(c);
            if (piece == PieceNone256) my_fatal("board_from_fen(): bad FEN (pos=%d)\n",pos);

            if (piece_is_king(piece)) king_pos[piece_colour(piece)] = sq;

            board->square[sq++] = piece;
            file++;
         }

         c = string[++pos];
      }

      if (rank > 0) {
         if (c != '/') my_fatal("board_from_fen(): bad FEN (pos=%d)\n",pos);
         c = string[++pos];
     }
   }

   // active colour

   if (c != ' ') my_fatal("board_from_fen(): bad FEN (pos=%d)\n",pos);
   c = string[++pos];

   switch (c) {
   case 'w':
      board->turn = White;
      break;
   case 'b':
      board->turn = Black;
      break;
   default:
      my_fatal("board_from_fen(): bad FEN (pos=%d)\n",pos);
      break;
   }

   c = string[++pos];

   // castling

   if (c != ' ') my_fatal("board_from_fen(): bad FEN (pos=%d)\n",pos);
   c = string[++pos];

   board->castle[White][SideH] = SquareNone;
   board->castle[White][SideA] = SquareNone;
   board->castle[Black][SideH] = SquareNone;
   board->castle[Black][SideA] = SquareNone;

   if (c == '-') { // no castling rights

      c = string[++pos];

   } else {

      // TODO: filter out illegal rights

      do {

         if (false) {

         } else if (c == 'K') {

            for (sq = H1; sq > king_pos[White]; sq--) {
               if (board->square[sq] == WhiteRook256) {
                  board->castle[White][SideH] = sq;
                  break;
               }
            }

         } else if (c == 'Q') {

            for (sq = A1; sq < king_pos[White]; sq++) {
               if (board->square[sq] == WhiteRook256) {
                  board->castle[White][SideA] = sq;
                  break;
               }
            }

         } else if (c == 'k') {

            for (sq = H8; sq > king_pos[Black]; sq--) {
               if (board->square[sq] == BlackRook256) {
                  board->castle[Black][SideH] = sq;
                  break;
               }
            }

         } else if (c == 'q') {

            for (sq = A8; sq < king_pos[Black]; sq++) {
               if (board->square[sq] == BlackRook256) {
                  board->castle[Black][SideA] = sq;
                  break;
               }
            }

         } else if (c >= 'A' && c <= 'H') {

            // white castling right

            sq = square_make(file_from_char(tolower(c)),Rank1);

            if (sq > king_pos[White]) { // h side
               board->castle[White][SideH] = sq;
            } else { // a side
               board->castle[White][SideA] = sq;
            }

         } else if (c >= 'a' && c <= 'h') {

            // black castling right

            sq = square_make(file_from_char(tolower(c)),Rank8);

            if (sq > king_pos[Black]) { // h side
               board->castle[Black][SideH] = sq;
            } else { // a side
               board->castle[Black][SideA] = sq;
            }

         } else {

            my_fatal("board_from_fen(): bad FEN (pos=%d)\n",pos);
         }

         c = string[++pos];

      } while (c != ' ');
   }

   // en-passant

   if (c != ' ') my_fatal("board_from_fen(): bad FEN (pos=%d)\n",pos);
   c = string[++pos];

   if (c == '-') { // no en-passant

      sq = SquareNone;
      c = string[++pos];

   } else {

      if (c < 'a' || c > 'h') my_fatal("board_from_fen(): bad FEN (pos=%d)\n",pos);
      file = file_from_char(c);
      c = string[++pos];

      if (c < '1' || c > '8') my_fatal("board_from_fen(): bad FEN (pos=%d)\n",pos);
      rank = rank_from_char(c);
      c = string[++pos];

      sq = square_make(file,rank);
   }

   board->ep_square = sq;

   // halfmove clock

   board->ply_nb = 0;
   board->move_nb = 0; // HACK, in case of broken syntax

   if (c != ' ') {
      if (!Strict) goto update;
      my_fatal("board_from_fen(): bad FEN (pos=%d)\n",pos);
   }
   c = string[++pos];

   if (!isdigit(c)) {
      if (!Strict) goto update;
      my_fatal("board_from_fen(): bad FEN (pos=%d)\n",pos);
   }

   board->ply_nb = atoi(&string[pos]);
   do c = string[++pos]; while (isdigit(c));

   // fullmove number

   board->move_nb = 0;

   if (c != ' ') {
      if (!Strict) goto update;
      my_fatal("board_from_fen(): bad FEN (pos=%d)\n",pos);
   }
   c = string[++pos];

   if (!isdigit(c)) {
      if (!Strict) goto update;
      my_fatal("board_from_fen(): bad FEN (pos=%d)\n",pos);
   }

   board->move_nb = atoi(&string[pos]) - 1;
   do c = string[++pos]; while (isdigit(c));

   // board update

update:
   board_init_list(board);

   return true;
}