Хабрахабр

[Перевод] Как создать надёжную игровую механику, пользуясь только Excel: моделирование и оптимизация решений

image

Мы занимаемся поиском, а не итерациями

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

Мы внимательно рассматриваем отдельный аспект дизайна — боевую систему, одну из частей игрового мира, дерево технологий в стратегии — и пытаемся найти способ улучшить его, изменив эту конфигурацию. Так же, как управляемый ИИ персонаж использует систему поиска пути для перемещения по игровому миру, дизайнеру необходимо перемещаться по очень высокоуровневому пространству возможных конфигураций, беря некую исходную конфигурацию и итеративно изменяя её.

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

Часто они приближают нас к цели, но часто оказывается непонятно, улучшилась ли от них игра. Такие «итерации» совсем непохожи на линейные изменения, которые обычно происходят в «итерациях» компьютерного кода; гораздо больше они напоминают поиск в лабиринте со множеством резких поворотов и вынужденных возвратов назад. Дизайн похож на тёмную комнату со множеством острых предметов; чрезвычайно сложно безопасно передвигаться по нему, отойдя от протоптанных дорог. Иногда обнаруживается, что изменения дизайна, которые, по нашему мнению, должны были улучшить игру, имеют непредвиденные изъяны и нам нужно откатить них или попробовать заново.
Гейм-дизайн — это невероятно сложная дисциплина. И у нас довольно мало инструментов для освещения этой тёмной комнаты, а также мало чётко заданных и подробных техник выполнения такого процесса дизайнерского поиска. Почти всегда по пути нас ожидают болезненные травмы, особенно если двигаться слишком быстро.

Другими словами, мы находимся в поиске (Уилл Райт в своём докладе на GDC 2004 назвал это «поиском в пространстве решений»). Из-за существования этой тёмной комнаты мы и выполняем «итерации» — нам неизвестно, какими будут последствия решений, пока мы их не проверим.

Бесчисленное количество команд разработчиков оказывалось связанными по рукам и ногам непродуманными дизайнерскими решениями, пробуксовкой в творческом процессе, изменением функционала, неправильным восприятием целевого рынка и другими проблемами дизайна, приводившими к проблемам качества продукта. Поэтому очень часто дизайн становится узким местом производительности, основным источником недостатков и крупнейшим фактором риска при разработке игр.

Именно поэтому они не идут на хорошо известные им риски инноваций в дизайне, которые могут принести неизвестные результаты. С учётом всех опасностей, связанных с экспериментами в дизайне, неудивительно, что многие издатели и крупные разработчики так стремятся избегать риска, предпочитая строго придерживаться сложившихся и хорошо исследованных жанров, лицензий и жанровых допущений. Исследование тёмной комнаты слишком рискованно.

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

Эта серия статей

Эта статья станет первой в цикле постов о моделировании решений — набора инструментов для декомпозиции решений в формальные модели, по которым затем можно будет выполнять поиск для нахождения наиболее желательного результата.

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

Опрос профессиональных дизайнеров на популярном форуме разработчиков показал, что всего 25% респондентов хотя бы слышали о моделировании решений (decision modeling), и только 8% использовали его на практике. Несмотря на все свои потенциальные преимущества, моделирование и оптимизация решений, похоже, достаточно неизведанная тема для дизайнеров в игровой индустрии. Похожий опрос, проводившийся среди дизайнеров через Facebook, показал примерно такие же результаты при схожем количестве респондентов.

При правильном использовании моделирование решений может значительно улучшить множество аспектов процесса дизайна:

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

В этой серии статей я расскажу о примерах из всех трёх категорий использования.

Определение

Что же такое «моделирование решений»?

Если говорить просто, то:

Моделирование решений — это процесс симулирования решения с последующей автоматизацией поиска его вычисления.

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

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

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

Зачем строить модели?

Если вы играли в Sid Meier’s Civilization, то наверняка когда-нибудь задавались вопросом: «Постой-ка, как правильнее всего начинать развитие города? Надо ли сначала построить монумент, а затем склад? Или склад нужен первым? А может сначала храм, а потом уже склад? Какое решение лучше принять? Можно ли вообще ответить на этот вопрос?»

