Esempio n. 1
0
std::tuple<Move, Value> 
AperyBook::probe(const Position &pos, const std::string &fname, bool pick_best) 
{
  AperyBookEntry entry;
  uint16_t best = 0;
  uint32_t sum = 0;
  Move move = kMoveNone;
  Key key = book_key(pos);
  Value min_book_score = static_cast<Value>(static_cast<int>(Options["Min_Book_Score"]));
  Value score = kValueZero;

  if (file_name_ != fname && !open(fname.c_str()))
    return std::make_tuple(kMoveNone, kValueZero);

  binary_search(key);
                                                                                                                                              
  while (read(reinterpret_cast<char*>(&entry), sizeof(entry)), entry.key == key && good()) 
  {
    best = std::max(best, entry.count);
    sum += entry.count;
                                                                                                                                              
    if 
    (
      min_book_score <= entry.score
      &&
      (
        (random_() % sum < entry.count)
        ||
        (pick_best && entry.count == best)
      )
    )
    {
      Square to = to_square(entry.from_to_pro & 0x007fU);
      int from_raw = (entry.from_to_pro >> 7) & 0x007fU;
      if (from_raw >= kBoardSquare) 
      {
        move = move_init(to, to_drop_piece_type(static_cast<Square>(from_raw)));
      }
      else
      {
        Square from = to_square(from_raw);
        PieceType pt_from = type_of(pos.square(from));
        if (entry.from_to_pro & kPromoted)
          move = move_init(from, to, pt_from, type_of(pos.square(to)), true);
        else
          move = move_init(from, to, pt_from, type_of(pos.square(to)), false);
      }
      score = entry.score;
    }
  }
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;
  }
}
Esempio n. 3
0
// 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;
}
Esempio n. 4
0
// converts a move to string notation for FEN
void move_to_str(move_t mv, char *buf, size_t bufsize) {
  square_t f = from_square(mv);  // from-square
  square_t t = to_square(mv);    // to-square
  rot_t r = rot_of(mv);          // rotation
  const char *orig_buf = buf;

  buf += square_to_str(f, buf, bufsize);
  if (f != t) {
    buf += square_to_str(t, buf, bufsize - (buf - orig_buf));
  } else {
    switch (r) {
      case NONE:
        buf += square_to_str(t, buf, bufsize - (buf - orig_buf));
        break;
      case RIGHT:
        buf += snprintf(buf, bufsize - (buf - orig_buf), "R");
        break;
      case UTURN:
        buf += snprintf(buf, bufsize - (buf - orig_buf), "U");
        break;
      case LEFT:
        buf += snprintf(buf, bufsize - (buf - orig_buf), "L");
        break;
      default:
        tbassert(false, "Whoa, now.  Whoa, I say.\n");  // Bad, bad, bad
        break;
    }
  }
}
Esempio n. 5
0
void
AperyBook::init()
{
  for (int p = 0; p < kPieceMax; ++p)
  {
    for (int sq = 0; sq < kBoardSquare; ++sq)
      zob_piece_[p][to_square(sq)] = mt64bit_();
  }

  for (int hp = 0; hp < 7; ++hp)
  {
    for (int num = 0; num < 19; ++num)
      zob_hand_[hp][num] = mt64bit_();
  }
  zob_turn_ = mt64bit_();
}
Esempio n. 6
0
// 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;
}
Esempio n. 7
0
int Search::alphaBeta(bool white_turn, int depth, int alpha, int beta, Board& board, Transposition *tt,
		bool null_move_in_branch, Move (&killers)[32][2], int (&history)[64][64], int ply) {

	// If, mate we do not need search at greater depths
	if (board.b[WHITE][KING] == 0) {
		return -10000;
	} else if (board.b[BLACK][KING] == 0) {
		return 10000;
	}
	if (depth == 0) {
		return capture_quiescence_eval_search(white_turn, alpha, beta, board);
	}
	if (depth == 1) {
		// futility pruning. we do not hope for improving a position more than 300 in one move...
		int static_eval = evaluate(board);
		if (white_turn && (static_eval + 300) < alpha) {
			return capture_quiescence_eval_search(white_turn, alpha, beta, board);
		}
		if (!white_turn && (static_eval - 300) > beta) {
			return capture_quiescence_eval_search(white_turn, alpha, beta, board);
		}
	}
	if (depth == 2) {
		// extended futility pruning. we do not hope for improving a position more than 500 in two plies...
		// not really proven to +ELO but does not worse performance at least
		int static_eval = evaluate(board);
		if ((white_turn && (static_eval + 500) < alpha) || (!white_turn && (static_eval - 500) > beta)) {
			return capture_quiescence_eval_search(white_turn, alpha, beta, board);
		}
	}

	// null move heuristic - we do this despite in check..
	if (!null_move_in_branch && depth > 3) {
		// skip a turn and see if and see if we get a cut-off at shallower depth
		// it assumes:
		// 1. That the disadvantage of forfeiting one's turn is greater than the disadvantage of performing a shallower search.
		// 2. That the beta cut-offs prunes enough branches to be worth the time searching at reduced depth
		int R = 2; // depth reduction
		int res = alphaBeta(!white_turn, depth - 1 - R, alpha, beta, board, tt, true, killers, history, ply + 1);
		if (white_turn && res > alpha) {
			alpha = res;
		} else if (!white_turn && res < beta) {
			beta = res;
		}
		if (beta <= alpha) {
			if (white_turn) {
				return alpha;
			}
			return beta;
		}
	}
	MoveList moves = get_children(board, white_turn);
	if (moves.empty()) {
		return 0;
	}
	Transposition tt_pv = tt[board.hash_key % HASH_SIZE];
	for (auto it = moves.begin(); it != moves.end(); ++it) {
		// sort pv moves first
		if (tt_pv.next_move != 0 && tt_pv.hash == board.hash_key && tt_pv.next_move == it->m) {
			it->sort_score += 1100000;
		}
		// ...then captures in MVVLVA order
		if (!is_capture(it->m)) {
			// killer moves are quite moves that has previously led to a cut-off
			if (killers[ply - 1][0].m == it->m) {
				it->sort_score += 999999;
			} else if (killers[ply - 1][1].m == it->m) {
				it->sort_score += 899999;
			} else {
				// "history heuristics"
				// the rest of the quite moves are sorted based on how often they increase score in the search tree
				it->sort_score += history[from_square(it->m)][to_square(it->m)];
			}
		}
	}
	total_generated_moves += moves.size();

	Transposition t;
	t.hash = board.hash_key;
	int next_move = 0;
	for (unsigned int i = 0; i < moves.size(); ++i) {
		// late move reduction.
		// we assume sort order is good enough to not search later moves as deep as the first 4
		if (depth > 5 && i == 10) {
			depth -= 2;
		}

		pick_next_move(moves, i);
		Move child = moves[i];
		node_count++;
		make_move(board, child);

		int res = alphaBeta(!white_turn, depth - 1, alpha, beta, board, tt, null_move_in_branch, killers, history,
				ply + 1);
		unmake_move(board, child);
		if (res > alpha && res < beta) {
			// only cache exact scores

		}

		if (res > alpha && white_turn) {
			next_move = child.m;
			alpha = res;
			//history heuristics
			if (!is_capture(child.m)) {
				history[from_square(child.m)][to_square(child.m)] += depth;
			}
			// update pv
		}
		if (res < beta && !white_turn) {
			next_move = child.m;
			beta = res;
			//history heuristics
			if (!is_capture(child.m)) {
				history[from_square(child.m)][to_square(child.m)] += depth;
			}
			// update pv
		}
		if (beta <= alpha || time_to_stop()) {
			if (!is_capture(child.m)) {
				if (killers[ply - 1][0].m != child.m) {
					killers[ply - 1][1] = killers[ply - 1][0];
					killers[ply - 1][0] = child;
				}
			}
			break;
		}
	}
	t.next_move = next_move;
	tt[board.hash_key % HASH_SIZE] = t;
	if (white_turn) {
		return alpha;
	}
	return beta;
}