Потребность в предсказуемом случайном генераторе

Я - веб-разработчик игр, и я получил проблему со случайными числами. Скажем, то, что у плеера есть 20%-й шанс получить критический хит с его мечом. Это означает, 1 из 5 хитов должно быть очень важным. Проблема, я получил очень плохие реальные результаты — иногда, игроки получают 3 критики в 5 хитах, иногда ни один в 15 хитах. Сражения довольно коротки (3-10 хитов), таким образом, важно получить хорошее случайное распределение.

В настоящее время я использую PHP mt_rand(), но мы просто перемещаем наш код в C++, таким образом, я хочу решить эту проблему в новом механизме нашей игры.

Я не знаю, является ли решением некоторый универсальный случайный генератор, или возможно помнить предыдущие случайные состояния для принуждения надлежащего распределения.

151
задан 6 revs, 5 users 40% 9 April 2016 в 18:25
поделиться

37 ответов

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

Я написал простую реализацию на Ruby, похожую на Shuffle Bag, и провел небольшое тестирование. Реализация сделала следующее:

  • Если это все еще кажется справедливым или мы не достигли порога минимального количества бросков, он возвращает справедливое попадание, основанное на нормальной вероятности.
  • Если наблюдаемая вероятность из прошлых бросков делает его несправедливым. , он возвращает "справедливое" совпадение.

Это считается несправедливым на основании граничных вероятностей. Например, для вероятности 20% вы можете установить 10% как нижнюю границу и 40% как верхнюю границу.

Используя эти границы, я обнаружил, что при сериях из 10 совпадений, 14. 2% случаев истинная псевдослучайная реализация давала результаты, выходящие за эти рамки . Примерно в 11% случаев за 10 попыток было получено 0 критических попаданий. В 3,3% случаев было нанесено 5 или более критических попаданий из 10. Естественно, при использовании этого алгоритма (с минимальным количеством бросков 5) гораздо меньшее количество (0,03%) "Fairish" запусков было за пределами поля. . Даже если приведенная ниже реализация не подходит (конечно, можно сделать более умные вещи), стоит отметить, что заметно часто ваши пользователи будут чувствовать, что это несправедливо с настоящим псевдослучайным решением.

Вот суть моего FairishBag написан на Ruby. Полная реализация и быстрое моделирование методом Монте-Карло доступны здесь (суть) .

def fire!
  hit = if @rolls >= @min_rolls && observed_probability > @unfair_high
    false
  elsif @rolls >= @min_rolls && observed_probability < @unfair_low
    true
  else
    rand <= @probability
  end
  @hits += 1 if hit
  @rolls += 1
  return hit
end

def observed_probability
  @hits.to_f / @rolls
end

Обновление: Использование этого метода действительно увеличивает общую вероятность получения критического удара примерно до 22% с использованием указанных выше границ. Вы можете компенсировать это, установив его «реальную» вероятность немного ниже. Вероятность 17,5% с модификацией Fairish дает наблюдаемую долгосрочную вероятность около 20% и сохраняет ощущение справедливости краткосрочных прогонов.

39
ответ дан 23 November 2019 в 22:12
поделиться

Вы смотрите на линейное распределение, когда вам, вероятно, нужно нормальное распределение.

Если вы помните, когда в юности играли в D&D, вас просили бросить несколько n-сторонних кубиков, а затем суммировать результаты.

Например, бросание кубика 4 x 6 отличается от броска 1 x 24-гранные игральные кости.

2
ответ дан 23 November 2019 в 22:12
поделиться

alt text

этот действительно предсказуем ... но вы никогда не можете быть уверены.

2
ответ дан 23 November 2019 в 22:12
поделиться

Как насчет взвешивания значения?

Например, если у вас есть 20% шанс нанести критический удар, сгенерируйте число от 1 до 5 с одним числом, представляющим критическое попадание, или число от 1 до 100, где 20 чисел являются критическим попаданием.

