Расчет шансов предметов в лутбоксе на основе цен
Сделал инструмент для геймдизайнеров, которым можно быстро считать шансы в лутбоксах.
Если посчитаете инструмент полезным, не стесняйтесь делиться ссылкой.
Если работали с похожими системами, буду рад услышать мнение со стороны.
Телеграмм-канал: https://t.me/SecretRoom_Gamedesign
«House Edge» — комиссия казино. Сколько процентов от оборота товаров оставляет за собой владелец, разыгрывая предметы.
Например, может быть равна 10%. В этом случае, если лутбокс будет стоить 100 долларов, то в среднем предметы будут падать из него на 90 долларов.
Другими словами, это сколько процентов комиссии зарабатывает казино.
Пример использования
Представьте, что у нас есть магазин кейсов с оружием из Counter Strike. Цена оружия динамическая и зависит от ситуации на рынке.
Вы, как обладатель площадки, владеете складом различного оружия на своих аккаунтах.
Вы хотите продавать кейсы с оружием. Из кейса можно получить только одно оружие на основе шансов. Цену кейсов и оружие в них вы формируете заранее.
Вам нужен инструмент, чтобы вычислять шансы.
Можно считать это руками довольно простой таблицей, перебирая шансы каждого предмета до тех пор, пока ваше матожидание не сойдется с ценой лутбокса.
Но что, если таких кейсов очень много, а пересчитывать их нужно часто? Нужна математическая модель для автоматического расчета.
Пример такого сайта: https://skin.club/en
Давайте посчитаем матожидание из примера на скриншоте и выясним комиссию продавца.
Первое рассуждение
Довольно быстро стало понятно, что решений у задачи может быть много.
Я взял пример и перераспределил шансы — получил то же самое матожидание.
При одних и тех же входных значениях может быть несколько решений. Значит нам нужен параметр, который будет дополнительно регулировать распределение шансов.
Функция распределения
Нам нужна функция, которая будет распределять шансы относительно цен. Я взял за основу степенную функцию (гиперболу). Про нее у меня есть отдельный пост. Этой функцией мы будем считать веса предметов. В свою очередь шансы будут считаться на основе весов.
Очевидно, что в списке предметов должны быть предметы разных цен. Обязательно должны быть предметы ниже и выше стоимости сундука. Только в таких случаях задача может быть решаема.
Сводим задачу к поиску коэффициентов формулы
Итак, у нас есть формула для вычисления веса предмета:
Задача сводится к тому, чтобы подобрать коэффициенты.
Какие-то коэффициенты стоит зафиксировать константами. Зафиксируем power = -1, потому что функция должна быть гиперболой и b = 1, потому что вес предмета должен быть больше нуля. (По сути b — минимальный вес).
В качестве x будет выступать цена предмета.
Допустим, что у нас есть предметы со стоимостями x1, x2 ... xn и весами w1, w2 ... wn.
В свою очередь веса будут выражены нашей степенной функцией. Подставляем ее вместо w1 ... wn.
Все, что с коэффициентом k в левую сторону, все остальное в правую:
Приведу это к приличному виду через промежуточные переменные:
А что насчет коэффициента «a», а?
Обращусь к своей статье о степенной функции. Там я показывал, что коэффициент «a», по своей сути, определяет вертикальную асимптоту гиперболы, то есть границу функции. Очевидно, что граница должна быть левее цены самого дешевого предмета.
То есть нужно, чтобы a по модулю была меньше цены самого дешевого предмета.
В какой-то момент, я понял, что будет лучше всего работать не с абстрактным коэффициентом, который нужно подгонять каждый раз под ситуацию, а с каким-то более осмысленным. Поэтому я ввел понятие Grouping.
Grouping — это расстояние от минимальной цены предметов до асимптоты функции.
В свою очередь коэффициент a выразил так:
По-русски я назвал бы этот новый коэффициент «кучностью». Потому что чем больше Grouping, тем более пологая будет кривая за пределами минимальной цены. То есть как бы веса у предметов будут кучковаться или группироваться и быть более похожими.
Первая версия модели
С этими рассуждениями получилось создать первую версию модели.
- Стоимость лутбокса.
- House edge (комиссия).
- Кучность призов (Grouping). В зависимости от призов нужно подбирать, можно экспериментировать с разной кучностью.
- Строчки с ценами призов. Можно добавлять новые строчки или удалять лишние. Но обязательно продлевайте формулы из строчек на новые строчки.
Автоматически рассчитываются шансы призов в строчках.
Могут выдаваться следующие ошибки, которые очевидно как исправлять:
// Constants power = -1 b = 1 // Input LootboxPrice HouseEdge // От 0 до 1 Grouping // Строго > 0 List PriceList // Список цен // Calculations SumOfPrices = Sum of elements from PriceList ExpectedPriceValue = LootboxPrice * (1 - HouseEdge) MinPrice = Minimum from PriceList MaxPrice = Minimum from PriceList If MinPrice >= ExpectedPriceValue then Print(Error: Price of lootbox is too low) If MaxPrice <= ExpectedPriceValue then Print(Error: Price of lootbox is too high) a = Grouping - MinPrice List XList XList[i] = (PriceList[i] + a) ^ power SumX = Sum of elements from XList SumProdX = Sum of (XList[i] * PriceList[i]) Denominator = ExpectedPriceValue * SumX - SumProdX If Denominator <= 0 then Print(Error: Value of grouping is too high)) k = b * (SumOfPrices - PriceList.Length * ExpectedPriceValue) / Denominator List WeightList WeightList[i] = k * (PriceList[i] + a) ^ power + b SumOfWeights = Sum of elements from WeightList List ChanceList ChanceList[i] = WeightList[i] / SumOfWeights ExpectedPriceValueForVerification = Sum of (PriceList[i] * ChanceList[i]) // Output ChanceList ExpectedPriceValueForVerification
Вторая версия
Полученная модель хорошо работает не для всех случаев.
Мне не понравилось как работает модель в случае, если у нас несколько дешевых предметов, которые несильно отличаются в цене, при этом у нас есть очень дорогие предметы.
Шансы у почти одинаковых предметов (8 и 9 долларов) слишком разные. Я бы хотел, чтобы они были примерно одинаковые. Увеличение кучности в этом случае не сильно помогает.
Я подумал, что в такой ситуации есть смысл упаковать все дешевые предметы в одну оболочку, и уже внутри нее решать, какой предмет из нее выпадет.
Модифицировал таблицу, изменив первый предмет на ссылку на матожидание от internal box:
С помощью такого внутреннего бокса можно модифицировать гиперболу, добавляя в нее начальную ступеньку, настраивая ее вручную.
Ссылка на таблицу
https://docs.google.com/spreadsheets/d/1kVMa3sadsIP7ehYju5Seq0WoTvBv9lY_DQlrLIOByos/edit?usp=sharing