Балансировка параметров множества юнитов в RTS — задача, печально известная своей сложностью. Также можно вспомнить механику боя в стратегии реального времени. Что, если бы мы могли задавать системе вопросы? Что, если бы у нас была система, позволяющая ускорить решение задачи балансировки, отвечая на вопросы о балансировке боя игры без плейтестинга каждого решения? Например: «сколько мечников нужно, чтобы победить двух пикейщиков и трёх лучников?» Или: «какая наиболее дешёвая комбинация лучников и катапульт может победить вражескую сторожевую башню?»

На самом деле, такую систему можно создать!

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

Вот пример похожей задачи — пример, который мы решим в будущей статье серии.

В SuperTank мы управляем огромным фантастическим танком, сражающимся на поле боя с другими супертанками. Допустим, у нас есть игра под названием SuperTank. Перед каждым боем мы можем выбрать для своего танка определённую комбинацию вооружения.

У нас есть 100 кредитов, которые можно потратить на снаряжение. Супертанк игрока может нести на себе 50 тонн оружия, а также имеет 3 «критических» слота под специальное высокомощное вооружение.

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

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

нужно разместить на супертанке? Теперь быстро ответьте, сколько пулемётов, ракет, лазеров и т.д. Какая комбинация из одного или более видов оружия даст нам наибольший урон, не превышая при этом ограничений веса, цены и критических слотов?

Попробуйте решить задачу вручную или с помощью калькулятора.

Можно ли это сделать?

Если попробуете, то быстро убедитесь, что это на удивление сложная задача.

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

Изменится ли ответ, если вместо 50 тонн супертанк сможет вместить 60? Задумайтесь также, как изменится ответ при других параметрах. Как изменится оптимальное снаряжение? Или если вместо 100 кредитов у нас будет 110 или 90? А если у нас будет 2 или 4 критических слота?

Достаточно ввести параметры оружия из таблицы, затем ввести параметры супертанка (50 тонн, 100 кредитов, 3 критических слота) — и БУМ! — мы получили наилучшее снаряжение. А теперь представьте, что у нас есть система, которая мгновенно вычисляет схему размещения оружия с набольшим уроном для любого множества параметров (Вес, Цена, Критические слоты).

Разве не было бы это замечательно?

Мы могли бы использовать эту систему для мгновенного получения ответа на всевозможные полезные вопросы:

  • Как будет меняться оптимальная схема при изменении параметров супертанка?
  • Как изменится оптимальное снаряжение при изменении параметров оружия?
  • Какой максимальный урон может наносить супертанк при любых заданных параметрах (Вес, Цена, Критические слоты)?
  • Являются ли все четыре параметра оружия (Урон, Вес, Цена, Критические слоты) соответствующим и сбалансированным для каждого вида оружия?
  • Есть ли у нас слишком мощные пушки, которые используются слишком часто? Если какой-то из видов оружия настолько полезен, что всегда правильно использовать его, то оно всегда будет оптимальным решением, поэтому значимого выбора здесь не будет. В таком случае нам стоит или убрать оружие из игры, или изменить его баланс так, чтобы в определённых условиях оно не было полезным.
  • Есть ли у нас редко или никогда не используемые виды оружия? Аналогично предыдущему пункту — если какой-то вид оружия так бесполезен, что правильным решением является никогда его не использовать, то тут тоже нет значимого выбора. В таком случае стоит или удалить оружие из игры, или изменить его баланс, чтобы в определённых условиях было разумно его использовать.

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

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

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

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

Дорожная карта

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

  • Простой пример боя для стратегической игры
  • Модель для оптимизации координат нескольких телепортов-«червоточин» относительно друг друга и населённых секторов в космической массовой многопользовательской игре (MMO)
  • Модель, определяющую уровень налогов для упрощённой модели города, чтобы уравновесить довольство жителей и поступление налогов в 4X-стратегии наподобие Sid Meier’s Civilization
  • Модель выбора заклинаний и навыков для классов персонажей в массивной многопользовательской игре
  • Модель оптимизации для определения оптимального порядка строительства планетарной колонии в 4X-стратегии наподобие классической Master of Orion
  • Пример команды, пытающейся подобрать правильную комбинацию «фич» для игры, и модель решений, помогающую им выбрать соответствующие компромиссы

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

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

