예제 #1
0
파일: fen.cpp 프로젝트: ZirconiumX/fruitfly
void board_from_fen(board_t * board, const char fen[]) {

   int pos;
   int file, rank, sq;
   int c;
   int i, len;
   int piece;
   int pawn;

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

   board_clear(board);

   pos = 0;
   c = fen[pos];

   // piece placement

   for (rank = Rank8; rank >= Rank1; rank--) {

      for (file = FileA; file <= FileH;) {

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

            len = c - '0';

            for (i = 0; i < len; i++) {
               if (file > FileH) my_fatal("board_from_fen(): bad FEN (pos=%d)\n",pos);
               board->square[SQUARE_MAKE(file,rank)] = Empty;
               file++;
            }

         } else { // piece

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

            board->square[SQUARE_MAKE(file,rank)] = piece;
            file++;
         }

         c = fen[++pos];
      }

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

   // active colour

   if (c != ' ') my_fatal("board_from_fen(): bad FEN (pos=%d)\n",pos);
   c = fen[++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 = fen[++pos];

   // castling

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

   board->flags = FlagsNone;

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

      c = fen[++pos];

   } else {

      if (c == 'K') {
         if (board->square[E1] == WK && board->square[H1] == WR) board->flags |= FlagsWhiteKingCastle;
         c = fen[++pos];
      }

      if (c == 'Q') {
         if (board->square[E1] == WK && board->square[A1] == WR) board->flags |= FlagsWhiteQueenCastle;
         c = fen[++pos];
      }

      if (c == 'k') {
         if (board->square[E8] == BK && board->square[H8] == BR) board->flags |= FlagsBlackKingCastle;
         c = fen[++pos];
      }

      if (c == 'q') {
         if (board->square[E8] == BK && board->square[A8] == BR) board->flags |= FlagsBlackQueenCastle;
         c = fen[++pos];
      }
   }

   // en-passant

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

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

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

   } else {

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

      if (c != (COLOUR_IS_WHITE(board->turn) ? '6' : '3')) my_fatal("board_from_fen(): bad FEN (pos=%d)\n",pos);
      rank = rank_from_char(c);
      c = fen[++pos];

      sq = SQUARE_MAKE(file,rank);
      pawn = SQUARE_EP_DUAL(sq);

      if (board->square[sq] != Empty
       || board->square[pawn] != PAWN_MAKE(COLOUR_OPP(board->turn))
       || (board->square[pawn-1] != PAWN_MAKE(board->turn)
        && board->square[pawn+1] != PAWN_MAKE(board->turn))) {
         sq = SquareNone;
      }
   }

   board->ep_square = sq;

   // halfmove clock

   board->ply_nb = 0;

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

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

   board->ply_nb = atoi(&fen[pos]);

   // board update

