by Josu? Forte » 27 Mar 2005, 01:31
Hi Sune,
Well, the first thing I do is to test for repetition after making a move. Then I call search() and the first thing I do in search() is to probe the HT.
Better to show you my code in Search() to clarify.
Here it is:
int Search(int alpha, int beta, int depth_remaining)
{
int *move;
int extension;
int score;
HASH_ENTRY *hash_entry;
int pvs = 0;
int temp_alpha = -MATE_VALUE; ///
if (++node_counter > node_counter_limit) ScanInput();
depth_remaining--;
// Install the next PV move into the hash table so that it will be played first.
hash_entry = &hashtable[moving_color][(unsigned int)hashkey & hashtable_size_mask];
if (follow_pv) {
MOVE *pv_move = (MOVE *)&pv[0][ply];
if (ply >= pv_length[0]) {
follow_pv = 0;
goto SKIP_HASHTABLE;
}
else if (depth_remaining <= 0)
depth_remaining = 1;
if (MoveIsLegal(pv_move->from, pv_move->to, pv_move->piece, pv_move)) {
hash_entry->always.hashkey = hashkey;
hash_entry->always.move = pv[0][ply];
hash_entry->always.flag.bound = EXACT_SCORE;
hash_entry->always.depth_remaining = (char)depth_remaining;
}
goto SKIP_HASHTABLE;
}
// Verify if this position is in the hashtable. ("always" element)
if (hash_entry->always.hashkey != hashkey)
follow_pv = 0;
else {
if (follow_pv) {
if (ply >= pv_length[0])
follow_pv = 0;
else if (depth_remaining <= 0)
depth_remaining = 1;
goto SKIP_HASHTABLE;
}
if (hash_entry->always.depth_remaining >= (char)depth_remaining) {
int hash_score = (int)hash_entry->always.score;
// Mate scores have to be adjusted because here "hash_score" represents mate in N plies
// from this position. We must retrieve "hash_score" as mate in N plies from the root.
if (abs(hash_score) >= MATE_VALUE - MAX_DEPTH) {
if (hash_score > 0) hash_score -= ply;
else hash_score += ply;
}
if (hash_entry->always.flag.bound & LOWER_BOUND) {
if (hash_score >= beta) {
return(hash_score);
}
}
else if (hash_entry->always.flag.bound & UPPER_BOUND) {
if (hash_score <= alpha) {
return(hash_score);
}
}
}
}
// Verify if this position is in the hashtable. ("depth" element)
if (hash_entry->depth.hashkey != hashkey);
else if (hash_entry->depth.depth_remaining >= (char)depth_remaining) {
int hash_score = (int)hash_entry->depth.score;
// Mate scores have to be adjusted because here "score" represents mate in N moves
// from this position. We must retrieve "score" as mate in N moves from the root.
if (abs(hash_score) >= MATE_VALUE - MAX_DEPTH) {
if (hash_score > 0) hash_score -= ply;
else hash_score += ply;
}
if (hash_entry->depth.flag.bound & LOWER_BOUND) {
if (hash_score >= beta) {
return(hash_score);
}
}
else if (hash_entry->depth.flag.bound & UPPER_BOUND) {
if (hash_score <= alpha) {
return(hash_score);
}
}
}
SKIP_HASHTABLE:
next_move_pointer[ply + 1] = LegalMoveGenerator(next_move_pointer[ply]);
legal_moves[ply] = next_move_pointer[ply + 1] - next_move_pointer[ply];
if (legal_moves[ply] > 1) {
ValuateMoves(next_move_pointer[ply], next_move_pointer[ply + 1], hash_entry);
SortMoves(next_move_pointer[ply], 0, legal_moves[ply] - 1);
}
// Search starts here.
for (move = next_move_pointer[ply]; move < next_move_pointer[ply + 1]; move++) {
(*move) &= 0x7FFFFF;
MakeMove((MOVE *)move);
current_move[ply] = *((MOVE*)move);
// Check for draw by 3 fold repetition or 50 move rule.
if (status[move_number].fifty_move_rule > 3) {
if (IsDraw()) {
follow_pv = score = 0;
pv_length[ply + 1] = 0;
goto SKIP_SEARCH;
}
}
// Check for insufficient material.
if (insufficient_material) {
if (!IsAttacked(KING_SQUARE(not_moving_color), moving_color)) {
follow_pv = score = 0;
pv_length[ply + 1] = 0;
goto SKIP_SEARCH;
}
}
// Check for maximum search depth.
if (ply >= MAX_DEPTH) {
score = -Evaluate(); /// Verificar depois se est? certo.
pv_length[ply + 1] = 0;
goto SKIP_SEARCH;
}
// Check for node search level.
if (node_search) {
if (node_counter >= node_search) {
stop_search = 1;
goto SKIP_SEARCH;
}
}
moving_color = not_moving_color;
not_moving_color ^= 1;
ply++;
if (depth_remaining > 0) {
if (pvs) {
score = -Search(-alpha - 1, -alpha, depth_remaining);
if ((score > alpha) && (score < beta))
score = -Search(-beta, -alpha, depth_remaining);
}
else score = -Search(-beta, -alpha, depth_remaining);
}
else
score = -QuiescentSearch(-beta, -alpha);
ply--;
not_moving_color = moving_color;
moving_color ^= 1;
SKIP_SEARCH:
UnMakeMove((MOVE *)move);
if (stop_search) return(score);
if (score >= beta) { // Fail High.
int temp_score = score;
if (abs(score) >= (MATE_VALUE - MAX_DEPTH)) {
if (score > 0) score += ply;
else score -= ply;
}
// Record search result in hashtable. ("always" element)
hash_entry->always.flag.bound = LOWER_BOUND;
hash_entry->always.move = *move;
hash_entry->always.hashkey = hashkey;
hash_entry->always.score = score;
hash_entry->always.depth_remaining = (char)depth_remaining;
// Record search result in hashtable. ("depth" element)
if ((age != hash_entry->depth.flag.age) ||
(hash_entry->depth.depth_remaining < (char)depth_remaining)) {
if (age != hash_entry->depth.flag.age) {
hashtable_write++;
hash_entry->depth.flag.age = (unsigned char)age;
}
hash_entry->depth.move = *move;
hash_entry->depth.hashkey = hashkey;
hash_entry->depth.depth_remaining = (char)depth_remaining;
hash_entry->depth.score = score;
hash_entry->depth.flag.bound = LOWER_BOUND;
}
return(temp_score);
}
if (score > alpha) {
alpha = score;
pv[ply][ply] = *move;
UpDatePV();
pvs = 1;
}
if (score > temp_alpha) temp_alpha = score;
}
if (legal_moves[ply] == 0) { // Verify if it is Mate or Stalemate.
pv[ply][ply] = 0;
pv_length[ply] = 0;
if (IsAttacked(KING_SQUARE(moving_color), not_moving_color))
return(ply - MATE_VALUE);
else
return(0);
}
score = alpha;
if (pvs) {
// This is an EXACT_SCORE, so update killer moves.
UpdateKillerMove((MOVE *)&pv[ply][ply]);
// Record search result in hashtable. ("always" element)
if (abs(alpha) >= (MATE_VALUE - MAX_DEPTH)) {
// Mate scores have to be adjusted because here "score" represents mate in N moves
// from this position. We must retrieve "score" as mate in N moves from the root.
if (alpha > 0) score = alpha + ply;
else score = alpha - ply;
// If EXACT_SCORE on +mate, change it to LOWER_BOUND.
if (alpha > 0) {
hash_entry->always.move = pv[ply][ply];
hash_entry->always.flag.bound = LOWER_BOUND;
}
// If EXACT_SCORE on -mate, change it to UPPER_BOUND.
else {
hash_entry->always.move = 0;
hash_entry->always.flag.bound = UPPER_BOUND;
}
}
else {
hash_entry->always.flag.bound = EXACT_SCORE;
hash_entry->always.move = pv[ply][ply];
}
hash_entry->always.hashkey = hashkey;
hash_entry->always.score = score;
hash_entry->always.depth_remaining = (char)depth_remaining;
// Record search result in hashtable. ("depth" element)
if ((age != hash_entry->depth.flag.age) ||
(hash_entry->depth.depth_remaining < (char)depth_remaining)) {
if (age != hash_entry->depth.flag.age) {
hashtable_write++;
hash_entry->depth.flag.age = (unsigned char)age;
}
if (abs(alpha) >= (MATE_VALUE - MAX_DEPTH)) {
// EXACT_BOUND on +mate. Change it to LOWER_BOUND.
if (alpha > 0) {
hash_entry->depth.move = pv[ply][ply];
hash_entry->depth.flag.bound = LOWER_BOUND;
}
// EXACT_BOUND on -mate. Change it to UPPER_BOUND.
else {
hash_entry->depth.move = 0;
hash_entry->depth.flag.bound = UPPER_BOUND;
}
}
else {
hash_entry->depth.move = pv[ply][ply];
hash_entry->depth.flag.bound = EXACT_SCORE;
}
hash_entry->depth.hashkey = hashkey;
hash_entry->depth.score = score;
hash_entry->depth.depth_remaining = (char)depth_remaining;
}
return(alpha);
}
else { // Fail Low.
if (abs(temp_alpha) >= (MATE_VALUE - MAX_DEPTH)) {
// Mate scores have to be adjusted because here "score" represents mate in N moves
// from this position. We must retrieve "score" as mate in N moves from the root.
if (temp_alpha > 0) score = temp_alpha + ply;
else score = temp_alpha - ply;
}
// Record search result in hashtable. ("always" element)
hash_entry->always.hashkey = hashkey;
hash_entry->always.move = 0;
hash_entry->always.flag.bound = UPPER_BOUND;
hash_entry->always.score = score;
hash_entry->always.depth_remaining = (char)depth_remaining;
// Record search result in hashtable. ("depth" element)
if ((age != hash_entry->depth.flag.age) ||
(hash_entry->depth.depth_remaining < (char)depth_remaining)) {
if (age != hash_entry->depth.flag.age) {
hashtable_write++;
hash_entry->depth.flag.age = (unsigned char)age;
}
hash_entry->depth.hashkey = hashkey;
hash_entry->depth.move = 0;
hash_entry->depth.flag.bound = UPPER_BOUND;
hash_entry->depth.score = score;
hash_entry->depth.depth_remaining = (char)depth_remaining;
}
return(temp_alpha);
}
}