Важно не то, в чём мы работаем — в Excel и Solver, Java/C++/C#, или в чём-то ещё, а то, что мы моделируем задачу и стремимся её решить. Кроме того, не забывайте, что внутреннее представление — будь то электронная таблица, программа на языке высокого уровня, или что-то ещё — неважно.

Зачем использовать модели решений?

Некоторые читатели сейчас могут быть настроены скептично. Кажется, что построение моделей решений требует много трудозатрат. Зачем нужны все эти усилия, если мы можем провести пользовательское тестирование в виде тестирования фокус-групп и бета-тестирования?

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

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

Как в случае с любым другими инструментом, его пользователь сам должен принимать решение о его применимости.

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

Работа программистов очень сложна, но она упрощается множеством инструментов, помогающих находить баги ещё до этапа тестирования. Подумайте об инструментах, доступных типичному программисту. У них есть компиляторы, которые постоянно напоминают о сделанных опечатках; у них есть защитные практики программирования, выявляющие дефекты ПО; они проводят ревью кода, которые помогают распознать в чужом коде изъяны или указать на порочные практики программирования; кроме того, у них есть множество инструментов профилирования и статического анализа, позволяющие избавиться от всевозможных багов производительности и других дефектов.

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

Это делает дизайн невероятно рискованным, долгим и затратным занятием.

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

Нам ещё нужно пройти путь, который сделали компиляторы, отладчики, профайлеры и инструменты статического анализа в программировании. Мы ещё очень далеко от обладания полноценными дизайнерскими инструментами, помогающими дизайнерам в исследовании пространства дизайна. Но мы уже видим рассвет нескольких специфических солверов и инструментов дизайна игр, в том числе тестировщика играбельности версии Cut the Rope под названием Cut the Rope: Play Forever (ссылка); абстрактной системы дизайна игр Ludi, которая сгенерировала настольную игру Yavalath (ссылка); и моего собственного автоматизированного помощника Evolver для балансировки мобильной игры City Conquest (ссылка).

И если у нас есть выбор: иметь или не иметь инструменты, зачем выбирать «не иметь»? Моделирование решений поможет нам сделать ещё несколько шагов к такому уровню поддержки и позволит начать дополнять и расширять собственный интеллект дизайнеров с помощью автоматизированных инструментов.

Главное — не электронные таблицы, главное — это модели

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

  • Никакого кода. В статьях не будет абсолютно никакого кода и мы будем иллюстрировать все примеры в Microsoft Excel с помощью встроенного инструмента Solver («Поиск решения»). Однако важно заметить, что эта серия не об электронных таблицах или Excel, а про моделирование и оптимизацию решений. Каждый шаг, который мы сделаем в этой серии, можно так же просто (а иногда и ещё проще) выполнить на любом языке высокого уровня.

  • Никакой математики (или, по крайней мере, ничего сложного). Мы стремимся сделать эту серию свободной от математики и не будем использовать ничего, кроме простейших арифметических операций: сложения, вычитания, умножения, деления и иногда вычисления квадратного корня. Греческие буквы будут под строгим запретом.

Если вы дизайнер, то эта серия статей даст вам все инструменты, необходимые для самостоятельного создания моделей решений без необходимости написания кода вами или программистами. Если вы программист, то серия даст вам достаточно прямолинейную инструкцию по программированию собственных моделей решений на любом ЯВУ, чтобы вы могли строить собственные модели решений, или с нуля, или на основе шаблона, который уже используется в Solver и в Excel.

Электронные таблицы — это надёжный фундамент для начала, но такие модели решений вероятнее всего станут только вашим трамплином к более богатым и сложным моделям, интегрируемым в архитектуру вашей игры. Эти статьи должны стать всего лишь отправной точкой, чтобы вы могли взять представленные здесь концепции и выбрать самостоятельно: реализовать ли их в Excel, выбрать ли другой инструмент оптимизации, или попробовать построить собственный солвер на языке высокого уровня.

Пояснения

Прежде чем мы заберёмся слишком далеко в моделировании решений, нужно дать некоторые пояснения. Моделирование и оптимизация решений не создают никакой завершённой системы для дизайна игры, и мы не будем утверждать ничего подобного. Полезно смотреть на них как на инструмент, помогающий в некоторых аспектах процесса дизайна, и как любой инструмент, он имеет множество ограничений.

