Мінімакс для Бомбермана


11

Я розвиваю клон гри Bomberman і експериментую з різними типами ШІ. Спочатку я використовував пошук через простір стану за допомогою A *, а тепер я хочу спробувати інший підхід з алгоритмом Minimax. Моя проблема полягає в тому, що кожна стаття про мінімакс, яку я знайшов, передбачає, що гравці чергуються. Але в Бомбермані кожен гравець одночасно робить якісь дії. Я думаю, що я міг генерувати всі можливі стани для однієї ігрової галочки, але з чотирма гравцями та 5 основними діями (4 ходи та місце бомби) це дає 5 ^ 4 стани на першому рівні ігрового дерева. Це значення буде зростати експоненціально з кожним наступним рівнем. Я щось пропускаю? Чи є якісь способи її реалізувати або я повинен використовувати зовсім інший алгоритм? Дякуємо за будь-які пропозиції


1
Хоча це трохи поза темою, одна річ мені подобається робити з ШІ - це використовувати цілі чи особистості для ШІ. Це можуть бути такі речі, як запаси живлення, неагресивні, шукати помсти, поспіху тощо. Завдяки таким цілям ви можете приблизно сказати, в якому напрямку ви повинні рухатись, і лише скинути бомбу, якщо вона спрямовує ваш прогрес до мети (якщо це досить близько до гравця, якого ви полюєте, або блоку, якого ви хочете знищити).
Бенджамін Дангер Джонсон

2
Так, вам не вистачає кількох речей, але ви не подякуєте мені за те, що вони вказали на них, тому що вони роблять це гірше. Немає 5 основних дій. Деякі квадрати мають 5 "ходів" (4 напрямки і залишаються нерухомими); інші мають 3 (оскільки вони заблоковані у двох напрямках); в середньому це 4. Але ви можете скинути бомбу під час бігу , тому в середньому коефіцієнт розгалуження дорівнює 8. А хтось із швидкісним джерелом живлення може вмістити більше рухів, ефективно підсилюючи свій розгалужуючий коефіцієнт.
Пітер Тейлор

Я дав вам відповідь на ваше запитання, використовуючи пошук дерева Монте Карло.
SDwarfs

Minimax просто не корисний у ситуації з такою кількістю виборів, як Bomberman. Ви будете виснажувати свою здатність до пошуку, перш ніж зайти досить далеко, щоб побачити, чи розумний хід чи ні.
Лорен Печтель

Відповіді:


8

Ігри про стратегію в реальному часі, такі як людина-бомбардувальник, мають складний час з AI. Ви хочете, щоб він був розумним, але в той же час він не може бути ідеальним.

Якщо AI ідеальний, ваші гравці будуть розчаровані. Або тому, що вони завжди втрачають, або ви отримуєте .3 кадри в секунду.

Якщо він недостатньо розумний, ваші гравці будуть нудьгувати.

Моя рекомендація - мати дві функції AI, одна визначає, куди йде ШІ, а інша визначає, коли найкраще скинути бомбу. Ви можете використовувати такі речі, як передбачення руху, щоб визначити, чи противник рухається до місця, яке буде небезпечним, якщо бомба буде скинута в поточне місце розташування.

Залежно від складності, ви можете змінити ці функції, щоб покращити або зменшити складність.


2
Час, розчарування та нудьга - це не проблема. Я пишу бакалаврську дисертацію про різні ІІ підходи в Бомбермані і порівнюю їх. Тож якщо воно ідеально, то краще. Я зараз застряг у цьому мінімаксі
Білда

1
Проблема, з якою ви зіткнетеся в алгоритмі minimax, - це час обробки. Вам потрібно буде відслідковувати всі дії противника та визначати їх стиль гри та стиль зустрічної гри. Здається, ви вже знаєте про це, але це може бути досить складним завданням для гри в режимі реального часу без уповільнення гри. Замість того, щоб будувати ігрове дерево, вам потрібно буде визначати свої дії в режимі реального часу, можливо, побудувати алгоритм машинного навчання, який стає кращим, чим більше він грає?
UnderscoreZero

4

Як ви помітили, Bomberman є занадто складним, щоб його змоделювати як гру покрокову гру. Екстраполяція будь-якого можливого власного рішення плюс кожне можливе рішення кожного іншого гравця просто не виходить.

Замість цього вам слід скористатися більш стратегічним підходом.

