Конечные автоматы в менюшных играх. Пишем доисторическое приключение на ink. Часть 1


Давайте начинать с ответов на вопросы.
  • Зачем нужно писать про конечные автоматы? Они позволяют моделировать сложное поведение, которое мы часто хотим видеть в текстовых играх. Есть большое количество статей по реализации конечных автоматов на обычных языках программирования, но мы будем рассматривать исключительно инструменты ИЛ.
  • Почему менюшный движок? В примере хочу остановиться на автоматном подходе и продемонстрировать, как можно использовать конечные автоматы в менюшных движках, где главной смысловой единицей в них является параграф (или узел как в ink). Эти сведения должны пригодиться для тех, кто интересуется представлением сложного поведения в ink, twine, undum, salet, axma и подобных.
  • Хорошо, тогда почему ink? ink очень перспективный язык с возможностью встраивания, сборкой под веб, тестированием истории в консоли, мощными фичами для потока управления и в тоже время минималистичным синтаксисом.

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



Идея

Начём, пожалуй, с самого фундаментального — игрового опыта, который должна преподнести игра. Полуфанстастический сеттинг будет заключаться в противостоянии охотника и динозавра в допотопные времена. Не сильно заезженная тема (я надеюсь). Для игры у меня есть визуальный прототип: point-and-click adventure Theropods.

Конепт опыта: «почувствовать себя древним охотником, выстоять против более сильного противника поможет только его храбрость и сообразительность». Ключевые составляющие игровых механик:
  1. Игрок может победить за счет хитрости, решая основную головоломку.
  2. Игрок не может умереть, все опасные ситуации приводят безопасному исходу.
  3. Вначале даётся не так много информации, решение открывается постепенно за счет взаимодействия с внешним миром и анализом реакций.
  4. Решение может быть не очевидное, надо пробовать, чтобы узнать какой вариант подходит.
  5. Подкрепление успехов. Каждый успех должен подкрепляться понятным сообщением, игрок решает не вслепую, а чувствует прогресс.
  6. Должен быть фиксированный набор действий. Они должны обрабатываться всегда, их текст не меняется, количество тоже. Это ограничение демонстрационного примера.


Центральная головоломка

Не скажу что очень быстро придумал придумал этот вариант, но постепенно пришел именно к такой формулировке. Охотник находится между костром и деревом, на противоположной стороне тусуется динозаврик. Наша цель — победить динозавра. Напрямую слишком скучно, поэтому будем его побеждать как в графическом аналоге — забраться на дерево и стукнуть по ветке, чтобы она отвалилась, упала в костёр и подожгла хвост динозавру, правда, не с первого раза. Чтобы залезть на ветку придётся незаметно приблизиться к дереву, а потом отпугнуть зверюгу. Итого план действий:
1. Незаметно пробираемся к дереву
2. Отпугиваем динозавра
3. Лезем наверх
4. Ударяем ветку
5. Повторяем пункты 1-4
Животное должно быть подвижное, чтобы мы могли пробираться мимо. И, конечно, копье должно использоваться. Тактические выборы игрока можно представить так:


Немного теории

Тем кто знаком с принципами конечных автоматов, можно пропустить. Кто о них не знает, советую почитать в интернете более подходящий для себя ресурс (лично мне нравиться книга Шалыто «Автоматное программирование», можно скачать отсюда: is.ifmo.ru/books/_book.pdf). Вкратце, конечные автоматы нужны для моделирования сложного поведения. Сложное поведение означает, что на одни и теже входы могут быть различные реакции. Например, электронные часы — всего пара кнопок, а мы можем настраивать текущее время, дату, будильник. Самое главное вовремя узнать, что мы имеем дело со сложным поведением и требуется использовать автоматный подход. В его основе выделение состояний и событий, по которым будет происходить переход из одного состояния в другое, изображают автомат в виде направленного графа.

Синтез автомата

Итак, у нас уже есть определённое видение игры, остаётся уточнить некоторые моменты, чтобы переходить к реализации. Глаголы:
— Ждать. Стандартный глагол, позволяет просто понаблюдать за происходящим.
— Метнуть копьё. Глагол прямого наступления, понятное дело, что в большинстве случаев не сработает.
— Лезть по дереву. Тут мы выражаем цель в спасении через дерево, то есть подойти к дереву тоже будет «лезть на дерево».
— Ударить ветку. Сразу открываем все карты, этот выбор должен открываться постепенно, но для того, чтобы не усложнять игру появлением/пропаданием вариантов, делаем видимым сразу.
Пожалуй хватит действий, переходим к синтезу состояний. Итак, у нас есть сущность герой, который может находиться в одной из трех локаций: вдали от дерева (за костром), возле дерева и на дереве. И динозавр, который может быть виден и скрыт в кустах. Дополнительно, у динозавра будет состояние когда он убежал от копья. Вид двух автоматов без лишних деталей:

Более подробная схема для главного героя:


Промежуточные результаты

Мы начали с очень общей концепции и дошли до детального проекта игры. Теперь мы можем приступать к реализации автомата, а затем и к дизайну веб-интерфейса. Продолжение следует…