Kebutuhan untuk generator acak yang dapat diprediksi

151

Saya seorang pengembang web-game dan saya mendapat masalah dengan angka acak. Katakanlah seorang pemain memiliki peluang 20% ​​untuk mendapatkan pukulan kritis dengan pedangnya. Itu berarti, 1 dari 5 hit harus kritis. Masalahnya adalah saya mendapat hasil kehidupan nyata yang sangat buruk - kadang-kadang pemain mendapatkan 3 crits dalam 5 hits, kadang-kadang tidak ada dalam 15 hit. Pertempuran agak pendek (3-10 hit) jadi penting untuk mendapatkan distribusi acak yang bagus.

Saat ini saya menggunakan PHP mt_rand(), tetapi kami hanya memindahkan kode kami ke C ++, jadi saya ingin menyelesaikan masalah ini di mesin baru permainan kami.

Saya tidak tahu apakah solusinya adalah generator acak yang seragam, atau mungkin untuk mengingat keadaan acak sebelumnya untuk memaksa distribusi yang tepat.

Thinker
sumber
58
Ada kemungkinan sekitar 0,5% dari 3 hit kritis dan 2 non-kritis dan peluang 3,5% dari 15 hit non-kritis berturut-turut, dengan asumsi angka acak yang sebenarnya.
Nixuz
10
+1 ke atas. Salah satu karakteristik angka acak adalah Anda mendapatkan outlier.
ConcernedOfTunbridgeWells
45
@Nixus: Tidak, ini peluang 5% untuk 3 hit kritis dan 2 non-kritis, Anda lupa mengalikan dengan (5! / (3! * 2!)) = 10. Dengan tingkat kepercayaan 95%, itu adalah tidak mungkin secara statistik untuk 3 serangan kritis terjadi dalam 5 serangan.
erikkallen
7
Pada awalnya saya pikir ini adalah pertanyaan konyol ... sekali lagi, saya merasa rendah hati oleh SO.
SergioL

Jawaban:

39

Saya setuju dengan jawaban sebelumnya bahwa keacakan nyata dalam menjalankan kecil beberapa permainan tidak diinginkan - sepertinya terlalu tidak adil untuk beberapa kasus penggunaan.

Saya menulis Shuffle Bag sederhana seperti implementasi di Ruby dan melakukan beberapa pengujian. Implementasi melakukan ini:

  • Jika masih tampak adil atau kami belum mencapai ambang batas minimum, itu mengembalikan hit yang adil berdasarkan probabilitas normal.
  • Jika probabilitas yang diamati dari gulungan terakhir membuatnya tampak tidak adil, ia mengembalikan hit "fair-ifying".

Itu dianggap tidak adil berdasarkan probabilitas batas. Misalnya, untuk probabilitas 20%, Anda bisa menetapkan 10% sebagai batas bawah dan 40% sebagai batas atas.

Dengan menggunakan batasan itu, saya menemukan bahwa dengan 10 hit, 14,2% dari waktu implementasi pseudorandom yang sebenarnya menghasilkan hasil yang di luar batas tersebut . Sekitar 11% dari waktu, 0 hit kritis dicetak dalam 10 percobaan. 3,3% dari waktu, 5 atau lebih hit kritis mendarat dari 10. Tentu saja, menggunakan algoritma ini (dengan jumlah roll minimum 5), jumlah yang jauh lebih kecil (0,03%) dari menjalankan "Fairish" berada di luar batas . Sekalipun implementasi di bawah ini tidak cocok (tentu saja hal yang lebih pintar dapat dilakukan), perlu dicatat bahwa secara mencolok sering kali pengguna Anda akan merasa tidak adil dengan solusi pseudorandom nyata.

Inilah daging FairishBagtulisan saya di Ruby. Seluruh implementasi dan simulasi Monte Carlo cepat tersedia di sini (inti) .

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

Pembaruan: Menggunakan metode ini meningkatkan kemungkinan keseluruhan untuk mendapatkan hit kritis, menjadi sekitar 22% menggunakan batas di atas. Anda dapat mengimbangi ini dengan mengatur probabilitas "nyata" nya sedikit lebih rendah. Probabilitas 17,5% dengan modifikasi berukuran menghasilkan probabilitas jangka panjang yang diamati sekitar 20%, dan membuat jangka pendek berjalan terasa adil.

Ian Terrell
sumber
Saya pikir ini adalah solusi terbaik yang sesuai dengan kebutuhan saya. Shuffle bag yang disebutkan dalam jawaban runcing terbaik tidak buruk, tetapi membutuhkan banyak perhitungan, dan saya suka solusi paling sederhana yang mengarah ke target.
Thinker
Steve Rabin menulis artikel menarik tentang keacakan dalam game. Singkatnya, perilaku "acak" yang sebenarnya tidak benar-benar "terasa" acak bagi kebanyakan orang dan penelitian telah mendukung hal ini. Artikelnya disebut Randomed Filtered untuk Keputusan AI dan Logika Game dan muncul dalam "AI Game Programming Wisdom 2" (2003). Anda harus memeriksanya, mungkin akan bermanfaat bagi Anda.
Jeff Tucker
@IanTerrell Akan lebih baik untuk menyatakan seberapa besar ukuran sampel pengujian Anda, yaitu berapa banyak pertempuran untuk menentukan probabilitas tersebut.
@ user677656: Ada di intinya, tapi 100k
Ian Terrell
223

