- PVSM.RU - https://www.pvsm.ru -

Заблуждения игроков при оценке рисков. Контроль генератора случайных чисел в разработке

Человеческий мозг [1] по своей природе очень плохо умеет оценивать вероятность срабатывания случайных событий, на основании выданной числовой оценки. И довольно хорошо на основании качественных оценок. А все потому, что человек мысленно делает конвертацию числовых вероятностей в качественные оценки, и делает это очень субъективно:

  • 80% попадания выстрела в игре — ну это почти гарантированное попадание;
  • 80% того, что ваш товарищ хоть когда-нибудь отдаст долг — не-не-не, так не пойдёт, это слишком большой риск;
  • 5% получения критического урона он NPC врага — маловероятно, риск можно игнорировать;
  • 1% риск падения сосульки, если пройти под крышей с капающими метровыми сосульками — ещё чего, лучше обойти с другой стороны тротуара;
  • 51% вероятность выигрыша в мини-игре в большой РПГ — можно рассчитывать на то, что после 20 ставок я чуть-чуть выиграю или, как минимум, останусь при своих… через 20 ставок… как такое могло случиться, что я проиграл половину всего своего золота? Тут явно сломан генератор случайных чисел!

Заблуждения игроков при оценке рисков. Контроль генератора случайных чисел в разработке - 1

В статье будут рассмотрены следующие вопросы:

  • ошибочные допущения в оценке вероятностей;
  • конкретные примеры заблуждений игроков и фактические вероятности «редких» событий;
  • генератор случайных чисел (вообще-то псевдослучайных);
  • ранние простые генераторы псевдослучайных чисел на примере Final Fantasy I;
  • подходы к реализации случайных событий с воспроизводимостью и без;
  • примеры удачно внедренных разных подходов и манипуляции в Fire Emblem.

I. Ошибочные допущения в оценке вероятностей

В процессе эволюции человеческий мозг [1] учился очень хорошо оперировать качественными оценками событий и образами своего опыта. А числа и абстрактную числовую оценку вероятности «случайных» событий человек придумал сравнительно недавно [1 [2]]. Тем не менее эти числа человек в своих оценках всё равно преобразует в качественные представления: чуть-чуть, мало, много, опасно, безопасно, достаточно. Оценки эти всегда зависят от контекста и субъективного отношения к этому контексту. Именно это и является основной причиной ошибочных числовых допущений.

В качестве примера будет рассмотрена пошаговая игра Disciples 2 [2 [3]]. В данной части статьи не будет рассматриваться качество генерации случайных чисел конкретно в этой игре. Про их генерацию будет достаточно данных во второй части статьи.

Заблуждения игроков при оценке рисков. Контроль генератора случайных чисел в разработке - 2

Disciples 2 — типичный промах [2 [3]]

Стандартная атака ближнего боя имеет шанс попадания 80%. Обычно этот шанс воспринимается игроком как "почти всегда", а риск промаха — "изредка / время от времени". Вероятность промахнуться 2 раза подряд при двух атаках равна 4%. Игрок этот риск воспринимает как "почти никогда / такое будет случаться крайне редко". И когда подобное случается, игроки возмущаются на «кривой рандом»: [3 [4]]; [4 [5]].

Но в ситуациях с двумя промахами подряд и оценкой риска в 4% беглая оценка игроком имеет несколько ошибочных допущений:

1. 4% это вовсе не "почти никогда". Это событие, которое будет случаться в каждом 25-ом независимом эксперименте (в среднем).

2. Оценка проводится на неправильном отрезке времени. Минимальным отрезком замера атак по 80% следует брать не 2 атаки, а все атаки одного класса (~80%) за время «настороженной» памяти игрока. Чаще всего за это время можно взять долгую игровую сессию или вообще всю игру, тут всё зависит от типа игры, памяти игрока и предпочтений считающего.

Так как настоящей статистики использования этой игры у меня нет, я буду исходить из предположения, что долгая игровая сессия в Disciples 2 длится 3 часа и за это время совершается около 250 атак с меткостью ~80%. Стоит заметить, что промахи врагов следует игнорировать, т.к. их промахи игрока не злят, и он редко их запоминает.