update:
   board_init_list(board);
}
예제 #2
0
static void parse_go(char string[]) {

   const char * ptr;
   bool infinite, ponder;
   int depth, mate, movestogo;
   sint64 nodes;
   double binc, btime, movetime, winc, wtime;
   double time, inc;
   double time_max, alloc;

   // init

   infinite = false;
   ponder = false;

   depth = -1;
   mate = -1;
   movestogo = -1;

   nodes = -1;

   binc = -1.0;
   btime = -1.0;
   movetime = -1.0;
   winc = -1.0;
   wtime = -1.0;

   // parse

   ptr = strtok(string," "); // skip "go"

   for (ptr = strtok(NULL," "); ptr != NULL; ptr = strtok(NULL," ")) {

      if (false) {

      } else if (string_equal(ptr,"binc")) {

         ptr = strtok(NULL," ");
         if (ptr == NULL) my_fatal("parse_go(): missing argument\n");

         binc = double(atoi(ptr)) / 1000.0;
         ASSERT(binc>=0.0);

      } else if (string_equal(ptr,"btime")) {

         ptr = strtok(NULL," ");
         if (ptr == NULL) my_fatal("parse_go(): missing argument\n");

         btime = double(atoi(ptr)) / 1000.0;
         ASSERT(btime>=0.0);

      } else if (string_equal(ptr,"depth")) {

         ptr = strtok(NULL," ");
         if (ptr == NULL) my_fatal("parse_go(): missing argument\n");

         depth = atoi(ptr);
         ASSERT(depth>=0);

      } else if (string_equal(ptr,"infinite")) {

         infinite = true;

      } else if (string_equal(ptr,"mate")) {

         ptr = strtok(NULL," ");
         if (ptr == NULL) my_fatal("parse_go(): missing argument\n");

         mate = atoi(ptr);
         ASSERT(mate>=0);

      } else if (string_equal(ptr,"movestogo")) {

         ptr = strtok(NULL," ");
         if (ptr == NULL) my_fatal("parse_go(): missing argument\n");

         movestogo = atoi(ptr);
         ASSERT(movestogo>=0);

      } else if (string_equal(ptr,"movetime")) {

         ptr = strtok(NULL," ");
         if (ptr == NULL) my_fatal("parse_go(): missing argument\n");

         movetime = double(atoi(ptr)) / 1000.0;
         ASSERT(movetime>=0.0);

      } else if (string_equal(ptr,"nodes")) {

         ptr = strtok(NULL," ");
         if (ptr == NULL) my_fatal("parse_go(): missing argument\n");

         nodes = my_atoll(ptr);
         ASSERT(nodes>=0);

      } else if (string_equal(ptr,"ponder")) {

         ponder = true;

      } else if (string_equal(ptr,"searchmoves")) {

         // dummy

      } else if (string_equal(ptr,"winc")) {

         ptr = strtok(NULL," ");
         if (ptr == NULL) my_fatal("parse_go(): missing argument\n");

         winc = double(atoi(ptr)) / 1000.0;
         ASSERT(winc>=0.0);

      } else if (string_equal(ptr,"wtime")) {

         ptr = strtok(NULL," ");
         if (ptr == NULL) my_fatal("parse_go(): missing argument\n");

         wtime = double(atoi(ptr)) / 1000.0;
         ASSERT(wtime>=0.0);
      }
   }

   // init

   search_clear();

   // depth limit

   // JAS
   int option_depth = 0;
   option_depth = option_get_int("Search Depth");
   if (option_depth > 0) {
   	  depth = option_depth;
   }
   // JAS end

   if (depth >= 0) {
      SearchInput->depth_is_limited = true;
      SearchInput->depth_limit = depth;
   } else if (mate >= 0) {
      SearchInput->depth_is_limited = true;
      SearchInput->depth_limit = mate * 2 - 1; // HACK: move -> ply
   }

   // time limit

   if (COLOUR_IS_WHITE(SearchInput->board->turn)) {
      time = wtime;
      inc = winc;
   } else {
      time = btime;
      inc = binc;
   }

   if (movestogo <= 0 || movestogo > 30) movestogo = 20; // HACK was 30
   if (inc < 0.0) inc = 0.0;

   // JAS
   int option_movetime = 0;
   option_movetime = option_get_int("Search Time");
   if (option_movetime > 0) {
   	  movetime = option_movetime;
   }
   // JAS end

   if (movetime >= 0.0) {

      // fixed time

      SearchInput->time_is_limited = true;
      SearchInput->time_limit_1 = movetime * 5.0; // HACK to avoid early exit
      SearchInput->time_limit_2 = movetime;

   } else if (time >= 0.0) {

      // dynamic allocation

      time_max = time * 0.95 - 1.0;
      if (time_max < 0.0) time_max = 0.0;

      SearchInput->time_is_limited = true;

      alloc = (time_max + inc * double(movestogo-1)) / double(movestogo);
      alloc *= (option_get_bool("Ponder") ? PonderRatio : NormalRatio);
      if (alloc > time_max) alloc = time_max;
      SearchInput->time_limit_1 = alloc;

      alloc = (time_max + inc * double(movestogo-1)) * 0.5;
      if (alloc < SearchInput->time_limit_1) alloc = SearchInput->time_limit_1;
      if (alloc > time_max) alloc = time_max;
      SearchInput->time_limit_2 = alloc;
   }

   if (infinite || ponder) SearchInput->infinite = true;

   // search

   ASSERT(!Searching);
   ASSERT(!Delay);

   Searching = true;
   Infinite = infinite || ponder;
   Delay = false;

   search();
   search_update_current();

   ASSERT(Searching);
   ASSERT(!Delay);

   Searching = false;
   Delay = Infinite;

   if (!Delay) send_best_move();
}
예제 #3
0
void board_init_list(board_t * board) {

   int sq_64, sq, piece;
   int colour, pos;
   int i, size;
   int square;
   int order;
   int file;

   ASSERT(board!=NULL);

   // init

   for (sq = 0; sq < SquareNb; sq++) {
      board->pos[sq] = -1;
   }

   board->piece_nb = 0;
   for (piece = 0; piece < 12; piece++) board->number[piece] = 0;

   // piece lists

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

      // piece list

      pos = 0;

      for (sq_64 = 0; sq_64 < 64; sq_64++) {

         sq = SQUARE_FROM_64(sq_64);
         piece = board->square[sq];
         if (piece != Empty && !piece_is_ok(piece)) my_fatal("board_init_list(): illegal position\n");

         if (COLOUR_IS(piece,colour) && !PIECE_IS_PAWN(piece)) {

            if (pos >= 16) my_fatal("board_init_list(): illegal position\n");
            ASSERT(pos>=0&&pos<16);

            board->pos[sq] = pos;
            board->piece[colour][pos] = sq;
            pos++;

            board->piece_nb++;
            board->number[PIECE_TO_12(piece)]++;
         }
      }

      if (board->number[COLOUR_IS_WHITE(colour)?WhiteKing12:BlackKing12] != 1) my_fatal("board_init_list(): illegal position\n");

      ASSERT(pos>=1&&pos<=16);
      board->piece[colour][pos] = SquareNone;
      board->piece_size[colour] = pos;

      // MV sort

      size = board->piece_size[colour];

      for (i = 1; i < size; i++) {

         square = board->piece[colour][i];
         piece = board->square[square];
         order = PIECE_ORDER(piece);

         for (pos = i; pos > 0 && order > PIECE_ORDER(board->square[(sq=board->piece[colour][pos-1])]); pos--) {
            ASSERT(pos>0&&pos<size);
            board->piece[colour][pos] = sq;
            ASSERT(board->pos[sq]==pos-1);
            board->pos[sq] = pos;
         }

         ASSERT(pos>=0&&pos<size);
         board->piece[colour][pos] = square;
         ASSERT(board->pos[square]==i);
         board->pos[square] = pos;
      }

      // debug

      if (DEBUG) {

         for (i = 0; i < board->piece_size[colour]; i++) {

            sq = board->piece[colour][i];
            ASSERT(board->pos[sq]==i);

            if (i == 0) { // king
               ASSERT(PIECE_IS_KING(board->square[sq]));
            } else {
               ASSERT(!PIECE_IS_KING(board->square[sq]));
               ASSERT(PIECE_ORDER(board->square[board->piece[colour][i]])<=PIECE_ORDER(board->square[board->piece[colour][i-1]]));
            }
         }
      }

      // pawn list

      for (file = 0; file < FileNb; file++) {
         board->pawn_file[colour][file] = 0;
      }

      pos = 0;

      for (sq_64 = 0; sq_64 < 64; sq_64++) {

         sq = SQUARE_FROM_64(sq_64);
         piece = board->square[sq];

         if (COLOUR_IS(piece,colour) && PIECE_IS_PAWN(piece)) {

            if (pos >= 8 || SQUARE_IS_PROMOTE(sq)) my_fatal("board_init_list(): illegal position\n");
            ASSERT(pos>=0&&pos<8);

            board->pos[sq] = pos;
            board->pawn[colour][pos] = sq;
            pos++;

            board->piece_nb++;
            board->number[PIECE_TO_12(piece)]++;
            board->pawn_file[colour][SQUARE_FILE(sq)] |= BIT(PAWN_RANK(sq,colour));
         }
      }

      ASSERT(pos>=0&&pos<=8);
      board->pawn[colour][pos] = SquareNone;
      board->pawn_size[colour] = pos;

      if (board->piece_size[colour] + board->pawn_size[colour] > 16) my_fatal("board_init_list(): illegal position\n");
   }

   // last square

   board->cap_sq = SquareNone;

   // PST

   board->opening = board_opening(board);
   board->endgame = board_endgame(board);

   // hash key

   for (i = 0; i < board->ply_nb; i++) board->stack[i] = 0; // HACK
   board->sp = board->ply_nb;

   board->key = hash_key(board);
   board->pawn_key = hash_pawn_key(board);
   board->material_key = hash_material_key(board);

   // legality

   if (!board_is_legal(board)) my_fatal("board_init_list(): illegal position\n");

   // debug

   ASSERT(board_is_ok(board));
}
예제 #4
0
파일: fen.cpp 프로젝트: ZirconiumX/fruitfly
bool board_to_fen(const board_t * board, char fen[], int size) {

   int pos;
   int file, rank;
   int sq, piece;
   int c;
   int len;

   ASSERT(board!=NULL);
   ASSERT(fen!=NULL);
   ASSERT(size>=92);

   // init

   if (size < 92) return false;

   pos = 0;

   // piece placement

   for (rank = Rank8; rank >= Rank1; rank--) {

      for (file = FileA; file <= FileH;) {

         sq = SQUARE_MAKE(file,rank);
         piece = board->square[sq];
         ASSERT(piece==Empty||piece_is_ok(piece));

         if (piece == Empty) {

            len = 0;
            for (; file <= FileH && board->square[SQUARE_MAKE(file,rank)] == Empty; file++) {
               len++;
            }

            ASSERT(len>=1&&len<=8);
            c = '0' + len;

         } else {

            c = piece_to_char(piece);
            file++;
         }

         fen[pos++] = c;
      }

      fen[pos++] = '/';
   }

   fen[pos-1] = ' '; // HACK: remove the last '/'

   // active colour

   fen[pos++] = (COLOUR_IS_WHITE(board->turn)) ? 'w' : 'b';
   fen[pos++] = ' ';

   // castling

   if (board->flags == FlagsNone) {
      fen[pos++] = '-';
   } else {
      if ((board->flags & FlagsWhiteKingCastle)  != 0) fen[pos++] = 'K';
      if ((board->flags & FlagsWhiteQueenCastle) != 0) fen[pos++] = 'Q';
      if ((board->flags & FlagsBlackKingCastle)  != 0) fen[pos++] = 'k';
      if ((board->flags & FlagsBlackQueenCastle) != 0) fen[pos++] = 'q';
   }

   fen[pos++] = ' ';

   // en-passant

   if (board->ep_square == SquareNone) {
      fen[pos++] = '-';
   } else {
      square_to_string(board->ep_square,&fen[pos],3);
      pos += 2;
   }

   fen[pos++] = ' ';

   // halfmove clock

   sprintf(&fen[pos],"%d 1",board->ply_nb);

   return true;
}
예제 #5
0
static void parse_go(char string[]) {

   const char * ptr;
   bool infinite, ponder;
   int depth, mate, movestogo;
   sint64 nodes;
   double binc, btime, movetime, winc, wtime;
   double time, inc;

   // init

   infinite = false;
   ponder = false;

   depth = -1;
   mate = -1;
   movestogo = -1;

   nodes = -1;

   binc = -1.0;
   btime = -1.0;
   movetime = -1.0;
   winc = -1.0;
   wtime = -1.0;

   // parse

   ptr = strtok(string," "); // skip "go"

   for (ptr = strtok(NULL," "); ptr != NULL; ptr = strtok(NULL," ")) {

      if (false) {

      } else if (string_equal(ptr,"binc")) {

         ptr = strtok(NULL," ");
         if (ptr == NULL) my_fatal("parse_go(): missing argument\n");

         binc = double(atoi(ptr)) / 1000.0;
         ASSERT(binc>=0.0);

      } else if (string_equal(ptr,"btime")) {

         ptr = strtok(NULL," ");
         if (ptr == NULL) my_fatal("parse_go(): missing argument\n");

         btime = double(atoi(ptr)) / 1000.0;
         ASSERT(btime>=0.0);

      } else if (string_equal(ptr,"depth")) {

         ptr = strtok(NULL," ");
         if (ptr == NULL) my_fatal("parse_go(): missing argument\n");

         depth = atoi(ptr);
         ASSERT(depth>=0);

      } else if (string_equal(ptr,"infinite")) {

         infinite = true;

      } else if (string_equal(ptr,"mate")) {

         ptr = strtok(NULL," ");
         if (ptr == NULL) my_fatal("parse_go(): missing argument\n");

         mate = atoi(ptr);
         ASSERT(mate>=0);

      } else if (string_equal(ptr,"movestogo")) {

         ptr = strtok(NULL," ");
         if (ptr == NULL) my_fatal("parse_go(): missing argument\n");

         movestogo = atoi(ptr);
         ASSERT(movestogo>=0);

      } else if (string_equal(ptr,"movetime")) {

         ptr = strtok(NULL," ");
         if (ptr == NULL) my_fatal("parse_go(): missing argument\n");

         movetime = double(atoi(ptr)) / 1000.0;
         ASSERT(movetime>=0.0);

      } else if (string_equal(ptr,"nodes")) {

         ptr = strtok(NULL," ");
         if (ptr == NULL) my_fatal("parse_go(): missing argument\n");

         nodes = my_atoll(ptr);
         ASSERT(nodes>=0);

      } else if (string_equal(ptr,"ponder")) {

         ponder = true;

      } else if (string_equal(ptr,"searchmoves")) {

         // dummy

      } else if (string_equal(ptr,"winc")) {

         ptr = strtok(NULL," ");
         if (ptr == NULL) my_fatal("parse_go(): missing argument\n");

         winc = double(atoi(ptr)) / 1000.0;
         ASSERT(winc>=0.0);

      } else if (string_equal(ptr,"wtime")) {

         ptr = strtok(NULL," ");
         if (ptr == NULL) my_fatal("parse_go(): missing argument\n");

         wtime = double(atoi(ptr)) / 1000.0;
         ASSERT(wtime>=0.0);
      }
   }

   // init

   search_clear();
   tb_clear();
   egbb_clear();

   eval_init_options();

   // depth limit

   if (depth >= 0) {
      SearchInput->depth_is_limited = true;
      SearchInput->depth_limit = depth;
   } else if (mate >= 0) {
      SearchInput->depth_is_limited = true;
      SearchInput->depth_limit = mate * 2 - 1; // HACK: move -> ply
   }

   // nodes limit

   if (nodes > 0) {
      if (nodes < 1000) nodes = 1000;
      SearchInput->nodes_is_limited = true;
      SearchInput->nodes = nodes;
   }

   // time limit

   if (COLOUR_IS_WHITE(SearchInput->board->turn)) {
      time = wtime;
      inc = winc;
   } else {
      time = btime;
      inc = binc;
   }

   if (movestogo <= 0 || movestogo > 30) movestogo = 30; // HACK
   if (inc < 0.0) inc = 0.0;

   if (movetime >= 0.0) {

      // fixed time

      SearchInput->time_is_limited = true;
      SearchInput->time_limit_1 = movetime * 5.0; // HACK to avoid early exit
      SearchInput->time_limit_2 = movetime;

   } else if (time >= 0.0) {

      SearchInput->time_is_limited = true;
      time_allocation(time,inc,movestogo);
   }

   if (infinite || ponder) SearchInput->infinite = true;

   // search

   ASSERT(!Searching);
   ASSERT(!Delay);

   Searching = true;
   Infinite = infinite || ponder;
   Delay = false;

   search();
   search_update_current();

   ASSERT(Searching);
   ASSERT(!Delay);

   Searching = false;
   Delay = Infinite;

   if (!Delay) send_best_move();
}
예제 #6
0
static bool kpk_draw(int wp, int wk, int bk, int turn) {

   int wp_file, wp_rank;
   int wk_file;
   int bk_file, bk_rank;

   ASSERT(SQUARE_IS_OK(wp));
   ASSERT(SQUARE_IS_OK(wk));
   ASSERT(SQUARE_IS_OK(bk));
   ASSERT(COLOUR_IS_OK(turn));

   ASSERT(SQUARE_FILE(wp)<=FileD);

   wp_file = SQUARE_FILE(wp);
   wp_rank = SQUARE_RANK(wp);

   wk_file = SQUARE_FILE(wk);

   bk_file = SQUARE_FILE(bk);
   bk_rank = SQUARE_RANK(bk);

   if (false) {

   } else if (bk == wp+16) {

      if (wp_rank <= Rank6) {

         return true;

      } else {

         ASSERT(wp_rank==Rank7);

         if (COLOUR_IS_WHITE(turn)) {
            if (wk == wp-15 || wk == wp-17) return true;
         } else {
            if (wk != wp-15 && wk != wp-17) return true;
         }
      }

   } else if (bk == wp+32) {

      if (wp_rank <= Rank5) {

         return true;

      } else {

         ASSERT(wp_rank==Rank6);

         if (COLOUR_IS_WHITE(turn)) {
            if (wk != wp-1 && wk != wp+1) return true;
         } else {
            return true;
         }
      }

   } else if (wk == wp-1 || wk == wp+1) {

      if (bk == wk+32 && COLOUR_IS_WHITE(turn)) { // opposition
         return true;
      }

   } else if (wk == wp+15 || wk == wp+16 || wk == wp+17) {

      if (wp_rank <= Rank4) {
         if (bk == wk+32 && COLOUR_IS_WHITE(turn)) { // opposition
            return true;
         }
      }
   }

   // rook pawn

   if (wp_file == FileA) {

      if (DISTANCE(bk,A8) <= 1) return true;

      if (wk_file == FileA) {
         if (wp_rank == Rank2) wp_rank++; // HACK
         if (bk_file == FileC && bk_rank > wp_rank) return true;
      }
   }

   return false;
}
예제 #7
0
uint64 hash_turn_key(int colour) {

   ASSERT(COLOUR_IS_OK(colour));

   return (COLOUR_IS_WHITE(colour)) ? RANDOM_64(RandomTurn) : 0;
}
예제 #8
0
static void add_quiet_moves(list_t * list, const board_t * board) {

   int me;
   const sq_t * ptr;
   int from, to;
   int piece;

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

   me = board->turn;

   // piece moves

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

      piece = board->square[from];

      switch (PIECE_TYPE(piece)) {

      case Knight64:

         to = from - 33;
         if (board->square[to] == Empty) LIST_ADD(list,MOVE_MAKE(from,to));

         to = from - 31;
         if (board->square[to] == Empty) LIST_ADD(list,MOVE_MAKE(from,to));

         to = from - 18;
         if (board->square[to] == Empty) LIST_ADD(list,MOVE_MAKE(from,to));

         to = from - 14;
         if (board->square[to] == Empty) LIST_ADD(list,MOVE_MAKE(from,to));

         to = from + 14;
         if (board->square[to] == Empty) LIST_ADD(list,MOVE_MAKE(from,to));

         to = from + 18;
         if (board->square[to] == Empty) LIST_ADD(list,MOVE_MAKE(from,to));

         to = from + 31;
         if (board->square[to] == Empty) LIST_ADD(list,MOVE_MAKE(from,to));

         to = from + 33;
         if (board->square[to] == Empty) LIST_ADD(list,MOVE_MAKE(from,to));

         break;

      case Bishop64:

         for (to = from-17; board->square[to] == Empty; to -= 17) {
            LIST_ADD(list,MOVE_MAKE(from,to));
         }

         for (to = from-15; board->square[to] == Empty; to -= 15) {
            LIST_ADD(list,MOVE_MAKE(from,to));
         }

         for (to = from+15; board->square[to] == Empty; to += 15) {
            LIST_ADD(list,MOVE_MAKE(from,to));
         }

         for (to = from+17; board->square[to] == Empty; to += 17) {
            LIST_ADD(list,MOVE_MAKE(from,to));
         }

         break;

      case Rook64:

         for (to = from-16; board->square[to] == Empty; to -= 16) {
            LIST_ADD(list,MOVE_MAKE(from,to));
         }

         for (to = from-1; board->square[to] == Empty; to -= 1) {
            LIST_ADD(list,MOVE_MAKE(from,to));
         }

         for (to = from+1; board->square[to] == Empty; to += 1) {
            LIST_ADD(list,MOVE_MAKE(from,to));
         }

         for (to = from+16; board->square[to] == Empty; to += 16) {
            LIST_ADD(list,MOVE_MAKE(from,to));
         }

         break;

      case Queen64:

         for (to = from-17; board->square[to] == Empty; to -= 17) {
            LIST_ADD(list,MOVE_MAKE(from,to));
         }

         for (to = from-16; board->square[to] == Empty; to -= 16) {
            LIST_ADD(list,MOVE_MAKE(from,to));
         }

         for (to = from-15; board->square[to] == Empty; to -= 15) {
            LIST_ADD(list,MOVE_MAKE(from,to));
         }

         for (to = from-1; board->square[to] == Empty; to -= 1) {
            LIST_ADD(list,MOVE_MAKE(from,to));
         }

         for (to = from+1; board->square[to] == Empty; to += 1) {
            LIST_ADD(list,MOVE_MAKE(from,to));
         }

         for (to = from+15; board->square[to] == Empty; to += 15) {
            LIST_ADD(list,MOVE_MAKE(from,to));
         }

         for (to = from+16; board->square[to] == Empty; to += 16) {
            LIST_ADD(list,MOVE_MAKE(from,to));
         }

         for (to = from+17; board->square[to] == Empty; to += 17) {
            LIST_ADD(list,MOVE_MAKE(from,to));
         }

         break;

      case King64:

         to = from - 17;
         if (board->square[to] == Empty) LIST_ADD(list,MOVE_MAKE(from,to));

         to = from - 16;
         if (board->square[to] == Empty) LIST_ADD(list,MOVE_MAKE(from,to));

         to = from - 15;
         if (board->square[to] == Empty) LIST_ADD(list,MOVE_MAKE(from,to));

         to = from - 1;
         if (board->square[to] == Empty) LIST_ADD(list,MOVE_MAKE(from,to));

         to = from + 1;
         if (board->square[to] == Empty) LIST_ADD(list,MOVE_MAKE(from,to));

         to = from + 15;
         if (board->square[to] == Empty) LIST_ADD(list,MOVE_MAKE(from,to));

         to = from + 16;
         if (board->square[to] == Empty) LIST_ADD(list,MOVE_MAKE(from,to));

         to = from + 17;
         if (board->square[to] == Empty) LIST_ADD(list,MOVE_MAKE(from,to));

         break;

      default:

         ASSERT(false);
         break;
      }
   }

   // pawn moves

   if (COLOUR_IS_WHITE(me)) {

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

         // non promotes

         if (SQUARE_RANK(from) != Rank7) {
            to = from + 16;
            if (board->square[to] == Empty) {
               ASSERT(!SQUARE_IS_PROMOTE(to));
               LIST_ADD(list,MOVE_MAKE(from,to));
               if (SQUARE_RANK(from) == Rank2) {
                  to = from + 32;
                  if (board->square[to] == Empty) {
                     ASSERT(!SQUARE_IS_PROMOTE(to));
                     LIST_ADD(list,MOVE_MAKE(from,to));
                  }
               }
            }
         }
      }

   } else { // black

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

         // non promotes

         if (SQUARE_RANK(from) != Rank2) {
            to = from - 16;
            if (board->square[to] == Empty) {
               ASSERT(!SQUARE_IS_PROMOTE(to));
               LIST_ADD(list,MOVE_MAKE(from,to));
               if (SQUARE_RANK(from) == Rank7) {
                  to = from - 32;
                  if (board->square[to] == Empty) {
                     ASSERT(!SQUARE_IS_PROMOTE(to));
                     LIST_ADD(list,MOVE_MAKE(from,to));
                  }
               }
            }
         }
      }
   }
}
예제 #9
0
static void add_captures(list_t * list, const board_t * board) {

   int me, opp;
   int opp_flag;
   const sq_t * ptr;
   int from, to;
   int piece, capture;

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

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

   opp_flag = COLOUR_FLAG(opp);

   // piece captures

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

      piece = board->square[from];

      switch (PIECE_TYPE(piece)) {

      case Knight64:

         to = from - 33;
         if (FLAG_IS(board->square[to],opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to));

         to = from - 31;
         if (FLAG_IS(board->square[to],opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to));

         to = from - 18;
         if (FLAG_IS(board->square[to],opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to));

         to = from - 14;
         if (FLAG_IS(board->square[to],opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to));

         to = from + 14;
         if (FLAG_IS(board->square[to],opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to));

         to = from + 18;
         if (FLAG_IS(board->square[to],opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to));

         to = from + 31;
         if (FLAG_IS(board->square[to],opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to));

         to = from + 33;
         if (FLAG_IS(board->square[to],opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to));

         break;

      case Bishop64:

         for (to = from-17; (capture=board->square[to]) == Empty; to -= 17)
            ;
         if (FLAG_IS(capture,opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to));

         for (to = from-15; (capture=board->square[to]) == Empty; to -= 15)
            ;
         if (FLAG_IS(capture,opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to));

         for (to = from+15; (capture=board->square[to]) == Empty; to += 15)
            ;
         if (FLAG_IS(capture,opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to));

         for (to = from+17; (capture=board->square[to]) == Empty; to += 17)
            ;
         if (FLAG_IS(capture,opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to));

         break;

      case Rook64:

         for (to = from-16; (capture=board->square[to]) == Empty; to -= 16)
            ;
         if (FLAG_IS(capture,opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to));

         for (to = from-1; (capture=board->square[to]) == Empty; to -= 1)
            ;
         if (FLAG_IS(capture,opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to));

         for (to = from+1; (capture=board->square[to]) == Empty; to += 1)
            ;
         if (FLAG_IS(capture,opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to));

         for (to = from+16; (capture=board->square[to]) == Empty; to += 16)
            ;
         if (FLAG_IS(capture,opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to));

         break;

      case Queen64:

         for (to = from-17; (capture=board->square[to]) == Empty; to -= 17)
            ;
         if (FLAG_IS(capture,opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to));

         for (to = from-16; (capture=board->square[to]) == Empty; to -= 16)
            ;
         if (FLAG_IS(capture,opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to));

         for (to = from-15; (capture=board->square[to]) == Empty; to -= 15)
            ;
         if (FLAG_IS(capture,opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to));

         for (to = from-1; (capture=board->square[to]) == Empty; to -= 1)
            ;
         if (FLAG_IS(capture,opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to));

         for (to = from+1; (capture=board->square[to]) == Empty; to += 1)
            ;
         if (FLAG_IS(capture,opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to));

         for (to = from+15; (capture=board->square[to]) == Empty; to += 15)
            ;
         if (FLAG_IS(capture,opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to));

         for (to = from+16; (capture=board->square[to]) == Empty; to += 16)
            ;
         if (FLAG_IS(capture,opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to));

         for (to = from+17; (capture=board->square[to]) == Empty; to += 17)
            ;
         if (FLAG_IS(capture,opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to));

         break;

      case King64:

         to = from - 17;
         if (FLAG_IS(board->square[to],opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to));

         to = from - 16;
         if (FLAG_IS(board->square[to],opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to));

         to = from - 15;
         if (FLAG_IS(board->square[to],opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to));

         to = from - 1;
         if (FLAG_IS(board->square[to],opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to));

         to = from + 1;
         if (FLAG_IS(board->square[to],opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to));

         to = from + 15;
         if (FLAG_IS(board->square[to],opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to));

         to = from + 16;
         if (FLAG_IS(board->square[to],opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to));

         to = from + 17;
         if (FLAG_IS(board->square[to],opp_flag)) LIST_ADD(list,MOVE_MAKE(from,to));

         break;

      default:

         ASSERT(false);
         break;
      }
   }

   // pawn captures

   if (COLOUR_IS_WHITE(me)) {

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

         to = from + 15;
         if (FLAG_IS(board->square[to],opp_flag)) add_pawn_move(list,from,to);

         to = from + 17;
         if (FLAG_IS(board->square[to],opp_flag)) add_pawn_move(list,from,to);

         // promote

         if (SQUARE_RANK(from) == Rank7) {
            to = from + 16;
            if (board->square[to] == Empty) {
               add_promote(list,MOVE_MAKE(from,to));
            }
         }
      }

   } else { // black

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

         to = from - 17;
         if (FLAG_IS(board->square[to],opp_flag)) add_pawn_move(list,from,to);

         to = from - 15;
         if (FLAG_IS(board->square[to],opp_flag)) add_pawn_move(list,from,to);

         // promote

         if (SQUARE_RANK(from) == Rank2) {
            to = from - 16;
            if (board->square[to] == Empty) {
               add_promote(list,MOVE_MAKE(from,to));
            }
         }
      }
   }
}