Itu berarti, 1 dari 5 hit harus kritis. Masalahnya adalah saya mendapat hasil kehidupan nyata yang sangat buruk - kadang-kadang pemain mendapatkan 3 crits dalam 5 hits, kadang-kadang tidak ada dalam 15 hit.

Yang Anda butuhkan adalah tas shuffle . Ini memecahkan masalah true random menjadi terlalu acak untuk game.

Algoritmanya kira-kira seperti ini: Anda memasukkan 1 hit kritis dan 4 non-kritis ke dalam tas. Kemudian Anda mengacak pesanan mereka di dalam tas dan memilihnya satu per satu. Ketika tas kosong, Anda mengisinya lagi dengan nilai yang sama dan mengacaknya. Dengan begitu Anda akan mendapatkan rata-rata 1 klik kritis per 5 klik, dan paling banyak 2 klik kritis dan 8 tidak kritis berturut-turut. Tingkatkan jumlah item dalam tas untuk lebih banyak keacakan.

Berikut adalah contoh implementasi (di Jawa) dan test case-nya yang saya tulis beberapa waktu lalu.

Esko Luontola
sumber
21
+1 untuk ide bagus tanpa kritik. Skala tas untuk tingkat keacakan yang lebih tinggi, dan untuk menangani varians dalam peluang kritis antara pemain (jika variabel ofc)
TheMissingLINQ
16
Anda dapat memiliki ukuran tas 10. Masukkan dalam 1 hit, ditambah peluang 30% per detik. Jika perubahan kesempatan kritis, Anda bisa membuang tas dan memulai yang baru. Perhatikan bahwa skema semacam itu berisiko jika Anda (atau lawan) mengetahui probabilitas hit kritis Anda dan ukuran tas, Anda terkadang dapat mengetahui dengan pasti bahwa Anda tidak akan mendapatkan kritikal lain untuk sejumlah gulungan. Ini mungkin memengaruhi taktik.
Steve Jessop
3
Ya ... dalam hal seperti ini Anda menjalankan rick mirip dengan penghitungan kartu. Apakah saya mengambil risiko prajurit infanteri atau masuk untuk pembunuhan besar ... satu set kecil hasil potensial dapat mengurangi risiko kehilangan dan meningkatkan kemungkinan "gamed"
Matthew Whited
8
Saya menyukai ide shuffle bag tetapi saya tidak berpikir ini cocok dengan "semangat" permainan karena probabilitas hit kritis Anda sebesar 20% (yang berarti Anda tidak dapat melakukan apapun dalam 10 hit) bukan probabilitas lagi. Ini menjadi tepat 1 hit setiap 5 hit. Selain itu, rerolling tas jika perubahan probabilitas hit kritis akan menyebabkan kesalahan dalam permainan. Jika hit kritis saya telah dilakukan, saya akan menggunakan mantra untuk mendapatkan kritik berikutnya sebelumnya: p
Michaël Carpentier
2
@ Jonathan: membuat tas ukuran besar yang Anda berikan sebenarnya membatalkan seluruh ide tas: untuk memastikan sesuatu terjadi (hal kritis yang dicapai) dalam jumlah lemparan yang dapat diterima. Membuat tas 50000 besar hampir sama dengan menggunakan generator nomor acak.
dstibbe
113

Anda memiliki kesalahpahaman tentang apa arti acak.

Manakah dari ini yang lebih acak?

masukkan deskripsi gambar di sini masukkan deskripsi gambar di sini

Sementara plot kedua terlihat lebih merata, plot yang lebih acak sebenarnya adalah plot pertama. Pikiran manusia sering melihat pola secara acak, jadi kita melihat rumpun di plot pertama sebagai pola, tetapi tidak - mereka hanya bagian dari sampel yang dipilih secara acak.

ceejayoz
sumber
25
Penjelasan Numb3rs yang bagus!
RMAAlmeida
9
Secara teknis, Anda tidak bisa mengukur keacakan. Kedua distribusi terlihat cukup sewenang-wenang bagi saya, meskipun dugaan saya keduanya dihasilkan secara algoritmik. Anda dapat melakukan sejumlah tes pada plot pertama dan menentukan bahwa itu kemungkinan berasal dari proses yang menempatkan poin berdasarkan distribusi yang seragam, tetapi Anda tidak akan dapat menyimpulkan bahwa itu lebih acak. Sebagai contoh tandingan, Anda bisa membuat plot seperti yang pertama menggunakan generator kongruensial linier, lalu membuat plot seperti yang kedua menggunakan noise yang diperkuat dari dioda zener. Coba kata tidak berkorelasi bukan acak.
Dietrich Epp
8
Anda dapat mengukur probabilitas bahwa distribusi tersebut adalah acak.
ceejayoz
6
@Dietich: Tentu saja Anda dapat mengukur keacakan
BlueRaja - Danny Pflughoeft
2
Agar adil, sementara OP mungkin tidak menggunakan istilah yang benar, ia mengerti bahwa generator angka acak memberinya sesuatu yang lebih seperti grafik pertama, ketika ia menginginkan sesuatu yang lebih seperti grafik kedua karena terasa lebih "adil" bagi pengguna.
Kip
88

