void *worker(void *arg) { struct board_t w_board; enum player_t player; int depth, col, type; double result; while (1) { MPI_Recv(&type, 1, MPI_INT, MPI_ANY_SOURCE, REQUEST, MPI_COMM_WORLD, MPI_STATUS_IGNORE); if (type == WORKER_QUIT) { break; } else if (type == WORKER_START) { MPI_Recv((char *)&w_board, sizeof(board), MPI_CHAR, MPI_ANY_SOURCE, REQUEST, MPI_COMM_WORLD, MPI_STATUS_IGNORE); MPI_Recv((char *)&player, sizeof(player), MPI_CHAR, MPI_ANY_SOURCE, REQUEST, MPI_COMM_WORLD, MPI_STATUS_IGNORE); MPI_Recv(&col, 1, MPI_INT, MPI_ANY_SOURCE, REQUEST, MPI_COMM_WORLD, MPI_STATUS_IGNORE); MPI_Recv(&depth, 1, MPI_INT, MPI_ANY_SOURCE, REQUEST, MPI_COMM_WORLD, MPI_STATUS_IGNORE); BoardMove(&w_board, col, player); result = EvaluateBoard(&w_board, player, col, depth); MPI_Send(&result, 1, MPI_DOUBLE, 0, col, MPI_COMM_WORLD); } } return NULL; }
float alphaBetaMax(BNTBoard board, float alpha, float beta, float depthleft, BNTPlayer player) { if (depthleft == 0 || IsGameEnd(board)) return EvaluateBoard(board, player); for (int x = 0; x < BOARD_SIZE; ++x) { for (int y = 0; y < BOARD_SIZE; ++y) { if (board[x][y] == BNTPlayerNone) { board[x][y] = NextPlayer(board); float score = alphaBetaMin(board, alpha, beta, depthleft - 1, player); board[x][y] = BNTPlayerNone; if (score >= beta) { return beta; } if (score > alpha) { alpha = score; } } } } return alpha; }
double EvaluateBoard(struct board_t *current, enum player_t last, int last_col, int depth) { double result, total; enum player_t now; int all_win = 1, all_lose = 1; int moves, col; if (BoardIsGameOver(current, last_col)) { if (last == COMPUTER) { return 1; } else { return -1; } } if (depth == 0) { return 0; } if (last == COMPUTER) { now = HUMAN; } else { now = COMPUTER; } total = 0; moves = 0; for (col = 0; col < BOARD_COLS; ++col) { if (BoardIsValidMove(current, col)) { moves ++; BoardMove(current, col, now); result = EvaluateBoard(current, now, col, depth - 1); BoardUndoMove(current, col); if (result > -1) all_lose = 0; if (result < 1) all_win = 0; if (result == 1 && now == COMPUTER) return 1; if (result == -1 && now == HUMAN) return -1; total += result; } } if (all_win) return 1; if (all_lose) return -1; return total / moves; }
int EvaluateMove(Board& board, int alpha, int beta, int depth, bool maximizing) { if (board.kingDead) { return maximizing ? -999111 : 999111; } if (depth == 0) { return EvaluateBoard(board); } vector<Move> possibleMoves; possibleMoves.reserve(100); GenerateAll(board, possibleMoves); int returnVal; if (maximizing) { for (Move move : possibleMoves) { board.MakeMove(move); alpha = max(alpha, EvaluateMove(board, alpha, beta, depth - 1, false)); if (beta <= alpha) { board.UndoMove(); break; } board.UndoMove(); } returnVal = alpha; } else { for (Move move : possibleMoves) { board.MakeMove(move); beta = min(beta, EvaluateMove(board, alpha, beta, depth - 1, true)); if (beta <= alpha) { board.UndoMove(); break; } board.UndoMove(); } returnVal = beta; } return returnVal; }
float alphabeta(BNTBoard board, int depth, float alpha, float beta, BNTPlayer player) { if (depth == 0 || IsGameEnd(board)) return EvaluateBoard(board, player) * (player == BNTPlayerX ? 1 : -1); if (player == BNTPlayerX) { for (int x = 0; x < BOARD_SIZE; ++x) { for (int y = 0; y < BOARD_SIZE; ++y) { if (board[x][y] == BNTPlayerNone) { board[x][y] = player; alpha = DEPTH_PENALTY * MAX(alpha, alphabeta(board, depth-1, alpha, beta, OppositePlayer(player))); board[x][y] = BNTPlayerNone; if (beta <= alpha) { break;/* Beta cut-off */ } } } } return alpha; } else { for (int x = 0; x < BOARD_SIZE; ++x) { for (int y = 0; y < BOARD_SIZE; ++y) { if (board[x][y] == BNTPlayerNone) { board[x][y] = player; beta = DEPTH_PENALTY * MIN(beta, alphabeta(board, depth-1, alpha, beta, OppositePlayer(player))); board[x][y] = BNTPlayerNone; if (beta <= alpha) { break;/* Alpha cut-off */ } } } } return beta; } }
float alphaBetaMin(BNTBoard board, float alpha, float beta, float depthleft, BNTPlayer player) { if (depthleft == 0 || IsGameEnd(board)) return -1 * EvaluateBoard(board, player); for (int x = 0; x < BOARD_SIZE; ++x) { for (int y = 0; y < BOARD_SIZE; ++y) { if (board[x][y] == BNTPlayerNone) { board[x][y] = NextPlayer(board); float score = alphaBetaMax(board, alpha, beta, depthleft - 1, player); board[x][y] = BNTPlayerNone; if(score <= alpha) return alpha; // fail hard alpha-cutoff if(score < beta) beta = score; // beta acts like min in MiniMax } } } return beta; }