Вот некоторые из ограничений, о которых вам нужно знать:

  • Их легко использовать неверно. Как и любой другой инструмент, модели решений можно использовать неправильно или несоответствующим образом, а неполная или ошибочная модель решений может привести вас к неверным выводам. Как и в случае с ПО, чем больше становится модель решений, тем больше вероятность наличия в ней ошибок. Кроме того, очень просто ошибочно интерпретировать то, что сообщает вам модель, или построить неполную модель, которая неточно моделирует решение, которое вам нужно принять.

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

  • Смоделировать можно не всё. Модели решений не могут сообщить вам, будет ли что-то увлекательным, эстетически приятным, «правильным» или дающим пользователю удобный и доступный интерфейс. Нет общего способа представления таких субъективных и эстетических аспектов в виде дискретной модели. Это значит, что есть чёткие границы использования моделирования решений, и что они гораздо полезнее для дизайна систем и оптимизации механик/динамики, чем для эстетики.

  • Они имеют ограничения. Все оптимизаторы имеют свои ограничения, в том числе и применяемый нами Excel Solver, и вполне возможно создать модели решений, имеющие правильные решения, но при этом настолько сложные, что никакой инструмент оптимизации не сможет их найти. В случае достаточно больших неограниченных входящих значений задача может перерасти способности Solver в поиске каждой возможной комбинации входящих значений, и вместо этого ему придётся положиться на различные способы оптимизации. Как мы увидим в этой серии статей, можно упрощать выражения моделей, чтобы «Поиску решений» было проще их обрабатывать. Разработчик Solver (Frontline) предлагает более мощный солвер для более объёмных задач, но совершенно точно можно создать модели, которые Solver решить неспособен.

  • Они не гарантируют оптимальности. Вследствие того, что мы работаем со сложными моделями, невозможно быть на 100% уверенными, что мы нашли оптимальное решение. Иногда нам приходится остановиться на втором по оптимальности: мы потратим больше времени на оптимизацию или начнём с нуля и оптимизируем заново, чтобы мы с высокой степенью уверенностью могли бы сказать, что нашли или оптимальное, или очень близкое к оптимальному решение.

Последнее и самое важное:

  • Нам нужно убедиться, что модель занимается нужными задачами. Не все задачи достаточно важны, чтобы потребовались такие усилия, нам нужно точно знать свои приоритеты и избегать излишнего сосредоточения на оптимизации бесполезных задач и игнорирования других, более крупных, которые могут оказаться гораздо важнее.

Говоря упрощённо, чтобы моделирование решений было полезным, должны удовлетворяться некоторые условия. Мы должны иметь возможность встроить рассматриваемое решение в некую дискретную модель, и выразить результат решения в виде одного значения. Другими словами, мы должны иметь возможность выразить с помощью модели решений конечное множество входящих данных в одном выходном значении таким образом, чтобы минимизация или максимизация выходного значения давало нам улучшенное решение.

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

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

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

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

Наконец, даже если вы решите не использовать моделирование решений, не пытаться оптимизировать электронные таблицы или создавать собственные солверы, понимание моделирования решений всё равно поможет вам изменить взгляд на принятие дизайнерских решений.

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

Заключение

В конце концов, мы хотим создавать дизайн правильно.

Но в некоторых случаях они несомненно есть. Многие вопросы дизайна субъективны, у них нет «правильных» или «неверных» ответов. И в таких случаях мы должны знать, как получить правильный ответ, или по крайней мере понять, как взяться за определение «правильного» ответа и искать, существует ли его решение.

Я считаю, что такие инструменты должны находиться в инструментарии каждого дизайнера. Моделирование и оптимизация решений — это мощные инструменты, которые помогают нам во многих случаях. В серии наших статей мы покажем, насколько много применений он имеет. Приспособившись к ним, вы поймёте, что у этих инструментов есть огромный нереализованный потенциал в более быстром и надёжном исследовании тёмной комнаты гейм-дизайна.

Часть 2. Основы оптимизации и развёртывание симуляции

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

Подготовка модели решений

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

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