Так вот, оценивать следует ситуацию: «За все 250 атак ни разу не произойдет 2 промахов подряд».
Для подсчета вероятности истинности данного события была использована рекуррентная формула: P1(n)=0.8*P1(n-1)+0.16*P1(n-2). В выведении этой формулы я воспользовался помощью сообщества, цитата вычислений, подробности и результат приведены ниже.

Можно попробовать применить индукцию. Введём несколько обозначений. Вероятность сохранить лапу после n-й вылазки обозначим P(n). Представим эту вероятность в виде суммы двух вероятностей
P(n) = P1(n)+P2(n), где P1(n) это вероятность, при которой крайняя n-ая вылазка оказалась удачной, а P2(n) — неудачной.

Может показаться что P1 и P2 пропорциональны 0.8 и 0.2, но это не так. Из-за того что мы рассматриваем не любые возможные исходы, а только те, которые сохранили лапу еноту.
Попробуем теперь вывести рекуррентную формулу
P1(n)=0.8*(P1(n-1)+P2(n-1))
P2(n)=0.2*P1(n-1)
Подставим P2 в формулу для P1 получим
P1(n)=0.8*P1(n-1)+0.16*P1(n-2)
Дальше Решение рекуррентных соотношений [5] [6]

Цитата с решением задачи от пользователя Serbbit [6 [7]]

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

var P1 = [];
P1[0] = 1;
P1[1] = 1;
for (var n=2; n<=250; n++) {
    P1[n] = 0.8 * P1[n-1] + 0.16 * P1[n-2];
    console.log(n + ') ' + P1[n]);
}
// ответ: 250) 0.0001666846271670716

В итоге ответ: 0.0001666846271670716
Или 0.0167%

Этот ответ совпадает с ответом другого автора Kojiec9: 0.000166684627177505 [6 [8]], который использовал свой выработанный метод с пятиричной системой счисления и вычислил результат по своей формуле в Паскале. Незначительные различия в ответах, объясняются, судя по всему, округлениями float чисел.

Так вот, за 3 часа игры в Disciples 2 игрок имеет шанс избежать двойного промаха при 80% меткости всего в 0.0167%. Вот это уже действительно очень маловероятно. (а вероятность хотя бы одного двойного промаха, соответственно равна 99.9833%).

Заблуждения игроков при оценке рисков. Контроль генератора случайных чисел в разработке - 3

Рост вероятности хотя бы одного двойного промаха с ростом числа экспериментов

Про несовершенство и искажения человеческой памяти, кстати, вообще целые исследования и книги существуют: «Иллюзии мозга [1]. Когнитивные искажения из-за переизбытка информации» [7 [9]]; «Не верьте своему мозгу» [8 [10]], если вас эта тема заинтересовала, рекомендую начать ознакомление с этих статей.

3. Третье неверное допущение — это ожидание зависимости во взаимно независимых экспериментах.

То есть после первого промаха игрок думает:

«Так, персонаж промахнулся с меткостью 80%. Теперь-то он точно попадёт, ведь риск двойного промаха равен всего 4%».

А вот и нет. После первого промаха риск очередного промаха будет так же равен 20%. Ведь прошлая атака уже случилась и никак не влияет на будущий выстрел. Более того, если до первой атаки вероятность двойного промаха была равна 4%, то после первого промаха вероятность двойного промаха становится уже 20%, то есть относительно ожиданий игрока риск только возрастает.

Эта особенность человеческого мозга [1] особенно привлекательна для манипуляций со стороны казино (и им подобных) в азартных играх (подробнее об устройстве игровых автоматов от производителя [9 [11]]).
Ещё интересные примеры заблуждений человеческого мозга [1] можно почерпнуть в статьях про баланс Яна Шрайбера «Level 5: Probability and Randomness Gone Horribly Wrong» (Уровень 5. Вероятность и случайность пошли вразнос) [10 [12]].

II. Генератор случайных чисел

Используемый в играх термин «Генератор случайных чисел» (RNG / random number generator) почти всегда в действительности означает «Генератор псевдослучайных чисел» [11 [13]]. Главной особенностью этого генератора является его воспроизводимость. Воспроизводимость означает то, что, зная изначальный порождающий элемент (или зерно / seed) всегда будет получена одна и та же последовательность случайных (псевдослучайных) чисел. В некоторых играх этот эффект проявляется в том, что после перезагрузки игры последовательность попаданий и промахов остается неизменной. А в других играх не остается той же самой.

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