Mengingat perilaku yang Anda minta, saya pikir Anda mengacak variabel yang salah.

Daripada mengacak apakah hit ini akan kritis, coba acakkan jumlah belokan hingga hit kritis berikutnya terjadi. Misalnya, pilih saja angka antara 2 & 9 setiap kali pemain mendapat kritikan, dan kemudian berikan mereka kritikan berikutnya setelah banyak putaran berlalu. Anda juga dapat menggunakan metode dadu untuk lebih mendekati distribusi normal - misalnya, Anda akan mendapatkan kritikal berikutnya dalam giliran 2D4.

Saya percaya teknik ini digunakan dalam RPG yang memiliki pertemuan acak di dunia luar juga - Anda mengacak penghitung langkah, dan setelah banyak langkah itu, Anda tertabrak lagi. Rasanya jauh lebih adil karena Anda hampir tidak pernah dihantam oleh dua pertemuan berturut-turut - jika itu terjadi sekali saja, para pemain menjadi marah.

Letakkan
sumber
Saya pikir ini solusi yang bagus, tetapi bagaimana dengan peluang 80%?
Thinker
Saya juga suka menggunakan generator acak multi-dimensi. Peluang untuk memukul + Peluang untuk kekuatan + Peluang untuk kritis. Sama seperti menggulirkan beberapa dadu berbeda dalam D&D
Matthew Whited
Saya suka ide ini, dan Anda sepenuhnya benar tentang hal penghitung langkah, yang telah digunakan dalam fantasi final untuk waktu yang sangat lama, misalnya
Ed James
Satu masalah dengan ini adalah bahwa itu hanya berfungsi jika probabilitas kritis kira-kira konstan di antara hit. Misalkan pada pertengahan pertarungan, pemain mengeluarkan mantra yang menggandakan kemungkinan serangan kritis. Lalu bagaimana Anda menyesuaikan jumlah belokan?
Alex319
+1 Sangat bagus, juga menangani kemungkinan hit kurang dari 20% sangat mudah.
Alice Purcell
53

Pertama, tentukan distribusi "tepat". Angka acak adalah, well, acak - hasil yang Anda lihat sepenuhnya konsisten dengan keacakan (semu).

Memperluas hal ini, saya berasumsi apa yang Anda inginkan adalah perasaan "adil", sehingga pengguna tidak dapat mencapai 100 putaran tanpa keberhasilan. Jika demikian, saya akan melacak jumlah kegagalan sejak keberhasilan terakhir, dan menimbang hasil yang dihasilkan. Anggap Anda ingin 1 dalam 5 gulungan "berhasil". Jadi, Anda secara acak menghasilkan angka dari 1 hingga 5, dan jika itu 5, bagus.

Jika tidak, catat kegagalannya, dan lain kali, buat angka dari 1 hingga 5, tetapi tambahkan pada katakanlah, lantai (numFailures / 2). Jadi kali ini, sekali lagi, mereka memiliki peluang 1 banding 5. Jika gagal, lain kali interval kemenangan adalah 4 dan 5; peluang sukses 2 in 5. Dengan pilihan-pilihan ini, setelah 8 kegagalan, mereka pasti akan berhasil.

Adam Wright
sumber
Pada catatan itu ... apakah kisaran angka acak akan mempengaruhi distribusi ... misalnya memilih Acak r = Acak baru (); r.Next (1,5) vs. r.Next (1, 1000000)% 200000
Eoin Campbell
23
+1 untuk melihat masalah di balik permintaan alih-alih memberi tahu OP dia salah paham secara acak.
Boris Callens
4
Perhatikan bahwa jika Anda melakukan ini, maka proporsi keseluruhan keberhasilan mereka akan lebih besar dari 1 banding 5. Cara lain adalah dengan (misalnya) memilih 20 angka berbeda secara acak dari kisaran 1..100, dan telah ditentukan sebelumnya bahwa mereka akan menjadi kritik mereka. Ini lebih banyak pembukuan.
Steve Jessop
"akan lebih besar dari 1 dalam 5" - diharapkan dalam jangka panjang, maksud saya.
Steve Jessop
Anda dapat mengurangi probabilitas mulai sedikit, sehingga proporsi keseluruhan dikurangi menjadi 1/5. Saya belum mengetahui seberapa banyak Anda harus menguranginya, tetapi semuanya terus menerus sehingga harus ada jawaban yang benar.
Steve Jessop
35

Bagaimana kalau mengganti mt_rand () dengan sesuatu seperti ini?

Komik XKCD (RFC 1149.5 menetapkan 4 sebagai nomor acak standar IEEE.)

(RFC 1149.5 menetapkan 4 sebagai nomor acak standar-IEEE.)

Dari XKCD .

