Example #1
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;
}
Example #2
0
int next_move(s_board *board, s_move_generator *generator, s_move *move)
{
  assert(board);
  assert(generator);
  assert(move);
  
  while(generator->move_num >= generator->num_moves)
  {
    generator->move_num = 0;
    
    /*
    if(generator->stage == NEXT_HASH)
    {
      generator->stage++;
      if(!move_is_legal(board, &generator->hash_move)) {continue;}
      generator->moves[0] = generator->hash_move;
      generator->num_moves = 1;
    }
    else if(generator->stage == NEXT_KILLER)
    {
      generator->stage++;
      if(!move_is_legal(board, &generator->killer_move)) {continue;}
      generator->moves[0] = generator->killer_move;
      generator->num_moves = 1;
    }
    else if(generator->stage == NEXT_CAPTURES)
    {
      generator->stage++;
      generator->num_moves = find_moves_captures(board, &generator->moves[0], board->turn);
      #ifdef SORT_MOVES
        moves_sort(generator->moves, generator->num_moves);
      #endif
    }
    else if(generator->stage == NEXT_QUIETS)
    {
      generator->stage++;
      generator->num_moves = find_moves_quiet(board, &generator->moves[generator->num_moves], board->turn);
    }
    else
    {
      return 0;
    }
    */
    
    if(generator->stage == 0)
    {
      int i;
      
      generator->stage++;
      
      // Captures
      generator->num_moves = find_moves_captures(board, &generator->moves[0], board->turn);
      
      for(i = 0; i < generator->num_moves; ++i)
      {
        // MVV-LVA (Most Valuable Victim - Least Valuable Aggressor)
        //generator->scores[i] = 400 + 10*generator->moves[i].taken - generator->moves[i].piece_type;
        
        // SEE (Static Exchange Evaluation)
        generator->scores[i] = 50000 + see_capture(board, generator->moves[i]);
        
        assert(generator->scores[i] >= 0);
      }
      
      // Quiets
      generator->num_moves += find_moves_quiet(board, &generator->moves[generator->num_moves], board->turn);
      
      /*
      for(; i < generator->num_moves; ++i)
      {
        //if(is_same_move(generator->moves[i], generator->killer_move))
        //{
        //  generator->scores[i] = 19000;
        //  continue;
        //}
        
        generator->scores[i] = 0;
        
        if(generator->moves[i].piece_type == KINGS) {continue;}
        
        int to   = pst_value(generator->moves[i].piece_type, generator->moves[i].to);
        int from = pst_value(generator->moves[i].piece_type, generator->moves[i].from);
        
        generator->scores[i] += 100 + (to - from);
        
        assert(generator->scores[i] >= 0);
      }
      */
      
      /*
      int pos = 3;
      
      if(num_captures < pos)
      {
        pos = num_captures;
      }
      */
      
      /*
      int pos = num_captures;
      
      for(i = num_captures; i < generator->num_moves; ++i)
      {
        if(is_same_move(generator->moves[i], generator->killer_move))
        {
          s_move store = generator->moves[i];
          int n;
          for(n = i; n > pos; --n)
          {
            generator->moves[n] = generator->moves[n-1];
          }
          generator->moves[pos] = store;
          break;
        }
      }
      
      for(i = 0; i < generator->num_moves; ++i)
      {
        if(is_same_move(generator->moves[i], generator->hash_move))
        {
          s_move store = generator->moves[i];
          int n;
          for(n = i; n > 0; --n)
          {
            generator->moves[n] = generator->moves[n-1];
          }
          generator->moves[0] = store;
          break;
        }
      }
      */
      
      
      // Hash & killer moves
      for(i = 0; i < generator->num_moves; ++i)
      {
        #ifdef HASHTABLE
        if(is_same_move(generator->moves[i], generator->hash_move))
        {
          generator->scores[i] = 100000;
          //break;
          
          //int store2 = generator->scores[0];
          //generator->scores[0] = generator->scores[i];
          //generator->scores[i] = store2;
          
          //s_move store = generator->moves[0];
          //generator->moves[0] = generator->moves[i];
          //generator->moves[i] = store;
        }
        #endif
        
        #ifdef KILLER_MOVES
        if(is_same_move(generator->moves[i], generator->killer_move))
        {
          generator->scores[i] = 50000;
          
          //int store2 = generator->scores[1];
          //generator->scores[1] = generator->scores[i];
          //generator->scores[i] = store2;
          
          //s_move store = generator->moves[1];
          //generator->moves[1] = generator->moves[i];
          //generator->moves[i] = store;
        }
        #endif
      }
      
    }
    else
    {
      return 0;
    }
  }
  
  /*
  if(generator->stage == NEXT_CAPTURES)
  {
    if(is_same_move(generator->moves[generator->move_num], generator->hash_move))
    {
      generator->move_num++;
      return next_move(board, generator, move);
    }
  }
  else if(generator->stage >= NEXT_QUIETS)
  {
    if(is_same_move(generator->moves[generator->move_num], generator->hash_move) ||
       is_same_move(generator->moves[generator->move_num], generator->killer_move))
    {
      generator->move_num++;
      return next_move(board, generator, move);
    }
  }
  */
  
  /*
  if(show)
  {
    printf("Swap'd: %i\n", show-1);
    int n;
    for(n = 0; n < generator->num_moves; ++n)
    {
      printf("%i) ", generator->scores[n]);
      print_move(generator->moves[n]);
    }
    getchar();
  }
  */
  
  /*
  */
  // New method
  int best_move = -1;
  int best_score = -99999;
  
  int i;
  for(i = 0; i < generator->num_moves; ++i)
  {
    if(generator->scores[i] > best_score)
    {
      best_move = i;
      best_score = generator->scores[i];
    }
  }
  
  *move = generator->moves[best_move];
  generator->scores[best_move] = -1;
  generator->move_num++;
  
  /*
  *move = generator->moves[generator->move_num];
  generator->move_num++;
  */
  return 1;
}