Если говорить упрощённо, то в наших электронных таблицах будет четыре типа ячеек:

  • Решение — эти ячейки содержат переменные, которые мы пытаемся оптимизировать — другими словами, мы заставим оптимизатор попытаться найти наилучшие значения для этих ячеек. В этих ячейках мы можем начать с 0 или какого-то другого приемлемого значения по умолчанию, а затем заставить оптимизатор вставить правильные значения. В большинстве случаев мы также ограничим их определённым интервалом, например минимальным и максимальным значениями, а в некоторых случаях целыми или двоичными значениями. Ради согласованности и удобства чтения ячейки решений всегда будут жёлтыми и иметь чёрную рамку.
  • «Заданное значение» — значения этих ячеек указываются непосредственно в условиях задачи. Например, если задача говорит нам, что леденец Tootsie Pop весит 17 грамм и каждый раз мы слизываем с него 0,25 грамм, то эти две ячейки будут «заданными значениями». Такие ячейки мы обозначим синим.
  • «Вычисление» — значения этих ячеек вычисляются из других ячеек электронной таблицы, которые не подпадают ни под какие другие категории. Мы сделаем их серыми.
  • «Цель» (или «выход») — это ячейка, значение которой мы стремимся минимизировать (или максимизировать) при выполнении оптимизатора. В наших примерах всегда будет только одна ячейка цели, она всегда имеет оранжевый цвет и чёрный контур. (Примечание: существуют более мощные солверы, поддерживающие работу с несколькими целями, но для наших статей это будет слишком сложно.)

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

Такие алгоритмы («Simplex LP», «GRG Nonlinear», «Evolutionary») спроектированы так, что они гораздо умнее исследования всех возможных вариантов переменных решений грубым перебором, и очень часто находят ответы на серьёзные задачи с удивительной эффективностью. Solver почти ничего не знает о вычислениях, происходящих внутри, или о связях между ячейками решений и ячейками целей; он просто выполняет один из нескольких доступных ему алгоритмов, пытаясь минимизировать или максимизировать значение ячейки цели с помощью поиска возможных значений ячеек решений.

Например, если бы мы хотели узнать, сколько раз нужно лизнуть, чтобы добраться до середины Tootsie Pop, то могли бы использовать подобную электронную таблицу:

Мы можем попросить Excel Solver решить эту задачу, приказав ему минимизировать ячейку цели «Mass remaining on Tootsie Pop» («масса оставшейся Tootsie Pop»), и он бы быстро с помощью экспериментов определил бы, что значение жёлтой ячейки решения, дающее такой результат («Сколько раз лизнуть, чтобы добраться до середины Tootsie Pop») равно 68.

Нет смысла запускать оптимизатор для решения задачи, которую можно решить простой арифметикой. Разумеется, так делать немного глупо, потому что из постановки задачи понятно, что ответ будет 17/0,25=68.

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

Мы сосредоточимся на описании задач, а всю сложную работу оставим Solver.

Пример 1: налоги

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

Мы находимся в процессе создания городов, имеющих определённый уровень недовольства, зависящий от их размера. Представьте, что мы создаём 4X-стратегию, похожую на Sid Meier’s Civilization. Также мы можем попытаться получить деньги с городов, изменяя налоговую ставку каждого города, но при увеличении налоговой ставки уровень неудовлетворённости будет расти экспоненциально, поэтому очень высокие налоги становятся контрпродуктивными. «Недовольные» жители по сути не настроены на сотрудничество, и мы не получаем от них доходов.

Вот скриншот, на котором показана похожая система из классической 4X-стратегии Master of Orion 2: Допустим также, что мы можем указывать налоговую ставку с инкрементом 10% в интервале значений от 0% до 50%.

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

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

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

Давайте начнём с того, что опишем задачу следующим образом:

  • У нас есть город размером 12 (что обозначает 12 миллионов людей). Эти люди представлены как 12 отдельных «граждан».
  • Каждый гражданин в любой момент времени может быть доволен или недоволен.
  • Довольные граждане платят в виде налогов (налоговую ставку x 10) (то есть, например, налоговая ставка 20% даёт нам 2 единицы валюты в налоговых доходах на каждого довольного гражданина).
  • Недовольные граждане не платят налогов.
  • В городе есть 3 недовольных граждан, которые остаются недовольными вне зависимости от налоговой ставки.
  • Дополнительное количество граждан становится недовольным на основании следующей формулы: (Население) x ((Налоговая ставка) x (Налоговая ставка)) x 3.5, значение округляется вниз до ближайшего целого числа. Для нашего города размером 12, это даст нам 0 дополнительных недовольных граждан при ставках 0% и 10%, 1 дополнительного недовольного гражданина при ставке 20%, 3 дополнительных недовольных граждан при ставке 30%, 6 — при ставке 40%, и 10 — при ставке 50%.