Colin Pickard
sumber
Bagus, tetapi apakah ini akan menyelesaikan masalah distribusi nomor acak OPs? ;-)
Arjan Einbu
Tidak juga; Dia meminta RNG non-acak, yang dengannya dia bisa menggunakan fungsi ini; tapi apa yang sebenarnya dia inginkan lebih baik dijelaskan oleh jawaban teratas saat ini ( stackoverflow.com/questions/910215/910224#910224 )
Colin Pickard
28
Ini lebih acak dari yang diinginkan OP
Çağdaş Tekin
-1 karena RFC1149 tidak memiliki bagian 5 (dan secara bergantian, tidak ada 1149.5); +1 untuk keacakan yang adil.
greyfade
34

Semoga artikel ini akan membantu Anda: http://web.archive.org/web/20090103063439/http://www.gamedev.net:80/reference/design/features/randomness/

Metode menghasilkan 'angka acak' ini umum di game rpg / mmorpg.

Masalah yang dipecahkannya adalah (ekstrak) ini:

Seekor laba-laba pisau ada di tenggorokan Anda. Itu hits dan Anda ketinggalan. Itu hits lagi dan kamu ketinggalan lagi. Dan lagi dan lagi, sampai tidak ada yang tersisa dari Anda untuk memukul. Anda sudah mati dan ada arachnid seberat dua ton yang melayang di atas mayat Anda. Mustahil? Tidak. Tidak mungkin? Iya. Tetapi mengingat pemain yang cukup dan diberi waktu yang cukup, yang mustahil menjadi hampir pasti. Bukan karena laba-laba bilah itu keras, itu hanya nasib buruk. Sangat frustasi. Sudah cukup membuat pemain ingin berhenti.

CiscoIPPhone
sumber
1
Saya pernah mendengar varian tentang ini - "peristiwa satu dalam sejuta terjadi 6.000 kali dalam populasi dunia".
ceejayoz
19

Yang Anda inginkan bukanlah angka acak, tetapi angka yang tampaknya acak bagi manusia. Lainnya telah menyarankan algoritma individual, yang dapat membantu Anda, seperti Shuffle Bad.

Untuk analisis terperinci dan luas dari domain ini, lihat AI Game Programming Wisdom 2 . Seluruh buku ini layak dibaca untuk setiap pengembang game, gagasan "angka yang tampaknya acak" dibahas di bab ini:

Keacakan yang Difilter untuk Keputusan AI dan Logika Game :

Abstrak: Kearifan konvensional menunjukkan bahwa semakin baik generator angka acak, permainan Anda akan semakin tidak dapat diprediksi. Namun, menurut studi psikologi, keacakan yang sebenarnya dalam jangka pendek sering terlihat jelas tidak acak bagi manusia. Artikel ini menunjukkan bagaimana membuat keputusan AI acak dan logika permainan terlihat lebih acak bagi pemain, sambil tetap mempertahankan keacakan statistik yang kuat.

Anda juga mungkin menemukan bab lain yang menarik:

Statistik Angka Acak

Abstrak: Angka acak paling banyak digunakan oleh Kecerdasan Buatan dan game pada umumnya. Mengabaikan potensi mereka berarti membuat game dapat diprediksi dan membosankan. Menggunakannya secara salah bisa sama buruknya dengan mengabaikannya begitu saja. Memahami bagaimana angka acak dihasilkan, keterbatasannya dan kemampuannya, dapat menghilangkan banyak kesulitan dalam menggunakannya di game Anda. Artikel ini menawarkan wawasan tentang angka acak, generasi mereka, dan metode untuk memisahkan yang baik dari yang buruk.

Suma
sumber
8

Tentunya setiap generasi nomor acak memiliki peluang untuk menghasilkan menjalankan seperti itu? Anda tidak akan mendapatkan set sampel yang cukup besar dalam 3-10 gulungan untuk melihat persentase yang sesuai.

Mungkin yang Anda inginkan adalah ambang belas kasihan ... ingat 10 gulungan terakhir, dan jika mereka belum mendapatkan pukulan kritis, berikan mereka freebie. Menghaluskan sling dan panah keacakan.

James
sumber
8

Solusi terbaik Anda mungkin bermain-pengujian dengan beberapa non yang berbeda skema acak yang dan memilih salah satu yang membuat pemain paling bahagia.

Anda juga dapat mencoba kebijakan mundur untuk nomor yang sama dalam pertemuan tertentu, misalnya, jika seorang pemain menggulirkan 1pada giliran pertama mereka menerimanya. Untuk mendapatkan yang lain 1mereka harus menggulung 2 1s secara berurutan. Untuk mendapatkan ketiga, 1mereka membutuhkan 3 berturut-turut, tanpa batas.

Hank Gay
sumber
7

Sayangnya yang Anda minta adalah penghasil angka yang tidak acak - karena Anda ingin hasil sebelumnya diperhitungkan saat menentukan nomor berikutnya. Saya rasa ini bukan cara penghasil bilangan acak.

Jika Anda ingin 1 dari setiap 5 hit menjadi kritis maka cukup pilih angka antara 1 dan 5 dan katakan bahwa hit itu akan menjadi kritis.

samjudson
sumber
1
dia ingin game friendly acak, jika Anda menggunakan angka acak yang ketat dalam beberapa kasus Anda akhirnya memiliki hasil "korean acak". Itu adalah hasil acak yang membuat pemain terlalu sering marah dan frustrasi (tanyakan pemain keturunan 2);)
Juan Techera
Konsekuensinya, jika hit pertama adalah crit, empat berikutnya tidak akan. Kedengarannya seperti inilah yang diinginkan OP, tetapi ketika Anda mengatakannya seperti ini, kedengarannya terbelakang. Anda mendapatkan UV saya untuk itu.
belgariontheking
-1 Anda tampaknya membingungkan "acak" dengan "tanpa memori" - en.wikipedia.org/wiki/Memorylessness
Alice Purcell
7

