Онлайн-справочник по самым часто задаваемым вопросам из темы "Как сделать?" на форуме QSP.su
20.3. Как сделать шанс на выпадение определённой вещи?
В: Как сделать шанс на выпадение определённой вещи? Например 25 процентный шанс на то, что в сундуке окажется золотая чаша?
О:
В самом простом виде, когда мы имеем дело с одним конкретным предметом и приблизительно знаем шансы его выпадения, можно сделать весьма простой алгоритм:
chance=25
! теперь выбрасываем случайное число от 1 до 100
bones=rand(1,100)
! проверяем попало ли выпавшее число в заданный нами предел
if bones<=chance:
! если выпавшее число меньше либо равно заданному
! получаем предмет
addobj "Золотая чаша"
"Вы нашли в сундуке золотую чашу."
else
! в противном случае ничего не получаем
"Вы ничего не нашли в сундуке."
end
Чуть более сложной задачей становится выбор из нескольких вариантов предметов. Эта задача осложняется тем, что начинающие авторы продолжают применять подход с процентным значением шансов к большому набору предметов:
Кувшин - 25%
Вострый меч — 50%
Убольшающее зелье — 25%
Если сложить все процентные значения в этом случае, мы получаем 125% на все предметы, но такого не может быть.
На самом деле данная запись означает вот что: золотая чаша, кувшин и убольшающее зелье имеют равные шансы для выпадения, но по сравнению с любым из них вострый меч должен выпадать чаще (приблизительно в два раза). Однако шанс выпадения вострого меча в этом случае на треть меньше, чем шанс выпадения золотой чаши, либо кувшина, либо убольшающего зелья.
Всё это говорит нам о том, что мы имеем дело уже не с процентными соотношениями, а с коэффициентами соотношений. Начнём разбор этой ситуации с двух предметов:
Убольшающее зелье — 25
Теперь мы знаем, что это не проценты, а коэффициенты соотношений шанса выпадения. Делим 50 на 25, и понимаем, что Вострый меч должен выпадать вдвое чаще, чем Убольшающее зелье. При условии, что хоть один предмет должен выпасть обязательно, составляем следующий алгоритм:
bones_max=50+25
! определяем отрезок для меча (от 1 до 50)
chance_sword=50
! определяем отрезок для зелья (от 51 до 75)
chance_potion=75
! выбрасываем случайное число от 1 до bones_max
bones=rand(1,bones_max)
! теперь используя сложное условие проверяем отрезки
if bones<=chance_sword:
! если мы уложились в отрезок для меча
! получаем меч
addobj "Вострый меч"
elseif bones<=chance_potion:
! иначе если мы уложились в отрезок для зелья
! получаем зелье
addobj "Убольшающее зелье"
end
Теперь можно составить алгоритм для случая с четырьмя предметами. Он не будет сильно отличаться от предыдущего:
bones_max=50+25+25+25
! отрезок меча (1-50)
chance_sword=50
! отрезок зелья (51-75)
chance_potion=75
! отрезок кувшина (76-100)
chance_jug=100
! отрезок чаши (101-125)
chance_cup=125
! выбрасываем число
bones=rand(1,bones_max)
! получаем выпавший предмет
if bones<=chance_sword:
addobj "Вострый меч"
elseif bones<=chance_potion:
addobj "Убольшающее зелье"
elseif bones<=chance_jug:
addobj "Кувшин"
elseif bones<=chance_cup:
addobj "Золотая чаша"
end
Что если мы хотим, чтобы в принципе предмет мог выпасть с 50% вероятностью, но между собой они делили шансы выпадения по-прежнему? Просто увеличиваем максимальное значение числа вдвое:
bones_max=(50+25+25+25)*2
! отрезок меча (1-50)
chance_sword=50
! отрезок зелья (51-75)
chance_potion=75
! отрезок кувшина (76-100)
chance_jug=100
! отрезок чаши (101-125)
chance_cup=125
! выбрасываем число
bones=rand(1,bones_max)
! получаем выпавший предмет
if bones<=chance_sword:
addobj "Вострый меч"
elseif bones<=chance_potion:
addobj "Убольшающее зелье"
elseif bones<=chance_jug:
addobj "Кувшин"
elseif bones<=chance_cup:
addobj "Золотая чаша"
else
! или ничего не получаем
"Вы ничего не нашли"
end
Конечно же данное решение не является универсальным, и для более универсального решения рамок обычного F.A.Q не хватит, но в большинстве случаев для написания сносной системы случайного выпадения предметов хватает и данного решения. Главное помнить, что выбирая между разными предметами мы уже работаем не с чистой вероятностью выпадения, а с тем, насколько чаще один предмет выпадает по отношению к другим предметам.