Saya ingin membuat parser aturan umum untuk sistem RPG gaya pena dan kertas. Suatu aturan biasanya melibatkan 1 hingga N entitas 1 hingga N peran dadu dan menghitung nilai berdasarkan beberapa atribut entitas.
Sebagai contoh:
Pemain memiliki STR 18, senjatanya yang dilengkapi saat ini memberinya bonus +1 STR tetapi malus dari DEX -1. Ia menyerang entitas monster dan logika game sekarang diperlukan untuk menjalankan serangkaian aturan atau tindakan:
Pemain melempar dadu, jika ia mendapatkan misalnya 8 atau lebih (nilai serangan dasar yang ia harus lewati adalah salah satu atribut dasarnya!) Serangannya berhasil. Monster itu kemudian melempar dadu untuk menghitung jika serangan melewati baju besinya. Jika ya kerusakan diambil jika bukan serangan itu diblokir.
Selain itu aturan matematika sederhana juga dapat memiliki kendala seperti menerapkan hanya untuk kelas pengguna tertentu (misalnya prajurit vs penyihir) atau atribut lainnya. Jadi ini tidak hanya terbatas pada operasi matematika.
Jika Anda terbiasa dengan sistem RPG seperti Dungeon dan Dragons, Anda akan tahu apa yang saya lakukan.
Masalah saya sekarang adalah bahwa saya tidak memiliki petunjuk bagaimana tepatnya membangun ini dengan cara terbaik. Saya ingin orang-orang dapat mengatur segala jenis aturan dan kemudian hanya melakukan tindakan seperti memilih pemain dan monster dan menjalankan tindakan (seperangkat aturan seperti serangan).
Saya kurang meminta bantuan dengan sisi database tetapi lebih lanjut tentang cara membuat struktur dan parser agar aturan saya fleksibel. Omong-omong, pilihan untuk ini adalah php.
Edit I:
Biarkan saya memperbaiki tujuan saya: Saya ingin membuat antarmuka yang ramah pengguna (yang tidak mengharuskan seseorang untuk belajar bahasa pemrograman) untuk membangun aturan permainan yang lebih atau kurang kompleks. Alasan sederhananya: Penggunaan pribadi untuk tidak perlu mengingat semua aturan sepanjang waktu, kita tidak bermain sesering itu dan merupakan penghenti untuk melihatnya setiap kali. Juga: Sepertinya tugas yang menyenangkan untuk dilakukan dan belajar sesuatu. :)
Apa yang saya coba sejauh ini: Hanya memikirkan sebuah konsep daripada membuang-buang waktu membangun arsitektur yang salah. Sejauh ini saya memiliki ide untuk memungkinkan pengguna untuk membuat atribut sebanyak yang mereka inginkan dan kemudian menetapkan atribut sebanyak yang mereka inginkan untuk semua jenis entitas. Entitas dapat menjadi pemain, monster, item, apa saja. Sekarang ketika menghitung sesuatu data tersedia untuk parser aturan sehingga aturan parser harus dapat melakukan hal-hal seperti jika Player.base_attack + dadu (1x6)> Monster.armor_check lalu Monster.health - 1; Pertanyaannya di sini adalah tentang cara membuat parser itu.
Edit II:
Berikut adalah contoh nilai yang cukup mendasar tetapi untuk menghitungnya dengan benar ada banyak hal dan variabel yang perlu dipertimbangkan:
Bonus Serangan Dasar (Jangka) Bonus serangan dasar Anda (biasanya disebut sebagai BAB oleh komunitas d20) adalah bonus serangan gulungan yang berasal dari kelas dan level karakter. Bonus serangan dasar meningkat pada tingkat yang berbeda untuk kelas karakter yang berbeda. Seorang karakter mendapat serangan kedua per putaran ketika bonus serangan dasarnya mencapai +6, yang ketiga dengan bonus serangan dasar +11 atau lebih tinggi, dan yang keempat dengan bonus serangan dasar +16 atau lebih tinggi. Bonus serangan basis diperoleh dari kelas yang berbeda, seperti untuk karakter multikelas, stack. Bonus serangan basis karakter tidak memberikan serangan lagi setelah mencapai +16, tidak boleh kurang dari +0, dan tidak meningkat karena level kelas setelah level karakter mencapai 20. Bonus serangan dasar minimum diperlukan untuk prestasi tertentu.
Anda dapat membacanya di sini http://www.dandwiki.com/wiki/Base_Attack_Bonus_(Term) termasuk tautan ke kelas dan prestasi yang memiliki lagi aturan mereka sendiri untuk menghitung nilai yang diperlukan untuk serangan dasar.
Saya mulai berpikir bahwa menjaganya se generik mungkin juga akan membuat sulit untuk menyelesaikan aturan parser yang baik.
Func
yang menginisialisasi status program berdasarkan argumen sebagai kunci ke kamus. Terkejut saya tidak pernah menemukan posting itu dari Yegge sebelumnya, sangat keren, terima kasih telah menunjukkannya.Jawaban:
Apa yang Anda minta pada dasarnya adalah bahasa khusus domain — bahasa pemrograman kecil untuk tujuan yang sempit, dalam hal ini mendefinisikan aturan P&P RPG. Merancang bahasa pada prinsipnya tidak sulit, tetapi ada banyak pengetahuan di muka yang harus Anda peroleh agar sama sekali produktif. Sayangnya, tidak ada referensi sentral untuk hal ini — Anda harus mengambilnya melalui uji coba, kesalahan, dan banyak penelitian.
Pertama, temukan satu set operasi primitif di mana operasi lain dapat diimplementasikan. Sebagai contoh:
Dapatkan atau atur properti pemain, NPC, atau monster
Dapatkan hasil die roll
Mengevaluasi ekspresi aritmatika
Mengevaluasi ekspresi kondisional
Lakukan percabangan bersyarat
Desain sintaksis yang mengekspresikan primitif Anda. Bagaimana Anda merepresentasikan angka? Seperti apa pernyataan itu? Apakah pernyataan diakhiri dengan tanda koma? Dihentikan baris baru? Apakah ada struktur balok? Bagaimana Anda menunjukkannya: melalui simbol atau lekukan? Apakah ada variabel? Apa yang merupakan nama variabel hukum? Apakah variabel bisa berubah? Bagaimana Anda mengakses properti objek? Apakah objek kelas satu? Bisakah Anda membuatnya sendiri?
Tulis parser yang mengubah program Anda menjadi pohon sintaksis abstrak (AST). Pelajari tentang pernyataan parsing dengan parser keturunan rekursif. Pelajari tentang bagaimana parsing ekspresi aritmatika dengan penurunan rekursif mengganggu, dan operator parser diutamakan operator top-down (Pratt parser) dapat membuat hidup Anda lebih mudah dan kode Anda lebih pendek.
Tulis penerjemah yang mengevaluasi AST Anda. Ini hanya dapat membaca setiap node di pohon dan melakukan apa yang dikatakannya:
a = b
menjadinew Assignment("a", "b")
menjadivars["a"] = vars["b"];
. Jika itu membuat hidup Anda lebih mudah, ubah AST menjadi bentuk yang lebih sederhana sebelum evaluasi.Saya sarankan merancang hal paling sederhana yang akan bekerja dan tetap dapat dibaca. Berikut adalah contoh dari bagaimana rupa suatu bahasa. Desain Anda tentu akan berbeda berdasarkan kebutuhan dan preferensi spesifik Anda.
Atau, pelajari cara menyematkan bahasa skrip yang ada seperti Python atau Lua ke dalam aplikasi Anda, dan gunakan itu. Kelemahan dari menggunakan bahasa tujuan umum untuk tugas khusus domain adalah abstraksi yang bocor: semua fitur dan gotcha bahasa masih ada. Sisi positifnya adalah Anda tidak harus mengimplementasikannya sendiri — dan itu adalah sisi positif yang signifikan. Pikirkan itu.
sumber
Saya akan mulai dengan menentukan "Fase" yang berbeda dari setiap tindakan.
Misalnya, Fase Tempur mungkin melibatkan:
Masing-masing metode ini akan memiliki akses ke beberapa objek yang cukup umum, seperti
Player
danMonster
, dan akan melakukan beberapa pemeriksaan yang cukup umum yang entitas lain dapat gunakan untuk memodifikasi nilai.Misalnya, Anda mungkin memiliki sesuatu yang terlihat seperti ini termasuk dalam
GetPlayerCombatStats()
metode Anda :Ini memungkinkan Anda untuk dengan mudah menambahkan entitas apa pun dengan aturan tertentu, seperti Kelas Pemain, monster, atau bagian Peralatan.
Sebagai contoh lain, anggaplah Anda menginginkan Pedang Membunuh Segalanya Kecuali Squid , yang memberi Anda +4 terhadap segalanya, kecuali benda itu memiliki tentakel, dalam hal ini Anda harus menjatuhkan pedang Anda dan mendapatkan -10 dalam pertempuran.
Kelas perlengkapanmu untuk pedang ini mungkin memiliki sesuatu
GetCombatStats
yang terlihat seperti ini:Ini memungkinkan Anda untuk dengan mudah memodifikasi nilai pertempuran tanpa perlu tahu tentang sisa logika pertempuran, dan memungkinkan Anda untuk dengan mudah menambahkan potongan baru ke aplikasi karena rincian dan logika implementasi Peralatan Anda (atau entitas apa pun itu) hanya perlu ada di kelas entitas itu sendiri.
Hal-hal kunci untuk dipecahkan adalah pada titik mana nilai dapat berubah, dan elemen apa yang memengaruhi nilai-nilai itu. Setelah Anda memilikinya, membangun komponen individual Anda harus mudah :)
sumber
Player
,Monster
,Dice
, dll), dan menyiapkan sesuatu yang memungkinkan pengguna untuk potongan badan drag / drop ke daerah "persamaan", mengisi parameter entitas (seperti mengisiplayer.base_attack
), dan tentukan operator sederhana tentang bagaimana potongan-potongan tersebut cocok. Saya sebenarnya memiliki sesuatu yang diposting di blog saya yang mem-parsing persamaan matematika yang mungkin dapat Anda gunakan.Saya akan melihat maptool khususnya kerangka kerja ke-4 Rumble . Ini sistem terbaik yang pernah saya lihat untuk mengatur apa yang Anda bicarakan. Sayangnya yang terbaik masih crufty mengerikan. Sistem "makro" mereka telah ... katakanlah ... berkembang seiring waktu.
Adapun "parser aturan" Saya hanya akan tetap dengan bahasa pemrograman apa pun yang Anda merasa nyaman, bahkan jika itu PHP. Tidak akan ada cara yang baik untuk menyandikan semua aturan sistem Anda.
Sekarang, jika Anda ingin pengguna Anda dapat menulis aturan MEREKA SENDIRI, maka Anda sedang mencari cara untuk mengimplementasikan bahasa skrip Anda sendiri. Para pengguna membuat skrip tindakan tingkat tinggi mereka sendiri, php Anda mengartikannya menjadi sesuatu yang benar-benar memengaruhi nilai-nilai basis data, dan kemudian melemparkan banyak kesalahan karena itu adalah sistem kekasaran mengerikan yang telah ditanduk sepatu pada tempatnya selama bertahun-tahun. Sungguh, jawaban Jon Purdy tepat pada waktunya.
sumber
Saya pikir Anda harus dapat berpikir secara abstrak tentang hal-hal yang akan terjadi di ruang masalah Anda, menghasilkan beberapa model dan kemudian mendasarkan DSL Anda pada itu.
Misalnya Anda mungkin memiliki entitas entitas, tindakan, dan acara di tingkat atas. Gulungan mati adalah peristiwa yang terjadi sebagai akibat dari tindakan. Tindakan akan memiliki kondisi yang menentukan apakah mereka tersedia dalam situasi tertentu dan "skrip" hal-hal yang terjadi ketika tindakan diambil. Hal yang lebih kompleks adalah kemampuan untuk menentukan urutan fase di mana tindakan yang berbeda dapat terjadi.
Setelah Anda memiliki semacam model konseptual (dan saya sarankan Anda menuliskannya dan / atau menggambar diagram untuk mewakilinya), Anda dapat mulai melihat berbagai cara untuk mengimplementasikannya.
Satu rute adalah untuk menentukan apa yang disebut DSL eksternal di mana Anda mendefinisikan sintaks Anda dan menggunakan alat seperti antlr untuk menguraikannya dan memanggil logika Anda. Rute lain adalah menggunakan fasilitas yang ada dalam bahasa pemrograman untuk menentukan DSL Anda. Bahasa seperti Groovy dan Ruby sangat bagus di ruang ini.
Satu jebakan yang perlu Anda hindari adalah mencampurkan logika tampilan Anda dengan model permainan yang diterapkan. Saya akan memilih agar tampilan membaca model Anda dan menampilkannya dengan tepat daripada mencampurkan kode tampilan Anda dicampur dengan model Anda.
sumber