Ejemplo n.º 1
0
Move AIPlayer::alpha_beta(GameBoard* game, int lookahead, int alpha, int beta, int player)
{
    vector<Move> all_moves = get_all_moves(game, player);
    //cout << "Moves are: " << endl;
        //cout << m.x +1  << ", " << m.y + 1 << " Score: " << m.score << endl;
    if (all_moves.empty())
        return Move(-1, -1, maximizing_player(player) * 35);
    if (lookahead == 0) {
        //return heuristic value of previous player
        if (!is_maximizing(player)) {
            Move temp = *(std::max_element(all_moves.begin(), all_moves.end(), [](Move m1, Move m2){return m1.score < m2.score;}));
            //cout << "return: "<< temp.x +1  << ", " << temp.y + 1 << " Score: " << temp.score << endl;
            return temp;
        }
            
        else {
            Move temp =  *(min_element(all_moves.begin(), all_moves.end(), [](Move m1, Move m2){return m1.score < m2.score;}));
            //cout << "return: "<< temp.x +1  << ", " << temp.y + 1 << " Score: " << temp.score << endl;
            return temp;
        }
    }
    Move return_move;
    if (is_maximizing(player)) {
        for (auto m : all_moves) {
            GameBoard temp_board(game);
            temp_board.make_move(m.x, m.y, player);
            Move temp_move = alpha_beta(&temp_board, lookahead - 1, alpha, beta, other_player(player));
            
            if (temp_move.score > alpha) {
                return_move = m;
                alpha = temp_move.score;
            }
            if (alpha >= beta) {
                break;
            }
        }
        return return_move;
    } else {
        for (auto m : all_moves) {
            GameBoard temp_board(game);
            temp_board.make_move(m.x, m.y, player);
            Move temp_move = alpha_beta(&temp_board, lookahead - 1, alpha, beta, other_player(player));
            
            if (temp_move.score < beta) {
                beta = temp_move.score;
                return_move = m;
            }
            if (alpha >= beta) {
                break;
            }
        }
        return return_move;
    }

}
AIMoves *ai_priority(const Board *b)
{
        AIMoves *moves;
        int i, j, stage[2] = {1, 1}, mask, bits;

        moves = ai_threats(b);

        /* Do not prioritize if we've won */
        if (threat_counts[connect_k - place_p + 1][b->turn - 1]) {
                moves->utility = AIW_WIN;
                return moves;
        }

        /* Find the largest supported threat for each player */
        for (i = 2; i < connect_k; i++) {
                if (threat_number(0, i - 1) >= place_p &&
                    threat_number(0, i) > place_p)
                        stage[0] = i;
                if (threat_number(1, i - 1) >= place_p &&
                    threat_number(1, i) > place_p)
                        stage[1] = i;
        }

        if (opt_debug_stage)
                g_debug("Stages %d/%d", stage[0], stage[1]);

        /* Do not prioritize if we're losing */
        if (stage[b->turn - 1] <= stage[other_player(b->turn) - 1]) {
                moves->utility = -stage[other_player(b->turn) - 1];
                return moves;
        }

        /* Threats above the player's stage are no more valuable than the
           stage */
        bits = 1 << (stage[b->turn - 1] * BITS_PER_THREAT);
        mask = bits - 1;
        for (i = 0; i < moves->len; i++) {
                AIWEIGHT w = moves->data[i].weight, w2;

                if (w < AIW_THREAT_MAX && w >= bits) {
                        w2 = w & mask;
                        w = w & ~mask;
                        for (j = stage[b->turn - 1];
                             w && j < connect_k - place_p + 1; j++) {
                                w = w >> BITS_PER_THREAT;
                                w2 += w & mask;
                        }
                        moves->data[i].weight = w2;
                }
        }
Ejemplo n.º 3
0
void move(board_type board, char player, int move_num, bool humans_only, char computer) {
    int square;
    
    if(humans_only) {
        do {
            printf("What is your move?: ");
            fflush(stdin);
            scanf("%d", &square);
            square--;
        } while(board[square] != empty);
        play(board, square, player);
    } else {
        if(player == computer) {
            total_nodes = 0;
            //describe(best_move(board, computer, &square, move_num, -infinity, infinity), computer);
            best_move(board, computer, &square, move_num, -infinity, infinity);
            //printf("Analyzed %d nodes\n", total_nodes);
            //getchar(); getchar();
            play(board, square, computer);
        } else {
            do {
                printf("What is your move?: ");
                fflush(stdin);
                scanf("%d", &square);
                square--;
            } while(board[square] != empty);
            play(board, square, other_player(computer));
        }
    }
}
Ejemplo n.º 4
0
Archivo: Chess.c Proyecto: ishefi/chess
moves pawn_moves(settings * set, cord curr, int color) {
	moves piece_simple_moves;
	piece_simple_moves.len = 0;
	cord dest;
	move * single_move;
	moves promotions;
	int dest_color;
	int y_dir = (color == WHITE) ? 1 : -1;

	dest.y = curr.y + y_dir;

	for (int x = -1; x <= 1; x++) {
		single_move = malloc(sizeof(move));
		if (single_move == NULL) {
			free_list(&piece_simple_moves, &free);
			return error_moves;
		}
		single_move->start = curr;
		single_move->promotion = FALSE;
		single_move->is_castle = FALSE;
		dest.x = curr.x + x;
		if (is_valid_cord(dest)) {
			dest_color = which_color(board_piece(set->board, dest));
			//logical XOR: check if pawn can eat XOR move up
			if (color == dest_color) {
				free(single_move);
				continue;
			}
			if ((x == 0) != (dest_color == other_player(color))) {
				single_move->end = dest;
				board_copy(set->board, single_move->board);
				move_from_to(single_move->board, curr, dest);
				// check if psaudo-legal move is legal
				if (is_king_checked(color, single_move->board)) {
					free(single_move);
					continue;
				}
				if (dest.y == promotion_row(color)) {
					promotions = promote(single_move);
					if (promotions.len == -1){
						free(single_move);
						free_list(&piece_simple_moves, &free);
						return promotions;
					}
					concat(&piece_simple_moves, promotions);
				}
				else if (!add_node(&piece_simple_moves, single_move, sizeof(move))) { //could not add node to linked list
					free(single_move);
					free_list(&piece_simple_moves, &free);
					return error_moves;
				}
				free(single_move);
			}
		}
	}
	return piece_simple_moves;
}
Ejemplo n.º 5
0
Archivo: Chess.c Proyecto: ishefi/chess
/* minimax algorithm with alpha-beta prunning.
* the function returns score (int) according to the minimax algorithm
* and the score() function. returns ERROR_SCORE in case of an error.
*/
int minimax(settings set, int alpha, int beta, int is_maxi_player, int depth, int is_best_difficulty){
	int player = set.next;
	if (depth == 0) {
		int scorrer = is_maxi_player ? player : other_player(player);
		int board_score = score(&set, scorrer, player, is_best_difficulty); //return score according to maximizing player
		return board_score;
	}
	moves possible_moves = make_all_moves(&set); // create all possible moves for player
	if (possible_moves.len == -1) { //there was an error, return an error score
		return SCORE_ERROR;
	}
	else if (possible_moves.len == 0){ // reached a "leaf" at the minimax tree (no more possible moves from here)
		if (is_king_checked(player, set.board))
			return is_maxi_player ? INT_MIN : INT_MAX;
		else // tie
			return TIE_SCORE;
	}
	int minimax_score = is_maxi_player ? INT_MIN : INT_MAX;
	move_node* curr = possible_moves.first;
	while (curr != NULL){ // continue recursively for each possible move
		move * cur_move = curr->data;
		settings next_set;
		memcpy(&next_set, &set, sizeof(settings));
		next_set.next = other_player(player);
		int cur_score = minimax(next_set, alpha, beta, !is_maxi_player, depth - 1, is_best_difficulty);
		if (cur_score == SCORE_ERROR) { //there was an error, return an error score
			free_list(&possible_moves, &free);
			return SCORE_ERROR;
		}
		// get maximum\minimum v_score according to is_maxi_player
		minimax_score = is_maxi_player ? maxi(minimax_score, cur_score) : mini(minimax_score, cur_score);
		if (is_maxi_player)
			alpha = maxi(alpha, minimax_score);
		else
			beta = mini(beta, minimax_score);
		if (beta <= alpha)
			break; //pruning
		curr = curr->next;
	}
	free_list(&possible_moves, &free);
	return minimax_score;
}
Ejemplo n.º 6
0
Token Board::play_random_game(Token next_player) {

    Token winner=NOT_PLAYED;
	Token player=next_player;
	while (this->play_random_move(player)) {
        winner=this->check_for_win();
		
		if (winner) break;

		player=other_player(player);
    }

    return winner;
}
Ejemplo n.º 7
0
Archivo: Chess.c Proyecto: ishefi/chess
/* find and return the best computer's next move acording to minimax algorithm.
* in case of an error - return a move with .steps_len = -1
* (envelope function that calls minimax())
*/
moves best_next_moves(settings set, int maximizer) {
	// minimax function
	moves best_moves = { 0 };
	move * temp_best_move;
	moves possible_moves = make_all_moves(&set);
	int best_score = INT_MIN;
	int curr_alpha = INT_MIN;
	if (possible_moves.len == -1) { //error
		return possible_moves;
	}

	int is_best_difficulty = (set.minimax_depth == BEST_DIFFICULTY);
	int depth = (!is_best_difficulty) ? set.minimax_depth : get_best_depth(&set, maximizer);

	move_node * curr = possible_moves.first;
	while (curr != NULL) {
		//get the score of each next possible moves, according to minimax algorithm
		settings next_set;
		memcpy(&next_set, &set, sizeof(settings));
		next_set.next = other_player(set.next);
		board_copy(((move*)curr->data)->board, next_set.board);
		int curr_score = minimax(next_set, curr_alpha, INT_MAX, FALSE, depth - 1, is_best_difficulty);
		if (curr_score == SCORE_ERROR) {
			free_list(&possible_moves, &free);
			free_list(&best_moves, &free);
			return error_moves;
		}
		if (curr_score > curr_alpha)
			curr_alpha = curr_score;
		temp_best_move = curr->data;
		if (curr_score > best_score) { // if new score is higher - free previous best moves
			free_list(&best_moves, &free);
			best_score = curr_score;
		}
		if (!(curr_score < best_score)) {
			if (!add_node(&best_moves, temp_best_move, sizeof(move))) {
				free_list(&best_moves, &free);
				free_list(&possible_moves, &free);
				return error_moves;
			}
		}
		curr = curr->next;
	}
	free_list(&possible_moves, &free);
	if (DEBUG)
		printf("CHOSEN SCORE: %d\n", best_score);
	return best_moves;
}
Ejemplo n.º 8
0
void player_vs_player(void) {
    char x_name[STRING_LENGTH];
    char o_name[STRING_LENGTH];
    board_type board;
    int move_num = 1;
    char player = 'X';
    
    system("cls");
    memset(x_name, '\0', STRING_LENGTH);
    memset(o_name, '\0', STRING_LENGTH);
    
    init(board);
    
    printf("Enter the name of player 'X': ");
    fflush(stdin);
    scanf("%32s", &x_name);
    printf("Enter the name of player 'O': ");
    fflush(stdin);
    scanf("%32s", &o_name);
    
    while(winner(board) == empty) {
        system("cls");
        printf("Match: Player vs. Player\n\n");
        print_board(board);
        if(player == 'X')
            printf("It is turn for %s!\n", x_name);
        else
            printf("It is turn for %s!\n", o_name);
        
        move(board, player, move_num, true, '\0');
        player = other_player(player);
        move_num++;
    }
    system("cls");
    printf("Match: Player vs. Player\n\n");
    print_board(board);
    
    if(winner(board) != 'T')
        printf("Winner is %s!\n", winner(board) == 'X' ? x_name : o_name);
    else
        printf("Draw!\n");
    
}
Ejemplo n.º 9
0
double efg_solve::Game::GameValue(const std::array<std::vector<double>, 2> &strategy_profile, std::vector<double> *utility, Player player) const {
  UtilityVector(strategy_profile[player_id(other_player(player))], utility, player);
  for (int infoset = num_infosets(player)-1; infoset >= 0; --infoset) {
    int first = infoset_first_sequence(player, infoset);
    int last = infoset_last_sequence(player, infoset);
    int parent = infoset_parent_sequence(player, infoset);

    for (int i = first; i <= last; ++i) {
      double sequence_probability = strategy_profile[player_id(player)][i];
      double expected_payoff = (*utility)[i];
      (*utility)[parent] += sequence_probability * expected_payoff;
    }
  }
  if (player == Player::P1) {
    return (*utility)[0];
  } else {
    return -(*utility)[0];
  }
}
Ejemplo n.º 10
0
// return the heuristic value used to determine the order
// in which the children of a node are searched.
// this increases speed and efficiency
int evaluate(board_type board, char player) {
    int i;
    int heuristic = 0;
    
    for(i=0; i<POSSIBLE_WINS; i++) {
        int j;
        int players = 0, other_players = 0;
        
        for(j=0; j<3; j++) {
            char piece = board[three_in_a_row[i][j]];
            if(piece == player)
                players++;
            else if(piece == other_player(player))
                other_players++;
        }
        
        heuristic += heuristic_array[players][other_players];
    }
    return heuristic;
}
Ejemplo n.º 11
0
void player_vs_computer(void) {
    // for now, ignore choosing different players
    char player = 'X';
    char ans;
    board_type board;
    int move_num = 1; // first move
    char computer;
    
    system("cls");
    // initialize board
    init(board);
    
    // who will move first?
    printf("Do you want to move first? (y/n): ");
    fflush(stdin);
    scanf("%c", &ans);
    
    if(toupper(ans) == 'Y')
        computer = 'O';
    else
        computer = 'X';
    
    // while !finished
    while(winner(board) == empty) {
        system("cls");
        printf("Match: Computer vs. Player\n\n");
        print_board(board);
        move(board, player, move_num, false, computer);
        player = other_player(player);
        move_num++;
    }
    system("cls");
    printf("Match: Computer vs. Player\n\n");
    print_board(board);
    
    if(winner(board) != 'T')
        printf("Winner is %c!\n", winner(board));
    else
        printf("Draw!\n");
    
}
void debug_counts(void)
{
        int i, sum = 0;

        if (!b)
                return;

        g_debug("Threat counts (black, white):");
        for (i = 1; i < connect_k; i++) {
                g_debug("%d: %3d %3d", i, threat_counts[i][0],
                        threat_counts[i][1]);
                sum += threat_counts[i][0] * threat_bits(i, b->turn) -
                       threat_counts[i][1] *
                       threat_bits(i, other_player(b->turn));
        }
        if (sum > 0)
                g_debug("Threat sum: %d (10^%.2f)", sum, log10((double)sum));
        else if (sum < 0)
                g_debug("Threat sum: %d (-10^%.2f)", sum, log10((double)-sum));
        else
                g_debug("Threat sum: 0");
}
Ejemplo n.º 13
0
int			main()
{
  struct timeval	tv;
  struct timezone	tz;
  t_util		*util;
  char			*str;

  gettimeofday(&tv, &tz);
  if (!(util = malloc(sizeof(t_util))))
    return (err_msg(": malloc fail"));
  if ((str = getenv("PWD")) == NULL)
    return (err_msg(": getenv fail"));
  srand(tv.tv_usec);
  if (!(util->key = ftok(str, 0)) == -1)
    return (err_msg(": ftok fail"));
  util->shm_id = shmget(util->key, (sizeof(char) * (MAP_X * MAP_Y)),
			SHM_R | SHM_W);
  if (util->shm_id == -1)
    first_step(util);
  else
    other_player(util);
  return (0);
}
Ejemplo n.º 14
0
Archivo: Chess.c Proyecto: ishefi/chess
void move_cords(char board[BOARD_SIZE][BOARD_SIZE], cord curr, int max_move, int color, int move_x, int move_y, cord end_cords[32]) {
	cord dest;
	int dest_color;

	// initialize end_cords
	if (DEBUG1){
		if (curr.x < -42) {
			printf("%s\n", "NO KING!");
		}
	}
	int i;
	for (i = 0; i < 32; i++){
		end_cords[i] = error_cord;
	}

	i = 0;
	for (int x_direction = (-move_x); x_direction <= move_x; x_direction += 2){
		for (int y_directrion = (-move_y); y_directrion <= move_y; y_directrion += 2) {
			for (int k = 1; k <= max_move; k++) {
				dest.x = curr.x + (k*x_direction);
				dest.y = curr.y + (k*y_directrion);
				// check if piece can walk to this destination
				if (!is_valid_cord(dest))
					break;
				dest_color = which_color(board_piece(board, dest));
				if (dest_color == color) //if destination is same color piece - cannot move this waty
					break;
				else
					end_cords[i++] = dest;
				if (dest_color == other_player(color)) //if ate - cannot continue moving in the same direction
					break;
			}

		}
	}
}
Ejemplo n.º 15
0
Archivo: Chess.c Proyecto: ishefi/chess
/*
*	compute computer's next move and play.
*	return move in case of success, in case of lose/tie - return LOSE_CODE / TIE_CODE.
*	in case of an error - exit
*/
move computer_turn(settings * game_settings) {
	moves best_moves = best_next_moves(*game_settings, game_settings->next); //find next move
	move_node * random_best_move;
	move best_move;
	if (best_moves.len == -1) { // there was an error
		return error_move;
	}
	if (best_moves.len == 0) { // no possible moves - player wins
		best_move.promotion = NO_MOVE_CODE;
		return best_move;
	}
	else { // play best_move
		int r = rand() % best_moves.len;
		random_best_move = best_moves.first;
		for (int i = 0; i < r; i++) {
			random_best_move = random_best_move->next;
		};
		best_move = *(move*)random_best_move->data;
		board_copy(best_move.board, game_settings->board);
		free_list(&best_moves, &free);
		game_settings->is_next_checked = (is_king_checked(other_player(game_settings->next), game_settings->board));
		return best_move;
	}
}
Ejemplo n.º 16
0
Archivo: Chess.c Proyecto: ishefi/chess
/* calculates the board's score.
* scoring_player = color of the minimax-maximizer player
* current_player = color of the player whose turn it is now.
*
* the function returns:
*				WIN_SCORE if scoring_player wins this board
*				LOSE_SCORE if scoring_player loses this board
*				scoring_player's total pieces value minus other player's total pieces value otherwise
*				ERROR_SCORE in case of an error
*/
int score(settings * set, int scoring_player, int current_player, int is_best){
	int total_score;
	cord piece;
	moves possible_moves;
	int no_more_moves = TRUE;
	int no_scoring_king = TRUE;
	int no_other_king = TRUE;
	int num_of_moves;
	int player_score = 0;
	int other_player_score = 0;
	int is_scoring_piece;
	int is_scoring_checked = is_king_checked(current_player, set->board);
	int is_other_checked = is_king_checked(other_player(current_player), set->board);

	for (int i = 0; i < BOARD_SIZE; i++){
		for (int j = 0; j < BOARD_SIZE; j++){
			piece.x = i;
			piece.y = j;
			char cur_piece = board_piece(set->board, piece);
			if (cur_piece == EMPTY)
				continue;

			int piece_color = which_color(cur_piece);
			is_scoring_piece = (piece_color == scoring_player);

			int piece_score = get_piece_score(cur_piece);
			if (piece_score == KING_SCORE) {
				no_scoring_king = (no_scoring_king && !is_scoring_piece);
				no_other_king = (no_other_king && is_scoring_piece);
			}
			if (is_scoring_piece)
				player_score += piece_score;
			else //piece_color is other player's color
				other_player_score += piece_score;

			// we have to check that current_player has at least one piece that
			// can move, otherwise current_player loses or it's a tie.
			if (no_more_moves && (piece_color == current_player)) {
				// check walking move for piece. checking move of distance 1 takes only O(1) time if
				// player cannot move and O(n) if player can move (creating new board. occurs at most once)
				// is enough for both king & man  (if king cannot move 1 he cannot move 2) 
				possible_moves = get_simple_moves(set, piece);
				num_of_moves = possible_moves.len;
				free_list(&possible_moves, &free);
				if (num_of_moves == -1) //there was an error, return an error score
					return SCORE_ERROR;
				// once one of the current_player can move, they do not lose,
				// no need to preform this check again.
				if (num_of_moves > 0) {
					no_more_moves = FALSE;
				}
			}
		}
	}
	// current_player cannot play.
	if (no_more_moves) {
		if (is_scoring_checked) // checkmate
			total_score = (scoring_player == current_player) ? LOSE_SCORE : WIN_SCORE;
		else // tie
			total_score = is_best ? 0 : TIE_SCORE; // in best difficulty: 0, otherwise: better only than LOSE_SCORE
	}
	// scoring_player's king has ceased to be
	else if (no_scoring_king)
		total_score = LOSE_SCORE;
	// other player's king is pushing up the daisies
	else if (no_other_king)
		total_score = WIN_SCORE;

	//RELEVANT ONLY FOR best DIFFICULTY!
	else if (is_best && is_scoring_checked) {
		if (is_scoring_checked)
			return LOSE_SCORE + 42;
		else if (is_other_checked)
			return WIN_SCORE - 42;
	}

	// both players' kings are alive and pining for the fjords
	else
		total_score = player_score - other_player_score;
	return total_score;
}
Ejemplo n.º 17
0
// return the score of the best move found for a board
// the best square is stored in *square
// note - recursive function, searches nodes and childs
int best_move(board_type board, char player, int *square, int move_num, int alpha, int beta) {
    int best_square = -1;
    int moves = 0;
    int i;
    move_heuristic_type move_heuristic[SQUARES]; // an array of 9 heuristc structs
    
    total_nodes++; // times we call best_move
    
    // we find calculate the heuristic value of each move
    // and sort the structs in descending order
    // this way, we speed things up a bit
    for(i=0; i<SQUARES; i++) {
        // if the square is available for play
        if(board[i] == empty) {
            int heuristic;
            int j;
            
            play(board, i, player); // we play the empty square
            heuristic = evaluate(board, player); // we get the heuristic value
            play(board, i, empty); // we reverse the play
            
            // now we must sort the picked up structs in descending order
            for(j = moves-1; j>=0 && move_heuristic[j].heuristic < heuristic; j--) {
                move_heuristic[j+1].heuristic = move_heuristic[j].heuristic;
                move_heuristic[j+1].square = move_heuristic[j].square;
            }
            move_heuristic[j+1].heuristic = heuristic;
            move_heuristic[j+1].square = i;
            moves++;
        }
        // we can store the structs and use qsort here instead.
    }
    
    for(i=0; i<moves; i++) {
        int score;
        int sq = move_heuristic[i].square;
        char w;
        
        // we make a move and get the score
        play(board, sq, player);
        
        w = winner(board);
        if(w == 'X')
            score = (max_moves + 1) - move_num;
        else if(w == 'O')
            score = move_num - (max_moves + 1);
        else if(w == 'T')
            score = 0;
        else // haven't finished board
            score = best_move(board, other_player(player), square, move_num + 1, alpha, beta); // we recurse
        
        // reverse the play
        play(board, sq, empty);
        
        // now we prune alpha-beta
        if(player == 'X') {
            if(score >= beta) { // cut off
                *square = sq;
                return score;
            } else if(score > alpha) { // we found a better alpha (alpha only increases)
                alpha = score;
                best_square = sq;
            }
        } else {
            if(score <= alpha) { // cut off
                *square = sq;
                return score;
            } else if(score < beta) { // we found that oponent has a best worse beta (beta only decreases)
                beta = score;
                best_square = sq;
            }
        }
    }
    
    *square = best_square;
    if(player == 'X')
        return alpha;
    else
        return beta;
}
Ejemplo n.º 18
0
Move AIPlayer_fork::alpha_beta(GameBoard* game, int lookahead, int alpha, int beta, int player)
{
    concurrent_vector<Move> all_moves = concurrent_get_all_moves(game, player);
    //cout << "Moves are: " << endl;
    //cout << m.x +1  << ", " << m.y + 1 << " Score: " << m.score << endl;
    if (all_moves.empty())
        return Move(-1, -1, maximizing_player(player) * 35);
    if (lookahead == 0) {
        //return heuristic value of previous player
        if (!is_maximizing(player)) {
            Move temp = *(std::max_element(all_moves.begin(), all_moves.end(), [](Move m1, Move m2) {
                return m1.score < m2.score;
            }));
            //cout << "return: "<< temp.x +1  << ", " << temp.y + 1 << " Score: " << temp.score << endl;
            return temp;
        }

        else {
            Move temp =  *(std::min_element(all_moves.begin(), all_moves.end(), [](Move m1, Move m2) {
                return m1.score < m2.score;
            }));
            //cout << "return: "<< temp.x +1  << ", " << temp.y + 1 << " Score: " << temp.score << endl;
            return temp;
        }
    }
    Move return_move;
    if (is_maximizing(player)) {

        task_group g;
        for (unsigned int i = 0; i < all_moves.size(); i++) {
            g.run([=, &all_moves, &return_move, &alpha, & beta] {
                GameBoard temp_board(game);
                temp_board.make_move(all_moves[i].x, all_moves[i].y, player);
                Move temp_move;
                temp_move = alpha_beta(&temp_board, lookahead - 1, alpha, beta, other_player(player));
                if (temp_move.score > alpha) {
                    return_move = all_moves[i];
                    alpha = temp_move.score;
                }
                if (alpha >= beta) {
                    //g.cancel();
                }
            });
        }
        g.wait();
        return return_move;
    } else {
        task_group g;
        for (unsigned int i = 0; i < all_moves.size(); i++) {
            g.run([=, &all_moves, &return_move, &alpha, &beta] {
                GameBoard temp_board(game);
                temp_board.make_move(all_moves[i].x, all_moves[i].y, player);
                Move temp_move;
                temp_move = alpha_beta(&temp_board, lookahead - 1, alpha, beta, other_player(player));

                if (temp_move.score < beta) {
                    beta = temp_move.score;
                    return_move = all_moves[i];
                }
                if (alpha >= beta) {
                    //g.cancel();
                }
            });
        }
        g.wait();
        return return_move;
    }
}