// Marks the path of the laser until it hits a piece or goes off the board. 
// Returns the number of unpinned pawns.
//
// p : current board state
// laser_map : end result will be stored here. Every square on the
//             path of the laser is marked with mark_mask
// c : color of king shooting laser
// mark_mask: what each square is marked with
int mark_laser_path(position_t *p, char *laser_map, color_t c,
                     char mark_mask) {
  int pinned_pawns = 0;
  uint8_t total_pawns;
  color_t color = opp_color(c);
  square_t o_king_sq = p->kloc[color];

  if (c == WHITE) { // opposing king pins our pawns 
    total_pawns = p->pawn_count[BLACK];
  } else {
    total_pawns = p->pawn_count[WHITE];
  }

  // Fire laser, recording in laser_map
  square_t sq = p->kloc[c];
  int bdir = ori_of(p->board[sq]);
  int beam = beam_of(bdir);

  tbassert(ptype_of(p->board[sq]) == KING,
           "ptype: %d\n", ptype_of(p->board[sq]));
  laser_map[sq] |= mark_mask;

  // we update h_attackable here
  h_attackable = h_dist(sq, o_king_sq);

  while (true) {
    sq += beam;
    laser_map[sq] |= mark_mask;
    tbassert(sq < ARR_SIZE && sq >= 0, "sq: %d\n", sq);

    switch (ptype_of(p->board[sq])) {
      case EMPTY:  // empty square
        h_attackable += h_dist(sq, o_king_sq);
        break;
      case PAWN:  // Pawn
        h_attackable += h_dist(sq, o_king_sq);
        if (color_of(p->board[sq]) == color) {
          pinned_pawns += 1;
        }
        bdir = reflect_of(bdir, ori_of(p->board[sq]));
        if (bdir < 0) {  // Hit back of Pawn
          return total_pawns - pinned_pawns;
        }
        beam = beam_of(bdir);
        break;
      case KING:  // King
        h_attackable += h_dist(sq, o_king_sq);
          return total_pawns - pinned_pawns;
        break;
      case INVALID:  // Ran off edge of board
        return total_pawns - pinned_pawns;
        break;
      default:  // Shouldna happen, man!
        tbassert(false, "Not cool, man.  Not cool.\n");
        break;
    }
  }
}
static void update_best_move_history(position_t *p, int index_of_best,
                                     sortable_move_t* lst, int count) {
  tbassert(ENABLE_TABLES, "Tables weren't enabled.\n");

  int color_to_move = color_to_move_of(p);

  for (int i = 0; i < count; i++) {
    move_t   mv  = get_move(lst[i]);
    ptype_t  pce = ptype_mv_of(mv);
    rot_t    ro  = rot_of(mv);  // rotation
    square_t fs  = from_square(mv);
    int      ot  = ORI_MASK & (ori_of(p->board[fs]) + ro);
    square_t ts  = to_square(mv);

    int  s = best_move_history[BMH(color_to_move, pce, ts, ot)];

    if (index_of_best == i) {
      s = s + 11200;  // number will never exceed 1017
    }
    s = s * 0.90;  // decay score over time

    tbassert(s < 102000, "s = %d\n", s);  // or else sorting will fail

    best_move_history[BMH(color_to_move, pce, ts, ot)] = s;
  }
}
Beispiel #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));
}
// Obtain a sorted move list.
static int get_sortable_move_list(searchNode *node, sortable_move_t * move_list,
                         int hash_table_move) {
  // number of moves in list
  int num_of_moves = generate_all_opt(&(node->position), move_list, false);

  color_t fake_color_to_move = color_to_move_of(&(node->position));

  move_t killer_a = killer[KMT(node->ply, 0)];
  move_t killer_b = killer[KMT(node->ply, 1)];

  // sort special moves to the front
  for (int mv_index = 0; mv_index < num_of_moves; mv_index++) {
    move_t mv = get_move(move_list[mv_index]);
    if (mv == hash_table_move) {
      set_sort_key(&move_list[mv_index], SORT_MASK);
    } else if (mv == killer_a) {
      set_sort_key(&move_list[mv_index], SORT_MASK - 1);
    } else if (mv == killer_b) {
      set_sort_key(&move_list[mv_index], SORT_MASK - 2);
    } else {
      ptype_t  pce = ptype_mv_of(mv);
      rot_t    ro  = rot_of(mv);   // rotation
      square_t fs  = from_square(mv);
      int      ot  = ORI_MASK & (ori_of(node->position.board[fs]) + ro);
      square_t ts  = to_square(mv);
      set_sort_key(&move_list[mv_index],
                   best_move_history[BMH(fake_color_to_move, pce, ts, ot)]);
    }
  }
  return num_of_moves;
}
// 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));
}
Beispiel #6
0
// Translate a position struct into a fen string
// NOTE: When you use the test framework in search.c, you should modify this
// function to match your optimized board representation in move_gen.c
//
// Input:   (populated) position struct
//          empty string where FEN characters will be written
// Output:   null
int pos_to_fen(position_t *p, char *fen) {
  int pos = 0;
  int i;

  for (rnk_t r = BOARD_WIDTH - 1; r >=0 ; --r) {
    int empty_in_a_row = 0;
    for (fil_t f = 0; f < BOARD_WIDTH; ++f) {
      piece_t piece = get_piece(p, r, f, &base_board);
      if (ptype_of(piece) == INVALID) {     // invalid square
        tbassert(false, "Bad news, yo.\n");        // This is bad!
      }

      if (ptype_of(piece) == EMPTY) {       // empty square
        empty_in_a_row++;
        continue;
      } else {
        if (empty_in_a_row) fen[pos++] = '0' + empty_in_a_row;
        empty_in_a_row = 0;
        int ori = ori_of(piece);  // orientation
        color_t c = color_of(piece);

        if (ptype_of(piece) == KING) {
          for (i = 0; i < 2; i++) fen[pos++] = king_ori_to_rep[c][ori][i];
          continue;
        }

        if (ptype_of(piece) == PAWN) {
          for (i = 0; i < 2; i++) fen[pos++] = pawn_ori_to_rep[c][ori][i];
          continue;
        }
      }
    }
    // assert: for larger boards, we need more general solns
    tbassert(BOARD_WIDTH <= 10, "BOARD_WIDTH = %d\n", BOARD_WIDTH);
    if (empty_in_a_row == 10) {
      fen[pos++] = '1';
      fen[pos++] = '0';
    } else if (empty_in_a_row) {
      fen[pos++] = '0' + empty_in_a_row;
    }
    if (r) fen[pos++] = '/';
  }
  fen[pos++] = ' ';
  fen[pos++] = 'W';
  fen[pos++] = '\0';

  return pos;
}
// Obtain a sorted move list.
static int get_sortable_move_list(searchNode *node, sortable_move_t * move_list,
                         int hash_table_move) {
  // number of moves in list
  int num_of_moves = generate_all(&(node->position), move_list, false);

  color_t fake_color_to_move = color_to_move_of(&(node->position));

  move_t killer_a = killer[KMT(node->ply, 0)];
  move_t killer_b = killer[KMT(node->ply, 1)];

  for (int mv_index = 0; mv_index < num_of_moves; mv_index++) {
    move_t mv = move_list[mv_index];   // don't use get_move. assumes generate_all doesn't bungle up high bits
    if (mv == hash_table_move) {
      set_sort_key(&move_list[mv_index], SORT_MASK);
    } else if (mv == killer_a) {
      set_sort_key(&move_list[mv_index], SORT_MASK - 1);
    } else if (mv == killer_b) {
      set_sort_key(&move_list[mv_index], SORT_MASK - 2);
    } else {
      ptype_t  pce = ptype_mv_of(mv);
      rot_t    ro  = rot_of(mv);   // rotation
      square_t fs  = from_square(mv);
      int      ot  = ORI_MASK & (ori_of(node->position.board[fs]) + ro);
      square_t ts  = to_square(mv);

      set_sort_key(&move_list[mv_index],
                   best_move_history[BMH(fake_color_to_move, pce, ts, ot)]);
    }
    sortable_move_t insert = move_list[mv_index];
    // TODO: enable this optimization for final since node counts change
    // if (insert > SORT_MASK) {
      int hole = mv_index;
      while (hole > 0 && insert > move_list[hole-1]) {
        move_list[hole] = move_list[hole-1];
        hole--;
      }
      move_list[hole] = insert;
    // }
  }
  return num_of_moves;
}