Чтобы лучше понять принцип работы генератора псевдослучайных чисел, можно рассмотреть способ его реализации в первых классических играх, когда ресурсы компьютеров (и консолей) были особенно сильно ограниченны. (Углубленное описание примеров и их особенностей читайте в статье «How classic games make smart use of random number generation» [12 [14]].)

Заблуждения игроков при оценке рисков. Контроль генератора случайных чисел в разработке - 4

How classic games make smart use of random number generation [12 [14]]

В Final Fantasy I использовались несколько таблиц с заранее заданными фиксированными числами с 256 значениями в каждой таблице:

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

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

Сейчас для генерации псевдослучайных чисел в основном используются стандартные библиотеки используемых языков программирования. В качестве источника энтропии чаще всего используется текущее системное время. Для нужд игровой индустрии характеристик стандартных библиотек обычно хватает. Недостатки генератора и источника энтропии используются игроками очень редко из-за сложности их вычисления и манипулирования. Обычно это остаётся уделом спидранеров-программистов (например, взламывающего логику Pokemon Colosseum [13 [15]]), а значит разработчикам такие тонкости чаще всего разумнее игнорировать.

III. Разные подходы к использованию генератора

1. Зерно фиксируется на момент старта миссии или игровой кампании.

Последствия для игрока: перезагрузка игры не изменит факт промаха персонажем (назовем его чокнутым Фиделем), даже если вероятность его попадания равна 99%. Однако, перед попыткой попасть игрок может совершить какое-либо другое действие, которое использует случайное число, например, походит другим персонажем — лысым Миком. В результате этого несчастливое случайное число будет использовано лысым Миком, а на чокнутого Фиделя будет использовано следующее случайное число в последовательности — тогда он, возможно, попадёт.

Как игрок может злоупотребить этим: если бросок с меткостью 50% приводит к промаху, то можно перезагрузиться и попробовать атаку с меткостью чуть-чуть повыше (55%), пока не попадёт. После попадания сохраниться и повторить это с другими бросками.

Положительные последствия для разработчика:

1) Игру можно воспроизвести пошагово, если хранить только начальное состояние, зерно и последовательность действий. Благодаря этому можно показывать повторы и даже очень компактно хранить файлы сохранений. Способ позволяет очень сильно сэкономить занимаемое место на диске/памяти.

2) Защита внутренних азартных игр, чтобы сохранение/загрузка не позволяла игроку обанкротить всех встречающихся NPC соперников.

Пример:

Игра roguelike Brogue [14 [16]] использует этот способ, начиная с генерации игрового мира и заканчивая просчетом всех действий игрока. В результате этого в файле сохранения хранится только стартовое зерно и последовательность игровых команд. Дополнительный бонус этого эффекта в том, что игру можно начать с выбранным номером зерна, предварительно выбрав наиболее интересный мир в таблицах сгенерированных миров Brogue [15 [17]].

Заблуждения игроков при оценке рисков. Контроль генератора случайных чисел в разработке - 5

Brogue roguelike — официальный сайт [14 [16]]

2. Зерно не фиксируется или обновляется каждый раз после перезагрузки.
Последствия для игрока: любая перезагрузка изменяет все расчеты в шансах попаданий.

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

Положительные последствия для разработчика:

1) Игроки воспринимают такую игру как более честную с настоящей случайностью, просто из-за отсутствия знаний внутренних механик.

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

3) Разработчик может прикрыть халяву разными методами: одним автосохранением на игру (то есть перезаписывание сохранений и перманентная смерть) или запретом сохранения во время миссии (в разных вариациях). А наиболее чувствительные участки (азартные мини игры) можно просчитывать на основании отдельного неизменного зерна, хотя технически это значительно труднее.

Пример:

Игра The Battle for Wesnoth [16 [18]] использует нефиксированное зерно с принципиально честной случайностью. Честность заключается в том, что иногда возможны совершенно маловероятные последовательности неудач, и движок игры их не корректирует. Результатом этого являются периодические гневные посты раздраженных игроков в адрес разработчиков игры.

Заблуждения игроков при оценке рисков. Контроль генератора случайных чисел в разработке - 6

