Я на самом деле написал код для этого . Суть его в том, чтобы использовать статистику для исправления неудачных полос. Вы можете сделать это, чтобы отследить, сколько раз произошло событие, и использовать это для смещения числа, сгенерированного PRNG.
Во-первых, как мы отслеживаем процент событий? Наивным способом сделать это было бы сохранить все числа, когда-либо созданные в памяти, и усреднить их: это сработало бы, но ужасно неэффективно. После недолгого размышления я придумал следующее (которое в основном является накопительной скользящей средней ).
Возьмите следующие образцы PRNG (где мы выполняем, если выборка> = 0.5):
Values: 0.1, 0.5, 0.9, 0.4, 0.8
Events: 0 , 1 , 1 , 0 , 1
Percentage: 60%
Обратите внимание, что каждое значение вносит вклад в 1/5 конечного результата. Давайте посмотрим на это по-другому:
Values: 0.1, 0.5
Events: 0 , 1
Обратите внимание, что 0
вклад составляет 50% стоимости, а 1
вклад - 50% стоимости. Взятые чуть дальше:
Values: [0.1, 0.5], 0.9
Events: [0 , 1 ], 1
Теперь первые значения дают 66% стоимости, а последние 33%. Мы можем в основном отнести это к следующему процессу:
result = // 0 or 1 depending on the result of the event that was just generated
new_samples = samples + 1
average = (average * samples / new_samples) + (result * 1 / new_samples)
// Essentially:
average = (average * samples / new_samples) + (result / new_samples)
// You might want to limit this to, say, 100.
// Leaving it to carry on increasing can lead to unfairness
// if the game draws on forever.
samples = new_samples
Теперь нам нужно сместить результат значения, отобранного из PRNG, потому что мы рассчитываем на процентный шанс, здесь все намного проще (по сравнению, скажем, со случайными величинами ущерба в RTS). Это будет трудно объяснить, потому что это «только что пришло мне в голову». Если среднее значение ниже, это означает, что нам нужно увеличить вероятность того, что событие произойдет, и наоборот. Итак, несколько примеров
average = 0.1
desired = 0.5
corrected_chance = 83%
average = 0.2
desired = 0.5
corrected_chance = 71%
average = 0.5
desired = 0.5
corrected_change = 50%
Теперь «пришло мне в голову», что в первом примере 83% были просто «0,5 из 0,6» (другими словами «0,5 из 0,5 плюс 0,1»). В терминах случайного события это означает либо:
procced = (sample * 0.6) > 0.1
// or
procced = (sample * 0.6) <= 0.5
Таким образом, для генерации события вы должны использовать следующий код:
total = average + desired
sample = rng_sample() * total // where the RNG provides a value between 0 and 1
procced = sample <= desired
И поэтому вы получаете код, который я поместил в суть. Я почти уверен, что все это можно использовать в сценарии случайного повреждения, но я не потратил время, чтобы понять это.
Отказ от ответственности: Это все домашние статистические данные, у меня нет образования в этой области. Мои юнит-тесты все же проходят.