int tt_get(Transposition_table *table, enum routine_id routine, int target1, int target2, int remaining_depth, Hash_data *extra_hash, int *value1, int *value2, int *move) { Hash_data hashval; Hashentry *entry; Hashnode *node; /* Sanity check. */ if (remaining_depth < 0 || remaining_depth > HN_MAX_REMAINING_DEPTH) return 0; /* Get the combined hash value. */ calculate_hashval_for_tt(&hashval, routine, target1, target2, extra_hash); /* Get the correct entry and node. */ entry = &table->entries[hashdata_remainder(hashval, table->num_entries)]; if (hashdata_is_equal(hashval, entry->deepest.key)) node = &entry->deepest; else if (hashdata_is_equal(hashval, entry->newest.key)) node = &entry->newest; else return 0; stats.read_result_hits++; /* Return data. Only set the result if remaining depth in the table * is big enough to be trusted. The move can always be used for move * ordering if nothing else. */ if (move) *move = hn_get_move(node->data); if (remaining_depth <= (int) hn_get_remaining_depth(node->data)) { if (value1) *value1 = hn_get_value1(node->data); if (value2) *value2 = hn_get_value2(node->data); stats.trusted_read_result_hits++; return 2; } return 1; }
/* Find a cache entry matching the data given in the parameters. * Important: We assume that unused parameters are normalized to NO_MOVE * when storing or retrieving, so that we can ignore them here. */ static struct persistent_cache_entry * find_persistent_cache_entry(struct persistent_cache *cache, enum routine_id routine, int apos, int bpos, int cpos, Hash_data *goal_hash, int node_limit) { int k; for (k = 0; k < cache->current_size; k++) { struct persistent_cache_entry *entry = cache->table + k; if (entry->routine == routine && entry->apos == apos && entry->bpos == bpos && entry->cpos == cpos && depth - stackp <= entry->remaining_depth && (entry->node_limit >= node_limit || entry->result_certain) && (goal_hash == NULL || hashdata_is_equal(entry->goal_hash, *goal_hash)) && verify_stored_board(entry->board)) return entry; } return NULL; }
void tt_update(Transposition_table *table, enum routine_id routine, int target1, int target2, int remaining_depth, Hash_data *extra_hash, int value1, int value2, int move) { Hash_data hashval; Hashentry *entry; Hashnode *deepest; Hashnode *newest; unsigned int data; /* Get routine costs definitions from liberty.h. */ static const int routine_costs[] = { ROUTINE_COSTS }; gg_assert(routine_costs[NUM_CACHE_ROUTINES] == -1); /* Sanity check. */ if (remaining_depth < 0 || remaining_depth > HN_MAX_REMAINING_DEPTH) return; /* Get the combined hash value. */ calculate_hashval_for_tt(&hashval, routine, target1, target2, extra_hash); data = hn_create_data(remaining_depth, value1, value2, move, routine_costs[routine]); /* Get the entry and nodes. */ entry = &table->entries[hashdata_remainder(hashval, table->num_entries)]; deepest = &entry->deepest; newest = &entry->newest; /* See if we found an already existing node. */ if (hashdata_is_equal(hashval, deepest->key) && remaining_depth >= (int) hn_get_remaining_depth(deepest->data)) { /* Found deepest */ deepest->data = data; } else if (hashdata_is_equal(hashval, newest->key) && remaining_depth >= (int) hn_get_remaining_depth(newest->data)) { /* Found newest */ newest->data = data; /* If newest has become deeper than deepest, then switch them. */ if (hn_get_remaining_depth(newest->data) > hn_get_remaining_depth(deepest->data)) { Hashnode temp; temp = *deepest; *deepest = *newest; *newest = temp; } } else if (hn_get_total_cost(data) > hn_get_total_cost(deepest->data)) { if (hn_get_total_cost(newest->data) < hn_get_total_cost(deepest->data)) *newest = *deepest; deepest->key = hashval; deepest->data = data; } else { /* Replace newest. */ newest->key = hashval; newest->data = data; } stats.read_result_entered++; table->is_clean = 0; }