In realtà ho scritto del codice per farlo . L'essenza sta usando le statistiche per correggere le serie sfortunate. Il modo in cui puoi farlo è tenere traccia di quante volte si è verificato l'evento e usarlo per distorcere il numero generato dal PRNG.
Innanzitutto, come tenere traccia della percentuale di eventi? Il modo ingenuo di fare questo sarebbe quello di mantenere tutti i numeri mai generati in memoria e di farne una media: che funzionerebbe ma è terribilmente inefficiente. Dopo un po 'di riflessione mi è venuto in mente quanto segue (che è fondamentalmente una media mobile cumulativa ).
Prelevare i seguenti campioni PRNG (dove si procede se il campione è> = 0,5):
Values: 0.1, 0.5, 0.9, 0.4, 0.8
Events: 0 , 1 , 1 , 0 , 1
Percentage: 60%
Si noti che ogni valore contribuisce a 1/5 del risultato finale. Diamo un'occhiata in un altro modo:
Values: 0.1, 0.5
Events: 0 , 1
Si noti che 0
contribuisce al 50% del valore e 1
contribuisce al 50% del valore. Preso leggermente oltre:
Values: [0.1, 0.5], 0.9
Events: [0 , 1 ], 1
Ora i primi valori contribuiscono al 66% del valore e all'ultimo 33%. Fondamentalmente, possiamo distillare questo fino al seguente processo:
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
Ora dobbiamo distorcere il risultato del valore campionato dal PRNG, perché stiamo andando per una probabilità percentuale qui le cose sono molto più facili (contro, diciamo, quantità casuali di danno in un RTS). Questo sarà difficile da spiegare perché "mi è appena venuto in mente". Se la media è inferiore significa che dobbiamo aumentare la possibilità che si verifichi l'evento e viceversa. Quindi alcuni esempi
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%
Ora quello che mi è venuto in mente è che nel primo esempio l'83% era solo "0,5 su 0,6" (in altre parole "0,5 su 0,5 più 0,1"). In termini di eventi casuali ciò significa:
procced = (sample * 0.6) > 0.1
// or
procced = (sample * 0.6) <= 0.5
Quindi, al fine di generare un evento, useresti sostanzialmente il seguente codice:
total = average + desired
sample = rng_sample() * total // where the RNG provides a value between 0 and 1
procced = sample <= desired
E quindi ottieni il codice che ho inserito in sintesi. Sono abbastanza sicuro che tutto ciò possa essere usato nello scenario del caso di danno casuale, ma non ho avuto il tempo di capirlo.
Dichiarazione di non responsabilità: si tratta di statistiche nazionali, non ho alcuna istruzione in questo campo. I miei test unitari superano comunque.