Но пока вы работаете со случайными или псевдослучайными числами, нет никакого способа потенциально избежать результатов, которые вы сейчас видите. Это природа случайности.

0
ответ дан 23 November 2019 в 22:12
поделиться

Реакция на: «Проблема в том, что у меня очень плохие результаты в реальной жизни - иногда игроки получают 3 крита за 5 ударов, иногда ни одного за 15 ударов».

У вас есть шанс где-то между 3 и 4% ничего не получить за 15 ударов. ..

0
ответ дан 23 November 2019 в 22:12
поделиться

Я бы предложил следующий «кристалл со случайной задержкой возврата»:

  • Поддерживать два массива, один ( в массиве ) изначально заполнен значениями от 0 до n. -1, другой ( out-array ) пустой
  • Когда запрашивается результат:
    • возвращает случайное значение из всех определенных значений в in-array
    • перемещает это значение из in-array в out-array
    • переместить один случайный (по всем элементам, включая неопределенный!) элемент из out-array обратно в in-array

Он имеет свойство «реагировать» "чем медленнее, тем больше n . Например, если вам нужен шанс 20%, установка n на 5 и попадание 0 будет «менее случайным», чем установка n на 10 и попадание на 0 или 1, и увеличение от 0 до 199 из 1000 будет почти неотличимо от истинной случайности для небольшой выборки. Вам нужно будет отрегулировать n в соответствии с размером выборки.

0
ответ дан 23 November 2019 в 22:12
поделиться

Я думаю, возможно, вы используете неправильную функцию случайного распределения. Вероятно, вам не нужно равномерное распределение по числам. Вместо этого попробуйте использовать нормальное распределение, чтобы критические попадания стали более редкими, чем «обычные».

Я работаю с Java, поэтому я не уверен, где вы можете найти что-то для C ++, которое дает вам случайные числа с нормальным распределением, но там должно что-то быть.

0
ответ дан 23 November 2019 в 22:12
поделиться

Pre-calculate a random critical hit for each player.

// OBJECT
//...
// OnAttack()
//...
c_h = c_h -1;
if ( c_h == 0 ) {
 // Yes, critical hit!
 c_h = random(5) + 1 // for the next time
 // ...
}
0
ответ дан 23 November 2019 в 22:12
поделиться

OP,

В значительной степени, если вы хотите, чтобы это было честно, это не будет случайным.

Проблема вашей игры заключается в реальной длине матча. Чем дольше совпадение, тем меньше случайности вы увидите (криты обычно составляют 20%) и они будут приближаться к вашим предполагаемым значениям.

У вас есть два варианта: предварительно рассчитать атаки на основе предыдущих бросков. Таким образом, вы будете получать один критический удар каждые 5 атак (в зависимости от ваших 20%), но вы можете выбрать случайный порядок его появления.

listOfFollowingAttacks = {Hit, Hit, Hit, Miss, Crit};

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

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

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

2
ответ дан 23 November 2019 в 22:12
поделиться

А как насчет того, чтобы сделать шанс критического удара зависеть от последних N атак. Одна простая схема - это своего рода цепочка Маркова: http://en.wikipedia.org/wiki/Markov_chain , но код в любом случае очень прост.


IF turns_since_last_critical < M THEN 
   critial = false
   turns_since_last_critical++;
ELSE
   critial = IsCritical(chance);
   IF Critial THEN
       turns_since_last_critica = 0;
   ELSE
       turns_since_last_critica++;
   END IF;
END IF;

Конечно, вы должны делать свои математические вычисления, потому что шанс критического удара ниже, чем шанс критического, если вы знаете, что с момента последнего хода прошло достаточно

3
ответ дан 23 November 2019 в 22:12
поделиться

Что ж, если вы немного в математику, вы, вероятно, можете попробовать Экспоненциальное распределение

