Beispiel #1
0
/**
 *
 * Execute the best play
 *
 * */
zet Agent::play(board& b,bool player){
	this->playing_color = player;
	if (lapse(get_generator())){
		std::vector<zet> s = enumerate_moves(b,player); 
		int rn_n = std::uniform_int_distribution<int>(0,s.size()-1)(get_generator());
		FILE_LOG(logDEBUG)<<" * lapsing - returning random move" <<std::endl;
		return s[rn_n];
	}
	std::vector<zet> s = solve(b,player); 
	FILE_LOG(logDEBUG)<<"Playing for player "<<((player==BLACK)?"BLACK":"WHITE")<< " there are "<< s.size() <<" moves" << std::endl;
	FILE_LOG(logDEBUG)<<" board is :" <<b<<std::endl;
	if(s.empty()){
		FILE_LOG(logERROR)<<" board with no moves "<<b <<std::endl;
	}
	assert(!s.empty());
	zet r;
	//std::random_shuffle(s.begin(),s.end());
	if (player == BLACK || is_negamax()){
		r=*std::max_element(s.begin(),s.end(),[](const zet& z1, const zet& z2 ){ return z1.val < z2.val;});
	} else{
		r=*std::min_element(s.begin(),s.end(),[](const zet& z1, const zet& z2 ){ return z1.val < z2.val;});
	}
	FILE_LOG(logDEBUG)<<((player==BLACK)?"BLACK":"WHITE")<<" playes move "<<r.zet_id<<" with value:"<<r.val <<std::endl;
	return r;
}
Beispiel #2
0
static int negamax_algo(struct chessboard *c, int color, int depth, int alpha, int beta)
{
	struct move_list *l;
	struct raw_move m;
	int n;
	int val, best_val = INT_MIN;

	if (!depth)
		return !color ? calculate_board_heuristic(c) : -calculate_board_heuristic(c);

	l = allocate_move_list();
	for (int i = 0; i < 16; i++) {
		n = enumerate_moves(c, (color << 4) | i, l);
		expanded_moves += n;

		for (int j = 0; j < n; j++) {
			get_move(l, j, &m.sx, &m.sy, &m.dx, &m.dy);

			execute_raw_move(c, &m);
			evaluated_moves++;

			val = -negamax_algo(c, !color, depth - 1, -beta, -alpha);

			unwind_raw_move(c, &m);

			best_val = max(best_val, val);
			alpha = max(alpha, val);
			if (alpha >= beta)
				break;
		}
	}

	free_move_list(l);
	return best_val;
}
Beispiel #3
0
/* Returns sx|sy|dx|dy in an integer byte-by-byte from least to most
 * significant, indicating which move should be made next.
 *
 * We seperate the initial iteration of negamax out like this to track the
 * actual move associated with the best score. Doing so during the
 * deeper iterations is a waste of time. */
unsigned int calculate_move(struct chessboard *c, int color, int depth)
{
	struct move_list *l;
	int n, fbsx = -1, fbsy = -1, fbdx = -1, fbdy = -1;
	int val, best_val = INT_MIN, alpha = INT_MIN, beta = INT_MAX;
	struct raw_move m;
	struct timespec *t;

	expanded_moves = 0;
	evaluated_moves = 0;

	t = start_timer();
	l = allocate_move_list();
	for (int i = 0; i < 16; i++) {
		n = enumerate_moves(c, (color << 4) | i, l);
		expanded_moves += n;

		for (int j = 0; j < n; j++) {
			get_move(l, j, &m.sx, &m.sy, &m.dx, &m.dy);
			execute_raw_move(c, &m);
			evaluated_moves++;

			val = -negamax_algo(c, !color, depth - 1, -beta, -alpha);

			alpha = max(alpha, val);
			if (val > best_val) {
				best_val = val;
				fbsx = m.sx;
				fbsy = m.sy;
				fbdx = m.dx;
				fbdy = m.dy;
			}

			debug("Move %d/%d for piece %d (%d,%d) => (%d,%d) has heuristic value %d\n", j + 1, n, (color << 4) | i, m.sx, m.sy, m.dx, m.dy, val);
			unwind_raw_move(c, &m);
		}
	}
	free_move_list(l);
	expanded_moves += n;
	debug("Evaluated %luM/%luM expanded moves in %lu seconds\n", evaluated_moves / 1000000, expanded_moves / 1000000, get_timer_and_free(t) / 1000);

	return (fbsx) | (fbsy << 8) | (fbdx << 16) | (fbdy << 24);
}