mt_rand () didasarkan pada implementasi Mersenne Twister , yang berarti menghasilkan salah satu distribusi acak terbaik yang bisa Anda dapatkan.

Tampaknya apa yang Anda inginkan bukanlah keacakan sama sekali, jadi Anda harus mulai menentukan dengan tepat apa yang Anda inginkan. Anda mungkin akan menyadari bahwa Anda memiliki harapan yang bertentangan - bahwa hasilnya harus benar-benar acak dan tidak dapat diprediksi, namun pada saat yang sama mereka tidak boleh menunjukkan variasi lokal dari probabilitas yang dinyatakan - tetapi kemudian menjadi dapat diprediksi. Jika Anda menetapkan maksimum 10 non-crits berturut-turut, maka Anda baru saja mengatakan kepada pemain "jika Anda memiliki 9 non-crit berturut-turut, yang berikutnya akan menjadi kritis dengan kepastian 100%" - Anda mungkin juga tidak repot-repot dengan keacakan sama sekali.

Michael Borgwardt
sumber
6

Lebih dari sejumlah kecil tes Anda harus mengharapkan hasil seperti itu:

Keacakan benar hanya dapat diprediksi pada ukuran set besar, sehingga sangat mungkin untuk melempar koin dan mendapatkan kepala 3 kali berturut-turut pertama kali, namun lebih dari beberapa juta flips Anda akan berakhir dengan sekitar 50-50.

Ed James
sumber
7
Meskipun masih ada kemungkinan bahwa setelah beberapa juta membalik, Anda masih akan melihat satu sisi mata uang. Meskipun jika ini pernah terjadi, Anda mungkin duduk terlalu dekat dengan drive ketidakmungkinan yang tak terbatas: P
Grant Peters
haha, ya tapi kesempatannya sangat rendah sehingga hukum matematika mengatakan Anda harus melihat distribusi genap.
Ed James
6

Saya melihat banyak jawaban menyarankan untuk melacak nomor yang dihasilkan sebelumnya atau untuk mengocok semua nilai yang mungkin.

Secara pribadi, saya tidak setuju, bahwa 3 crit berturut-turut buruk. Saya juga tidak setuju bahwa 15 non-crits berturut-turut itu buruk.

Saya akan memecahkan masalah, dengan memodifikasi peluang itu sendiri, setelah setiap angka. Contoh (untuk menunjukkan ide):

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
}

Semakin lama Anda tidak mendapatkan kritik - semakin tinggi peluang yang Anda miliki untuk tindakan selanjutnya ke kritik. Reset yang saya sertakan sepenuhnya opsional dan perlu pengujian untuk mengetahui apakah perlu atau tidak. Mungkin diinginkan atau tidak diinginkan untuk memberikan probabilitas kritik yang lebih tinggi untuk lebih dari satu tindakan berturut-turut, setelah rantai aksi non-kritik yang panjang.

Hanya melempar 2 sen saya ...

Paulius
sumber
Saya suka pendekatan semacam ini. Saya mungkin akan melakukannya dengan cara lain. Mulailah dengan peluang yang lebih rendah dan tingkatkan hingga maksimum 20% + beberapa persentase tambahan hingga hit dan reset lagi ke jumlah rendah.
Matius
5

Beberapa jawaban teratas adalah penjelasan yang bagus, jadi saya hanya akan fokus pada algoritma yang memberi Anda kendali atas kemungkinan "coretan buruk" sementara tidak pernah menjadi deterministik. Inilah yang saya pikir harus Anda lakukan:

Alih-alih menentukan p , parameter distribusi Bernoulli, yang merupakan probabilitas Anda untuk hit kritis, tentukan a dan b , parameter distribusi beta, "konjugat prior" dari distribusi Bernoulli. Anda perlu melacak A dan B , jumlah hit kritis dan non-kritis sejauh ini.

Sekarang, untuk menentukan a dan b , pastikan bahwa a / (a ​​+ b) = p, peluang hit kritis. Yang rapi adalah bahwa (a + b) menghitung seberapa dekat Anda ingin A / (A + B) menjadi p secara umum.

Anda melakukan pengambilan sampel seperti ini:

biarkan p(x)menjadi fungsi kepadatan probabilitas dari distribusi beta. Ini tersedia di banyak tempat, tetapi Anda dapat menemukannya di GSL sebagai gsl_ran_beta_pdf.

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

Pilih hit kritis dengan pengambilan sampel dari distribusi bernoulli dengan probabilitas p_1 / (p_1 + p_2)

Jika Anda menemukan bahwa angka acak memiliki terlalu banyak "goresan buruk", skala a dan b , tetapi dalam batasnya, ketika a dan b pergi hingga tak terbatas, Anda akan memiliki pendekatan kocokan kocokan yang dijelaskan sebelumnya.