Например, если лямбда = 0,5, ожидаемое значение равно 2 (прочтите эту статью!), это означает, что вы, скорее всего, будете наносить удар / крит / что угодно каждый второй ход (вроде 50%, да?). Но с таким распределением вероятностей вы определенно пропустите (или сделаете что-то противоположное) на 0-м ходу (тот, в котором событие уже произошло и turn_counter был сброшен), у вас будет примерно 40% шанс попасть в следующий ход, примерно 65% шанс сделать это 2-м ходом ( следующий за следующим) ходом, около 80% для попадания 3-го и т. д.

Вся цель этого распределения состоит в том, что если у кого-то есть шанс попадания 50% и он промахивается 3 раза подряд, он наверняка (ну, более 80 % шанс, и он увеличивается с каждым следующим ходом) попадание. Это приводит к более "справедливым" результатам, оставляя более 50% вероятности неизменной.

Принимая 20% шанс критического удара, у вас есть

  • 17% критического удара в первый ход
  • 32% критического удара во втором ходу, если нет крит появляется во всех предыдущих.
  • 45% к критическому удару в 3-й ход, если не происходит критического удара во всех предыдущих.
  • 54% к критическому срабатыванию на 4-м ходу, если критический удар не происходит во всех предыдущих ходах.
  • .. .
  • 80% к криту 8-го хода, И есть 14% шанс на 4 последовательных некрита, 5% из 5, 1,5% для 6, 0,3% для 7, 0,07% для 8 последовательных некритов. Держу пари, что это «более справедливо», чем 41%, 32%, 26%, 21% и 16%.

    Надеюсь, вам все еще не до смерти скучно.

4
ответ дан 23 November 2019 в 22:12
поделиться

First, define "proper" distribution. Random numbers are, well, random - the results you're seeing are entirely consistent with (pseudo) randomness.

Expanding on this, I assume what you want is some feeling of "fairness", so the user can't go 100 turns without a success. If so, I'd keep track of the number of failures since the last success, and weight the generated result. Let's assume you want 1 in 5 rolls to "succeed". So you randomly generate a number from 1 to 5, and if it's 5, great.

If not, record the failure, and next time, generate a number from 1 to 5, but add on say, floor(numFailures / 2). So this time, again, they have a 1 in 5 chance. If they fail, next time the winning interval is 4 and 5; a 2 in 5 chance of success. With these choices, after 8 failures, they are certain to succeed.

53
ответ дан 23 November 2019 в 22:12
поделиться

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

Возможно, вам нужен порог милосердия ... вспомните последние 10 рулонов, и если они не имели критический удар, дайте им халяву. Расправьте пращи и стрелы случайности.

8
ответ дан 23 November 2019 в 22:12
поделиться

Надеюсь, эта статья вам поможет: http://web.archive.org/web/20090103063439/http://www.gamedev.net:80/reference/design/features/randomness/

Этот метод генерации «случайных чисел» является распространенным в играх rpg / mmorpg.

Проблема, которую он решает, заключается в следующем (отрывок):

Паук-клинок у вас в горле. Он попадает, и вы промахиваетесь. Он снова попадает, и вы снова промахиваетесь. И снова и снова, пока от вас не останется ничего, чтобы ударить. Ты мертв, а над твоим трупом злорадствует двухтонный паукообразный. Невозможно? Нет. Невероятно? Да. Но при наличии достаточного количества игроков и времени маловероятное становится почти неизбежным. Дело не в том, что паук-клинок был тяжелым, это просто невезение. Какое разочарование. Этого достаточно, чтобы игрок захотел выйти.

34
ответ дан 23 November 2019 в 22:12
поделиться

Как насчет замены mt_rand () чем-то вроде этого?

XKCD comic (RFC 1149.5 specifies 4 as the standard IEEE-vetted random number.)

(RFC 1149.5 определяет 4 в качестве стандартного случайного числа, проверенного IEEE.)

Из XKCD .

35
ответ дан 23 November 2019 в 22:12
поделиться

