Minimax cho Bomberman


11

Tôi đang phát triển bản sao của trò chơi Bomberman và tôi đang thử nghiệm các loại AI khác nhau. Đầu tiên tôi sử dụng tìm kiếm trong không gian trạng thái với A * và bây giờ tôi muốn thử cách tiếp cận khác với thuật toán Minimax. Vấn đề của tôi là mỗi bài viết minimax tôi tìm thấy người chơi giả định thay thế. Nhưng trong Bomberman, mọi người chơi đều thực hiện một số hành động cùng một lúc. Tôi nghĩ rằng tôi có thể tạo ra tất cả các trạng thái có thể cho một tích tắc trò chơi, nhưng với bốn người chơi và 5 hành động cơ bản (4 lần di chuyển và đặt bom), nó mang lại 5 ^ 4 trạng thái ở cấp độ đầu tiên của cây trò chơi. Giá trị đó sẽ tăng theo cấp số nhân với mọi cấp độ tiếp theo. Tui bỏ lỡ điều gì vậy? Có cách nào để thực hiện nó hay tôi nên sử dụng thuật toán hoàn toàn khác nhau? Cảm ơn vì những gợi ý


1
Mặc dù điều này hơi lạc đề, nhưng một điều tôi thích làm với AI là sử dụng các mục tiêu hoặc tính cách cho AI. Nó có thể là những thứ như tích trữ sức mạnh, không gây hấn, tìm cách trả thù, vội vàng, v.v ... Với những mục tiêu như thế, bạn có thể nói đại khái là bạn nên di chuyển theo hướng nào và chỉ thả một quả bom nếu nó tiến tới mục tiêu của bạn (nếu nó gần hợp lý với một người chơi bạn đang săn hoặc một khối bạn muốn phá hủy).
Benjamin Danger Johnson

2
Vâng, bạn đang thiếu một vài điều, nhưng bạn sẽ không cảm ơn tôi vì đã chỉ ra chúng vì chúng làm cho nó tồi tệ hơn. Không có 5 hành động cơ bản. Một số hình vuông có 5 "di chuyển" (4 hướng và đứng yên); những người khác có 3 (vì họ bị chặn theo hai hướng); trung bình là 4. Nhưng bạn có thể thả một quả bom trong khi chạy , vì vậy trung bình hệ số phân nhánh là 8. Và ai đó có sức mạnh tốc độ cao có thể phù hợp với nhiều di chuyển hơn, đẩy mạnh hệ số phân nhánh của họ.
Peter Taylor

Tôi đã cho bạn câu trả lời trong câu hỏi của bạn bằng cách sử dụng tìm kiếm cây monte carlo.
SDwarf

Minimax đơn giản là không hữu ích trong một tình huống có nhiều lựa chọn như Bomberman. Bạn sẽ cạn kiệt khả năng tìm kiếm trước khi đi đủ xa để xem liệu một động thái có hợp lý hay không.
Loren Pechtel

Câu trả lời:


8

Các trò chơi Chiến lược thời gian thực như người ném bom có ​​một thời gian khó khăn với AI. Bạn muốn nó thông minh, nhưng đồng thời nó không thể hoàn hảo.

Nếu AI hoàn hảo, người chơi của bạn sẽ thất vọng. Hoặc bởi vì họ luôn thua hoặc bạn nhận được .3 khung hình mỗi giây.

Nếu nó không đủ thông minh, người chơi của bạn sẽ chán.

Đề nghị của tôi là có hai chức năng AI, một chức năng xác định AI sẽ đi đâu, chức năng còn lại sẽ xác định thời điểm tốt nhất để thả bom. Bạn có thể sử dụng những thứ như dự đoán chuyển động để xác định xem kẻ thù đang di chuyển đến một điểm sẽ nguy hiểm nếu bom rơi ở vị trí hiện tại.

Tùy thuộc vào độ khó, bạn có thể sửa đổi các chức năng này để cải thiện hoặc giảm độ khó.


2
Thời gian, sự thất vọng và buồn chán không phải là vấn đề. Tôi đang viết luận án cử nhân về cách tiếp cận AI khác nhau trong Bomberman và so sánh chúng. Vì vậy, nếu nó là hoàn hảo tốt hơn của nó. Tôi đang bị mắc kẹt với minimax đó ngay bây giờ
Billda

1
Vấn đề bạn sẽ gặp trong thuật toán minimax là thời gian xử lý. Bạn sẽ cần theo dõi tất cả các hành động của kẻ thù và xác định lối chơi của chúng và lối chơi phản công của bạn. Có vẻ như bạn đã nhận thức được điều này, nhưng đây có thể là một nhiệm vụ khá khó khăn đối với một trò chơi thời gian thực mà không làm chậm trò chơi. Thay vì xây dựng một cây chơi, bạn sẽ cần xác định hành động của mình trong thời gian thực, có thể xây dựng một thuật toán học máy trở nên tốt hơn khi chơi nhiều hơn?
UnderscoreZero