Jika Anda menerapkan ini, beri tahu saya bagaimana hasilnya!

Neil G
sumber
5

Jika Anda menginginkan distribusi yang menghambat nilai pengulangan, Anda bisa menggunakan algoritma penolakan berulang sederhana.

misalnya

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;
    }
}

Kode ini menolak nilai berulang 95% dari waktu, membuat pengulangan tidak mungkin tetapi tidak mustahil. Secara statistik ini agak jelek, tetapi mungkin akan menghasilkan hasil yang Anda inginkan. Tentu saja, itu tidak akan mencegah distribusi seperti "5 4 5 4 5". Anda bisa menjadi pelamun dan menolak yang terakhir kedua (katakanlah) 60% dari waktu dan yang ketiga terakhir (katakanlah) 30%.

Saya tidak merekomendasikan ini sebagai desain game yang bagus. Cukup menyarankan cara mencapai apa yang Anda inginkan.

Michael J
sumber
Beberapa nilai dalam permainan saya seperti hit kritis tidak dapat memiliki peluang lebih dari 50%, jadi saya memblokir pengulangan sama sekali, tetapi ini menurunkan peluang acara untuk beberapa persen.
Thinker
4

Tidak begitu jelas apa yang Anda inginkan. Dimungkinkan untuk membuat fungsi sedemikian rupa sehingga 5 kali pertama Anda menyebutnya, ia mengembalikan angka 1-5 dalam urutan acak.

Tapi itu tidak terlalu acak. Pemain akan tahu bahwa dia akan mendapatkan tepat 5 dalam 5 serangan berikutnya. Mungkin itu yang Anda inginkan, dan dalam hal ini, Anda hanya perlu kode itu sendiri. (buat larik yang berisi angka-angka lalu kocok)

Atau, Anda bisa tetap menggunakan pendekatan Anda saat ini, dan menganggap bahwa hasil Anda saat ini disebabkan oleh generator acak yang buruk. Perhatikan bahwa tidak ada yang salah dengan nomor Anda saat ini. Nilai acak adalah acak. terkadang Anda mendapatkan 2, 3 atau 8 dengan nilai yang sama berturut-turut. Karena mereka acak. Generator acak yang baik hanya menjamin bahwa rata-rata, semua angka akan dikembalikan secara merata.

Tentu saja jika Anda telah menggunakan generator acak yang buruk, yang mungkin membuat hasil Anda miring, dan jika demikian, hanya beralih ke generator acak yang lebih baik akan menyelesaikan masalah. (Lihat perpustakaan Boost.Random untuk generator yang lebih baik)