Вам нужны не случайные числа, а числа, которые кажутся человеку случайными. Другие уже предложили отдельные алгоритмы, которые могут вам помочь, например Shuffle Bad.

Подробный и обширный анализ этой области см. В AI Game Programming Wisdom 2 . Всю книгу стоит прочитать любому разработчику игр. Идея «кажущихся случайными числами» рассматривается в главе:

Отфильтрованная случайность для решений ИИ и логики игры :

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

Вы также можете найти интересную другую главу:

Статистика случайных чисел

Аннотация: Случайные числа наиболее активно используются в искусственном интеллекте и играх в целом. Игнорировать их потенциал - значит сделать игру предсказуемой и скучной. Неправильное их использование может быть так же плохо, как и полное их игнорирование. Понимание того, как генерируются случайные числа, их ограничений и возможностей, может устранить многие трудности их использования в вашей игре. Эта статья предлагает понимание случайных чисел, их генерации и методов отделения хороших от плохих.

19
ответ дан 23 November 2019 в 22:12
поделиться

Я рекомендую прогрессивную процентную систему, такую ​​как использует Blizzard: http://www.shacknews.com/onearticle.x/57886

Обычно вы бросаете ГСЧ, а затем сравниваете его со значением, чтобы определить, получилось это или нет. Это может выглядеть так:

if ( randNumber <= .2 ) {
   //Critical
} else {
   //Normal
}

Все, что вам нужно сделать, это добавить прогрессивное увеличение базового шанса ...

if (randNumber <= .2 + progressiveChance ) {
   progressiveChance = 0;
   //Critical
} else {
   progressiveChance += CHANCE_MODIFIER;
   //Normal hit
}

Если вам нужно, чтобы это было более модно, довольно легко добавить больше. Вы можете ограничить количество, которое может получить прогрессивный шанс, чтобы избежать 100% критического шанса или сбросить его при определенных событиях. У вас также может быть прогрессивное увеличение на меньшее количество при каждом повышении с чем-то вроде прогрессивногоШанс + = (1 - прогрессивныйШанс) * SCALE, где SCALE <1.

4
ответ дан 23 November 2019 в 22:12
поделиться

Your best solution might be play-testing with multiple different nonrandom schemes and pick the one that makes players happiest.

You might also try a back-off policy for the same number in a given encounter, e.g., if a player rolls a 1 on their first turn accept it. To get another 1 they need to roll 2 1s in a row. To get a third 1 they need 3 in a row, ad infinitum.

8
ответ дан 23 November 2019 в 22:12
поделиться

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

7
ответ дан 23 November 2019 в 22:12
поделиться

mt_rand () основан на реализации Mersenne Twister , что означает одно из лучших случайных распределений, которые вы можете получить.

Очевидно, то, что вы хотите, не случайность вообще, поэтому вы должны начать с указания именно того, что вы хотите. Вы, вероятно, поймете, что у вас противоречивые ожидания - что результаты должны быть действительно случайными и непредсказуемыми, но в то же время они не должны демонстрировать локальных отклонений от заявленной вероятности - но тогда это становится предсказуемым. Если вы установите максимум 10 некритов подряд, то вы только что сказали игрокам: «Если у вас было 9 некритов подряд, следующий будет критическим со 100% уверенностью» - вы можете, как ну, вообще не беспокойтесь о случайности.

7
ответ дан 23 November 2019 в 22:12
поделиться

По такому небольшому количеству тестов вы должны ожидать таких результатов:

Истинная случайность предсказуема только для огромного размера набора, так что вполне возможно подбросить монетку и получить орел В первый раз 3 раза подряд, однако после нескольких миллионов подбрасываний вы получите примерно 50-50.

6
ответ дан 23 November 2019 в 22:12
поделиться

Я вижу много ответов, предлагающих отслеживать ранее сгенерированные числа или перемешивать все возможные значения.

Лично я не согласен с тем, что 3 крита подряд - это плохой. Я также согласен с тем, что 15 некритов подряд - это плохо.

