Exemplo n.º 1
0
int iod_put(char *key,char *value, int count)
{
	return tt_put(key,value,count,IO_DATA);
}
Exemplo n.º 2
0
// Unified alpha-beta and quiescence search
int abq(board *b, int alpha, int beta, int ply, int centiply_extension, bool allow_extensions, bool side_to_move_in_check) {
	if (search_terminate_requested) return 0; // Check for search termination

	int alpha_orig = alpha; // For use in later TT storage

	// Retrieve the value from the transposition table, if appropriate
	evaluation stored;
	tt_get(b, &stored);
	if (!e_eq(stored, no_eval) && stored.depth >= ply && use_ttable) {
		if (stored.type == qexact || stored.type == exact) return stored.score;
		if (stored.type == qlowerbound || stored.type == lowerbound) alpha = max(alpha, stored.score);
		else if (stored.type == qupperbound || stored.type == upperbound) beta = min(beta, stored.score);
		if (alpha >= beta) return stored.score;
	}

	// Futility pruning: enter quiescence early if the node is futile
	if (use_futility_pruning && !side_to_move_in_check && ply == 1) {
		if (relative_evaluation(b) + frontier_futility_margin < alpha) ply = 0;
	} else if (use_futility_pruning && !side_to_move_in_check && ply == 2) {
		if (relative_evaluation(b) + prefrontier_futility_margin < alpha) ply = 0;
	}

	bool quiescence = (ply <= 0);

	// Generate all possible moves for the quiscence search or normal search, and compute the
	// static evaluation if applicable.
	move *moves = NULL;
	int num_available_moves = 0;
	if (quiescence) moves = board_moves(b, &num_available_moves, true); // Generate only captures
	else moves = board_moves(b, &num_available_moves, false); // Generate all moves
	if (quiescence && !use_qsearch) {
		free(moves);
		return relative_evaluation(b); // If qsearch is turned off
	}

	// Abort if the quiescence search is too deep (currently 45 plies)
	if (ply < -quiesce_ply_cutoff) { 
		sstats.qnode_aborts++;
		free(moves);
		return relative_evaluation(b);
	}

	int quiescence_stand_pat;
	// Allow the quiescence search to generate cutoffs
	if (quiescence) {
		quiescence_stand_pat = relative_evaluation(b);
		alpha = max(alpha, quiescence_stand_pat);
		if (alpha >= beta) {
			free(moves);
			return quiescence_stand_pat;
		}
	} else if (!e_eq(stored, no_eval) && use_tt_move_hueristic) {
		assert(is_legal_move(b, stored.best)); // TODO
		// For non-quiescence search, use the TT entry as a hueristic
		moves[num_available_moves] = stored.best;
		num_available_moves++;
	}

	// Update search stats
	if (quiescence) sstats.qnodes_searched++;
	else sstats.nodes_searched++;

	// Search hueristic: sort exchanges using MVV-LVA
	if (quiescence && mvvlva) nlopt_qsort_r(moves, num_available_moves, sizeof(move), b, &capture_move_comparator);

	// Search extensions
	bool no_more_extensions = false;

	// Extend the search if we are in check
	//coord king_loc = b->black_to_move ? b->black_king : b->white_king;
	bool currently_in_check = side_to_move_in_check; //in_check(b, king_loc.col, king_loc.row, b->black_to_move);
	if (check_extend && currently_in_check && ply <= check_extend_threshold && !quiescence && allow_extensions) { // only extend in shallow non-quiescence situations 
		centiply_extension += check_extension_centiply;
		no_more_extensions = true;
	}

	// Process any extensions
	if (allow_extensions && centiply_extension >= 100) {
		centiply_extension -= 100;
		ply += 1;
	} else if (allow_extensions && centiply_extension <= -100) {
		centiply_extension += 100;
		ply -= 1;
	}

	if (no_more_extensions) allow_extensions = false; // Only allow one check extension

	move best_move_yet = no_move;
	int best_score_yet = NEG_INFINITY; 
	int num_moves_actually_examined = 0; // We might end up in checkmate
	//for (int iterations = 0; iterations < 2; iterations++) { // ABDADA iterations
		for (int i = num_available_moves - 1; i >= 0; i--) { // Iterate backwards to match MVV-LVA sort order
			/*int claimed_node_id = -1;
			if (i != num_available_moves - 1 && iterations == 1) { // Skip redundant young brothers on the first pass
				if (!tt_try_to_claim_node(b, &claimed_node_id)) continue; // Skip the node if it is already being searched
			} else tt_always_claim_node(b, &claimed_node_id);*/
			apply(b, moves[i]);
			bool we_moved_into_check;
			// Choose the more efficient version if possible
			// If we were already in check, we need to do the expensive search
			if (side_to_move_in_check) {
				coord king_loc = b->black_to_move ? b->white_king : b->black_king; // for side that just moved
				we_moved_into_check = in_check(b, king_loc.col, king_loc.row, !(b->black_to_move));
			} else we_moved_into_check = puts_in_check(b, moves[i], !b->black_to_move);
			// Never move into check
			if (we_moved_into_check) {
				unapply(b, moves[i]);
				//tt_unclaim_node(claimed_node_id);
				continue;
			}
			bool opponent_in_check = puts_in_check(b, moves[i], b->black_to_move);
			/*coord opp_king_loc = b->black_to_move ? b->black_king : b->white_king;
			bool opponent_in_check = in_check(b, opp_king_loc.col, opp_king_loc.row, (b->black_to_move));*/
			int score = -abq(b, -beta, -alpha, ply - 1, centiply_extension, allow_extensions, opponent_in_check);
			num_moves_actually_examined++;
			unapply(b, moves[i]);
			if (score > best_score_yet) {
				best_score_yet = score;
				best_move_yet = moves[i];
			}
			alpha = max(alpha, best_score_yet);
			if (alpha >= beta) {
				//tt_unclaim_node(claimed_node_id);
				break;
			}
			//tt_unclaim_node(claimed_node_id);
		}
	//}
	free(moves); // We are done with the array

	// We have no available moves (or captures) that don't leave us in check
	// This means checkmate or stalemate in normal search
	// It might mean no captures are available in quiescence search
	if (num_moves_actually_examined == 0) {
		if (quiescence) return quiescence_stand_pat; // TODO: qsearch doesn't understand stalemate or checkmate
		// This seems paradoxical, but the +1 is necessary so we pick some move in case of checkmate
		if (currently_in_check) return NEG_INFINITY + 1; // checkmate
		else return 0; // stalemate
	}

	if (quiescence && best_score_yet < quiescence_stand_pat) return quiescence_stand_pat; // TODO experimental stand pat

	if (search_terminate_requested) return 0; // Search termination preempts tt_put

	// Record the selected move in the transposition table
	evaltype type;
	if (best_score_yet <= alpha_orig) type = (quiescence) ? qupperbound : upperbound;
	else if (best_score_yet >= beta) type = (quiescence) ? qlowerbound : lowerbound;
	else type = (quiescence) ? qexact : exact;
	evaluation eval = {.best = best_move_yet, .score = best_score_yet, .type = type, .depth = ply};
	tt_put(b, eval);
	return best_score_yet;
}
Exemplo n.º 3
0
int md_put(char *path,Meta_Data *md)
{
	return tt_put(path,md,sizeof(Meta_Data),META_DATA);
}