Reddit — супер ловкая русалка в Wesnoth [17 [19]]

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

3. Зерно не фиксируется, а сами результаты подвергаются дополнительным манипуляциям.

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

Последствия для игрока: аналогично играм с нефиксированным зерном — перезагрузка позволяет пересчитать результаты.

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

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

Примеры:

Разработчик Carsten Germer использует функцию контролируемой случайности для редких и не только событий [18 [20]]. Например, чтобы гарантировать периодическое выпадение особо редкого бонуса с шансом 1 к 10000, он после каждого «промаха» увеличивает шансы по порядку: 1 к 9900; 1 к 9800; 1 к 9700… и так до фиксации события. А чтобы гарантировать отсутствие частых редкостей, он ввел дополнительную переменную, блокирующую срабатывание на 100% в течение 10 следующих проверок после прошлого срабатывания.

В своем рогалике Grue the Monster [19 [21]] я также использовал манипуляции со случайностями. Обычно при преследовании жертв персонаж игрока должен прятаться за их спинами, поджидая, когда они сделают шаг назад и попадут к нему в лапы. Обычно такой шанс равен 1/6 в открытом пространстве (1/2 в коридорах и 1/1 в тупиках), но чтобы уменьшить раздражающий эффект особенно невезучих ситуаций, перед каждой проверкой направления хода жертвы в 15% случаев она гарантированно шла в направлении к Гру.

Самый интересный случай: в игре Fire Emblem: The Binding Blade [20 [22]] была реализована скрытая механика определения попадания при атаках [21 [23]]. Традиционно для серии вероятность попадания показывается игрой в процентах от 0 до 100%. В более ранних играх серии факт попадания определялся одним случайным числом от 1 до 100: если выпадающее число (например, 61) меньше или равно вероятности попадания (например, 75), то засчитывается удар, если больше, то промах.

Заблуждения игроков при оценке рисков. Контроль генератора случайных чисел в разработке - 7

Fire Emblem: The Binding Blade [20 [22]]

В данной части была введена щадящая система: вместо одного случайного числа бралось среднее двух случайных чисел, и это среднее сравнивалось со значением меткости. То есть случайное число в большей степени стремится к значению 50. Это приводит к искажению линейного эффекта случайности попадания: бойцы с меткостью больше 50% попадают чаще, чем в 50% случаев, а с меткостью меньше 50% значительно реже. А так как в игре подавляющее большинство персонажей игрока имеют большую меткость, а большинство врагов меньшую, то игрок получает очень серьёзное скрытое преимущество [21 [23]]. Ниже показан график этого эффекта, где синей линий показана частота попаданий в старой системе, а красной частота попаданий в новой в зависимости процента меткости атакующего. Например, при показываемой вероятности попадания в 90%, фактическая вероятность будет равна 98,1%, при 80% — 92,2%, а при 10% — всего 1,9%!

Заблуждения игроков при оценке рисков. Контроль генератора случайных чисел в разработке - 8

Искажение шанса попадания. По оси Y фактическая вероятность, по оси X — показываемая игроку

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

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

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

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

4. Вообще убрать элемент случайности из механики игры.

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

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

Последствия для игрока: перезагрузка либо никак не влияет на результаты, либо влияет незначительно.

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

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

Пример:

Любые шахматы с классическими правилами.

Также сюда подходят логические roguelike. Например, очень хорошо данный метод реализован в Desktop Dungeons Alpha [22 [24]].

Заблуждения игроков при оценке рисков. Контроль генератора случайных чисел в разработке - 9

Desktop Dungeons Alpha [22 [24]]

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

Заключение

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

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

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

Источники и литература

1. История математики, теория вероятностей — Википедия [2].
2. Disciples 2 — GOG Gold [3].
3. Disciples 2 — комментарий про кривой рандом №1 [4].
4. Disciples 2 — комментарий про кривой рандом №2 [5].
5. Решение рекуррентных соотношений [6].
6. Цитата с решением задачи от пользователя Serbbit [7].
7. Иллюзии мозга. Когнитивные искажения из-за переизбытка информации [9].
8. Не верьте своему мозгу [10].
9. Игровой аппарат изнутри и снаружи. Обзор от производителя [11].
10. Level 5: Probability and Randomness Gone Horribly Wrong [12].
11. Генератор псевдослучайных чисел — Википедия [13].
12. How classic games make smart use of random number generation [14].
13. Controlling luck in video games — Pokemon Colosseum and XD [15].
14. Brogue roguelike — официальный сайт [16].
15. The Brogue Seed Scummer [17].
16. The Battle for Wesnoth [18].
17. Супер ловкая русалка в Wesnoth [19].
18. «Not So Random Randomness» in Game Design and Programming [20].
19. Grue the Monster roguelike [21].
20. Fire Emblem: The Binding Blade [22].
21. Random Number Generator in Fire Emblem [23].
22. Desktop Dungeons Alpha roguelike [24].