Atau, Anda bisa mengingat nilai N terakhir yang dikembalikan oleh fungsi acak Anda, dan timbang hasilnya. (contoh sederhana adalah, "untuk setiap kemunculan hasil baru, ada kemungkinan 50% kita harus membuang nilainya dan mendapatkan yang baru"

Jika saya harus menebak, saya akan mengatakan tetap dengan keacakan "sebenarnya" adalah taruhan terbaik Anda. Pastikan Anda menggunakan generator acak yang bagus, dan terus seperti yang Anda lakukan sekarang.

jalf
sumber
Sebenarnya, fungsi yang dia gunakan sama dengan RNG terbaik di boost library.
Michael Borgwardt
MT bukan yang "terbaik", terakhir saya periksa. Ini bagus, sederhana dan cepat, tetapi tidak menghasilkan distribusi terbaik. Pokoknya, ambil satu juta angka acak dan periksa distribusinya. Cari tahu apakah fungsi acak Anda benar-benar memberi Anda distribusi yang seragam atau tidak. Jika tidak, cari generator yang lebih baik. Jika ya, isap dan terima deretan kata sandi sesekali, atau selingkuh dan buat hasilnya kurang acak dan lebih mudah diprediksi.
jalf
4

Anda dapat membuat daftar yang berisi angka dari 1 hingga 5, dan menyortirnya secara acak. Kemudian cukup buka daftar yang Anda buat. Anda memiliki jaminan berlari ke setiap nomor setidaknya sekali ... Ketika Anda selesai dengan 5 angka pertama, cukup buat 5 angka lainnya ...

Arjan Einbu
sumber
4

Saya merekomendasikan sistem persentase progresif seperti Blizzard menggunakan: http://www.shacknews.com/onearticle.x/57886

Secara umum Anda menggulung RNG kemudian membandingkannya dengan nilai untuk menentukan apakah berhasil atau tidak. Itu mungkin terlihat seperti:

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

Yang perlu Anda lakukan adalah menambahkan peningkatan kesempatan dasar ...

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

Jika Anda ingin lebih mewah, cukup mudah untuk menambahkan lebih banyak. Anda dapat membatasi jumlah yang bisa didapat oleh progressiveChance untuk menghindari peluang kritis 100% atau mengatur ulangnya pada acara tertentu. Anda juga dapat memiliki peningkatan progressiveChance dalam jumlah yang lebih kecil setiap dorongan dengan sesuatu seperti progressiveChance + = (1 - progressiveChance) * SKALA tempat SKALA <1.

JonBWalsh
sumber
4

Nah, jika Anda sedikit ke matematika, Anda mungkin dapat mencoba distribusi eksponensial

Misalnya, jika lambda = 0,5, nilai yang diharapkan adalah 2 (baca artikel itu!), Berarti Anda kemungkinan besar akan menekan / crit / apa pun setiap putaran kedua (seperti 50%, ya?). Tetapi dengan distribusi probabilitas seperti itu, Anda pasti akan melewatkan (atau melakukan yang berlawanan dengan apa pun) pada putaran ke-0 (yang, di mana peristiwa telah terjadi dan turn_counter telah diatur ulang), memiliki peluang 40% untuk mencapai giliran berikutnya, sekitar 65% kesempatan untuk melakukannya putaran ke-2 (berikutnya setelah berikutnya), sekitar 80% untuk mencapai peringkat ke-3 dan seterusnya.

Seluruh tujuan dari distribusi itu adalah jika seseorang memiliki peluang hit 50% dan ia melewatkan 3 kali berturut-turut, ia akan melakukan shurely (well, lebih dari 80% peluang, dan ia meningkatkan setiap giliran berikutnya) mengenai. Ini mengarah ke hasil yang lebih "adil", menjaga kemungkinan 50% secara keseluruhan tidak berubah.

Mengambil kesempatan 20% Anda dari kritik, Anda punya

  • 17% untuk krit ke-1 putaran pertama
  • 32% untuk krit ke-2, jika tidak ada kritik di semua yang sebelumnya.
  • 45% untuk krit ke-3, jika tidak ada kritik di semua yang sebelumnya.
  • 54% ke krit ke-4, jika tidak ada kritikal di semua yang sebelumnya.
  • ...
  • 80% ke krit ke-8, jika tidak ada krit di semua yang sebelumnya.

Masih sekitar 0,2% (vs 5%) kemungkinan 3 crits + 2 non-crits dalam 5 putaran konsekuen. Dan ada 14% kemungkinan dari 4 non-crits, 5% dari 5, 1,5% untuk 6, 0,3% untuk 7, 0,07% untuk 8 non-crit sebagai akibatnya. Saya bertaruh "lebih adil" dari 41%, 32%, 26%, 21% dan 16%.

Semoga Anda tidak bosan sampai mati.

Gelap
sumber
ini sangat mirip dengan solusi saya, kecuali bahwa itu hanya "mengingat" waktu sejak hit kritis terakhir. Di bawah solusi ini, untaian 4 hit kritis sama dengan untaian 1 hit kritis sejauh kemungkinan tentang masa depan. Jadi, jika hit kritis itu baik, solusi ini membatasi risiko penurunan Anda, tetapi tidak pada sisi positif Anda. Solusi saya memengaruhi keduanya.
Neil G
Sudah jelas bahwa solusi yang berbeda memiliki manfaatnya sendiri. Yang satu ini berfokus pada menjaga kebersihan dari sudut pandang sains. Itu tidak berarti, itu entah bagaimana lebih baik, daripada tas shuffle atau apa pun. Itu hanya solusi yang sepertinya layak untuk dicoba.
Dark
3

Bagaimana dengan membuat peluang kritis tergantung pada serangan N terakhir. Satu skema sederhana adalah semacam rantai markov: http://en.wikipedia.org/wiki/Markov_chain tetapi kodenya juga sangat sederhana.


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;

Tentu saja Anda harus membuat matematika Anda karena kemungkinan kritis lebih rendah daripada peluang kritis setelah Anda tahu bahwa itu sudah cukup berubah sejak yang terakhir

borjab
sumber
Anda mendapatkan sebagian besar efek dengan hanya mengambil serangan terakhir di akun. Biarkan P menjadi hit rate yang diamati, R hit rate setelah kehilangan dan R / 2 hit rate setelah hit. Menurut definisi, pada titik mana pun Anda kemudian memiliki kesempatan untuk menekan P = P * R + (1-P) * (R / 2). Ini berarti P = R / (2-R)
MSalters
2

OP,

Cukup banyak, jika Anda ingin adil, itu tidak akan acak.

Masalah permainan Anda adalah panjang pertandingan yang sebenarnya. Semakin lama kecocokannya, semakin sedikit keacakan yang akan Anda lihat (crit akan cenderung 20%) dan akan mendekati nilai yang Anda inginkan.

Anda mendapat dua opsi, pra-hitung serangan berdasarkan gulungan sebelumnya. Yang mana Anda akan mendapatkan satu krit setiap 5 serangan (berdasarkan 20% serangan Anda), tetapi Anda dapat membuat urutannya terjadi secara acak.

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

Itulah pola yang Anda inginkan. Jadi buat itu pilih secara acak dari daftar itu, sampai kosong, mereka membuatnya kembali.

Itu adalah pola yang saya buat untuk permainan saya, itu bekerja dengan sangat baik, untuk apa yang saya inginkan.

pilihan kedua Anda, akan, meningkatkan kesempatan untuk kritik, Anda mungkin akan melihat angka yang lebih merata di akhir semua serangan (menganggap bahwa pertandingan Anda berakhir agak cepat). Semakin sedikit kesempatan, semakin banyak RNG yang Anda dapatkan.

Rodrigo
sumber
2

Anda melihat distribusi linier, ketika Anda mungkin menginginkan distribusi normal.

Jika Anda ingat kembali pada masa muda Anda bermain D & D, Anda diminta untuk melempar beberapa n-sided die, lalu jumlah hasilnya.

Misalnya, menggulung dadu bersisi 4 x 6 berbeda dengan menggulirkan dadu bersisi 1 x 24.

dar7yl
sumber
2

City of Heroes sebenarnya memiliki mekanik yang disebut "streakbreaker" yang memecahkan masalah ini dengan tepat. Cara kerjanya adalah bahwa setelah serangkaian kesalahan panjang terkait dengan probabilitas hit terendah dalam string, serangan berikutnya dijamin akan menjadi hit. Misalnya, jika Anda melewatkan serangan dengan lebih dari 90% untuk memukul peluang maka serangan berikutnya akan otomatis mengenai, tetapi jika peluang hit Anda lebih rendah seperti 60% maka Anda harus memiliki beberapa kesalahan berturut-turut untuk memicu "streakbreaker" (I tidak tahu angka pastinya)

Alex319
sumber
2

teks alternatif

ini benar-benar dapat diprediksi ... tetapi Anda tidak pernah bisa yakin.

太極 者 無極 而 生
sumber
Ini harus menjadi wallpaper desktop saya !!
0

Bagaimana dengan menimbang nilainya?

Misalnya, jika Anda memiliki peluang 20% ​​untuk hit kritis, hasilkan angka antara 1 dan 5 dengan satu angka mewakili hit kritis, atau angka antara 1 dan 100 dengan 20 angka menjadi hit kritis.

Tetapi selama Anda bekerja dengan nomor acak atau pseudorandom, tidak ada cara untuk berpotensi menghindari hasil yang Anda lihat saat ini. Itu sifat keacakan.

Thomas Owens
sumber
Dan mengapa itu membuat perbedaan? Ada peluang yang sama persis untuk mendapatkan kritis untuk kedua set angka.
samjudson
Persis. Saya hanya menyajikan dua opsi untuknya untuk contoh 20% nya. Meskipun 100 mungkin akan bekerja lebih baik jika Anda berurusan dengan persentase jumlah keseluruhan, karena Anda hanya perlu mensimulasikan satu "mati", jika Anda ingin memikirkannya seperti itu.
Thomas Owens
Pilihan yang Anda berikan persis seperti apa yang sudah ia lakukan.
ceejayoz
2
Bukan untuk apa yang dia inginkan. Dia menginginkan generator nomor non-acak, bahkan jika dia pikir itu disebut generator nomor acak.
ceejayoz
0

Reaksi atas: "Masalahnya adalah saya mendapat hasil kehidupan nyata yang sangat buruk - kadang-kadang pemain mendapat 3 crits dalam 5 hits, kadang-kadang tidak ada dalam 15 hit."

Anda memiliki peluang antara 3 dan 4% untuk tidak mendapatkan apa pun dalam 15 hit ...

Fortega
sumber
Ketika Anda memiliki 3500 pemain yang bertarung secara online 10.000 pertempuran dalam satu menit, masalah yang terjadi dalam 3% pertempuran adalah masalah yang sangat umum.
Thinker
Kemudian lagi, nasib buruk yang terjadi dalam 3% pertempuran masih hanya nasib buruk.
MSalters
0

Saya akan mengusulkan "mati putback tertunda secara acak" sebagai berikut:

  • Pertahankan dua array, satu ( in-array) awalnya diisi dengan nilai dari 0 hingga n-1, yang lainnya ( out-array) kosong
  • Ketika suatu hasil diminta:
    • mengembalikan nilai acak dari semua nilai yang ditentukan diin-array
    • pindahkan nilai ini dari in-arraykeout-array
    • pindahkan satu elemen acak (atas semua elemen, termasuk elemen yang tidak ditentukan!) dari out-arraykembali kein-array

Ini memiliki sifat yang akan "bereaksi" lebih lambat semakin besar n . Misalnya, jika Anda menginginkan peluang 20%, pengaturan n ke 5 dan memukul pada 0 adalah "kurang acak" daripada pengaturan n ke 10 dan memukul pada 0 atau 1, dan menjadikannya 0 hingga 199 dari 1000 akan hampir tidak bisa dibedakan dari keacakan benar atas sampel kecil. Anda harus menyesuaikan n dengan ukuran sampel Anda.

Svante
sumber
0

Pra-hitung hit kritis acak untuk setiap pemain.

// OBJECT
//...
// OnAttack()
//...
c_h = c_h -1;
if ( c_h == 0 ) {
 // Yes, critical hit!
 c_h = random(5) + 1 // for the next time
 // ...
}
Nick Dandoulakis
sumber
0

Saya pikir mungkin Anda menggunakan fungsi distribusi acak yang salah. Anda mungkin tidak ingin pemerataan atas angka. Cobalah distribusi yang normal sehingga hit kritis menjadi lebih jarang daripada hit 'biasa'.

Saya bekerja dengan Java jadi saya tidak yakin di mana Anda dapat menemukan sesuatu untuk C ++ yang memberi Anda angka acak dengan distribusi normal tetapi harus ada sesuatu di luar sana.

Alex
sumber