Я бы решил проблему, изменив сам шанс крита после каждого числа. Пример (для демонстрации идеи):

int base_chance = 20;
int current_chance = base_chance;

int hit = generate_random_number(0, 100) + 1; // anything from 1 to 100
if(hit < current_chance)//Or whatever method you use to check
{
    //crit!
    if(current_chance > base_chance)
        current_chance = base_chance; // reset the chance.
    else
        current_chance *= 0.8; // decrease the crit chance for the NEXT hit.
}
else
{
    //no crit.
    if(current_chance < base_chance)
        current_chance = base_chance; // reset the chance.
    else
        current_chance *= 1.1; // increase the crit chance for the NEXT hit.
    //raise the current_chance
}

Чем дольше вы не получаете критический удар, тем выше у вас вероятность критического удара вашим следующим действием. Включенный мной сброс является совершенно необязательным, и его нужно будет протестировать, чтобы определить, нужен он или нет. Может быть, а может и быть желательно дать более высокую вероятность критического удара для более чем одного действия подряд после длинной цепочки действий без критического удара.

Просто добавляю свои 2 цента ...

6
ответ дан 23 November 2019 в 22:12
поделиться

Если вам нужен дистрибутив, который не поощряет повторение значений, вы можете использовать простой алгоритм отклонения повторений.

например

int GetRand(int nSize)
{
    return 1 + (::rand() % nSize);
}
int GetDice()
{
    static int nPrevious=-1;
    while (1) {
        int nValue = GetRand(6);
        // only allow repeat 5% of the time
        if (nValue==nPrevious && GetRand(100)<95)
            continue;
        nPrevious = nValue;
        return nValue;
    }
}

Этот код отклоняет повторяющиеся значения в 95% случаев, что делает повторение маловероятным но не невозможно. Статистически это немного некрасиво, но, вероятно, даст желаемые результаты. Конечно, это не предотвратит распространение типа «5 4 5 4 5». Вы можете стать более привлекательным и отклонить второе последнее (скажем) в 60% случаев и третье последнее (скажем) в 30%.

Я не рекомендую это как хороший игровой дизайн. Просто предлагаю, как достичь желаемого.

5
ответ дан 23 November 2019 в 22:12
поделиться

You could create a list containing the numbers from 1 to 5, and have them sorted by randomness. Then just go through the list you created. You have a guarantee of running into every number at least once... When you're through with the first 5, just create another 5 numbers...

4
ответ дан 23 November 2019 в 22:12
поделиться

Вы неправильно понимаете, что означает случайное значение.

Какой из них более случайный?

enter image description here enter image description here

Хотя второй график выглядит более равномерно распределенным, более случайный на самом деле является первым графиком. Человеческий разум часто видит закономерности в случайном порядке, поэтому мы видим сгустки на первом графике как закономерности, но это не так - они просто часть случайно выбранной выборки.

тем более random на самом деле является первым сюжетом. Человеческий разум часто видит закономерности в случайном порядке, поэтому мы видим сгустки на первом графике как закономерности, но это не так - они просто часть случайно выбранной выборки.

тем более random на самом деле является первым сюжетом. Человеческий разум часто видит закономерности в случайном порядке, поэтому мы видим сгустки на первом графике как закономерности, но это не так - они просто часть случайно выбранной выборки.

113
ответ дан 23 November 2019 в 22:12
поделиться

Это означает, что 1 из 5 попаданий должен быть критическим. Проблема в том, что у меня очень плохие результаты в реальной жизни - иногда игроки получают 3 крита за 5 ударов, иногда ни одного за 15 ударов.

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

Алгоритм примерно такой: вы кладете в мешок 1 критическое и 4 некритических попадания. Затем вы рандомизируете их порядок в сумке и выбираете их по одному. Когда мешок пуст, вы снова наполняете его теми же значениями и рандомизируете. Таким образом, вы получите в среднем 1 критическое попадание на 5 ударов и максимум 2 критических и 8 некритических попаданий подряд. Увеличьте количество предметов в сумке для большей случайности.

