void test_board_san() {
    puts("test_board_san");
    board_t pos;
    char san[LEN_SAN];

    // Double pawn move.
    board_reset(&pos);
    board_san(&pos, move_make(SQ_H2, SQ_H4, kNone), san);
    assert(strcmp(san, "h4") == 0);

    // Promotion.
    assert(board_set_fen(&pos, "4k3/8/8/8/8/8/6p1/4K3 b - - 0 1"));
    board_san(&pos, move_make(SQ_G2, SQ_G1, kRook), san);
    assert(strcmp(san, "g1=R+") == 0);

    // Not ambiguous because of pin.
    assert(board_set_fen(&pos, "4k3/8/8/b7/8/2N3N1/8/4K3 w - - 0 1"));
    board_san(&pos, move_make(SQ_G3, SQ_E4, 0), san);
    puts(san);
    assert(strcmp(san, "Ne4") == 0);

    // Ambiguous.
    board_remove_piece_at(&pos, SQ_A5);
    board_san(&pos, move_make(SQ_G3, SQ_E4, 0), san);
    assert(strcmp(san, "Nge4") == 0);
}
void test_pawn_divide(int depth)
{
  int i,move_count;
  move_t ms[MOVE_STACK];
  uint64 nodes = 0;
  uint64 total_nodes = 0;
  int legal_moves = 0;
  
  if(!depth) return;
  pawnhits = 0;
  pawncollisions = 0;
  pht_init();
  depth -= 1;
  timer_start();
  move_count = move_gen(&ms[0]);
  for(i = 0; i < move_count; i++)
  {
    if(!move_make(ms[i])) continue;
    nodes = perft(depth);
    print_move(ms[i].p);
    legal_moves++;
    printf("%I64u",nodes);
    printf("\n");
    move_undo();
    total_nodes += nodes;
  }
  printf("\nNodes: %I64u",total_nodes);
  printf("\nMoves: %d",legal_moves);
  printf("\nPawnHits: %d",pawnhits);
  printf("\nPawnCollisions: %d",pawncollisions);
  printf("\n\n");
  timer_stop();
  pht_free();
}
Exemple #3
0
MOVE ConvertTextInputToMove (STRING input)
{
	int theInput = atoi(input);
	int from = theInput/10;
	int to = theInput%10;
	return ((MOVE) move_make(from, to));
}
void test_board_parse_san() {
    puts("test_board_parse_san");
    board_t pos;
    move_t move;

    board_reset(&pos);
    assert(board_parse_san(&pos, "e4", &move));
    assert(move == move_make(SQ_E2, SQ_E4, 0));

    assert(board_set_fen(&pos, "r1bqkb1r/pppp1ppp/2n2n2/4p3/2B1P3/2N2N2/PPPP1PPP/R1BQK2R b KQkq - 5 4"));
    assert(board_parse_san(&pos, "Nxe4", &move));
    assert(move == move_make(SQ_F6, SQ_E4, 0));

    assert(board_set_fen(&pos, "r3r2R/pppb1kP1/n2p4/3Pp3/2P1P3/2N1K3/PP3P2/6R1 w - - 3 23"));
    assert(board_parse_san(&pos, "g8=Q+", &move));
    assert(move == move_make(SQ_G7, SQ_G8, kQueen));
}
void test_board_evasive_capture() {
    puts("test_board_evasive_capture");
    board_t pos;
    assert(board_set_fen(&pos, "r3k2r/Pppp1ppp/1b3nbN/nP6/BBP1P3/q4N2/Pp1P1RPP/R2Q2K1 b af - 1 1"));
    board_move(&pos, move_make(SQ_B6, SQ_F2, 0));

    move_t moves[255];
    move_t *end = board_legal_moves(&pos, moves, BB_ALL, BB_ALL);
    assert(end - moves == 3);
}
void test_divide(int depth)
{
  int i,move_count;
  move_t ms[MOVE_STACK];
  uint64 nodes;
  uint64 total_nodes;
  int legal_moves;
  #ifdef EVASIONS
  char strbuff[256];
  move_t ms_test[MOVE_STACK];
  #endif
  
  if(!depth) return;
  nodes = 0;
  total_nodes = 0;
  legal_moves = 0;
  
  pht_init();
  depth -= 1;
  timer_start();
    
  #ifdef EVASIONS
  if(is_in_check(board->side))
  { move_count = move_gen_evasions(&ms[0]);
    if(move_count != move_gen_legal(&ms_test[0]))
    { board_to_fen(&strbuff[0]);
      printf("error: \n %s \n",strbuff);
    }
  }
  else
  { move_count = move_gen(&ms[0]);
  }
  #else
  move_count = move_gen(&ms[0]);
  #endif
    
  for(i = 0; i < move_count; i++)
  { if(!move_make(ms[i])) continue;
    nodes = perft(depth);
    print_move(ms[i].p);
    legal_moves++;
    printf("%I64u",nodes);
    printf("\n");
    move_undo();
    total_nodes += nodes;
  }
  printf("\nNodes: %I64u",total_nodes);
  printf("\nMoves: %d",legal_moves);
  printf("\n\n");
  timer_stop();
  pht_free();
}
void test_board_pin() {
    puts("test_board_pin");

    board_t pos;
    assert(board_set_fen(&pos, "4k3/8/8/b7/8/2N3N1/8/4K3 w - - 0 1"));

    move_t moves[255];
    move_t *end = board_legal_moves(&pos, moves, BB_ALL, BB_ALL);
    bool found_Nge4 = false, found_Nce4 = false;
    for (move_t *current = moves; current < end; current++) {
        char san[LEN_SAN], uci[LEN_UCI];
        move_uci(*current, uci);
        board_san(&pos, *current, san);
        printf("- %s %s\n", uci, san);

        if (*current == move_make(SQ_C3, SQ_E4, kNone)) found_Nce4 = true;
        if (*current == move_make(SQ_G3, SQ_E4, kNone)) found_Nge4 = true;
    }

    assert(found_Nge4);
    assert(!found_Nce4);
}
void test_board_pseudo_legal_ep() {
    puts("test_board_pseudo_legal_ep");

    struct board pos;
    assert(board_set_fen(&pos, "4k3/8/8/8/4Pp2/8/8/4K3 b - e3 0 1"));
    move_t ep = move_make(SQ_F4, SQ_E3, 0);

    move_t moves[255];
    move_t *end = board_pseudo_legal_moves(&pos, moves, BB_ALL, BB_ALL);

    bool found = false;
    for (move_t *current = moves; current < end; current++) {
        if (*current == ep) found = true;

        char uci[6];
        move_uci(*current, uci);
        puts(uci);
    }

    assert(found);
}
void test_legal_promotion() {
    puts("test_legal_promotion");

    board_t pos;
    assert(board_set_fen(&pos, "4k3/1P6/8/8/8/8/8/4K3 w - - 0 1"));
    move_t moves[255];
    move_t *end = board_legal_moves(&pos, moves, BB_ALL, BB_ALL);

    move_t needle = move_make(SQ_B7, SQ_B8, kQueen);
    bool found = false;
    bool found_uci = false;
    for (move_t *current = moves; current < end; current++) {
        if (*current == needle) found = true;

        char uci[6];
        move_uci(*current, uci);
        if (strcmp(uci, "b7b8q") == 0) found_uci = true;

        puts(uci);
    }

    assert(found);
    assert(found_uci);
}
Exemple #10
0
static int move_from_lan(const char string[], const board_t * board) {

   int len;
   int move;
   int promote;
   char s[256];
   int from, to;
   int colour;
   int inc;
   int piece_char;
   int n;
   const uint8 * ptr;
   int piece;
   int side;

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

   // init

   len = strlen(string);
   if (len != 7) return MoveNone;

   move = MoveNone;
   colour = board->turn;

   // promote

   promote = 0;

   switch (string[6]) {
   case '?': // not a promotion
      break;
   case 'N':
      promote = MovePromoteKnight;
      break;
   case 'B':
      promote = MovePromoteBishop;
      break;
   case 'R':
      promote = MovePromoteRook;
      break;
   case 'Q':
      promote = MovePromoteQueen;
      break;
   default:
      return MoveNone;
      break;
   }

   // to square

   s[0] = string[4];
   s[1] = string[5];
   s[2] = '\0';

   to = square_from_string(s);
   if (to == SquareNone) return MoveNone;

   // known from square?

   if (string[1] != '?' && string[2] != '?') {

      // from square

      s[0] = string[1];
      s[1] = string[2];
      s[2] = '\0';

      from = square_from_string(s);
      if (from == SquareNone) return MoveNone;

      // convert "king slide" castling to KxR

      if (piece_is_king(board->square[from])
       && square_rank(to) == square_rank(from)
       && abs(to-from) > 1) {
         side = (to > from) ? SideH : SideA;
         to = board->castle[colour][side];
         if (to == SquareNone) return MoveNone;
      }

      // move

      move = move_make(from,to) | promote;

      return move;
   }

   // pawn non-capture?

   if (string[0] == '?' && string[1] == '?') {

      if (board->square[to] != Empty) return MoveNone; // useful?

      inc = (colour_is_white(colour)) ? +16 : -16;

      from = to - inc;
      if (board->square[from] == Empty && square_side_rank(to,colour) == Rank4) {
         from -= inc;
      }

      if (board->square[from] != piece_make_pawn(colour)) { // useful?
         return MoveNone;
      }

      // move

      move = move_make(from,to) | promote;

      return move;
   }

   // pawn capture?

   piece_char = string[0];

   if (piece_char == '?' && string[1] != '?') {
      piece_char = 'P';
   }

   // attack loop

   n = 0;

   for (ptr = board->list[colour]; (from=*ptr) != SquareNone; ptr++) {

      piece = board->square[from];

      if (toupper(piece_to_char(piece)) == piece_char) {
         if (piece_attack(board,piece,from,to)) {
            if (true
             && (string[1] == '?' || file_to_char(square_file(from)) == string[1])
             && (string[2] == '?' || rank_to_char(square_rank(from)) == string[2])) {
               if (!is_pinned(board,from,to,colour)) {
                  move = move_make(from,to) | promote;
                  n++;
               }
            }
         }
      }
   }

   if (n != 1) move = MoveNone;

   return move;
}
Exemple #11
0
int qsearch(s_search_info *info, s_stack *stack, s_board *board, int alpha, int beta)
{
    assert(info != NULL);
    assert(stack != NULL);
    assert(board != NULL);
    assert(alpha < beta);

    int stand_pat = evaluate(board);

    if(stack->ply > info->seldepth)
    {
        info->seldepth = stack->ply-1;
    }

    if(stand_pat >= beta)
    {
        return beta;
    }

#ifdef DELTA_PRUNING
    const int safety = 900; // The value of a queen

    if(stand_pat < alpha - safety && !is_endgame(board))
    {
        return alpha;
    }
#endif

    if(stand_pat > alpha)
    {
        alpha = stand_pat;
    }

    if(stack->ply >= MAX_DEPTH)
    {
        return stand_pat;
    }

    // Set old permissions
    s_irreversible permissions;
    store_irreversible(&permissions, board);

    s_move moves[MAX_MOVES];
    int num_moves = find_moves_captures(board, moves, board->turn);
#ifdef SORT_MOVES
    moves_sort_see(board, moves, num_moves);
#endif

    for(int m = 0; m < num_moves; ++m)
    {
        int val = see_capture(board, moves[m]);
        if(val < -50)
        {
            break;
        }

        move_make(board, &moves[m]);

        if(square_attacked(board, board->pieces[KINGS]&board->colour[!board->turn], board->turn))
        {
            // Restore old permissions
            restore_irreversible(&permissions, board);

            move_undo(board, &moves[m]);
            continue;
        }

        info->nodes++;

        int score = -qsearch(info, stack+1, board, -beta, -alpha);

        // Restore old permissions
        restore_irreversible(&permissions, board);

        move_undo(board, &moves[m]);

        if(score >= beta)
        {
#ifndef NDEBUG
            info->num_cutoffs[m]++;
#endif
            return beta;
        }

        if(score > alpha)
        {
            alpha = score;
        }
    }

    return alpha;
}
uint64 perft(int depth)
{ 
  int i,move_count;
  move_t ms[MOVE_STACK];
  uint64 nodes;
  uint64 val;
  #ifdef EVASIONS
  char strbuff[256];
  move_t ms_test[MOVE_STACK];
  #endif
  #ifdef BITS
  bitboard_t bb;
  #endif
  
  if(depth == 0) return 1;
  if((val = probe_hash(depth)) != 0) 
    return val;

  nodes = 0;
  val = 0;
    
  #ifdef BITS
  bb = 0;
  for(i = PLS(WP); i <= H8; i = PLN(i))
    bitset(&bb, rsz[i]);
  if(bb != board->bb_pawns[W])
    printf("pawn_error\n");
  bb = 0;
  for(i = PLS(BP); i <= H8; i = PLN(i))
    bitset(&bb, rsz[i]);
  if(bb != board->bb_pawns[B])
    printf("pawn_error\n");
  #endif
  
  #ifdef EVASIONS
  if(is_in_check(board->side))
  { move_count = move_gen_evasions(&ms[0]);
    if(move_count != move_gen_legal(&ms_test[0]))
    { board_to_fen(&strbuff[0]);
      printf("error: \n %s \n",strbuff);
    }
  }
  else
  { move_count = move_gen(&ms[0]);
  }
  #else
  move_count = move_gen(&ms[0]);
  #endif
    
  for(i = 0; i < move_count; i++)
  { if(!move_make(ms[i])) continue;
    if(depth == 1)
      nodes++;
    else
      nodes += perft(depth - 1);

    move_undo();
  }
  record_hash(depth,nodes);
  return (nodes);
}