Автор: qnok

Источник [25]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/gamedev/302761

Ссылки в тексте:

[1] мозг: http://www.braintools.ru

[2] 1: https://ru.wikipedia.org/wiki/%D0%98%D1%81%D1%82%D0%BE%D1%80%D0%B8%D1%8F_%D0%BC%D0%B0%D1%82%D0%B5%D0%BC%D0%B0%D1%82%D0%B8%D0%BA%D0%B8

[3] 2: https://www.gog.com/game/disciples_2_gold

[4] 3: http://nevendaar.com/forum/17-98-88989-16-1332796965

[5] 4: http://forums.playground.ru/disciples_2_dark_prophecy/kto_silnee-56926/#comment-1054762

[6] Решение рекуррентных соотношений [5]: https://neerc.ifmo.ru/wiki/index.php?title=%D0%E5%F8%E5%ED%E8%E5_%F0%E5%EA%F3%F0%F0%E5%ED%F2%ED%FB%F5_%F1%EE%EE%F2%ED%EE%F8%E5%ED%E8%E9

[7] 6: https://pikabu.ru/story/matematicheskaya_zadacha_kakaya_veroyatnost_togo_chto_k_vyikhodu_na_pensiyu_enot_mikhail_sokhranit_svoyu_pravuyu_lapu_6329318?cid=127758009

[8] 6: https://pikabu.ru/story/matematicheskaya_zadacha_kakaya_veroyatnost_togo_chto_k_vyikhodu_na_pensiyu_enot_mikhail_sokhranit_svoyu_pravuyu_lapu_6329318?cid=127755779

[9] 7: https://habr.com/post/398831/

[10] 8: https://habr.com/post/154681/

[11] 9: https://habr.com/post/405065/

[12] 10: https://gamebalanceconcepts.wordpress.com/2010/08/04/level-5-probability-and-randomness-gone-horribly-wrong/

[13] 11: https://ru.wikipedia.org/wiki/%D0%93%D0%B5%D0%BD%D0%B5%D1%80%D0%B0%D1%82%D0%BE%D1%80_%D0%BF%D1%81%D0%B5%D0%B2%D0%B4%D0%BE%D1%81%D0%BB%D1%83%D1%87%D0%B0%D0%B9%D0%BD%D1%8B%D1%85_%D1%87%D0%B8%D1%81%D0%B5%D0%BB

[14] 12: https://www.gamasutra.com/view/news/320213/How_classic_games_make_smart_use_of_random_number_generation.php

[15] 13: https://aldelaro5.wordpress.com/2018/09/09/controlling-luck-in-video-games-an-explanation-of-the-rng-manipulation-on-pokemon-colosseum-and-xd/

[16] 14: https://sites.google.com/site/broguegame/

[17] 15: http://brogue.wikia.com/wiki/Seedscummer

[18] 16: https://www.wesnoth.org/

[19] 17: https://www.reddit.com/r/gaming/comments/7cf4dt/wesnoth_can_be_very_unfair/

[20] 18: https://www.gamasutra.com/blogs/CarstenGermer/20131118/204997/quotNot_So_Random_Randomnessquot_in_Game_Design_and_Programming.php

[21] 19: https://play.google.com/store/apps/details?id=rpg.roguelike.grue.monster

[22] 20: https://en.wikipedia.org/wiki/Fire_Emblem:_The_Binding_Blade

[23] 21: https://fireemblem.fandom.com/wiki/Random_Number_Generator

[24] 22: http://www.desktopdungeons.net/media/

[25] Источник: https://habr.com/post/432080/?utm_source=habrahabr&utm_medium=rss&utm_campaign=432080