223
ответ дан 23 November 2019 в 22:12
поделиться

Несколько основных ответов являются отличным объяснением, поэтому я просто сосредоточусь на алгоритме, который дает вам контроль над вероятностью «плохих полос», в то время как никогда не станет детерминированным. Вот что, я думаю, вам следует сделать:

Вместо указания p , параметра распределения Бернулли, который является вашей вероятностью критического попадания, укажите a и b , параметры бета-распределения, «сопряженный априор» распределения Бернулли. Вам необходимо отслеживать A и B , количество критических и некритических попаданий на данный момент.

Теперь, чтобы указать a и b , убедитесь, что a / (a ​​+ b) = p, вероятность критического попадания. Замечательно то, что (a + b) количественно определяет, насколько близко вы хотите, чтобы A / (A + B) находился к p в целом.

Вы делаете выборку следующим образом:

let p (x ) - функция плотности вероятности бета-распределения. Он доступен во многих местах, но вы можете найти его в GSL как gsl_ran_beta_pdf.

S = A+B+1
p_1 = p((A+1)/S)
p_2 = p(A/S)

Выберите критическое попадание путем выборки из распределения Бернулли с вероятностью p_1 / (p_1 + p_2)

Если вы обнаружите, что случайные числа имеют слишком много «плохих полос», увеличьте масштаб a и b , но в пределе, поскольку a и b уходят в бесконечность, у вас будет подход с перемешиванием в случайном порядке, описанный ранее.

Если вы реализуете это , дайте мне знать, как дела!

пусть p (x) будет функцией плотности вероятности бета-распределения. Он доступен во многих местах, но вы можете найти его в GSL как gsl_ran_beta_pdf.

S = A+B+1
p_1 = p((A+1)/S)
p_2 = p(A/S)

Выберите критическое попадание путем выборки из распределения Бернулли с вероятностью p_1 / (p_1 + p_2)

Если вы обнаружите, что случайные числа имеют слишком много «плохих полос», увеличьте масштаб a и b , но в пределе, поскольку a и b уходят в бесконечность, у вас будет подход с перемешиванием в случайном порядке, описанный ранее.

Если вы реализуете это , дайте мне знать, как дела!

пусть p (x) будет функцией плотности вероятности бета-распределения. Он доступен во многих местах, но вы можете найти его в GSL как gsl_ran_beta_pdf.

S = A+B+1
p_1 = p((A+1)/S)
p_2 = p(A/S)

Выберите критическое попадание путем выборки из распределения Бернулли с вероятностью p_1 / (p_1 + p_2)

Если вы обнаружите, что случайные числа имеют слишком много «плохих полос», увеличьте масштаб a и b , но в пределе, поскольку a и b уходят в бесконечность, у вас будет подход с перемешиванием в случайном порядке, описанный ранее.

Если вы реализуете это , дайте мне знать, как дела!

5
ответ дан 23 November 2019 в 22:12
поделиться

Непонятно, чего вы хотите. Можно создать функцию, которая при первых 5 вызовах будет возвращать числа от 1 до 5 в случайном порядке.

Но это не совсем случайно. Игрок будет знать, что он получит ровно одну 5 из следующих 5 атак. Это может быть то, что вы хотите, и в этом случае вам просто нужно самому написать код. (создайте массив, содержащий числа, а затем перемешайте их)

В качестве альтернативы вы можете продолжить использовать свой текущий подход и предположить, что ваши текущие результаты связаны с плохим генератором случайных чисел. Обратите внимание, что с вашими текущими цифрами все может быть неправильно. Случайные значения случайны. иногда вы получаете 2, 3 или 8 одинаковых значений подряд. Потому что они случайны. Хороший генератор случайных чисел просто гарантирует, что в среднем все числа будут возвращаться одинаково часто.