4

Như bạn đã nhận thấy, Bomberman quá phức tạp để được mô phỏng như một trò chơi theo lượt. Ngoại suy bất kỳ quyết định riêng nào có thể cộng với mọi quyết định có thể có của mọi người chơi khác chỉ không thành công.

Thay vào đó, bạn nên sử dụng một cách tiếp cận chiến lược hơn.

Bạn nên tự hỏi: Làm thế nào để một người chơi đưa ra quyết định trong khi chơi bomberman? Thông thường, người chơi nên tuân theo bốn ưu tiên cơ bản:

  1. tránh các khu vực nổ bom
  2. đặt bom để những người khác không thể tránh khu vực nổ của họ
  3. thu thập sức mạnh
  4. đặt bom để nổ tung đá

Ưu tiên đầu tiên có thể được thực hiện bằng cách tạo ra một "bản đồ nguy hiểm". Khi đặt bom, tất cả các ô được bao phủ bởi nó phải được đánh dấu là "nguy hiểm". Bom phát nổ càng sớm (giữ các phản ứng dây chuyền trong tâm trí!), Mức độ nguy hiểm càng cao. Bất cứ khi nào AI thông báo rằng nó đang ở trên một lĩnh vực có độ nguy hiểm cao, nó sẽ di chuyển đi. Khi nó vẽ một đường dẫn (vì bất kỳ lý do gì) các trường có mức độ nguy hiểm cao nên tránh (có thể được thực hiện bằng cách thêm một cách giả tạo một chi phí đường dẫn cao hơn cho chúng).

Tính toán bản đồ nguy hiểm có thể được tăng cường hơn nữa để bảo vệ AI khỏi các quyết định ngu ngốc (như đi vào các khu vực khó thoát khỏi khi có người chơi khác ở gần).

Điều này đã tạo ra một AI phòng thủ hợp lý. Vậy hành vi phạm tội thì sao?

Khi AI nhận ra rằng nó an toàn một cách hợp lý ngay bây giờ, nó nên lập kế hoạch điều động tấn công: Nó nên xem xét làm thế nào nó có thể tăng bản đồ nguy hiểm xung quanh những người chơi khác bằng cách đặt bom. Khi chọn một vị trí để đặt bom, nó nên chọn những vị trí gần để nó không phải di chuyển quá xa. Nó cũng nên bỏ qua các vị trí đặt bom khi bản đồ nguy hiểm dẫn đến không cho phép một lối thoát hợp lý.


Kinh nghiệm hạn chế của tôi khi chơi nó là bạn thường phải đặt nhiều quả bom để tiêu diệt đối thủ có năng lực - một chiến lược cần phải cân nhắc điều này. Tôi đã chơi với AI với chiến lược xấp xỉ của bạn, chúng khá kém hiệu quả trong việc giết bạn trừ khi bạn có thể bị dồn vào chân tường.
Loren Pechtel

4

Tôi nghĩ rằng tôi có thể tạo ra tất cả các trạng thái có thể cho một tích tắc trò chơi, nhưng với bốn người chơi và 5 hành động cơ bản (4 lần di chuyển và đặt bom), nó mang lại 5 ^ 4 trạng thái ở cấp độ đầu tiên của cây trò chơi.

Chính xác! Bạn cần tìm kiếm tất cả 5 ^ 4 (hoặc thậm chí 6 ^ 4, vì bạn có thể đi bộ theo 4 hướng, dừng lại và "đặt bom"?) Cho mỗi lần đánh dấu trò chơi. NHƯNG, khi một người chơi đã quyết định di chuyển, phải mất một thời gian cho đến khi việc di chuyển được thực hiện (ví dụ: 10 tích tắc trò chơi). Trong giai đoạn này số lượng khả năng giảm.

Giá trị đó sẽ tăng theo cấp số nhân với mọi cấp độ tiếp theo. Tui bỏ lỡ điều gì vậy? Có cách nào để thực hiện nó hay tôi nên sử dụng thuật toán hoàn toàn khác nhau?

