int get_score_func(gameState* state, piece board[BOARD_SIZE][BOARD_SIZE], int depth, move* user_move){ board_t tmp_board; copyStoS(tmp_board, board); int score; int colo_mult = 1; int best_depth = depth; // in case we are in const minimax depth mode makeMoveInPlace(state->board, user_move); if (state->turn == BLACK){ colo_mult = -1; } if (depth == 1){ score = scoreOfBoard(state)*colo_mult; } else{ state->turn = getEnemyColor(state->turn); if (depth == 5){ // need to decide what is the best depth best_depth = get_best_depth(state); } score = minimax(state, best_depth - 1, 0).value; state->turn = getEnemyColor(state->turn); } copyStoS(state->board, tmp_board); // update the state->board to the original board return score; }
/* 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; }
/*present the options of selecting depth for best_moves func and return the chosen the lise of the best_moves*/ itemMove* best_move_choise(SDL_Surface* screen){ int dep_chosen, depth; itemMove* all_moves = getMoves(state); itemMove* best_moves; dep_chosen = select_depth(screen); if (dep_chosen == -1){ quit = TRUE; destroyMoveList(all_moves); return NULL; } if (dep_chosen == 5){ depth = get_best_depth(state); } else{ depth = dep_chosen; } best_moves = get_best_moves(all_moves, state, state->board, depth); destroyMoveList(all_moves); return best_moves; }
/*function that perform the computer turn- returns 1 beacuse the computer always perform a move*/ int computer_turn_func(SDL_Surface* screen,itemMove* moves){ itemMove* head; move* computer_move; minimaxRes res; int i; if (minimax_depth == 5){ minimax_depth = get_best_depth(state); } res = minimax(state, minimax_depth, 1); head = moves; for (i = 0; i < res.index; i++){ head = head->next; } computer_move = &(head->move); makeMoveInPlace(state->board, computer_move); isCheckWithUpdate(state); update_gameState(state); COMPUTER_TURN = 0; USER_TURN = 1; return 1; }
void GameMinimaxDepth_ButtonClick(control* input) { // 1 if (strcmp(input->name, BUTTON1NAME) == 0) { if (curSettings->minimax_depth != 1) { curSettings->minimax_depth = 1; SwitchOffHighlightAllMinimaxDepths(); SwitchOnHighlightbyName(BUTTON1NAME); } } // 2 else if (strcmp(input->name, BUTTON2NAME) == 0) { if (curSettings->minimax_depth != 2) { curSettings->minimax_depth = 2; SwitchOffHighlightAllMinimaxDepths(); SwitchOnHighlightbyName(BUTTON2NAME); } } // 3 else if (strcmp(input->name, BUTTON3NAME) == 0) { if (curSettings->minimax_depth != 3) { curSettings->minimax_depth = 3; SwitchOffHighlightAllMinimaxDepths(); SwitchOnHighlightbyName(BUTTON3NAME); } } // 4 else if (strcmp(input->name, BUTTON4NAME) == 0) { if (curSettings->minimax_depth != 4) { curSettings->minimax_depth = 4; SwitchOffHighlightAllMinimaxDepths(); SwitchOnHighlightbyName(BUTTON4NAME); } } // Best else if (strcmp(input->name, BUTTONBESTNAME) == 0) { if (curSettings->minimax_depth != MAX_MINIMAX_DEPTH_POSSIBLE) { curSettings->minimax_depth = get_best_depth(board); SwitchOffHighlightAllMinimaxDepths(); SwitchOnHighlightbyName(BUTTONBESTNAME); } } if (-1 == HighlightBestMove(BLINKNUM, &error_global)) { guiQuit = -1; return; } // DrawTree if (-1 == FlipTree(&error_global)) { guiQuit = -1; return; } }