Saya sedang dalam proses membuat game sederhana baru di ponsel dan saya telah menghabiskan beberapa hari di bagian berikut.
Untuk kesederhanaan, katakanlah saya punya dua pejuang. Satu-satunya atribut dari mereka adalah Serangan dan Pertahanan. Saat serangan pertama, satu-satunya hal yang penting adalah serangannya dan pertahanan lawan. Dan sebaliknya.
Mereka tidak memiliki peralatan, barang, stamina atau kesehatan. Hanya Serang vs Pertahanan.
Contoh:
Petarung 1:
Serangan: 50, Pertahanan: 35
Petarung 2:
Attack 20, Defense: 80
Proses pertarungan akan menjadi hanya satu serangan yang akan menentukan pemenang. Jadi, tidak ada banyak serangan atau putaran. Saya tidak ingin membuatnya menjadi deterministik, tetapi tambahkan versi ringan yang tidak terduga. Seorang pejuang dengan serangan yang lebih rendah akan dapat memenangkan pejuang lain dengan pertahanan yang lebih tinggi (tapi tentu saja tidak setiap waktu)
Ide pertama saya adalah membuatnya linier dan memanggil generator nomor acak yang seragam.
If Random() < att1 / (att1 + def2) {
winner = fighter1
} else {
winner = fighter2
}
Contoh dengan serangan 50 dan pertahanan 80, pejuang penyerang akan memiliki sekitar 38% untuk menang. Namun, menurut saya hal yang tak terduga itu terlalu jauh dan petarung terburuk akan menang banyak.
Saya bertanya-tanya bagaimana Anda bekerja dalam situasi yang sama.
PS Saya mencari banyak di QnA ini dan sumber lain dan saya menemukan pertanyaan serupa yang disebut terlalu luas untuk SE. Tetapi mereka memiliki banyak atribut, senjata, barang, kelas dll yang bisa membuatnya terlalu rumit. Saya pikir versi saya jauh lebih sederhana agar pas dengan gaya QnA dari SE.
Jawaban:
Jika Anda ingin hasil pertarungan Anda lebih dapat diprediksi tetapi tidak sepenuhnya deterministik, miliki sistem terbaik .
Ulangi waktu pertarungan
n
(di manan
harus angka yang tidak rata) dan nyatakan pejuang sebagai pemenang yang menang lebih sering. Semakin besar nilai Anda untukn
kemenangan dan kerugian yang tidak terlalu mengejutkan yang akan Anda miliki.Sistem ini hanya bekerja dalam kasus khusus di mana perkelahian adalah hasil biner sederhana dari menang atau kalah. Ketika pertempuran memiliki hasil yang lebih kompleks, seperti ketika pemenang masih kehilangan beberapa poin hit tergantung pada seberapa dekat kemenangan itu, pendekatan ini tidak berfungsi lagi. Solusi yang lebih umum adalah mengubah cara Anda menghasilkan angka acak. Saat Anda menghasilkan beberapa angka acak dan kemudian mengambil rata-rata, hasilnya akan mengelompok di dekat pusat rentang dan hasil yang lebih ekstrem akan lebih jarang. Sebagai contoh:
akan memiliki kurva distribusi seperti ini:
(Gambar milik anydice - alat yang sangat berguna untuk merancang rumus mekanik permainan yang melibatkan keacakan, bukan hanya untuk permainan meja)
Dalam proyek saya saat ini, saya menggunakan fungsi pembantu yang memungkinkan untuk mengatur ukuran sampel sewenang-wenang:
sumber
+
alih-alih*
atau saya salah mengerti apa fungsinya?Ini adalah apa yang saya gunakan untuk menentukan pemenang pertempuran di applet Lords of Conquest Imitator saya. Dalam game ini, mirip dengan situasi Anda, hanya ada nilai serangan dan nilai pertahanan. Probabilitas bahwa penyerang menang adalah lebih besar semakin banyak poin yang dimiliki penyerang, dan semakin sedikit poin yang dimiliki oleh penyerang, dengan nilai yang sama dievaluasi dengan peluang 50% dari serangan yang berhasil.
Algoritma
Balikkan koin acak.
1a. Kepala: pertahanan kehilangan satu poin.
1b. Ekor: kepala kehilangan satu poin.
Jika pertahanan dan penyerang masih memiliki poin, kembali ke langkah 1.
Siapa pun yang turun ke 0 poin kalah dalam pertempuran.
3a. Penyerang ke 0: Serangan gagal.
3b. Pertahanan ke 0: Serangan berhasil.
Saya menulisnya di Jawa, tetapi harus mudah diterjemahkan ke bahasa lain.
Sebuah contoh
Misalnya, katakanlah att = 2 dan def = 2, hanya untuk memastikan bahwa probabilitasnya adalah 50%.
Pertempuran akan ditentukan dalam jumlah maksimum
n = att + def - 1
koin membalik, atau 3 dalam contoh ini (pada dasarnya ini adalah yang terbaik dari 3 di sini). Ada 2 n kemungkinan kombinasi membalik koin. Di sini, "W" berarti penyerang memenangkan flip koin, dan "L" berarti penyerang kehilangan flip koin.Penyerang menang di 4/8, atau 50% dari kasus.
Matematika
Probabilitas matematika yang timbul dari algoritma sederhana ini lebih rumit daripada algoritma itu sendiri.
Jumlah kombinasi di mana tepatnya x Ls diberikan oleh fungsi kombinasi:
Penyerang menang ketika ada di antara
0
danatt - 1
Ls. Jumlah kombinasi pemenang sama dengan jumlah kombinasi dari0
throughatt - 1
, distribusi binomial kumulatif:Probabilitas penyerang menang adalah w dibagi 2 n , probabilitas binomial kumulatif:
Berikut adalah kode di Jawa untuk menghitung probabilitas ini untuk nilai arbitrer
att
dandef
:Kode pengujian:
Keluaran:
Pengamatan
Peluangnya adalah
0.0
jika penyerang memiliki0
poin,1.0
jika penyerang memiliki poin tetapi pertahanan memiliki0
poin,0.5
jika poinnya sama, kurang dari0.5
jika penyerang memiliki lebih sedikit poin daripada pertahanan, dan lebih besar dari0.5
jika penyerang memiliki lebih banyak poin daripada pertahanan .Mengambil
att = 50
dandef = 80
, saya perlu beralih keBigDecimal
s untuk menghindari overflow, tapi saya mendapatkan probabilitas sekitar 0,0040.Anda dapat membuat probabilitas lebih dekat ke 0,5 dengan mengubah
att
nilai menjadi rata-rataatt
dandef
nilai. Att = 50, Def = 80 menjadi (65, 80), yang menghasilkan probabilitas 0,1056.sumber
Anda dapat memodifikasi serangan dengan nomor acak yang diambil dari distribusi normal. Dengan cara ini sebagian besar hasilnya akan seperti yang Anda harapkan, tetapi kadang-kadang serangan yang lebih tinggi akan kalah melawan pertahanan yang lebih rendah atau serangan yang lebih rendah akan menang melawan pertahanan yang lebih tinggi. Kemungkinan terjadinya ini akan semakin kecil karena perbedaan antara serangan dan pertahanan meningkat.
Fungsi
norm(x0, sigma)
mengembalikan pelampung sampel dari distribusi normal yang berpusat di x0, dengan sigma deviasi standar. Sebagian besar bahasa pemrograman menyediakan perpustakaan dengan fungsi seperti itu, tetapi jika Anda ingin membuatnya sendiri lihatlah pertanyaan ini . Anda harus menyesuaikan sigma sedemikian rupa sehingga 'terasa benar', tetapi nilai 10-20 mungkin merupakan tempat yang baik untuk memulai.Untuk beberapa nilai sigma, probabilitas kemenangan untuk yang diberikan
att1 - def2
terlihat seperti ini:sumber