Алгоритм ИИ для игры "RaceTrack" - PullRequest
18 голосов
/ 06 июля 2011

Кто-нибудь знает (или может предложить) хороший алгоритм для ИИ для RaceTrack игры с карандашом?

, так как у вас есть 9 возможных вариантов на каждом шаге, и вам нужно смотреть как минимум на 6-10 шагов вперед, чтобы выбрать хорошую стратегию, брутфорс становится очень дорогим, даже если вы можете исключить некоторые варианты из-за пересечения с границей .

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

Ответы [ 8 ]

13 голосов
/ 06 июля 2011

Я сделал решатель C ++, который слишком длинный (187 строк), чтобы поместиться здесь удобно, поэтому вместо этого я поместил его в pastebin: http://pastebin.com/3G4dfTjR. Программа либо вычисляет оптимальное (минимально возможное количество ходов)) решение или сообщает, что ничего не возможно.

Использование

Запустите программу как racetrack startX startY goalX goalY [circleX circleY radius] .

В программе предполагается, что сетка 100x100 может содержать одно круговое препятствие, центр и радиус которого вы укажете.Вы должны дополнительно указать начальное местоположение автомобиля и местоположение одной цели.Хотя эти ограничения несколько ограничивающие, при взгляде на код должно быть очевидно, что они не ограничивают алгоритм в целом - вся соответствующая логика инкапсулирована в подпрограммах isMoveValid() и isGoalState(), поэтому, если кто-то можетНадоело реализовывать более общие версии этих подпрограмм (например, позволяя пользователю указывать битовую карту местоположений сетки и / или разрешать множественные местоположения целей), тогда это может быть включено без затруднений.

Единственное небольшое осложнение будет вполучить целевое местоположение, которое будет таким же (или близко, но «на другой стороне») от стартового местоположения, что вам нужно, если вы хотите, чтобы ваш трек был трассой.В этом случае, чтобы избежать того, чтобы решатель просто развернул автомобиль или сразу же остановился, вам нужно указать невидимую «стартовую линию» и изменить isMoveValid(), чтобы запретить «обратные» движения по этой линии.

Как это работает

Поскольку каждый шаг стоит ровно 1, можно использовать поиск в ширину в пространстве состояний 4D, чтобы найти оптимальное решение.Всякий раз, когда мы посещаем данное состояние s, которое состоит из 4-х кортежей (x, y, dx, dy), где dx и dy являются вектором скорости, который мы использовали для получения (x, y), мы рассматриваем все 9 состояний, которые мыможно добраться от с одним движением.Для любого такого состояния t, которое еще не было замечено, этот путь к t (то есть через s) гарантированно будет оптимальным, поскольку BFS всегда посещает узлы в порядке их минимального расстояния от корня.Всякий раз, когда мы определяем оптимальный путь для состояния, мы записываем состояние предшественника, позволяя в конце создать трассировку полного пути.

BFS проще и, следовательно, быстрее, чем алгоритм Дейкстры или A* поиск, которые являются более общими алгоритмами, которые позволяют перемещениям иметь различные затраты - гибкость, которая нам здесь не нужна.A * может быть быстрее, если существует несколько препятствий, мешающих его эвристике, но на каждом этапе ему нужно искать узел с минимальными затратами, что обычно выполняется с использованием кучи, тогда как для BFS узел с минимальными затратами всегда доступен вначало очереди.

Примеры

беговая дорожка секундомера 30 3 90 10

Starting at (30, 3).
Goal is (90, 10).
Grid size is 100*100 (W*H).
No obstacle.
11-step solution:
(90, 10) (dx=10, dy=4)
(80, 6) (dx=9, dy=3)
(71, 3) (dx=8, dy=2)
(63, 1) (dx=7, dy=1)
(56, 0) (dx=6, dy=0)
(50, 0) (dx=5, dy=0)
(45, 0) (dx=5, dy=0)
(40, 0) (dx=4, dy=0)
(36, 0) (dx=3, dy=-1)
(33, 1) (dx=2, dy=-1)
(31, 2) (dx=1, dy=-1)
(30, 3) (dx=0, dy=0)
128113 states were examined in the process.
stopwatch: Terminated. Elapsed time: 343ms
stopwatch: Process completed with exit code 0.