Всё просто, правда?

Мы опишем это в прикреплённой к статье электронной таблице следующим образом:

Вы можете заметить, что мы задаём жёлтую ячейку решения (Tax Level (0-5)) как косвенный способ указания налоговой ставки. Вместо указания налоговой ставки непосредственно в ячейке решения, ячейка вычислений Tax Rate берёт число Tax Level из ячейки решения и умножает его на 10%. Есть логичная причина делать это косвенно, и мы скоро это увидим.

Можно просто ввести в ячейку Tax Level каждую из цифр от 0 до 5, и получить следующее: Теперь мы можем экспериментировать и подставить все возможные значения уровня налогов.

Как видите, существует оптимальное значение налоговой ставки: 30%, которое максимизирует доход от налогов, давая 18 единиц валюты.

Давайте автоматизируем систему!

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

Как мы увидим, именно для этого и используется Solver.

Затем перейдём во вкладку Data («Данные») Excel и увидим в правой части ленты, в разделе Analysis («Анализ»), кнопку Solver («Поиск решения»). Для начала мы сбросим значение ячейки Tax Level до нуля.

Если вы её не видите, то зайдите в Options («Параметры») Excel, выберите категорию Add-Ins («Надстройки»), убедитесь, что в раскрывающемся списке Manage («Управление») выбрано Excel Add-Ins («Надстройки Excel»), нажмите Go («Перейти...») и убедитесь, что поставлен флажок Solver Add-in («Поиск решения»).

После нажатия на кнопку Solver («Поиск решения») вы должны увидеть похожее диалоговое окно.

Давайте теперь рассмотрим все этапы настройки диалогового окна Solver.

В данном случае мы пытаемся получить как можно больший доход от налогов, поэтому выберем оранжевую ячейку цели, которая обозначает доход от налогов, а затем нажмём на «To: Max» («До: Максимум») в списке радиокнопок. В поле «Set Objective» («Оптимизировать целевую функцию») мы укажем то, что нужно оптимизировать.

Нам нужно определить оптимальную налоговую ставку, поэтому выбираем жёлтую ячейку решения (Tax Level (0-5)). В разделе «By Changing Variable Cells» («Изменяя ячейки переменных») выберем ячейки, которые «Поиск решений» должен вычислить. Если всё получится правильно, то в результате этой ячейке будет присвоено значение 3, соответствующее налоговой ставке 30%, оптимальность которой мы уже определили при вычислениях вручную.

По сути, ограничения являются условиями для любых ячеек нашей модели решений, и Excel Solver сосредоточится только на тех решениях, которые удовлетворяют указанным ограничениям. Наконец, нам нужно добавить несколько ограничений. Ограничения невероятно полезны для создания корректной модели, которой будет ограничен. Такие ограничения могут ограничивать определённые ячейки (обычно ячейки решений и ячейки вычислений) заданными минимальным и/или максимальным значениями, и/или заставлять Solver обрабатывать их как целые или двоичные переменные (0 или 1).

Чтобы добавить ограничение, нужно нажать на кнопку Add («Добавить») справа, после чего откроется следующее диалоговое окно: Solver требует хотя бы несколько ограничений, позволяющих ему определить границы ячеек решений — другими словами, минимальное и максимальное значения для каждой ячейки.

Мы добавим два ограничения, одно для того, чтобы ячейка решения Tax Level удовлетворяла условию >=0, и ещё одно, чтобы ячейка решения была

Поработав примерно 30 секунд, Solver выдаст нам подобный ответ:

Ой-ёй, возникала проблема. Solver получил верную сумму дохода, но уровень налогов неправильный. Игрок может задавать налоги только с инкрементом в 10%, но Solver очевидно задаёт дробные налоговые ставки, чего игрок сделать не сможет.

Оно может быть равно только 0, 1, 2, 3, 4 или 5, но без промежуточных значений. Решить проблему можно, ограничив значения ячейки налоговой ставки только целыми числами.

Откройте Solver, нажмите кнопку Add («Добавить»), выберите ячейку решения Tax Level, а затем выберите в раскрывающемся списке посередине ограничение int («цел»): К счастью, в Solver этого можно довольно легко добиться.