Bạn có thể sử dụng Bảng Hash để chỉ tính toán trạng thái trò chơi "phụ" trong cùng một lần. Hãy tưởng tượng người chơi A đi lên và xuống, trong khi tất cả những người chơi khác "chờ", bạn kết thúc trong cùng một trạng thái trò chơi. Nó giống như "trái phải" hoặc "phải trái". Cũng di chuyển kết quả "lên-sau-trái" và "trái-sau-lên" trong cùng một trạng thái. Sử dụng Bảng băm, bạn có thể "sử dụng lại" điểm được tính cho trạng thái trò chơi đã được đánh giá. Điều này làm giảm tốc độ tăng trưởng khá nhiều. Về mặt toán học, nó làm giảm cơ sở của hàm tăng trưởng theo cấp số nhân của bạn. Để có được ý tưởng về mức độ giảm độ phức tạp, chúng ta hãy xem xét các động tác có thể chỉ cho một người chơi so với các vị trí có thể tiếp cận trên bản đồ (= các trạng thái trò chơi khác nhau) nếu người chơi chỉ có thể di chuyển lên / xuống / trái / phải / dừng .

độ sâu 1: 5 di chuyển, 5 trạng thái khác nhau, 5 trạng thái bổ sung cho đệ quy này

độ sâu 2: 25 di chuyển, 13 trạng thái khác nhau, 8 trạng thái bổ sung cho đệ quy này

độ sâu 3: 6125 di chuyển, 25 trạng thái khác nhau, 12 trạng thái bổ sung cho đệ quy này

Để hình dung điều đó, hãy tự trả lời: những trường nào trên bản đồ có thể đạt được bằng một lần di chuyển, hai lần di chuyển, ba lần di chuyển. Câu trả lời là: Tất cả các trường có khoảng cách tối đa = 1, 2 hoặc 3 từ vị trí bắt đầu.

Khi sử dụng HashTable, bạn chỉ phải đánh giá từng trạng thái trò chơi có thể tiếp cận (trong ví dụ 25 của chúng tôi ở độ sâu 3) một lần. Trong khi không có HashTable, bạn cần đánh giá chúng nhiều lần, điều đó có nghĩa là 6125 đánh giá thay vì 25 ở cấp độ sâu 3. Tốt nhất: Khi bạn đã tính một mục HashTable, bạn có thể sử dụng lại trong các bước sau ...

Bạn cũng có thể sử dụng các cây con "cắt" tăng cường độ sâu và cắt tỉa alpha-beta mà không đáng để tìm kiếm sâu hơn. Đối với cờ vua, điều này làm giảm số lượng nút tìm kiếm xuống còn khoảng 1%. Giới thiệu ngắn về cách cắt tỉa alpha-beta có thể được tìm thấy dưới dạng video tại đây: http://www.teachingtree.co/cs/watch?concept_name=Alpha-beta+Pruning

Một khởi đầu tốt cho các nghiên cứu tiếp theo là http://chessprogramming.wikispaces.com/Search . Trang này có liên quan đến cờ vua, nhưng các thuật toán tìm kiếm và tối ưu hóa hoàn toàn giống nhau.

Một thuật toán AI (nhưng phức tạp) khác - sẽ phù hợp hơn với trò chơi - là "Học khác biệt tạm thời".

Trân trọng

Stefan

Tái bút: Nếu bạn giảm số lượng trạng thái trò chơi có thể có (ví dụ kích thước bản đồ rất nhỏ, chỉ một quả bom cho mỗi người chơi, không có gì khác), có thể tính toán trước một đánh giá cho tất cả các trạng thái trò chơi.

--biên tập--

Bạn cũng có thể sử dụng kết quả tính toán ngoại tuyến của các tính toán minimax để huấn luyện mạng nơ ron. Hoặc bạn có thể sử dụng chúng để đánh giá / so sánh các chiến lược được thực hiện bằng tay. Ví dụ, bạn có thể thực hiện một số "tính cách" được đề xuất và một số phương pháp phỏng đoán phát hiện, trong đó tình huống nào là chiến lược tốt. Do đó, bạn nên "phân loại" các tình huống (ví dụ: trạng thái trò chơi). Điều này cũng có thể được xử lý bởi một mạng nơ-ron thần kinh: Huấn luyện một mạng nơ-ron thần kinh để dự đoán chiến lược mã hóa nào đang chơi tốt nhất trong tình huống hiện tại và thực hiện nó. Điều này sẽ tạo ra các quyết định thời gian thực cực kỳ tốt cho một trò chơi thực sự. Tốt hơn nhiều so với tìm kiếm giới hạn độ sâu thấp có thể đạt được bằng cách khác, vì việc tính toán ngoại tuyến mất bao lâu (chúng ở trước trò chơi).

- chỉnh sửa số 2 -

