Пример #1
0
// PBETWEEN heuristic: Bonus for Pawn at (f, r) in rectangle defined by Kings at the corners
ev_score_t pbetween(position_t *p, rnk_t r, fil_t f, full_board_t* board) {
  bool is_between =
      between(f, fil_of(board->pieces[WHITE][0]), fil_of(board->pieces[BLACK][0])) &&
      between(r, rnk_of(board->pieces[WHITE][0]), rnk_of(board->pieces[BLACK][0]));
//  return is_between ? PBETWEEN : 0;
  // changed for better branch prediction
  return (-((int) is_between)) & PBETWEEN;
}
Пример #2
0
// Harmonic-ish distance: 1/(|dx|+1) + 1/(|dy|+1)
float h_dist_old(square_t a, square_t b) {
  //  printf("a = %d, FIL(a) = %d, RNK(a) = %d\n", a, FIL(a), RNK(a));
  //  printf("b = %d, FIL(b) = %d, RNK(b) = %d\n", b, FIL(b), RNK(b));
  int delta_fil = abs(fil_of(a) - fil_of(b));
  int delta_rnk = abs(rnk_of(a) - rnk_of(b));
  float x = (1.0 / (delta_fil + 1)) + (1.0 / (delta_rnk + 1));
  //  printf("max_dist = %d\n\n", x);
  return x;
}
Пример #3
0
// KFACE heuristic: bonus (or penalty) for King facing toward the other King
ev_score_t kface(position_t *p, rnk_t r, fil_t f, full_board_t* board) {
  piece_t x = get_piece(p, r, f, board);
  color_t c = color_of(x);
  square_t opp_sq = board->pieces[opp_color(c)][0];
  int delta_fil = fil_of(opp_sq) - f;
  int delta_rnk = rnk_of(opp_sq) - r;
  int bonus;

  switch (ori_of(x)) {
    case NN:
      bonus = delta_rnk;
      break;

    case EE:
      bonus = delta_fil;
      break;

    case SS:
      bonus = -delta_rnk;
      break;

    case WW:
      bonus = -delta_fil;
      break;

    default:
      bonus = 0;
      tbassert(false, "Illegal King orientation.\n");
  }

  return (bonus * KFACE) / (abs(delta_rnk) + abs(delta_fil));
}
Пример #4
0
// KAGGRESSIVE heuristic: bonus for King with more space to back
ev_score_t kaggressive(position_t *p, rnk_t r, fil_t f, full_board_t* board) {
  piece_t x = get_piece(p, r, f, board);
  color_t c = color_of(x);
  tbassert(ptype_of(x) == KING, "ptype_of(x) = %d\n", ptype_of(x));

  square_t opp_sq = board->pieces[opp_color(c)][0];
  fil_t of = fil_of(opp_sq);
  rnk_t _or = (rnk_t) rnk_of(opp_sq);

  int delta_fil = of - f;
  int delta_rnk = _or - r;

  int bonus = 0;

  if (delta_fil >= 0 && delta_rnk >= 0) {
    bonus = (f + 1) * (r + 1);
  } else if (delta_fil <= 0 && delta_rnk >= 0) {
    bonus = (BOARD_WIDTH - f) * (r + 1);
  } else if (delta_fil <= 0 && delta_rnk <= 0) {
    bonus = (BOARD_WIDTH - f) * (BOARD_WIDTH - r);
  } else if (delta_fil >= 0 && delta_rnk <= 0) {
    bonus = (f + 1) * (BOARD_WIDTH - r);
  }

  return (KAGGRESSIVE * bonus) / (BOARD_WIDTH * BOARD_WIDTH);
}
Пример #5
0
// KFACE heuristic: bonus (or penalty) for King facing toward the other King
ev_score_t kface(position_t *p, fil_t f, rnk_t r) {
  square_t sq = square_of(f, r);
  piece_t x = p->board[sq];
  color_t c = color_of(x);
  square_t opp_sq = p->kloc[opp_color(c)];
  int delta_fil = fil_of(opp_sq) - f;
  int delta_rnk = rnk_of(opp_sq) - r;
  int bonus;

  switch (ori_of(x)) {
    case NN:
      bonus = delta_rnk;
      break;

    case EE:
      bonus = delta_fil;
      break;

    case SS:
      bonus = -delta_rnk;
      break;

    case WW:
      bonus = -delta_fil;
      break;

    default:
      bonus = 0;
      tbassert(false, "Illegal King orientation.\n");
  }

  return (bonus * KFACE) / (abs(delta_rnk) + abs(delta_fil));
}
Пример #6
0
// KAGGRESSIVE heuristic: bonus for King with more space to back
ev_score_t kaggressive_old(position_t *p, fil_t f, rnk_t r) {
  square_t sq = square_of(f, r);
  piece_t x = p->board[sq];
  color_t c = color_of(x);
  tbassert(ptype_of(x) == KING, "ptype_of(x) = %d\n", ptype_of(x));

  square_t opp_sq = p->kloc[opp_color(c)];
  fil_t of = fil_of(opp_sq);
  rnk_t _or = (rnk_t) rnk_of(opp_sq);

  int delta_fil = of - f;
  int delta_rnk = _or - r;

  int bonus = 0;

  if (delta_fil >= 0 && delta_rnk >= 0) {
    bonus = (f + 1) * (r + 1);
  } else if (delta_fil <= 0 && delta_rnk >= 0) {
    bonus = (BOARD_WIDTH - f) * (r + 1);
  } else if (delta_fil <= 0 && delta_rnk <= 0) {
    bonus = (BOARD_WIDTH - f) * (BOARD_WIDTH - r);
  } else if (delta_fil >= 0 && delta_rnk <= 0) {
    bonus = (f + 1) * (BOARD_WIDTH - r);
  }

  return (KAGGRESSIVE * bonus) / (BOARD_WIDTH * BOARD_WIDTH);
}
Пример #7
0
// converts a square to string notation, returns number of characters printed
int square_to_str(square_t sq, char *buf, size_t bufsize) {
  fil_t f = fil_of(sq);
  rnk_t r = rnk_of(sq);
  if (f >= 0) {
    return snprintf(buf, bufsize, "%c%d", 'a'+ f, r);
  } else  {
    return snprintf(buf, bufsize, "%c%d", 'z' + f + 1, r);
  }
}
Пример #8
0
int mobility_list(position_t *p, color_t color, square_t* laser_list, int laser_list_len, full_board_t* board) {
  int mobility = 0;
  square_t king_sq = board->pieces[color][0];
  mobility++;

  for (int i = 0; i < laser_list_len-1; i++){
    square_t start = laser_list[i];
    square_t end = laser_list[i+1];
    //check if the square is between laser_list[i] and laser_list[i+1]. if so add to mobility
    if(between(rnk_of(king_sq), rnk_of(start), rnk_of(end)) && between(fil_of(king_sq), fil_of(start), fil_of(end))) {
      mobility--;
      break;
    }
  }
  for (int d = 0; d < 8; ++d) {
    square_t sq = king_sq + dir_of(d);
    if (in_bounds(sq)) {
      mobility++;
      //decrement if it is in laser path
      for (int i = 0; i < laser_list_len-1; i++){
      //check if the square is between laser_list[i] and laser_list[i+1]. if so add to mobility
        square_t start = laser_list[i];
        square_t end = laser_list[i+1];

        if(between(rnk_of(sq), rnk_of(start), rnk_of(end)) && between(fil_of(sq), fil_of(start), fil_of(end))) {
          mobility--;
          break;
        }
      }
    }
  }
  return mobility;
}
Пример #9
0
//TODO: make euphoric by just subtracting 2 values in a sum table instead
static inline float fast_h_dist(square_t start, square_t end, rnk_t k_rnk, fil_t k_fil) {
  tbassert(start >= 4, "olooloo\n");

  rnk_t start_r = rnk_of(start);
  rnk_t end_r = rnk_of(end);
  fil_t start_f = fil_of(start);
  fil_t end_f = fil_of(end);
  if (start_r == end_r) {
    float length = abs(start_f - end_f);

    int firstDist = k_fil - start_f;
    int secondDist = k_fil - end_f;
    secondDist += ((firstDist > secondDist) - (secondDist > firstDist));

    float partial_sum;
    if(firstDist*secondDist > 0){ //same sign, disjoint segment
      partial_sum = fabsf(harmonicSum[abs(firstDist)] - harmonicSum[abs(secondDist)]) + h_table[MIN(abs(firstDist), abs(secondDist))];
    } else {
      partial_sum = harmonicSum[abs(firstDist)] + harmonicSum[abs(secondDist)] - 1;
    }

    return partial_sum + length * h_table[abs(start_r - k_rnk)];
  } else {
    float length = abs(start_r - end_r);

    int firstDist = k_rnk - start_r;
    int secondDist = k_rnk - end_r;
    secondDist += ((firstDist > secondDist) - (secondDist > firstDist));

    float partial_sum;
    if(firstDist*secondDist > 0){ //same sign, disjoint segment
      partial_sum = fabsf(harmonicSum[abs(firstDist)] - harmonicSum[abs(secondDist)]) + h_table[MIN(abs(firstDist), abs(secondDist))];
    } else {
      partial_sum = harmonicSum[abs(firstDist)] + harmonicSum[abs(secondDist)] - 1;
    }

    return partial_sum + length * h_table[abs(start_f - k_fil)];
  }
}
Пример #10
0
// H_SQUARES_ATTACKABLE heuristic: for shooting the enemy king
float h_squares_attackable(position_t *p, color_t c,
      square_t* laser_list, int laser_list_length, full_board_t* board) {
  square_t o_king_sq = board->pieces[opp_color(c)][0];
  rnk_t k_rnk = rnk_of(o_king_sq);
  fil_t k_fil = fil_of(o_king_sq);
  float h_attackable = 0;

  for (int i = 0; i < laser_list_length - 1; i++) {
    h_attackable += fast_h_dist(laser_list[i], laser_list[i+1], k_rnk, k_fil);
  }
  if (in_bounds(laser_list[laser_list_length - 1])) {
    h_attackable += fast_h_dist(laser_list[laser_list_length - 1], laser_list[laser_list_length - 1] + 1, k_rnk, k_fil);
  }

  return h_attackable;
}
Пример #11
0
// Static evaluation.  Returns score
score_t eval(position_t *p, bool verbose, full_board_t* board) {
  // seed rand_r with a value of 1, as per
  // http://linux.die.net/man/3/rand_r
  static __thread unsigned int seed = 1;
  // verbose = true: print out components of score
  ev_score_t score[2] = { 0, 0 };
  //  int corner[2][2] = { {INF, INF}, {INF, INF} };
  ev_score_t bonus;

  color_t c = WHITE;
  while (true) {
    for (pnum_t pnum = 0; pnum <= board->pawn_count[c]; pnum++) {
      square_t sq = board->pieces[c][pnum];
      rnk_t r = rnk_of(sq);
      fil_t f = fil_of(sq);
      piece_t x = board->board[sq];

      switch (ptype_of(x)) {
        case EMPTY:
          tbassert(false, "Jose says: no way!\n");   // No way, Jose!
        case PAWN:
          // PBETWEEN heuristic
          bonus = pbetween(p, r, f, board);
          score[c] += bonus;

          // PCENTRAL heuristic
          bonus = pcentral(r, f);
          score[c] += bonus;
          break;

        case KING:
          // KFACE heuristic
          bonus = kface(p, r, f, board);
          score[c] += bonus;

          // KAGGRESSIVE heuristic
          bonus = kaggressive(p, r, f, board);
          score[c] += bonus;
          break;
        case INVALID:
          tbassert(false, "Jose says: no way!\n");   // No way, Jose!
        default:
          tbassert(false, "Jose says: no way!\n");   // No way, Jose!
      }
    }
    if (c == BLACK)
      break;
    c = BLACK;
  }

  score[WHITE] += board->pawn_count[WHITE] * PAWN_EV_VALUE;
  score[BLACK] += board->pawn_count[BLACK] * PAWN_EV_VALUE;

  square_t white_laser_list[MAX_NUM_PIECES];
  square_t black_laser_list[MAX_NUM_PIECES];

  int whitePathCount = get_laser_path_list(p, white_laser_list, WHITE, board);
  int blackPathCount = get_laser_path_list(p, black_laser_list, BLACK, board);

  ev_score_t w_hattackable = HATTACK * h_squares_attackable(p, WHITE, white_laser_list, whitePathCount, board);
  score[WHITE] += w_hattackable;
  ev_score_t b_hattackable = HATTACK * h_squares_attackable(p, BLACK, black_laser_list, blackPathCount, board);
  score[BLACK] += b_hattackable;

  int w_mobility_list = MOBILITY * mobility_list(p, WHITE, black_laser_list, blackPathCount, board);
  score[WHITE] += w_mobility_list;

  int b_mobility_list = MOBILITY * mobility_list(p, BLACK, white_laser_list, whitePathCount, board);
  score[BLACK] += b_mobility_list;

  // PAWNPIN Heuristic --- is a pawn immobilized by the enemy laser.
  int w_pawnpin = PAWNPIN * pawnpin(p, WHITE, black_laser_list, blackPathCount, board); //use other color's laser map
  score[WHITE] += w_pawnpin;
  int b_pawnpin = PAWNPIN * pawnpin(p, BLACK, white_laser_list, whitePathCount, board); //use other color's laser map
  score[BLACK] += b_pawnpin;

  // score from WHITE point of view
  ev_score_t tot = score[WHITE] - score[BLACK];

  if (RANDOMIZE) {
    ev_score_t  z = rand_r(&seed) % (RANDOMIZE*2+1);
    tot = tot + z - RANDOMIZE;
  }

  if (color_to_move_of(p) == BLACK) {
    tot = -tot;
  }



  return tot / EV_SCORE_RATIO;
}
Пример #12
0
// PBETWEEN heuristic: Bonus for Pawn at (f, r) in rectangle defined by Kings at the corners
ev_score_t pbetween(position_t *p, fil_t f, rnk_t r) {
  bool is_between =
      between(f, fil_of(p->kloc[WHITE]), fil_of(p->kloc[BLACK])) &&
      between(r, rnk_of(p->kloc[WHITE]), rnk_of(p->kloc[BLACK]));
  return is_between ? PBETWEEN : 0;
}
Пример #13
0
// Static evaluation.  Returns score
score_t eval(position_t *p, bool verbose) {
  // seed rand_r with a value of 1, as per
  // http://linux.die.net/man/3/rand_r
  static __thread unsigned int seed = 1;
  // verbose = true: print out components of score
  ev_score_t score[2] = { 0, 0 };
  //  int corner[2][2] = { {INF, INF}, {INF, INF} };
  ev_score_t bonus;

  //char buf[MAX_CHARS_IN_MOVE];
  color_t c;
  for (fil_t f = 0; f < BOARD_WIDTH; f++) {
    for (rnk_t r = 0; r < BOARD_WIDTH; r++) {
      square_t sq = square_of(f, r);
      piece_t x = p->board[sq];

      //if (verbose) {
      //  square_to_str(sq, buf, MAX_CHARS_IN_MOVE);
      //}

      switch (ptype_of(x)) {
        case EMPTY:
          break;
        case PAWN:
          c = color_of(x);

          // MATERIAL heuristic: Bonus for each Pawn
          bonus = PAWN_EV_VALUE;
          // if (verbose) {
          //  printf("MATERIAL bonus %d for %s Pawn on %s\n", bonus, color_to_str(c), buf);
          // }
          score[c] += bonus;

          // PBETWEEN heuristic
          bonus = pbetween(p, f, r);
          // if (verbose) {
          //   printf("PBETWEEN bonus %d for %s Pawn on %s\n", bonus, color_to_str(c), buf);
          // }
          score[c] += bonus;

          // PCENTRAL heuristic
          bonus = pcentral(f, r);
          // if (verbose) {
          //   printf("PCENTRAL bonus %d for %s Pawn on %s\n", bonus, color_to_str(c), buf);
         //  }
          score[c] += bonus;
          break;

        case KING:
          c = color_of(x);

          // KFACE heuristic
          bonus = kface(p, f, r);
          // if (verbose) {
          //   printf("KFACE bonus %d for %s King on %s\n", bonus,
          //          color_to_str(c), buf);
          // }
          score[c] += bonus;

          // KAGGRESSIVE heuristic
          color_t othercolor = opp_color(c);
          square_t otherking = p->kloc[othercolor];
          fil_t otherf = fil_of(otherking);
          rnk_t otherr = rnk_of(otherking);
          bonus = kaggressive(f, r, otherf, otherr);
          assert(bonus == kaggressive_old(p, f, r));

          // if (verbose) {
          //   printf("KAGGRESSIVE bonus %d for %s King on %s\n", bonus, color_to_str(c), buf);
         //  }
          score[c] += bonus;
          break;
        case INVALID:
          break;
        default:
          tbassert(false, "Jose says: no way!\n");   // No way, Jose!
      }
      laser_map_black[sq] = 0;
      laser_map_white[sq] = 0;
    }
  }
   
  int black_pawns_unpinned = mark_laser_path(p, laser_map_white, WHITE, 1);  // 1 = path of laser with no moves
  
  ev_score_t w_hattackable = HATTACK * (int) h_attackable;
  score[WHITE] += w_hattackable;
  // if (verbose) {
  //   printf("HATTACK bonus %d for White\n", w_hattackable);
  // }

  // PAWNPIN Heuristic --- is a pawn immobilized by the enemy laser.
  int b_pawnpin = PAWNPIN * black_pawns_unpinned;
  score[BLACK] += b_pawnpin;

  int b_mobility = MOBILITY * mobility(p, BLACK);
  score[BLACK] += b_mobility;
  // if (verbose) {
  //   printf("MOBILITY bonus %d for Black\n", b_mobility);
  // }

  int white_pawns_unpinned = mark_laser_path(p, laser_map_black, BLACK, 1);  // 1 = path of laser with no moves
  
  ev_score_t b_hattackable = HATTACK * (int) h_attackable;
  score[BLACK] += b_hattackable;
  // if (verbose) {
  //   printf("HATTACK bonus %d for Black\n", b_hattackable);
  // }

  int w_mobility = MOBILITY * mobility(p, WHITE);
  score[WHITE] += w_mobility;
  // if (verbose) {
  //   printf("MOBILITY bonus %d for White\n", w_mobility);
  // }
  int w_pawnpin = PAWNPIN * white_pawns_unpinned;
  score[WHITE] += w_pawnpin;


  // score from WHITE point of view
  ev_score_t tot = score[WHITE] - score[BLACK];

  if (RANDOMIZE) {
    ev_score_t  z = rand_r(&seed) % (RANDOMIZE*2+1);
    tot = tot + z - RANDOMIZE;
  }

  if (color_to_move_of(p) == BLACK) {
    tot = -tot;
  }

  return tot / EV_SCORE_RATIO;
}