void add_move(Pos piece, Pos* dests, int dests_num){ if (moves == NULL){ moves = malloc(sizeof(Move)); moves_head = moves; } else if (moves->captures < dests_num && abs(piece.row - dests->row) != 1){ clear_old_moves(moves_head); moves = malloc(sizeof(Move)); moves_head = moves; } else if ((moves->captures == 0 && abs(piece.row - dests->row) == 1) || (moves->captures == dests_num && abs(piece.row - dests->row) != 1)){ moves->next = malloc(sizeof(Move)); moves = moves->next; } else return; moves->piece.col = piece.col; moves->piece.row = piece.row; moves->dest = malloc(sizeof(Pos) * dests_num); for (int i = 0; i < dests_num; i++){ moves->dest[i].row = dests[i].row; moves->dest[i].col = dests[i].col; } if (abs(piece.row - dests->row) == 1) moves->captures = 0; else moves->captures = dests_num; moves->next = NULL; }
void clear_old_moves(Move* head){ if (head != NULL){ clear_old_moves(head->next); free(head->dest); free(head); } }
// adds a move to the list, while making sure it contains valid moves only void add_move(Pos piece, Pos* dests, int move_captures){ if (moves == NULL){ moves = malloc(sizeof(Move)); moves_head = moves; } else if (moves->captures < move_captures && abs(piece.row - dests->row) != 1){ clear_old_moves(moves_head); moves = malloc(sizeof(Move)); moves_head = moves; } else if ((moves->captures == 0 && abs(piece.row - dests->row) == 1) || (moves->captures == move_captures && abs(piece.row - dests->row) != 1)){ moves->next = malloc(sizeof(Move)); moves = moves->next; } else return; moves->piece.col = piece.col; moves->piece.row = piece.row; if (move_captures == 0){ moves->dest = malloc(sizeof(Pos)); moves->dest->row = dests->row; moves->dest->col = dests->col; } else{ moves->dest = malloc(sizeof(Pos) * move_captures); for (int i = 0; i < move_captures; i++){ moves->dest[i].row = dests[i].row; moves->dest[i].col = dests[i].col; } } moves->captures = move_captures; moves->next = NULL; }
int estimate_best_depth(char board[BOARD_SIZE][BOARD_SIZE], COLOR player){ int p_moves, op_moves, p_exp, op_exp, sum; int ret_depth = 0; clear_old_moves(moves_head); get_all_moves(board, !player); op_moves = count_moves_num(moves_head); clear_old_moves(moves_head); get_all_moves(board, player); p_moves = count_moves_num(moves_head); sum = op_moves + p_moves; p_exp = p_moves; op_exp = op_moves; while (sum < BOARD_LIMIT){ ret_depth++; op_exp *= op_moves; p_exp *= p_moves; sum = op_exp + p_exp; } return ret_depth; }
Move * get_all_moves(char board[BOARD_SIZE][BOARD_SIZE], COLOR player){ clear_old_moves(moves_head); Pos p; for (int i = 0; i < BOARD_SIZE; i++) for (int j = 0; j < BOARD_SIZE; j++) if (!is_opposite(player, board[i][j]) && board[i][j] != EMPTY){ p.row = j; p.col = i; if (is_king(board[i][j])) get_king_moves(board, player, p); else get_man_moves(board, player, p); } return moves_head; // need to handle man becoming kings }
// manages the computer's turn int computer_turn(char board[BOARD_SIZE][BOARD_SIZE],COLOR color){ curr_player = color; alpha_beta_minimax(board, color, 0, -100, 100); Move * move2do = best_move; int ret_val; if (move2do == NULL) ret_val = WIN_POS; else{ exc_move(board, move2do); printf("Computer: move "); print_move(move2do); print_board(board); ret_val = GAME_ON; } clear_old_moves(moves_head); return ret_val; }
// minimax recursive func, using alpha-beta pruning int alpha_beta_minimax(char board[BOARD_SIZE][BOARD_SIZE], COLOR player, int depth, int alpha, int beta){ Move* move_list = get_all_moves(board, player); Move* curr_move = move_list; if (depth == 0 && curr_move == NULL){ best_move = NULL; return -500; } if (curr_move == NULL && player != curr_player){ if (!is_check(board, !curr_player)) return -450; else return 500; } if (curr_move == NULL && player == curr_player){ if (!is_check(board, curr_player)) return 450; else return -500; } if (depth == minimax_depth || curr_move == NULL){ clear_old_moves(move_list); return calc_score(board, curr_player); } if (depth == 0){ best_move = curr_move; if (curr_move->next == NULL){ best_move->score = 500; return 500; } } char init_board[BOARD_SIZE][BOARD_SIZE]; duplicate_board(board, init_board); // MAX if (depth % 2 == 0){ while (curr_move != NULL){ exc_move(board, curr_move, player); curr_move->score = alpha_beta_minimax(board, (player == 0), depth + 1, alpha, beta); if (curr_move->score > alpha){ alpha = curr_move->score; if (depth == 0) best_move = curr_move; } if (alpha >= beta){ if (depth != 0) clear_old_moves(move_list); else moves_head = move_list; duplicate_board(init_board, board); return alpha; } curr_move = curr_move->next; duplicate_board(init_board, board); } if (depth != 0) clear_old_moves(move_list); else moves_head = move_list; return alpha; } // MIN else{ while (curr_move != NULL){ exc_move(board, curr_move, player); curr_move->score = alpha_beta_minimax(board, (player == 0), depth + 1, alpha, beta); if (curr_move->score < beta){ beta = curr_move->score; if (depth == 0) best_move = curr_move; } if (alpha >= beta){ if (depth != 0) clear_old_moves(move_list); else moves_head = move_list; duplicate_board(init_board, board); return beta; } curr_move = curr_move->next; duplicate_board(init_board, board); } if (depth != 0) clear_old_moves(move_list); else moves_head = move_list; return beta; } }
// manages the users turn, game state user input loop int user_turn(char board[BOARD_SIZE][BOARD_SIZE], COLOR color){ get_all_moves(board, color); if (moves_head == NULL) return WIN_POS; char *word1; char *command = NULL; Move* new_move = NULL; int ret_val; while (1){ printf(ENTER_YOUR_MOVE); if (new_move != NULL) clear_old_moves(new_move); new_move = malloc(sizeof(Move)); new_move->dest = malloc(sizeof(Pos) * 2 * BOARD_SIZE); new_move->next = NULL; if (command != NULL) free(command); command = input2str(stdin); word1 = strtok(command, " "); if (strcmp(word1, "quit") == 0){ ret_val = QUIT; break; } else if (strcmp(word1, "get_moves") == 0){ print_moves(moves_head); continue; } else if (strcmp(word1, "move") == 0){ char * piece_coor1 = strtok(NULL, " <,>"); char * piece_coor2 = strtok(NULL, " <,>"); new_move->piece.col = piece_coor1[0] - 'a'; new_move->piece.row = atoi(piece_coor2) - 1; if (!is_valid_pos(new_move->piece)){ printf(WRONG_POSITION); continue; } int i = 0; char * dest_coor1 = strtok(NULL, " <,>to"); char * dest_coor2 = strtok(NULL, " <,>to"); while (dest_coor1 != NULL){ new_move->dest[i].col = dest_coor1[0] - 'a'; new_move->dest[i].row = atoi(dest_coor2) - 1; if (!is_valid_pos(new_move->dest[i])){ i = -1; break; } i++; dest_coor1 = strtok(NULL, " <,>[]"); if (dest_coor1 != NULL) dest_coor2 = strtok(NULL, " <,>[]"); } if (i == -1){ printf(WRONG_POSITION); continue; } if (!is_valid_piece(board, new_move, color)){ printf(NO_DISC); continue; } new_move->dest = realloc(new_move->dest, sizeof(Pos) * i); new_move->captures = i; Move * move2do = is_valid_move(moves_head, new_move); if (move2do == NULL){ printf(ILLEGAL_MOVE); continue; } else{ exc_move(board, move2do); print_board(board); ret_val = GAME_ON; break; } } else printf(ILLEGAL_COMMAND); } free(command); clear_old_moves(new_move); clear_old_moves(moves_head); return ret_val; }