Nếu bạn chỉ tính toán lại các bước di chuyển tốt nhất của mình sau mỗi 1 giây, bạn cũng có thể cố gắng thực hiện các kế hoạch cấp cao hơn. Ý tôi là gì? Bạn biết có bao nhiêu động tác bạn có thể làm trong 1 giây. Vì vậy, bạn có thể lập danh sách các vị trí có thể tiếp cận (ví dụ: nếu đây là 3 lần di chuyển trong 1 giây, bạn sẽ có 25 vị trí có thể tiếp cận). Sau đó, bạn có thể lên kế hoạch như: đi đến "vị trí x và đặt bom". Như một số người khác đề nghị bạn có thể tạo bản đồ "nguy hiểm", được sử dụng cho thuật toán định tuyến (làm thế nào để đi đến vị trí x? Nên chọn đường dẫn nào [có một số biến thể có thể xảy ra trong hầu hết các trường hợp]). Điều này ít tiêu tốn bộ nhớ hơn so với HashTable khổng lồ, nhưng tạo ra kết quả ít tối ưu hơn. Nhưng vì nó sử dụng ít bộ nhớ hơn nên nó có thể nhanh hơn do hiệu ứng bộ đệm (sử dụng tốt hơn bộ nhớ đệm L1 / L2 của bạn).

BỔ SUNG: Bạn có thể thực hiện các tìm kiếm trước chỉ chứa các di chuyển cho mỗi người chơi để sắp xếp các biến thể dẫn đến mất. Do đó, đưa tất cả những người chơi khác ra khỏi trò chơi ... Lưu trữ những kết hợp mà mỗi người chơi có thể chọn mà không mất. Nếu chỉ có các bước di chuyển bị mất, hãy tìm kiếm các kết hợp di chuyển mà người chơi vẫn sống lâu nhất. Để lưu trữ / xử lý loại cấu trúc cây này, bạn nên sử dụng một mảng với các con trỏ chỉ mục như thế này:

class Gamestate {
  int value;
  int bestmove;
  int moves[5];
};

#define MAX 1000000
Gamestate[MAX] tree;

int rootindex = 0;
int nextfree = 1;

Mỗi trạng thái có một "giá trị" đánh giá và liên kết đến các Gamestates tiếp theo khi di chuyển (0 = stop, 1 = up, 2 = right, 3 = down, 4 = left) bằng cách lưu trữ chỉ mục mảng trong "cây" trong di chuyển [0 ] để di chuyển [4]. Để xây dựng cây của bạn một cách đệ quy, nó có thể trông như thế này:

const int dx[5] = { 0,  0, 1, 0, -1 };
const int dy[5] = { 0, -1, 0, 1,  0 };

int search(int x, int y, int current_state, int depth_left) {
  // TODO: simulate bombs here...
  if (died) return RESULT_DEAD;

  if (depth_left == 0) {
    return estimate_result();
  }

  int bestresult = RESULT_DEAD;

  for(int m=0; m<5; ++m) {
    int nx = x + dx[m];
    int ny = y + dy[m];
    if (m == 0 || is_map_free(nx,ny)) {
      int newstateindex = nextfree;
      tree[current_state].move[m] = newstateindex ;
      ++nextfree;

      if (newstateindex >= MAX) { 
        // ERROR-MESSAGE!!!
      }

      do_move(m, &undodata);
      int result = search(nx, ny, newstateindex, depth_left-1);
      undo_move(undodata);

      if (result == RESULT_DEAD) {
        tree[current_state].move[m] = -1; // cut subtree...
      }

      if (result > bestresult) {
        bestresult = result;
        tree[current_state].bestmove = m;
      }
    }
  }

  return bestresult;
}

Kiểu cấu trúc cây này nhanh hơn nhiều, vì bộ nhớ phân bổ động rất chậm! Nhưng, việc lưu trữ cây tìm kiếm cũng khá chậm ... Vì vậy, đây là một nguồn cảm hứng nhiều hơn.


0

Nó sẽ giúp để tưởng tượng rằng tất cả mọi người thay phiên nhau?

Về mặt kỹ thuật, trong hệ thống cơ bản, chúng thực sự làm được, nhưng vì mọi thứ được xen kẽ và chồng chéo, chúng dường như đang chạy đồng thời.

Cũng nên nhớ rằng bạn không phải chạy AI sau mỗi khung hình hoạt hình. Nhiều trò chơi thông thường thành công chỉ chạy thuật toán AI mỗi giây một lần hoặc lâu hơn, cung cấp cho các nhân vật do AI kiểm soát thông tin về nơi họ sẽ đến hoặc những gì họ phải làm, sau đó thông tin đó được sử dụng để kiểm soát các nhân vật AI trên các khung khác.


Tôi không tính toán AI từng khung hình hoạt hình mà mỗi giây. Mỗi giây, môi trường của tôi thu thập hành động của tất cả người chơi và gửi cho họ trạng thái cập nhật mới.
Billda
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.