Эту и другие статьи можно найти в моем блоге Вконтакте: https://vk.com/mistle_gamer
Предыдущие статьи цикла:
Введение и общая функциональность Google таблиц
Google Sheets для геймдизайнера. Часть 1: Сортировка данных
Google Sheets для геймдизайнера. Часть 2: Работа с текстом
Страница 3: Рандомайзер
Рандомайзеры в таблицах — это довольно удобная вещь, если вы хотите сделать прототип какой-то случайно генерящейся в игре механики. Например, вы хотите сделать систему монстров, которые будут случайно создаваться на локации. Или сделать механизм генерации имен для NPC. Возможно, вы хотите по каким-то условиям генерить для игрока квесты? Прежде чем ставить программистам задачу на разработку и внедрять эти механики в игру, нужно сначала протестировать их «на бумаге». Сегодня я покажу несколько простых, но довольно наглядных способов использовать рандомайзеры в дизайн-документах.
Напоминаю, что для наглядности я создала табличку на Google диске. Вы можете ее открыть, скопировать к себе на диск, пощупать все формулы и посмотреть более подробно как они сделаны и вообще экспериментировать с ней по вашему усмотрению. Ссылка на табличку:
https://docs.google.com/spreadsheets/d/1bsDebERvoNifQQwQd9asLiUQRwjGUbz5XG0IT2f7uas/edit#gid=1586458683
Идем в File — Make a copy — выбираем папку на своем диске Google, куда вы хотите скопировать таблицу.
Таблица 1: Генерация имен и бэкграунда NPC
Задача 1
Дано:
Таблица 1
Столбец B — Город, в котором проживает NPC;
Столбец C — Пол
Столбец D — Имя
Столбец E — Фамилия
Вопрос:
Как можно случайно создать список имен с указанием пола?
Решение:
Таблица 1 содержит в себе несколько формул, поэтому пойдем от простого к сложному. Сначала давайте посмотрим как нам просто вывести случайный список имен.
Вспомогательная таблица 1.2
Из этой таблички мы будем брать случайную пару пол — имя.
Общий вид формулы:
Тут у нас сразу две формулы, первая из которых — INDEX.
INDEX — это формула, которая берет массив и возвращает из него значение на пересечении столбца и строки.
Синтаксис формулы:
Где:
reference — это ссылка на массив, в котором нужно произвести поиск;
[row] — номер строки;
[column] — номер столбца.
На простом примере:
Мы как бы выделяем все ячейки A2:B6, и внутри этого выделенного массива мы ищем пересечение столбца и строки. При этом номера строк, как и номера столбцов, отсчитываются внутри массива, а не внутри таблицы. То есть, в таблице строчка с «помидоркой» — четвертая, а в массиве — третья.
Теперь вторая формула, RANDBETWEEN.
RANDBETWEEN — это формула, которая возвращает случайное значение в указанном диапазоне. Диапазоном могут быть как ячейки, так и два числа, введенные вручную.
При работе с этой формулой следует помнить следующее:
- RANDBETWEEN работает только с числами, она не работает с текстовыми значениями.
- Если выделить массив ячеек, то RANDBETWEEN не будет работать.
- Если выделить первую и последнюю ячейку столбца со значениями, RANDBETWEEN выведет случайное число между ними, не из других значений столбца.
- Каждый раз, когда вы что-то меняете на странице, даже ширину столбцов, RANDBETWEEN и формулы, в которых участвует RANDBETWEEN, будут генерить значения заново.
Синтаксис формулы:
Где:
low — нижняя граница диапазона для выборки случайных значений;
high — верхняя граница диапазона для выборки случайных значений.
На простом примере:
Выводим случайное число от 0 до 100. Адреса ячейки со знаками «$» для того, чтобы можно было протянуть формулу на любое количество строк.
Соберем вместе две формулы и рассмотрим их относительно нашей таблицы:
Поскольку нам нужно вернуть текстовое значение, нам недостаточно формулы RANDBETWEEN, мы используем INDEX.
Первый аргумент формулы INDEX — это массив с парами пол — имя. Мы выбираем весь массив, потому что хотим, чтобы имя соответствовало полу.
Второй аргумент формулы INDEX — это номер строки. Его-то мы как раз и вычисляем с помощью RANDBETWEEN. Мы знаем, сколько всего у нас строк в массиве и просто просим RANDBETWEEN взять случайный порядковый номер из общего массива строк.
Третий аргумент — номер столбца — мы не указываем, потому что нам нужны значения обоих столбцов. Мы просто растягиваем формулу в столбце C, а она сама заполняет собой два столбца подряд.
Задача 2
Дано:
Таблица 1
Вопрос:
Как присвоить NPC, сгенеренным в задаче 1, фамилии, соответствующие территориям, на которых они проживают?
Решение:
Вспомогательная таблица 1.3 — Соответствие территорий и фамилий
Если бы нашей задачей было присваивание NPC случайной фамилии, мы могли бы использовать формулу из задачи 1, и заставить ее искать по вспомогательному столбцу с фамилиями. Но перед нами стоит более сложная задача: мы знаем, что на каждой территории NPC бастарды должны носить фамилию, традиционную на этих территорий. Flowers на просторе, Sand в Дорне, Hill — в Западных землях, и так далее.
Мы могли бы создать таблицу соответствий Названий крепости и фамилий, перечислить все крепости в одном столбце, а повторяющиеся фамилии в другом, и искать по такой таблице соответствие с помощью VLOOKUP. Это одно из решений, самое простое. Но оно делает нашу таблицу негибкой.
— Что если крепости на разных территориях будут носить одинаковое название?
— Что если список крепостей будет постоянно меняться? Придется поддерживать в порядке обе таблички.
— Что если крепости в результате войны будут переходить в соседние королевства?
— Что если список крепостей вообще нельзя составить, так как названия для них придумывают игроки?
Попробуем отталкиваться в наших расчетах исходя из более константных значений, а именно названий королевств.
Общий вид формулы:
В формуле используются два именных диапазона — w_terr (westeros territories) и w_fnames (westeros family names). Именной диапазон w_terr ссылается на вспомогательную таблицу 1.1:
А точнее, на первый и второй столбец таблицы, соответствие крепости и королевства.
Именной диапазон w_fnames ссылается на нашу вспомогательную таблицу 1.3, которую я упоминала выше.
Подробнее об именных диапазонах можно почитать в первой статье цикла о Google таблицах.
С формулой VLOOKUP мы уже работали раньше, поэтому давайте просто разберем, как именно она используется тут. На всякий случай напомню синтаксис формулы:
Где:
search_key — та ячейка, для которой мы будем искать соответствие;
range — диапазон, в котором мы будем искать соответствие;
index — столбец из которого будем возвращать соответствие;
[is_sorted] — отсортирован столбец, или нет. Для текста всегда указываем FALSE.
Итак, задача стоит следующая: мы должны понять, к какому королевству относится указанная крепость, затем по королевству выяснить, какая фамилия за ним закреплена.
Первую формулу VLOOKUP мы используем для того, чтобы вычислить в какой территории принадлежит крепость. Именно название королевства и будет являться результатом этой формулы.
Вторую формулу VLOOKUP мы используем для поиска соответствия фамилии. Результат первой формулы и будет являться аргументом search key общей формулы.
Задача 3
Дано:
Таблица 1
Вопрос:
Как сделать случайную выборку значений из списка с учетом процента вероятности выпадения каждого значения?
Решение
Вспомогательная таблица 1.1 — Соответствия крепостей и королевств с шансом выпадения каждой крепости.
Для того, чтобы вывести значения, нам нужно распределить шанс выпадения каждого отдельного значения. Его мы прописываем вручную. Общая сумма шансов должна быть равна 100%. В таблице с примерами расчетов эти проценты указаны в столбце I.
В столбце J нам нужно подсчитать суммарную вероятность. Суммарная вероятность в данном примере нам нужна для того, чтобы выбрать нужное значение из нашего диапазона, так как указанные проценты недостаточно информативны в нашем случае.
Как работает в формуле суммарная вероятность
Скажем, у нас есть три события, вероятность каждого из которых 8%, 2% и 3% соответственно. Суммарная вероятность представляет собой сумму этих вероятностей. Таким образом, в данном примере, мы совершаем бросок, в котором выкидываем случайное число от 1 до 13. Чем больше процент, тем больший диапазон суммарной вероятности ему соответствует. Выходит, что вероятность выпадения первого значения выше потому, что бросков с результатом 1, 2, 3, 4, 5, 6, 7 и 8 будет больше, чем с результатом, скажем, 9 и 10.
Вернемся к нашим таблицам.
Общий вид формулы:
Здесь у нас две новых формулы — MATCH и RAND.
MATCH — это формула, которая ищет совпадение в диапазоне и возвращает порядковый номер этого совпадения. То есть не само значение ячейки, а его порядковый номер в столбце или строке.
Синтаксис формулы:
Где:
search_key — значение, которое мы ищем. Может быть как числовым, так и текстовым.
range — диапазон, в котором осуществляется поиск. Это может быть либо диапазон одного столбца, либо одной строки. Массив ячеек разных столбцов и строк выделять нельзя.
search_type — это особые условия поиска:
- 1 — значение по умолчанию, указывает на то, что массив значений диапазона, среди которых осуществляется поиск, отсортирован по возрастанию;
- 0 — требует поиска точного совпадения;
- -1 — указывает на то, что массив значений поиска отсортирован по убыванию.
На простом примере:
Результат формулы — 4, потому что в указанном диапазоне из 5 строк слово «Пельмешек» находится в ячейке с порядковым номером 4.
В случае с числовыми значениями, если MATCH не находит точного совпадения, она округляет число и выбирает наиболее близкое. Если диапазон поиска отсортирован по возрастанию, как в примере, формула округляет значение в меньшую сторону, именно поэтому она выбирает значение «40» как наиболее близкое.
В случае, если search_type будет «-1», а значения в строке 2 будут отсортированы по убыванию, от 80 до 1, то результатом формулы будет «1», то есть ячейка со значением «80». При search_type = -1, округление происходит в большую сторону.
Формула RAND просто выводит случайное значение от 0 до 1.
Синтаксис формулы:
Эта формула генерит примерно вот такие числа:
Нужно учесть, что RAND, так же как и RANDBETWEEN, заново создает все значения при совершении любых манипуляций со страницей.
Соберем вместе две формулы и рассмотрим их относительно нашей таблицы:
С помощью формулы INDEX мы найдем нужное значение в столбце. Для этого, как мы помним, нам нужен диапазон поиска и номер строки или столбца. В нашем случае поиск осуществляется по одному столбцу, так что нам просто нужен номер строки.
Диапазон функции INDEX нам известен — это группа ячеек $G$5:$G$22 — наш список крепостей.
Номер строки мы вычисляем с помощью функции MATCH. Для этого, с помощью RAND мы генерим случайное число от 0 до 1, а затем ищем соответствия в столбце с нашей суммарной вероятностью. Так как столбец с суммарной вероятностью отстортирован по возрастанию, округление будет производиться в меньшую сторону. Именно поэтому в первой ячейке диапазона $J$5:$J$22 мы вручную вводим значение 0: формула RAND может сгенерировать значение 0,001… и тогда, при округлении в меньшую сторону, у нас выпадет Highgarden, который соответствует нулевой суммарной вероятности.
В нашей таблице крепость Sunspear имеет наибольший шанс выпадения — 26%. Именно поэтому суммарная вероятность выпадения следующей в списке крепости, Lemonwood, так высока — 0,67 против 0,41 у Sunspear. Тем не менее, из-за того, что функция MATCH округляет значения в меньшую сторону, все результаты RAND начиная с 0,41 и заканчивая 0,66 будут приходиться именно на Sunspear, а это самый большой промежуток для бросков в таблице.
Таблица 2: Генератор квестов
Задача 4
Дано:
Таблица 2 — Генератор заданий
Столбец L — уровень игрока;
Столбец M— максимальное (или среднее) время для задания на данном уровне;
Столбец N— задание;
Столбец O — предмет для задания;
Столбец P — время на однократное выполнение условия задания;
Столбец Q — максимум предметов, который мы можем попросить в задании;
Столбец R— количество предметов, которые мы просим по заданию;
Столбец S— итоговое количество времени, которое игрок потратит на выполнение задания.
Вопрос:
Как сделать генератор заданий с учетом уровня игрока?
Решение
Таблица, которую я сделала в примере в принципе довольно простая. Моей задачей было показатьдополнительные свособы использования функций формул-рандомайзеров. Вы, конечно же, сможете сделать ваши таблицы сложнее, надстроив на них другие, нужные вам формулы.
Представим, что у нашего генератора есть ряд условий.
- Предметы, которые мы просим в задании, доступны игроку не с 1 уровня, а открываются постепенно.
- На каждом уровне есть максимальное количество времени, которое игрок должен тратить на задания.
- У каждого предмета есть лимит, больше которого мы не хотим просить в заданиях, чтобы они не превращались в гринд и рутину.
- В итоге нам необходима наглядная таблица с большим количеством данных, чтобы мы могли в полной мере оценить потенциальные задачи игрока на каждом этапе игры.
Вспомогательная таблица 2.1 — Список всех возможных условий
Вспомогательная таблица 2.2 — Параметры предметов
Стобец M — уровень, когда предмет становится доступен игроку;
Стобец N— название предмета;
Стобец O — время, необходимое для совершения действия с одним предметом;
Стобец P — максимальное количество предметов, которые могут участвовать в задании.
Теперь пройдемся по каждому столбцу большой таблицы 2.
Таблица 2, столбец L
Тут мы просто вручную прописываем уровни игрока по порядку.
Таблица 2, столбец M
Максимальное (или среднее) время на задание прописывается вручную в этом столбце. В идеале оно тоже рассчитывается по формуле в соответствии с вашим балансом.
Таблица 2, столбец N
Условия задания мы выводим той же формулой, с помощью которой ранее выбирали случайные имена для NPC в задаче 1:
В качестве диапазона для формулы INDEX мы указываем условия заданий в таблице 2.1, а в качестве номера строки генерируем RANDBETWEEN случайное число от 1 до 5 (количество вероятных условий).
Таблица 2, столбец О
Для того, чтобы подобрать подходящий предмет для условия задания, нам недостаточно просто выбрать случайное значение, как в случае с условием в столбце N, необходимо также учесть доступность предмета по уровню.
Разберем формулу по частям.
Для формулы INDEX мы указываем диапазон ячеек, из которого нам нужно вернуть значения. В нашем примере это таблица 2.2, столбец с названиями предметов.
Номер строки мы вычисляем с помощью формулы MATCH.
Поскольку на пятом уровне игроку доступны все предметы, открытые на предыдущих уровнях, мы можем просить у него в заданиях любые из них, а не только предметы пятого уровня. Поэтому в качестве искомого значения MATCH мы используем не просто уровень, на котором будет выдаваться задание, а случайное значение из списка всех полученных уровней. В формуле это значение из диапазона L$5:L5, потому что она была взята из ячейки для первого уровня. Для, скажем, седьмого, будет участвовать диапазон L$5:L11. Первое значение диапазона мы делаем фиксированным со знаком «$», потому что хотим, чтобы генерация предмета начиналась с предметов первого уровня, то есть с пятой строки.
В качестве второго аргумента формулы MATCH мы указываем диапазон, в котором нужно искать соответствие. В нашем случае это уровни анлока предметов в таблице 2.2.
Таблица 2, столбцы P и Q
Информация для этих столбцов копируется из таблицы 2.2 обычной формулой VLOOKUP. Они нужны нам для дальнейших расчетов.
Таблица 2, столбец R
Здесь нам нужно вычислить количество предметов, которые мы просим в задании. В расчетах нужно учесть максимальный лимит предметов в задании и время, которое отводиться на выполнение задания на уровне.
Общий вид формулы:
Здесь у нас есть одна новая формула — ROUNDUP.
ROUNDUP — это формула, которая округляет число вверх с настраиваемой точностью.
Синтаксис формулы:
Где:
value — это значение, которое нужно округлить;
places — количество знаков после запятой, на которое происходит округление. Можно указать ряд значений:
- 0 — округление без знаков после запятой;
- 1, 2, 3, … — количество знаков после запятой, до которого нужно округлить;
- -1, -2, -3, … — округление до знака влево от запятой.
На простом примере:
Теперь разберем нашу формулу по частям:
Для начала мы делим количество времени, которое отводится на задание на количество времени на 1 предмет. Так мы получаем количество предметов, которое игрок может сделать на этом уровне в рамках задания. Полученное число округляем вверх до целого числа.
Если количество предметов превышает лимит, указанный в таблице, то в задании мы попросим именно этот максимум и ничего не будем считать больше.
Если же посчитанное число предметов меньше максимума, то мы оставляем его.
Таблица 2, столбец S
В этом столбце мы для удобства просто считаем сколько времени нам потребуется на выполнение сгенеренного задания и насколько оно отличается от максимального (среднего) времени на задание на уровне. По текущей формуле из-за ROUNDUP, некоторые задания сложнее среднестатистических, а некоторые, наоборот, проще. Можно модифицировать формулу, заменив ROUNDUP на ROUNDDOWN для округления вниз, или просто ROUND для математического округления.
Эту и другие статьи можно найти в моем блоге Вконтакте: https://vk.com/mistle_gamer