Ви повинні запитати себе: як гравець людини приймає рішення, граючи в бомбермен? Зазвичай гравцеві слід дотримуватися чотирьох основних пріоритетів:

  1. уникайте районів вибухів бомб
  2. розміщуйте бомби, щоб інші не могли уникнути своїх районів вибуху
  3. збирати бонуси
  4. ставити бомби, щоб підірвати скелі

Перший пріоритет можна виконати, створивши «карту небезпеки». Коли бомба розміщена, усі плитки, накриті нею, повинні бути позначені як "небезпечні". Чим швидше вибухне бомба (пам’ятайте про ланцюгові реакції!), Тим вище рівень небезпеки. Щоразу, коли ШІ помічає, що він знаходиться на полі з високою небезпекою, він повинен відійти. Коли він намічає шлях (з будь-якої причини), поля з високим рівнем небезпеки слід уникати (можна реалізувати, штучно додаючи до них більшу вартість шляху).

Розрахунок карти небезпеки можна додатково покращити, щоб захистити ШІ від дурних рішень (наприклад, в'їжджати в райони, з яких важко уникнути, коли інший гравець поруч).

Це вже повинно створити розумний захисний ШІ. То як щодо образи?

Коли AI зрозуміє, що зараз він досить безпечний, він повинен спланувати наступальні маневри: він повинен розглянути, як він може збільшити карту небезпеки навколо інших гравців, розмістивши самі бомби. Вибираючи місце для установки бомби, слід віддавати перевагу близьким місцям, тому не потрібно рухатись так далеко. Він також повинен нехтувати місцями бомб, коли отримана карта небезпеки не дозволяє отримати розумний шлях втечі.


Мій обмежений досвід його гри полягає в тому, що вам зазвичай доводиться розміщувати кілька бомб, щоб вбити компетентного супротивника. Я грав проти ІС приблизно з вашою стратегією, вони досить неефективні у вбивстві, якщо ви не зможете забитись.
Лорен Печтел

4

Я думаю, що я міг генерувати всі можливі стани для однієї ігрової галочки, але з чотирма гравцями та 5 основними діями (4 ходи та місце бомби) це дає 5 ^ 4 стани на першому рівні ігрового дерева.

Правильно! Вам потрібно шукати всі 5 ^ 4 (або навіть 6 ^ 4, оскільки ви можете ходити в 4-х напрямках, зупинятися і «ставити бомбу»?) Для кожної ігрової галочки. АЛЕ, коли гравець уже вирішив рухатись, потрібен певний час, поки хід не буде виконаний (наприклад, 10 ігрових тиків). У цей період кількість можливостей зменшується.

Це значення буде зростати експоненціально з кожним наступним рівнем. Я щось пропускаю? Чи є якісь способи її реалізувати або я повинен використовувати зовсім інший алгоритм?

Ви можете використовувати таблицю Hash-таблиць, щоб обчислити одне і те ж стан «піддерева» гри. Уявіть, що гравець А ходить вгору і вниз, а всі інші гравці "чекають", ви опинитеся в тому ж ігровому стані. Це те саме, що і для "ліво-право" або "право-ліво". Також переміщення "вгору-вліво" і "вліво-потім-вгору" призводить до того ж стану. Використовуючи хеш-таблицю, ви можете "повторно використовувати" обчислений бал для стану гри, який вже був оцінений. Це досить скорочує швидкість росту. Математично це зменшує основу вашої функції експоненціального росту. Щоб отримати уявлення про те, наскільки це зменшує складність, давайте подивимось на можливі рухи лише для одного гравця порівняно з доступними позиціями на карті (= різні стани гри), якщо гравець може просто рухатися вгору / вниз / вліво / вправо / стоп .

глибина 1: 5 рухів, 5 різних станів, 5 додаткових станів для цієї рекурсії

глибина 2: 25 рухів, 13 різних станів, 8 додаткових станів для цієї рекурсії

глибина 3: 6125 рухів, 25 різних станів, 12 додаткових станів для цієї рекурсії

Щоб візуалізувати це, відповідайте собі: до яких полів на карті можна дійти одним рухом, двома рухами, трьома рухами. Відповідь: Усі поля з максимальною відстані = 1, 2 або 3 від стартового положення.

При використанні HashTable вам потрібно лише один раз оцінити кожен доступний стан гри (у нашому прикладі 25 на глибині 3). Тоді як без HashTable вам потрібно оцінити їх кілька разів, що означало б 6125 оцінок замість 25 на рівні глибини 3. Найкраще. Після того, як ви обчислили запис HashTable, ви можете його повторно використовувати в наступних етапах часу ...

Ви також можете використовувати поглиблене поглиблення та обрізання альфа-бета-обрізки підрізів, які не варто шукати більш глибоко. Для шахів це зменшує кількість шуканих вузлів приблизно до 1%. Короткий вступ до обрізки альфа-бета можна знайти як відео тут: http://www.teachingtree.co/cs/watch?concept_name=Alpha-beta+Pruning

Гарним початком для подальших досліджень є http://chessprogramming.wikispaces.com/Search . Сторінка пов'язана з шахами, але алгоритми пошуку та оптимізації абсолютно однакові.

Інший (але складний) алгоритм ШІ - який би більше підходив до гри - це "Навчання часовій різниці".

З повагою

Стефан

PS: Якщо ви зменшите кількість можливих ігрових станів (наприклад, дуже малий розмір карти, лише одна бомба на гравця, нічого іншого), є шанс попередньо обчислити оцінку для всіх ігрових станів.

--edit--

Ви також можете використовувати розраховані в автономному режимі результати розрахунків мінімаксу для тренування нейронної мережі. Або ви можете використовувати їх для оцінки / порівняння стратегій, що реалізуються вручну. Наприклад, ви можете реалізувати деякі запропоновані "особистості" та деякі евристики, які виявляють, в яких ситуаціях стратегія є хорошою. Тому слід "класифікувати" ситуації (наприклад, стани гри). З цим може впоратися і нейрональна мережа: Навчіть нейронну мережу, щоб передбачити, яка із стратегій, кодованих рукою, найкраще грає в поточній ситуації та виконайте її. Це повинно дати надзвичайно хороші рішення в реальному часі для реальної гри. Набагато краще, ніж пошук з низькою глибиною, який можна досягти інакше, оскільки не має значення стільки часу, як тривати офлайн-обчислення (вони до гри).

- редагування №2 -

Якщо ви перераховуєте лише свої найкращі рухи кожні 1 секунду, ви також можете спробувати зробити більше планування вищого рівня. Що я маю на увазі під цим? Ви знаєте, скільки рухів ви можете зробити за 1 секунду. Таким чином, ви можете скласти список доступних позицій (наприклад, якщо це було б 3 ходи за 1 секунду, у вас було б 25 доступних позицій). Тоді ви могли б планувати так: перейдіть до "положення х і поставте бомбу". Як деякі інші запропонували, ви можете створити карту "небезпеки", яка використовується для алгоритму маршрутизації (як перейти до позиції x? Якому шляху слід віддати перевагу [можливі варіанти в більшості випадків]). Це менше споживає пам'ять у порівнянні з величезним HashTable, але дає менш оптимальні результати. Але оскільки він використовує менше пам'яті, він може бути швидшим через кешування ефектів (краще використовувати кеш пам'яті L1 / L2).

ДОПОМОГО: Ви можете робити попередній пошук, який містить лише ходи для одного гравця, щоб розібрати варіанти, які призводять до втрати. Тому вийміть із гри всіх інших гравців ... Зберігайте, які комбінації кожен гравець може вибрати, не програючи. Якщо є лише втрачені рухи, шукайте комбінації рухів, де гравець залишається живим найдовше. Щоб зберігати / обробляти такі структури дерев, ви повинні використовувати масив з такими покажчиками:

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

#define MAX 1000000
Gamestate[MAX] tree;

int rootindex = 0;
int nextfree = 1;

Кожен стан має оцінювальне "значення" та посилається на наступні Gamestates під час руху (0 = стоп, 1 = вгору, 2 = праворуч, 3 = вниз, 4 = ліворуч), зберігаючи індекс масиву в межах "дерева" в ходах [0 ] рухатися [4]. Для того щоб будувати дерево рекурсивно, це може виглядати приблизно так:

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;
}

Така структура дерева набагато швидша, оскільки динамічне розподілення пам’яті дійсно дуже повільне! Але зберігання дерева пошуку відбувається досить повільно ... Тож це більше натхнення.


0

Чи допомогло б уявити, що всі по черзі?

Технічно в базовій системі вони насправді є, але оскільки речі переплітаються і перекриваються, вони, здається, працюють одночасно.

Також пам’ятайте, що вам не потрібно запускати AI після кожного кадру анімації. Багато успішних казуальних ігор запускають алгоритм AI раз на секунду або близько того, надаючи символам, контрольованим AI, інформацію про те, куди вони повинні йти або що вони повинні робити, то ця інформація використовується для управління символами AI на інших кадрах.


Я не обчислюю AI не кожен кадр анімації, а кожну секунду. Щосекунди моє оточення збирає дії всіх гравців і надсилає їм новий оновлений стан.
Білда
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.