беговая дорожка секундомера 30 3 90 10 5020 25

Starting at (30, 3).
Goal is (90, 10).
Grid size is 100*100 (W*H).
A circular obstacle of radius 25 is centred at (50, 20).
22-step solution:
(90, 10) (dx=5, dy=-8)
(85, 18) (dx=5, dy=-7)
(80, 25) (dx=4, dy=-6)
(76, 31) (dx=4, dy=-5)
(72, 36) (dx=5, dy=-4)
(67, 40) (dx=6, dy=-3)
(61, 43) (dx=7, dy=-2)
(54, 45) (dx=8, dy=-1)
(46, 46) (dx=7, dy=0)
(39, 46) (dx=6, dy=1)
(33, 45) (dx=5, dy=2)
(28, 43) (dx=4, dy=3)
(24, 40) (dx=3, dy=4)
(21, 36) (dx=2, dy=5)
(19, 31) (dx=1, dy=6)
(18, 25) (dx=0, dy=6)
(18, 19) (dx=-1, dy=5)
(19, 14) (dx=-2, dy=4)
(21, 10) (dx=-3, dy=3)
(24, 7) (dx=-3, dy=2)
(27, 5) (dx=-2, dy=1)
(29, 4) (dx=-1, dy=1)
(30, 3) (dx=0, dy=0)
949565 states were examined in the process.
stopwatch: Terminated. Elapsed time: 3076ms
stopwatch: Process completed with exit code 0.

Обратите внимание на то, как оптимальное решение здесь сначала должно «двинуться назад», подняться вверх и снова, а затем снова вниз, так как круговое препятствие простирается до самого днаgrid.

Небольшая ошибка: код, который был опубликован, даст короткий (но ненулевой!) ответ, если вы установите цель цели равной начальной позиции.Очевидно, что это можно проверить как особый случай, но я уже поместил код на pastebin, когда понял, что это ...:)

5 голосов
/ 06 июля 2011

Пока что я не думаю, что кто-то обращался к ключевому пункту вашего вопроса: как вы находите хорошую «ценность качества»?В AI значение качества, на которое вы ссылаетесь, обычно называется «эвристическим».В идеале ваша эвристика должна точно указывать минимальное количество ходов, необходимое для достижения финиша, учитывая текущую позицию / скорость.В действительности, мы должны согласиться с тем, что легче вычислить.

Одно важное правило заключается в том, что хорошая эвристика должна быть допустимой ;то есть он никогда не должен переоценивать стоимость достижения цели (в вашем случае, количество ходов, чтобы достичь финиша).Алгоритм A * зависит от наличия допустимой эвристики.

Обычная техника для создания допустимой эвристики состоит в том, чтобы ослабить исходную проблему.В играх вы часто можете сделать это, изменив игру так, чтобы она стала проще (например, удалив правила).Например, в RaceTrack вы можете выправить дорожку, чтобы сделать ее более легкой игрой.С прямой трассой, лучшая стратегия состоит в том, чтобы просто непрерывно ускоряться.Таким образом, допустимой эвристикой является вычисление расстояния от текущей позиции до финиша (т. Е. Длины выпрямленной дорожки), а затем вычисление количества ходов, необходимых для прохождения этого расстояния в предположении постоянного ускорения.

Вы можете придумать другую эвристику, ослабив другие правила, но часто существует компромисс между точностью эвристики и количеством требуемых вычислений.

5 голосов
/ 06 июля 2011

Другие рекомендуют A *, что, вероятно, является подходящим способом, но есть проблема с этим подходом. Позвольте мне сначала сказать, что «стоимость» перехода от одного узла к другому всегда равна 1, так как вы хотите минимизировать количество шагов, просто другие затраты не требуются.

Но важно отметить, что местоположение (x, y) не является уникальным узлом в поисковом графе A *! Узел характеризуется x и y, но также и координатами x и y узла, из которого идет машина (или, если хотите, компонентами скорости vx и vy). Таким образом, вы не можете просто пройти алгоритм A * по двумерной сетке; на самом деле это должно быть 4-мерным. Тем не менее, A *, вероятно, еще путь.

Что касается эвристики, вы можете по-настоящему проявить творческий подход к этому, но я предлагаю что-то вроде расстояния до конца минус текущая скорость, где расстояние предварительно рассчитывается для каждой точки в обычной двумерной сетке (для этого используйте алгоритм Дейкстры) , Это заставляет алгоритм A * искать сначала к финишной черте и предпочтительно максимально быстро. Я полагаю, что такой алгоритм будет очень полезен для немедленного расчета всего маршрута.

Одной из проблем, однако, является то, что A * всегда будет давать оптимальный маршрут, поэтому ИИ, использующий такой алгоритм, будет неинтересным, так как он всегда выигрывает (при условии, что начальные позиции справедливы).

4 голосов
/ 06 июля 2011
1 голос
/ 06 июля 2011

Я бы предложил начать с решения проблемы. Используйте ретроградный анализ (как это делают в шахматных эндшпилях http://en.wikipedia.org/wiki/Retrograde_analysis), чтобы рассчитать в обратном направлении с конца, предполагая, что вы единственный игрок, чтобы увидеть, сколько шагов необходимо, чтобы пересечь финишную линию, учитывая позицию и скорость. Если мое мышление верное, время для расчета должно быть линейным по количеству позиций. Должно быть очень быстрым.

Это не будет абсолютной истиной, поскольку у вас есть конкуренты, мешающие вашему пути, но это даст вам очень хорошую эвристику для вашего алгоритма поиска.

1 голос
/ 06 июля 2011

Вы упомянули идею «присвоения каждому выбору некоторого значения качества» - это называется эвристической функцией. Многие алгоритмы ИИ (такие как A * и альфа-бета-обрезка, упомянутые другими) хороши только в той эвристической функции, которую вы в них вставляете.

Однако, если вам удастся создать хорошую эвристическую функцию, то эти алгоритмы автоматически будут работать намного лучше «бесплатно» - так что вам стоит потратить время на разработку хорошей.

Другой аспект - попытаться предварительно рассчитать всю гонку с самого начала. Тогда речь идет о минимизации количества поворотов, чтобы пересечь финишную черту. Одним из удобных алгоритмов нахождения минимума является имитация отжига .

Кроме того, было бы здорово увидеть какое-то решение с генетическим алгоритмом для такой игры. Не уверен, что это правильно, но я мог бы представить себе «мозг», который принимает различные входные данные - ожидаемое расстояние от стены на несколько оборотов в будущем, скорость, расстояние до других гонщиков и т. Д. - и развивает логику этого мозг с генетическим алгоритмом. Хитрость заключается в том, чтобы разбить проблему на части, которые могут быть существенно видоизменены.

На самом деле, вы могли бы даже объединить их и использовать генетический алгоритм. разработать эвристическую функцию, которая подключена к стандартному алгоритму поиска AI.

Честно говоря, грубая сила, вероятно, будет хорошо работать на стесненной дорожке, поскольку вы можете выбросить поддерево, если вы столкнетесь (а сбой типичен для плохих путей).

1 голос
/ 06 июля 2011

Хотя это не будет сразу применимо к RaceTrack, вы можете узнать что-то из A * алгоритма поиска пути . Он используется во многих играх, чтобы помочь ИИ понять, как быстро добраться из пункта А в пункт Б.

0 голосов
/ 06 июля 2011

В шахматах известно несколько алгоритмов, таких как обрезка альфа-бета, упорядочение ходов и т. Д., Возможно, вам повезет больше, если вы будете искать в шахматном контексте.


альфа-бета , стратегия


Редактировать : Эти алгоритмы поиска пути работают, только если у вас нет дополнительных правил и условий. Например, если у вас также есть скорость и центростремительные силы, вам не повезло. Если у вас нет этих сложных условий, вам лучше использовать простой алгоритм поиска пути, как указано в других ответах.

...