Теперь снова запустим Solver и получим следующее:

Идеально! Приложив незначительные усилия, мы получили в Solver правильный ответ. Как мы скоро увидим, при увеличении масштаба задач объём выполняемой за нас инструментом работы значительно превышает время, потраченное на его настройку.

Растущий город

Давайте теперь расширим задачу, слегка усложнив модель города.

Мы допустим, что город имеет постоянный прирост в 8% за ход, начиная с 1500 тысяч (1,5 миллиона) горожан, и увеличиваясь до размера в 12 миллионов жителей. В любой 4X-стратегии города (или планеты, или колонии, или другие населяемые единицы) со временем растут. Теперь наша электронная таблица будет выглядеть так:

Каждая новая последующая строка таблицы описывает один ход игры.

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

Мы получим 0, 102, 190, 222, 144 и 65 единиц валюты в доходах от налогов, при каждом из уровней налогов от 0% до 50%. Как и раньше, мы можем поэкспериментировать с уровнями налогов вручную, изменяя значения Tax Level.

Вот, как выглядит диалоговое окно Solver: И мы снова можем заставить Solver решать эту задачу; он быстро определит, что оптимальная налоговая ставка как и раньше равна 30%, что даёт нам доход в 222 единиц валюты.

Переменные налоговые ставки

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

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

Она мгновенно будет сообщать нам, как игрок может наилучшим образом настроить налоги.

Уже настроив модель решений правильным образом, мы можем реализовать это невероятно просто. И оказывается, что это можно сделать!

Самое большое отличие заключается в том, что нам нужно убрать ячейку решения Tax Level (0-5) и заменить её целым столбцом ячеек уровней налогов, как показано ниже.

Теперь вместо того, чтобы заставлять Solver оптимизировать отдельную ячейку, мы прикажем ему оптимизировать весь столбец Tax Level. Вот как будет выглядеть диалоговое окно Solver — можно заметить, что оно практически такое же, как и раньше, только вместо одной ячейки переменные и ограничения теперь представляют целый диапазон ячеек столбца Tax Level.

Solver и в самом деле доказывает, что изменение налоговой ставки изменяет результаты — кумулятивный доход теперь составил 232 единиц валюты. По сравнению с одинаковой налоговой ставкой рост составляет всего 5% процентов (222 против 232 единиц), но он всё равно значим, потому что мы знаем, что некоторые игроки смогут его достичь.

В процессе роста города инструмент изменяет в каждом ходу налоговую ставку в интервале от 20% до 30%, в зависимости от того, какая из них принесёт больший доход. Приглядевшись к полученному Solver решению, можно увидеть, что оно начинается с налоговой ставки 50%, потому что город размером 1 не содержит достаточного количества населения для генерации недовольства.

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

Заключение

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

Заставляет ли механика игроков считать, что для игры им нужно в каждом ходу заниматься микроменеджментом уровней налогов? Такая ситуация приводит к интересному вопросу: этого ли мы хотим? И хотим ли мы допустить, чтобы нацеленные на победу игроки (power gamers) могли обыгрывать систему таким образом; соответствует ли такой хитрости получаемый ими выигрыш в 5%?

В конце концов, вы являетесь дизайнером, задающим цели дизайна, поэтому вам решать, соответствует ли такой уровень эксплуатации систем целям, которым вы поставили перед игрой. На эти вопросы я не могу ответить.

В реальной 4X-стратегии игроки могут принимать всевозможные решения о том, как развивать город, строить здания и вносить другие изменения, влияющие на рост города, довольство, доходы от налогов и продуктивность. Разумеется, эта модель — всего лишь голый каркас.

Этот пример будет гораздо более изощрённым, потому что мы сможем принимать в каждом ходу решения, которые будут в дальнейшем влиять на все эти параметры, такие как рост и продуктивность, то есть каждое решение будет иметь последствия, влияющие на последующие решения. В одной из будущих статей цикла мы построим похожую, но гораздо более сложную модель целой планетарной колонии в игре, напоминающей Master of Orion 2. Однако мы всё же убедимся, что эволюционный оптимизатор инструмента Solver способен справиться с этой задачей.

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

Показать больше

Похожие публикации

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Кнопка «Наверх»