Конечно, если вы использовали плохой генератор случайных чисел, это могло исказить ваши результаты, и если да, то простое переключение на лучший генератор случайных чисел должно решить проблему. (Проверьте библиотеку Boost.Random, чтобы найти лучшие генераторы)

В качестве альтернативы вы можете запомнить последние N значений, возвращенных вашей случайной функцией, и взвесить результат по ним. (простой пример: «для каждого появления нового результата есть 50% шанс, что мы должны отбросить значение и получить новое»

Если бы мне пришлось угадывать, я бы сказал, придерживаясь «фактического» случайность - ваш лучший выбор. Убедитесь, что вы используете хороший генератор случайных чисел, а затем продолжайте делать то, что делаете сейчас.

это могло исказить ваши результаты, и если да, то простое переключение на лучший генератор случайных чисел должно решить проблему. (Проверьте библиотеку Boost.Random, чтобы найти лучшие генераторы)

В качестве альтернативы вы можете запомнить последние N значений, возвращенных вашей случайной функцией, и взвесить результат по ним. (простой пример: «для каждого появления нового результата есть 50% -ная вероятность, что мы должны отбросить значение и получить новое»

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

это могло исказить ваши результаты, и если да, то простое переключение на лучший генератор случайных чисел должно решить проблему. (Проверьте библиотеку Boost.Random, чтобы найти лучшие генераторы)

В качестве альтернативы вы можете запомнить последние N значений, возвращенных вашей случайной функцией, и взвесить результат по ним. (простой пример: «для каждого появления нового результата есть 50% шанс, что мы должны отбросить значение и получить новое»

Если бы мне пришлось угадывать, я бы сказал, придерживаясь «фактического» случайность - ваш лучший выбор. Убедитесь, что вы используете хороший генератор случайных чисел, а затем продолжайте делать то, что делаете сейчас.

вы можете запомнить последние N значений, возвращенных вашей случайной функцией, и взвесить результат по ним. (простой пример: «для каждого появления нового результата есть 50% шанс, что мы должны отбросить значение и получить новое»

Если бы мне пришлось угадывать, я бы сказал, придерживаясь «фактического» случайность - ваш лучший выбор. Убедитесь, что вы используете хороший генератор случайных чисел, а затем продолжайте делать то, что делаете сейчас.

вы можете запомнить последние N значений, возвращенных вашей случайной функцией, и взвесить результат по ним. (простой пример: «для каждого появления нового результата есть 50% -ная вероятность, что мы должны отбросить значение и получить новое»

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

4
ответ дан 23 November 2019 в 22:12
поделиться

Given the behavior you're asking for, I think you're randomizing the wrong variable.

Rather than randomizing whether this hit will be critical, try randomizing the number of turns until the next critical hit occurs. For example, just pick a number between 2 & 9 every time the player gets a critical, and then give them their next critical after that many rounds have passed. You can also use dice methods to get closer to a normal distribution -- for example, you will get your next critical in 2D4 turns.

I believe this technique gets used in RPGs that have random encounters in the overworld as well -- you randomize a step counter, and after that many steps, you get hit again. It feels a lot more fair because you almost never get hit by two encounters in a row -- if that happens even once, the players get irritable.

88
ответ дан 23 November 2019 в 22:12
поделиться

В City of Heroes на самом деле есть механика под названием «streakbreaker», которая решает именно эту проблему. Это работает следующим образом: после серии промахов, длина которых соответствует наименьшей вероятности попадания в цепочку, следующая атака гарантированно будет попаданием. Например, если вы пропустите атаку с вероятностью попадания более 90%, тогда ваша следующая атака будет автоматически поражена, но если ваш шанс попадания ниже 60%, тогда вам понадобится несколько последовательных промахов, чтобы вызвать «разбиватель полос» (I не знаю точных цифр)

2
ответ дан 23 November 2019 в 22:12
поделиться
Другие вопросы по тегам:

Похожие вопросы: