Командный приказ архитектуры Крепости гномов


21

Какой самый элегантный способ реализовать систему командных команд для ИИ? например, в крепости гномов, когда вы помечаете лесную зону для рубки леса, гномы затем выполняют следующую последовательность действий:

  1. Иди к дереву
  2. Рубить дерево
  3. Доставить дрова на склад
  4. Перейти к другому дереву
  5. и так далее..

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

Чего я боюсь, так это того, как это может стать грязным, когда я создаю больше заказов, как это:

Построить дом

  1. Перейти на склад
  2. привезти древесину на строительную площадку
  3. вернуться на склад
  4. Доведите камень до строительной площадки
  5. одушевленный строительный спрайт

насаждение

  1. Перейти на склад
  2. принести семена на ферму

пивоварение

  1. Перейти на склад
  2. Доведите растение до сих пор
  3. одушевленный пивоваренный спрайт

Итак, мой вопрос: как мне реализовать систему упорядочивания команд, такую ​​как dwarf fortress, и одновременно избегать кода спагетти? Есть ли какие-либо структуры данных, которые мне нужно изучить? Нужно ли помещать последовательность команд в отдельный XML-файл?


1
Dwarf Fortress на самом деле не имеет такой системы. Гномам назначается по одной задаче за раз, и праздные гномы будут искать что-то для дела. («Эй, есть дерево, помеченное для рубки - я должен его рубить!» / «Эй, дерева нет в запасе - я должен взять его с собой!»)
user253751

1
Гномы ничего не назначают игроку, но "назначают" задачи системой, которая является точно архитектурой, описанной Джедом Т. выше. Создайте заказ, и система назначит отдельные задачи компонента для выполнения этого заказа.
Attackfarm

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

@Attackfarm Система не решает все задачи заранее; он также не назначает несколько задач одному и тому же дварфу. Первоначально назначается одна задача, и после ее завершения становится доступной другая задача.
user253751

2
Это звучит как отличный пример использования для планирования действий, ориентированных
проблематично

Ответы:


27

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

Резка дерева

  • Я ношу дрова, и на складе? Да : брось
  • Я несу дрова? Да : иди на склад
  • Я у дерева? Да : нарезать
  • Нет всему вышеперечисленному : иди к дереву

Преимущества этого:

  • Очень просто реализовать
  • Гибкость - вы можете свободно разбивать этот список, добавлять элементы, удалять элементы, комбинировать элементы
  • Нет состояния - вы можете запустить этот список сверху для любого дварфа в любом состоянии, и дварф просто сделает правильную вещь TM

Недостатки:

  • Легко застрять в петлях, так как нет состояния и нет осознания застревания

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


2
Это также имеет то преимущество, что позволяет командам отмены статуса. Я голоден? если да, отбросьте все и поставьте задачу «есть», когда еда похожа на работу по транспортировке древесины.
фрик с трещоткой

7
@ratchetfreak "Я знаю, что безопасность моей крепости зависит от того, как я сражаюсь с этим монстром, чтобы он не атаковал мирных жителей, но, черт возьми, мой живот только что зарычал!" Постарайтесь не делать это слишком похоже на DF в этом отношении: P
полковник Тридцать два

Я думаю, что это напоминает то, что использует (или, по крайней мере, использовал), что позволило ошибочный артефакт в planepacked (это было из-за запрещенного элемента, который вызвал указанное зацикливание)
Destrictor

3
@ColonelThirtyTwo Где funв этом? ;)
Лассе

Я настоятельно рекомендую не использовать декларативное символическое планирование действий для этого. Это в принципе невозможно отладить, и может легко возникнуть нежелательное поведение. Гораздо проще жестко кодировать последовательности действий для каждой задачи процедурным способом.
mklingen

10

Если вы можете сделать последовательности довольно общими, там не так много кода для спагетти.

В случае поставок, например: WorkTask работает с WorkPlan. Рабочий план говорит, какой ресурсный блок должен выбрать, из какого дома, с помощью какой анимации ходьбы, с помощью какой рабочей анимации, времени на работу и всех подобных деталей. В итоге WorkTask может выглядеть так:

  1. Найти% resource1% на карте
  2. Перейдите в это место, используя% animation_1%
  3. Работайте на месте, используя% animation_2% для% time%
  4. Взять% req_resource1% в счет% req_count1%
  5. Перейти к% home% используя% animation%
  6. Запустите% animation_6% внутри для% time_2%
  7. так далее..

Мы успешно используем описанный подход. В нашей игре ~ 15 заданий. Некоторые основные моменты:

  • Задачи дают действия юнита (идти туда, входить, выходить, идти сюда, оставаться, работать, идти)
  • Действие заканчивается в состоянии «Готово» или «Прервано» и передает его в задачу
  • Все жестко закодировано (не нужно писать парсер, методы интерфейса, обратную совместимость)
  • Каждая задача реализует абстрактный класс Task с помощью нескольких распространенных методов (создание, выполнение, сохранение, загрузка).
  • Обычно одна задача на модуль, но похожие задачи в одном модуле
  • Очень похожие задачи выполняются в пределах одного класса и управляются несколькими IF (доставить на дом или доставить на место)
  • Каждой задаче требуется правильная блокировка и разблокировка ресурсов (например, если юнит умирает на ЛЮБОМ шаге, заблокированный ресурс должен быть освобожден)

2
Это система, которую мы используем в нашей игре, похожей на крепость дварфов. Задачи выполняются деревьями поведения. Ресурсы блокируются поведением и разблокируются при сбое. Это гораздо надежнее и проще в отладке, чем подход к планированию действий, описанный в главном ответе
mklingen

5

Так что это в основном проблема топографической сортировки.

У вас есть график, каждый узел - это задача, которую необходимо выполнить, а некоторые узлы зависят от некоторых других узлов (это представлено ребром в графе от зависимого узла до узла, от которого он зависит). Вы хотите выполнить все задачи, поэтому вам нужно произвести НЕКОТОРОЕ упорядочение узлов, которое топографически нормально (зависимые узлы расположены после узлов, от которых они зависят).

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

Также возможно, что нет способа сортировать топографический график - это происходит, когда на графике есть циклы (у вас нет дерева, чтобы получить дерево, вам нужно рубить дерево, рубить дерево, вам нужен топор, чтобы вы топорили вас нужен лес). В таком случае алгоритм, вероятно, должен указывать игроку, что эти задачи не могут быть выполнены.

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

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

Теперь, как решить это - http://en.wikipedia.org/wiki/Topological_sorting

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.