Математика невезения: как игры подкручивают случайность
Всем привет! Меня зовут Гриша Дядиченко, и я технический директор и основатель White Label Games. Уже больше десяти лет работаю с компьютерной графикой, AR/VR и компьютерным зрением — в основном заказная разработка, иногда собственные прототипы по выходным.
На этой неделе в телеграм-канале я постил короткие разборы про случайность в играх: про криты Dota, которые стартуют с 8,5% при обещанных 25%, про seed Minecraft, вычисленный по одной картинке, и про нож из кейса CS, где «монетка 50/50» стоит 660 $. Пора собрать всё в одну историю — с формулами, выводом констант и интерактивами, которые можно покрутить прямо со страницы.
Сталкивались ли вы с ситуацией, когда игрок после тридцати убийств без дропа на пятипроцентном шансе пишет в саппорт «у вас сломан рандом»? Генератор при этом работает идеально. Сломаны ожидания.
Сквозная идея простая. Случайность в играх собрана из трёх слоёв. Внизу — Pseudo-random number generator, генератор псевдослучайных чисел: детерминированная рекуррента, у которой случайного только начальное состояние — seed., детерминированная формула, которая лишь притворяется костями. В середине — искажатели вроде PRD и pity, которые меняют распределение под человеческое восприятие, потому что честная равномерность ощущается сломанной. Наверху — экономика: геометрическое распределение, кривая 1 − (1 − p)^N и регуляторы, которые решают, где тут граница с казино.
Если интересна тема — добро пожаловать.
[больше интересного в телеграм]1. Внутри генератора
Одна картинка против 2⁴⁸ вариантов
В Minecraft есть файл pack.png — маленькая картинка 512×512, которая годами лежала в ресурсах игры как заставка. Скриншот какого-то мира из старой версии. В 2020 году группа энтузиастов Minecraft@Home задалась вопросом: а можно ли по одной этой картинке вычислить seed мира, в котором её сняли?
Можно. Сначала по облакам и текстурам восстановили точку съёмки и ракурс (выяснилось заодно, что снимали обычным Print Screen с кропом до 512×512). Потом написали фильтр: какие сиды вообще могут породить вот такое сочетание песка и земли в кадре. Прогнали перебор по всем 2⁴⁸ вариантам на распределённой сети BOINC — около 3700 добровольцев, примерно три дня машинного времени. Фильтр сузил пространство до ~700 тысяч кандидатов, дальше добили точной проверкой. Ответ: seed 3257840388504953787.
Вдумайтесь в постановку: по одной картинке восстановили вселенную. Весь мир Minecraft — миллиарды блоков, пещеры, деревни, биомы — однозначно разворачивается из одного числа. И раз так, то перебрав все числа, мир можно «вскрыть» обратно.
Почему перебор был именно по 2⁴⁸, мы сейчас увидим — это число прямо следует из формулы генератора.
Строка арифметики
Minecraft написан на Java, а java.util.Random устроен так: внутри лежит 48-битное состояние, и каждый запрос нового числа делает один шаг рекурренты
state = (a · state + c) mod m
с конкретными константами a = 0x5DEECE66D, c = 0xB, m = 2⁴⁸ — они прописаны в официальной документации класса. Наружу отдаются старшие биты состояния. Вот и весь источник «случайности»: умножить, прибавить, взять остаток. Такая схема называется линейным конгруэнтным генератором (LCG), и в учебниках она идёт первой уже полвека.
На C# тот же генератор пишется в пять строк:
public class Lcg
{
private ulong _state; // seed
public Lcg(ulong seed) => _state = seed;
public double Next()
{
_state = (0x5DEECE66DUL * _state + 0xBUL) & ((1UL << 48) - 1);
return (_state >> 24) / (double)(1UL << 24); // [0, 1)
}
}Из числа в [0, 1) дальше делается всё: value < 0.05 — выпал ли дроп на 5%, min + value * (max - min) — разброс урона, индекс в массиве — выбор реплики NPC.
Ключевое свойство здесь — детерминизм. Начальное значение _state и есть seed. Один seed — одна и та же последовательность, всегда, на любой машине. Проверьте сами:
Отсюда сиды Minecraft, общие daily-уровни в Spelunky и RNG-манипуляции в спидранах, где игроки покадрово «заказывают» себе нужный дроп. И отсюда же история pack.png: состояние генератора 48-битное, значит миров существует ровно 2⁴⁸, и это число переборное. Сообщество, кстати, развлекается этим до сих пор — есть инструмент SeedcrackerX, который вычисляет seed чужого сервера просто по координатам найденных структур.
Чтож, формула из одной строки порождает мир. Но почему этой строке вообще можно доверять? Любые ли a, c, m годятся?
Спектральный тест и 15 плоскостей RANDU
Конечно же нет. И хрестоматийный пример провала — генератор RANDU, который IBM поставляла в 60-х и которым успели посчитать заметное количество научных работ. У RANDU a = 65539, c = 0, m = 2³¹. Выглядит безобидно, пока не взять три подряд идущих числа и не нарисовать их как точку в кубе. Все такие точки ложатся ровно на 15 плоскостей. Причина зашита в арифметике: 65539 = 2¹⁶ + 3, и если возвести это в квадрат по модулю 2³¹, получится тождество
x[k+2] = 6·x[k+1] − 9·x[k] (mod 2³¹)
Каждая тройка «случайных» чисел RANDU связана линейным уравнением. Для физической симуляции, которая берёт по три числа на координаты точки, это катастрофа: вся «случайность» живёт на 15 листах внутри куба. Покрутите ракурс — плоскости видны глазами:
Формальный способ ловить такие провалы — спектральный тест: он меряет, насколько плотно точки из последовательных чисел генератора заполняют пространство, и описан у Кнута во втором томе The Art of Computer Programming вместе с разбором, какие константы LCG выбирать. Там же критерий полного периода — теорема Халла—Добелла. Так что подбор a, c, m давно перестал быть искусством, это таблицы и проверки.
Что стоит в движках сегодня
Индустрия из LCG в основном выросла. Кто чем пользуется:
- Java
java.util.Random— тот самый LCG с 48-битным состоянием. Живая классика. - Python
randomи C++std::mt19937— Mersenne Twister (Мацумото и Нисимура, 1998). Период 2¹⁹⁹³⁷ − 1, гигантское состояние в 2,5 КБ. - JavaScript — в V8
Math.random()работает на xorshift128+: несколько сдвигов и XOR, очень быстро. - .NET — начиная с .NET Core 3.0 внутри
System.Randomсемейство xoshiro. - Unity
UnityEngine.Random— Xorshift128 по статье Марсальи, это прямо написано в документации. Состояние из четырёх 32-битных слов, статическое, поэтому из джобов и потоков пользоваться им нельзя. - PCG (Мелисса О'Нил, 2014, pcg-random.org) — LCG с пермутацией выходных бит; популярный выбор, когда в проекте нужен свой переносимый генератор с маленьким состоянием.
С генератором разобрались. Дальше начинается интересное: равномерная случайность, которую он выдаёт, игрокам не нравится.
2. Слой искажения: PRD против тильта
Почему Spotify переписал shuffle
В 2014 году Spotify опубликовал в инженерном блоге пост «How to shuffle songs?». Завязка такая: с запуска сервиса shuffle работал на тасовании Фишера—Йетса, то есть выдавал математически безупречную случайную перестановку плейлиста. И пользователи писали жалобы, что shuffle сломан. Два трека одного исполнителя подряд? «Это не рандом». Песня повторилась в начале новой сессии? «Это не рандом».
В посте Spotify прямо ссылается на ошибку игрока (gambler's fallacy): человек ждёт, что случайность «помнит» прошлое и обязана выравниваться на коротких дистанциях. Настоящая случайность ничего не помнит. Кластеры и повторы для неё норма, и именно кластеры люди опознают как неслучайность. Spotify сдался и заменил честный shuffle на алгоритм, который намеренно размазывает треки одного исполнителя по плейлисту. Стало «менее случайно» и перестало раздражать.
Теперь переложите это на игры. На крите с шансом 25% серия из шести промахов подряд имеет вероятность 0,75⁶ ≈ 17,8% — почти каждая пятая шестёрка атак. За вечер у игрока таких серий будет несколько, и каждая ощущается как обман. Поэтому поверх честного генератора игры строят второй слой — искажение распределения под восприятие. Давайте разберём основные приёмы, все с формулами.
PRD: крит, который помнит прошлые промахи
Самый известный приём — pseudo-random distribution (PRD) из Warcraft III и Dota 2. Идея: шанс прока растёт с каждой неудачей и сбрасывается после успеха. Вероятность на N-й атаке после последнего крита:
Первая атака — шанс C, вторая — 2C, третья — 3C, и так до прока. Крит случился — счётчик обнулился.
Вся хитрость в подборе константы C. Условие: на длинной дистанции частота критов обязана совпасть с номиналом из тултипа. Распишем. Вероятность того, что прок случится ровно на n-й атаке:
Отсюда среднее число атак на один прок E[N] — обычное матожидание по этому распределению, а эффективная частота критов — 1/E[N]. Требуем 1/E[N] = p, где p — номинал, и решаем относительно C. В замкнутом виде уравнение не решается, C находят численно. Для номинальных 25% получается C = 0,08474409…
Смотрите, что это означает на практике для «25% крита» в Dota:
| Атака после крита | Шанс крита |
|---|---|
| 1 | 8,5% |
| 2 | 16,9% |
| 3 | 25,4% |
| 6 | 50,8% |
| 12 | 100% |
Первый удар критует в три раза реже тултипа, зато к 12-й атаке (C·12 ≥ 1) крит гарантирован. Длинная полоса невезения становится математически невозможной. Таблица констант для других номиналов (по Liquipedia, там она полная, от 5% до 95%):
| Номинал | C | Гарантия на атаке |
|---|---|---|
| 5% | 0,00380 | 264 |
| 10% | 0,01475 | 68 |
| 15% | 0,03222 | 32 |
| 20% | 0,05570 | 18 |
| 25% | 0,08474 | 12 |
| 30% | 0,11895 | 9 |
| 50% | 0,30210 | 4 |
| 70% | 0,57143 | 3 |
Реализация — десяток строк:
public class PrdRoller
{
private readonly float _c;
private int _n;
public PrdRoller(float c) => _c = c; // C под номинал, из таблицы
public bool Roll()
{
_n++;
if (Random.value < _c * _n) // UnityEngine.Random, [0, 1)
{
_n = 0;
return true;
}
return false;
}
}В Dota через PRD идут криты Crystalys и Daedalus, Coup de Grace у Phantom Assassin, Blade Dance Джаггернаута, Chaos Strike, бэши Skull Basher и Abyssal Blade — список длинный.
А вот как PRD ощущается против честной монетки — симуляция на 200 000 атак. Смотрите на хвост распределения: у честного генератора он уходит далеко вправо, у PRD обрывается на гарантии:
3. Pity, два броска и aim assist
Pity: у невезения появляется потолок
Гача-игры решают ту же проблему другим инструментом — pity-системой, то есть жёсткой гарантией. Канонический пример — Genshin Impact. Официально раскрытые в самой игре цифры для пятизвёздочного персонажа: базовый шанс 0,6%, «суммарная вероятность с учётом гарантии» 1,6%, гарантия на 90-й крутке. Откуда берётся разрыв между 0,6 и 1,6? Из устройства pity: где-то ближе к концу окна шанс начинает расти, и почти все «пятёрки» выпадают в этой зоне.
Соберите свою гарантию и посмотрите, как база превращается в эффективную вероятность:
Hearthstone устроен похоже. Гарантию легендарки в первых 10 паках нового набора и защиту от дублей (легендарка, которая у вас уже есть, из пака не выпадет, пока не собран весь пул сета) Blizzard анонсировала официально. Третье правило вывело комьюнити по статистике вскрытий: дольше 40 паков подряд сет легендарку не задерживает, и таймер у каждого набора свой.
По сути pity превращает геометрическое распределение «сколько паков до удачи» в распределение с обрезанным хвостом: «мне не везёт уже 200 круток» становится невозможным событием. Игрок защищён от худшего сценария. Запомните этот механизм — в разделе про деньги мы увидим его вторую сторону.
Fire Emblem: два броска вместо одного
Приём поинтереснее — подкрутить сами проценты на экране. В Fire Emblem начиная с Binding Blade (2002) и примерно до 12-й части работала система, которую фанаты назвали 2RN или true hit. Игра показывает шанс попадания, скажем, 70%. Но при расчёте бросается два числа от 0 до 99, берётся их среднее, и попадание засчитывается, если среднее меньше экранного шанса.
Сумма двух равномерных бросков распределена треугольником: середина диапазона вероятна, края редки. Поэтому реальная вероятность расходится с экранной:
| На экране | На самом деле |
|---|---|
| 30% | 18,3% |
| 50% | 50,5% |
| 70% | 82,3% |
| 90% | 98,1% |
| 99% | 99,99% |
Высокие шансы система завышает, низкие — занижает. И это ровно та поправка, которой требует интуиция: игроки воспринимают «90%» как «почти наверняка», и 2RN делает 90% почти наверняка (98,1%). А вражеский удар с шансом 30% долетает лишь в 18,3% случаев, и игрок чувствует себя «тактиком, который грамотно рискнул». Числа на экране врут, и именно поэтому им верят.
XCOM: подкрутка прямо в конфиге
XCOM с его легендарными промахами в упор пошёл тем же путём, только это можно прочитать глазами. В XCOM 2 откройте DefaultGameCore.ini — скрытые модификаторы меткости лежат прямо там. На ветеране работает BaseXComHitChanceModifier=1.2: экранные шансы вашего отряда умножаются на 1,2. После серии промахов включается aim assist: +10 к шансу на ветеране, +15 на командире. Отключено всё это только на сложности Legend. Источник знания — сами файлы игры и моды вроде Remove Aim Assists, которые эти строки вычищают.
То есть «подлый рандом XCOM», про который написаны тысячи гневных постов, на самом деле жульничает в пользу игрока. Просто промах с экранными «95%» запоминается на годы, а тихая прибавка +20% к реальному шансу — нет.
Shuffle bag: мешок вместо бросков
Последний приём — самый старый и самый простой: убрать независимые броски совсем. Shuffle bag: складываем все варианты в мешок, тасуем, раздаём по очереди; мешок опустел — собираем и тасуем заново. Канонический пример — правило 7-bag из Tetris Guideline: семь фигур тасуются и выдаются все по разу, потом новый мешок. Поэтому засуха по конкретной фигуре ограничена 12 ходами (фигура первой в одном мешке и последней в следующем), I-образная палка гарантированно приходит.
public class ShuffleBag<T>
{
private readonly List<T> _items;
private int _cursor;
public ShuffleBag(IEnumerable<T> items)
{
_items = new List<T>(items);
_cursor = _items.Count;
}
public T Next()
{
if (_cursor >= _items.Count) // мешок пуст — тасуем (Фишер—Йетс)
{
for (int i = _items.Count - 1; i > 0; i--)
{
int j = Random.Range(0, i + 1);
(_items[i], _items[j]) = (_items[j], _items[i]);
}
_cursor = 0;
}
return _items[_cursor++];
}
}Тот же принцип отлично работает для всего, что не должно слипаться: фоновые реплики NPC, случайные события на карте, выбор музыкального трека. Spotify со своим размазыванием исполнителей по плейлисту, по сути, построил усложнённую версию мешка.
Итак, у нас есть честный генератор и набор искажателей поверх него. Остался третий слой — тот, где вероятности встречаются с кошельком.
[больше интересного в телеграм]4. Математика дропрейта и деньги
Сколько стоит нож
11 сентября 2017 года издатель Perfect World, через которого Valve работает в Китае, впервые опубликовал точные шансы кейсов CS:GO — китайский регулятор обязал раскрывать вероятности. Цифры такие: Mil-Spec 79,92%, Restricted 15,98%, Classified 3,20%, Covert 0,64%, нож или перчатки — 0,26%. Комьюнити-статистика по миллионам вскрытий эти проценты подтверждает, и до CS2 они не менялись. Ключ к кейсу стоит 2,49 $ с 2013 года. Pity-механики в кейсах нет: каждое вскрытие независимо.
Чтож, p = 0,0026 — давайте посчитаем, что это значит. Число попыток до первого успеха при независимых испытаниях описывается геометрическим распределением, и у него среднее равно 1/p:
Звучит как ответ на вопрос «сколько кейсов до ножа». Да? Конечно же нет. Среднее у геометрического распределения тянет вверх длинный хвост везунчиков наоборот — тех, кто открыл тысячи. Спросим лучше: к какому кейсу нож выпадет у половины игроков? Это медиана:
Медиана 267 при среднем 385. И даже дойдя до «среднего» 385-го кейса, вы с вероятностью 36,7% всё ещё сидите без ножа — потому что 0,9974³⁸⁵ ≈ 0,367. У распределения нет памяти: после 384 пустых кейсов шанс в следующем всё те же 0,26%.
Теперь деньги. Медианный путь до ножа — 267 ключей по 2,49 $, то есть около 660 $ (цену самих кейсов на маркете для простоты опустим). Хотите уверенности 99%? Считаем N из 1 − 0,9974^N = 0,99, получается ≈1769 кейсов — около 4 400 $. А теперь мой любимый парадокс этой недели. Вероятность открыть 2000 кейсов и остаться без ножа:
Это вдвое больше шанса выбить нож из первого же кейса (0,26%). Человек, потративший пять тысяч долларов впустую, статистически встречается чаще, чем человек, поймавший нож с первой попытки. Когда в следующий раз увидите ролик «нож с первого кейса» — помните, что где-то рядом ходят двое таких же везучих, только наоборот, и роликов они не снимают.
Кривая «хотя бы один раз»
Общая формула всей этой кухни — шанс хотя бы одного успеха за N независимых попыток:
Для p = 1%: сто попыток дают 63,4%, девяносто процентов уверенности требуют 230 попыток, девяносто девять — 459. Интуиция читает «1%» как «гарантия за сотню», формула отвечает: за сотню — почти монетка, и даже после 459 попыток один из ста игроков уйдёт пустым.
У кривой есть наглядная характеристика — период полураспада. Каждые ln(2)/p попыток (для ножа CS — каждые ~266 кейсов) вероятность «всё ещё ничего» падает вдвое: 100% → 50% → 25% → 12,5%… Хвост тает по экспоненте, но в ноль не превращается никогда.
Введите свой дропрейт и цену попытки — кривая пересчитает невезение в деньги:
Где вероятность становится монетизацией
До этого момента вся математика была нейтральной: PRD и pity честно режут дисперсию, формулы открыты. Монетизация начинается там, где знание этих формул применяют против интуиции игрока, которая их не знает.
Зазор «среднее против медианы» мы уже видели: «в среднем нож за 385 кейсов» звучит как обещание, при том что треть игроков на 385-м кейсе ещё ни с чем, а часть улетает в хвост за 2000. «В среднем» в маркетинге дропрейта почти ничего не обещает конкретному человеку — это свойство распределения, у которого правый хвост бесконечный.
Дальше классика дарк-паттернов. Near-miss: анимация рулетки, где легендарка проезжает мимо указателя и тормозит в соседней ячейке — приём, давно описанный в литературе про игровые автоматы; проигрыш, замаскированный под «почти выигрыш», подталкивает к следующей попытке. Sunk cost через pity: счётчик «до гарантии осталось 12 круток» превращает накопленное невезение в актив, который жалко бросить, и игрок докупает круток, чтобы «не потерять прогресс» — та же механика, которая защищает от худшего сценария, работает двигателем доплат. Нераскрытые шансы: пока закон не заставит, точные вероятности предпочитают не публиковать, и кейсы CS — живой пример: цифры мир увидел только после китайского регулятора, через четыре года после запуска механики.
Что на это ответили регуляторы
Хронология короткая, и она вся вертится вокруг одного вопроса: является ли платный случайный приз азартной игрой.
- Китай, 2017 — первый серьёзный ход: обязательное раскрытие вероятностей для лутбоксов и гачи. Прямое следствие — те самые проценты кейсов CS:GO от Perfect World.
- Apple, декабрь 2017 — App Store Review Guidelines, пункт 3.1.1: приложение с платными лутбоксами обязано раскрывать шансы каждого типа предмета до покупки.
- Бельгия, апрель 2018 — Gaming Commission изучила FIFA 18, Overwatch, CS:GO и Star Wars Battlefront II и признала платные лутбоксы в первых трёх азартной игрой по бельгийскому закону. Издатели отключили продажу лутбоксов в стране. Честности ради: исследование 2023 года в Collabra показало, что на практике запрет соблюдается неровно — формально запрещённые механики в бельгийских сторах находятся до сих пор.
- Нидерланды — самый поучительный сюжет. В 2020-м суд Гааги поддержал регулятора: ЕА грозил штраф до 10 млн евро за паки FIFA Ultimate Team. А в марте 2022-го Государственный совет решение отменил: паки признали частью «более широкой игры навыка», под закон об азартных играх они не попадают. Регулирование лутбоксов — живой процесс с ходами в обе стороны, и финальной точки в нём пока нет.
Для разработчика мораль практическая: если в игре есть платная случайность, раскрытие шансов уже фактически стандарт (этого требуют Китай и App Store), а юридический статус механики зависит от страны и может поменяться за один судебный цикл.
5. Что выбрать разработчику
Соберём инструменты в одну картину. Выбор зависит от того, насколько игрок видит последовательность исходов.
- Голый PRNG — когда отдельные исходы не образуют видимой игроку серии: разброс урона, ветвление генерации, визуальный шум. Дёшево, честно, дисперсию никто не заметит.
- PRD — когда игрок наблюдает длинную плотную серию проверок: криты, проки, уклонения в бою. Режет тильт и отрезает катастрофы. Помните о цене: короткие серии промахов учащаются, а счётчик выучивается и становится частью меты.
- Pity — когда событие редкое и дорогое: легендарки, пятизвёздочные персонажи, джекпот-дроп. Защищает худший сценарий и удерживает игрока. И он же — самый мощный монетизационный крючок из всех перечисленных, так что решение про pity всегда продуктовое, со всеми вытекающими вопросами этики.
- Shuffle bag — когда варианты не должны слипаться и каждый обязан появляться регулярно: фигуры, треки, реплики, события. Простейший код, нулевая математика, предсказуемый максимум засухи.
И общее ограничение, которое стоит проговорить вслух: дисперсию нельзя убрать бесплатно. Любое сглаживание оплачивается либо предсказуемостью (PRD-счётчик в Dota отсчитывают, мешок Тетриса просчитывают), либо смещением коротких серий, либо — в случае pity — созданием финансового крючка. Случайность в игре всегда компромисс между математической честностью, ощущением честности и деньгами. Полезно хотя бы понимать, в какую сторону вы этот компромисс двигаете и что именно говорите игроку в тултипе. Если тултип обещает 25%, а первый удар критует с 8,5% — где-то об этом стоит честно рассказать хотя бы вики-сообществу, Valve вон не скрывает.
Итого
Пробежимся по выводам. Случайность в играх собрана из трёх слоёв. Внизу генератор — детерминированная рекуррента, у которой случайного только seed, а качество измеряется спектральным тестом. В середине искажатели — PRD, pity, 2RN, aim assist, shuffle bag, которые меняют распределение под человеческое восприятие, потому что честная равномерность ощущается сломанной. Наверху экономика — геометрическое распределение с его зазором между средним и медианой, кривая 1 − (1 − p)^N и регуляторы, которые пытаются решить, где тут граница с казино.
Мне в этой истории больше всего нравится момент со Spotify: компания с лучшими инженерами по рекомендациям публично признала, что математически идеальный shuffle пришлось сломать, потому что людям он казался нечестным. В геймдеве это знание стоит денег в обе стороны — и когда вы делаете криты приятными, и когда кто-то делает кейсы прибыльными.
Надеюсь, материал был полезен. Буду рад обсудить ваши способы готовить случайность — особенно если вы шипили игру с собственной pity-системой и можете рассказать, как она пережила встречу с игроками.
Референсы
- Pseudo Random Distribution — Liquipedia Dota 2 — формула PRD, полная таблица констант C, список способностей.
- Документация java.util.Random — константы LCG (0x5DEECE66D, 0xB, 2⁴⁸).
- Minecraft@Home, проект pack.png — перебор 2⁴⁸ сидов на BOINC; SeedcrackerX — вскрытие seed по структурам мира.
- Donald Knuth, The Art of Computer Programming, Vol. 2: Seminumerical Algorithms — спектральный тест, выбор констант LCG, разбор RANDU.
- Matsumoto, Nishimura, «Mersenne Twister» (1998) и Melissa O'Neill, «PCG» (2014) — современные генераторы общего назначения.
- UnityEngine.Random — Scripting API — Xorshift128 в Unity.
- Spotify Engineering, «How to shuffle songs?» (2014) — Фишер—Йетс, жалобы пользователей и gambler's fallacy.
- True Hit — Serenes Forest и Fire Emblem Wiki — таблицы 2RN.
- XCOM 2:
DefaultGameCore.ini— скрытые модификаторы меткости; мод Remove Aim Assists (Steam Workshop id 617993180). - Шансы кейсов CS:GO — публикация Perfect World, 11.09.2017; цена ключа.
- Card pack statistics — Hearthstone Wiki — гарантии и pity-таймеры Hearthstone.
- Wish — Genshin Impact Wiki — официальные шансы и комьюнити-данные по soft pity.
- Apple App Store Review Guidelines, п. 3.1.1 — раскрытие шансов лутбоксов (декабрь 2017).
- Xiao, «Breaking Ban» — Collabra: Psychology (2023) — как на практике работает бельгийский запрет 2018 года.
- Решение Госсовета Нидерландов по делу EA / FIFA Ultimate Team (март 2022) — отмена штрафа 10 млн евро.
- Loot box — Wikipedia — хронология регулирования, Китай 2017.