1 poin oleh GN⁺ 2024-10-12 | 1 komentar | Bagikan ke WhatsApp
  • Membahas pendekatan untuk merancang mekanisme inti game dengan relasi logis dan predikat, alih-alih fungsi, kelas, atau variabel status
  • Alasan Prolog terasa lebih asing daripada LISP bukan karena sintaksnya, melainkan karena ia menangani struktur data dan algoritme dengan berpusat pada relasi matematis
  • Jika baris dalam basis data relasional, input/output rangkaian digital, dan objek game semuanya dipandang sebagai relasi n-ary, maka model deklaratif Prolog terhubung dengan desain berbasis data
  • Sulit mengimplementasikan grafis, audio, fisika, dan I/O sederhana sepenuhnya dengan Prolog, tetapi ada potensi penerapan pada mekanisme gameplay
  • Bagian 1 mengekspresikan tag dan relasi antaraktor sebagai predikat Prolog berdasarkan world dan actor, sementara perubahan waktu dan game loop disisakan untuk bagian berikutnya

Cara pandang menerapkan Prolog pada mekanisme game

  • LISP dan Prolog termasuk dalam paradigma pemrograman yang berbeda dari bahasa berorientasi objek umum seperti C# dan Java
  • LISP kuat dalam pemrograman fungsional dan pola meta-bahasa, sedangkan Prolog diperlakukan sebagai bahasa perwakilan dari pemrograman logika
  • LISP ternyata lebih mudah didekati daripada perkiraan berkat konsep seperti lambda expression dan higher-order function di C#, serta latar belakang teknik elektro dan pemrosesan sinyal
  • Sebaliknya, meskipun sintaks Prolog terlihat sederhana, kesulitan besarnya adalah cara ia menangani struktur data dan algoritme sebagai relasi matematis
  • Pendekatan Prolog bersinggungan dengan berbagai model rekayasa
    • Setiap baris dalam basis data relasional dapat dipandang sebagai predikat n-ary dalam sintaks Prolog
    • Perilaku input/output komponen rangkaian digital dapat diimplementasikan sebagai relasi n-ary yang menggabungkan port masukan dan keluaran
    • Objek seperti potongan hardware atau data murni di dalam memori juga dapat didefinisikan sebagai relasi dalam pemrograman logika
  • Seperti objek dapat dipandang sebagai fungsi dalam pemrograman fungsional, objek juga dapat dipandang sebagai relasi dalam pemrograman logika

Mekanisme inti game dan desain deklaratif

  • Pemrograman logika dapat dimanfaatkan untuk merancang dan mengimplementasikan sistem kompleks seperti mekanisme gameplay inti dalam video game
  • Mengimplementasikan seluruh game dengan Prolog merupakan tantangan besar bagi developer game pada umumnya, kecuali untuk tujuan eksperimen
  • Tidak semua komponen game cocok dengan Prolog
    • Modul I/O sederhana
    • Modul grafis
    • Modul audio
    • Modul fisika
  • Sasaran penerapannya lebih dekat ke mekanisme inti daripada keseluruhan game
  • Jika sistem gameplay disusun sebagai himpunan pernyataan deklaratif, ia bisa menjadi lebih kokoh dan modular daripada sistem imperatif, serta lebih bebas dari edge case yang membingungkan seperti race condition
  • Dalam metodologi ini, sistem harus dirancang hanya dengan relasi logis dan predikat
    • tanpa fungsi
    • tanpa struct
    • tanpa class
    • tanpa interface
    • tanpa variabel status

Model World dan Actor

  • Inti pemrograman game berbasis Prolog adalah menggunakan relasi sebagai komponen paling primitif, seperti resistor, transistor, kapasitor, dan induktor dalam rangkaian listrik
  • Game secara besar dibagi menjadi world dan actor
    • world adalah adegan tempat semua hal terjadi
    • actor adalah objek yang berada di dalam world
  • Actor mengacu pada entitas individual yang memiliki nama dan atribut, seperti player, enemy, obstacle, dan item
  • Actor dapat berinteraksi dengan actor lain maupun dengan dirinya sendiri, dan dalam proses ini berbagai event dapat terjadi
  • Gameplay dapat dipandang sebagai rangkaian dari event-event tersebut
  • Dalam model ini, world mencakup banyak actor, dan setiap actor memiliki status serta perilakunya sendiri

Merepresentasikan tag sebagai predikat unari

  • Setiap actor diidentifikasi dengan nama unik
    • Dalam contoh, actor1 dan actor2 mewakili actor pertama dan kedua
  • Tag adalah kata kunci yang ditempelkan pada actor dan menunjukkan actor itu apa
  • bread(actor1). dan bread(actor2). berarti actor1 dan actor2 sama-sama roti
bread(actor1).
bread(actor2).
  • Dalam Prolog, bread adalah relasi unari, dan bread(actor1) serta bread(actor2) adalah instans individual dari relasi tersebut
  • Actor dapat memiliki banyak tag
  • Jika semua roti harus flammable dan decomposable, maka menempelkan tag secara manual pada setiap actor akan merepotkan dan rawan kesalahan
  • Dengan Horn clause, ketika bread(X) bernilai benar, maka flammable(X) dan decomposable(X) otomatis berlaku
flammable(X) :- bread(X).
decomposable(X) :- bread(X).
  • Horn clause ini bekerja seperti data konfigurasi dalam game
    • Mirip dengan definisi karakteristik character type, skill type, atau mission type dalam dokumen desain teknis atau spreadsheet
    • Strukturnya adalah type-specifier bernama bread yang mencakup atribut flammable dan decomposable
  • Jika dianalogikan ke Unity, ini mirip menambahkan komponen Flammable dan Decomposable ke prefab Bread
  • Dalam lingkungan berorientasi objek, ini serupa dengan class Bread yang mengimplementasikan interface IFlammable dan IDecomposable
  • Dalam konteks ini, Horn clause di Prolog berperan sebagai definisi tipe data

Tag kustom yang menempel pada actor individual

  • Terpisah dari tag yang telah didefinisikan sebelumnya, tag kustom dapat ditempelkan hanya pada actor tertentu
  • Dalam contoh, seorang penyihir telah memberi sihir pada roti kedua, actor2, sehingga diperlukan tag enchanted
enchanted(actor2).
  • flammable dan decomposable adalah karakteristik yang dimiliki semua roti
  • enchanted adalah karakteristik yang hanya menempel pada roti khusus yang telah disihir

Merepresentasikan relasi antaractor sebagai predikat biner

  • Sistem gameplay tidak hanya perlu mengekspresikan karakteristik actor individual, tetapi juga relasi antarakor
  • Contoh relasi antara lain sebagai berikut
    • Dalam ekosistem, predator mengejar prey dan prey melarikan diri dari predator
    • Dalam dating simulator, pria mencoba menggoda wanita dan wanita menolak
    • Dalam social simulator seperti The Sims, orang bisa saling berteman, bermusuhan, atau berada di antaranya
    • Dalam catur, bishop menangkap rook secara diagonal, dan rook menangkap bishop secara ortogonal
  • Di Prolog, sebagaimana predikat unari menyatakan karakteristik satu actor, predikat biner dapat menyatakan relasi antara dua actor
  • Dengan menggunakan Horn clause, relasi dapat diinferensikan secara dinamis dari himpunan kondisi yang diperlukan

Contoh canEat dan canSpoil

  • Jika actor3 adalah manusia dan manusia dapat memakan roti, maka dapat didefinisikan relasi “jika X adalah human dan Y adalah bread, maka X dapat memakan Y”
human(actor3).
canEat(X, Y) :- human(X), bread(Y).
  • Di sini, canEat(X, Y) adalah relasi yang berlaku antara X dan Y
  • Jika actor4 adalah fungus dan roti bersifat decomposable, maka fungus dapat merusakkan actor yang decomposable
fungus(actor4).
canSpoil(X, Y) :- fungus(X), decomposable(Y).
  • canSpoil(X, Y) adalah relasi yang berarti “jika X adalah fungus dan Y adalah decomposable, maka X dapat merusakkan Y”
  • decomposable(Y) sebelumnya dapat diinferensikan dari bread(Y) melalui Horn clause

Masalah yang masih tersisa: perubahan waktu dan game loop

  • Contoh-contoh sejauh ini mengekspresikan karakteristik dan relasi actor, tetapi semuanya masih statis
  • Game bukanlah lanskap yang diam; actor harus bergerak dan berinteraksi seiring waktu
  • Hanya dengan sifat deklaratif Prolog, persoalan karakteristik yang berubah seiring waktu tampak tidak mudah dipecahkan
  • Cara mengonseptualisasikan game loop di Prolog dilanjutkan pada Part 2

1 komentar

 
GN⁺ 2024-10-12
Komentar Hacker News
  • Biasanya saya memandang rendah tulisan yang hanya punya Part 1 lalu berhenti, tetapi tulisan ini benar-benar terus merilis lanjutan
    https://thingspool.net/morsels/page-11.html (bagian 2)
    https://thingspool.net/morsels/page-12.html (bagian 3)
    https://thingspool.net/morsels/page-13.html (bagian 4)
    https://thingspool.net/morsels/page-14.html (bagian 5)
    Dan masih berlanjut

    • Katanya berlanjut sampai Part 13. Membacanya mungkin akan memakan waktu, tetapi saya sangat menyukainya, dan saya berencana mengikuti https://github.com/mthom/scryer-prolog, yaitu Scryer Prolog yang ditulis dengan Rust
      Sepertinya teknik-teknik ini bisa dibawa ke pemrograman game dengan Rust
    • Mungkin lebih baik mengubah tautan itu menjadi daftar isi: https://thingspool.net/morsels/list.html
    • Justru kalau ingin mendukung situs penulis dan membuatnya terus menulis, mungkin sebaiknya melakukan kebalikannya
  • Dalam desain game Breath of the Wild ada konsep yang disebut mesin kimia. Biasanya mesin game memiliki mesin fisika yang menghitung bagaimana benda saling berinteraksi dari sisi gerak, sedangkan mesin kimia menangani bagaimana material saling berinteraksi dalam pengertian alkimia
    Seperti mesin berbasis aturan, ia menghitung interaksi antarberbagai zat yang berbeda, sehingga muncul interaksi mengejutkan seperti panah bisa dibakar karena terbuat dari kayu
    Tautan YouTube: https://www.youtube.com/watch?v=QyMsF31NdNc&t=2354s
    Elemen berbasis aturan dalam game biasanya relatif sederhana dan tidak perlu bersifat umum, jadi tampaknya ditulis langsung dengan tangan. Saat pembuat Baba is You ditanya apakah ia mengimplementasikan mesin Datalog, jawabannya juga tidak, dan Breath of the Wild kemungkinan serupa
    Meski begitu, saya sering berpikir bahwa mesin kimia seperti ini bukankah paling baik diimplementasikan dengan bahasa logika seperti Prolog atau Datalog untuk eksperimen cepat. SQL juga awalnya dipakai demi menjaga fleksibilitas kueri lalu akhirnya dikirim apa adanya, dan dulu mungkin banyak keluhan bahwa kueri SQL lambat, tetapi fleksibilitas itu cukup berguna sehingga orang menghabiskan banyak waktu untuk membuatnya cepat. Sekarang hampir tidak ada yang berpikir, “Saya bisa menulis kode imperatif langsung yang lebih cepat daripada kueri ini”

    • Noita adalah game yang berpusat pada konsep mesin kimia tingkat piksel, dan menggunakan mesin aturan buatan sendiri yang ditulis dalam C++
      Ini termasuk salah satu game paling menarik yang pernah saya mainkan sejauh ini
      https://store.steampowered.com/app/881100/Noita/
      https://www.youtube.com/watch?v=prXuyMCgbTc
    • Sistem objek itu pada dasarnya sama dengan desain ZMachine. Objek bisa memiliki properti, dan bekerja seperti objek serta metode dalam pemrograman berorientasi objek
      Mungkin MUD juga mirip
      Hal-hal yang ingin dibuat revolusioner oleh game grafis sebenarnya sudah dilakukan 40 tahun lalu oleh game teks, terutama fiksi interaktif. Ini bahkan lebih menonjol bukan pada karya awal Infocom, melainkan pada renaisans game amatir hebat tahun 1990-an seperti Curses, Jigsaw, Anchorhead, Devours, Spider and Web, juga roguelike seperti NetHack/Slash'EM dan CDDA: Bright Nights, serta MUD online yang menangani material aneh dan interaksi, bukan hanya dalam latar fantasi tetapi juga cyberpunk atau fiksi ilmiah
      Pembuat game terbaik seperti Warren Spector kemungkinan juga memainkan game perangkat lunak bebas, game indie, dan game nyentrik untuk mendapatkan ide gameplay baru
      Referensi NetHack dalam Deus Ex versi asli menurut saya bukan sekadar easter egg, melainkan penghormatan terhadap gameplay emergen yang mungkin terinspirasi dari NetHack
      Kekuatan Deus Ex bukan pada grafis atau dunianya, melainkan pada apa yang bisa dilakukan pemain di dalam game, dan pada keberhasilannya mematahkan struktur linear FPS sambil tetap lebih mudah diakses dibandingkan System Shock 1 dan 2. Seri System Shock punya sisi yang gagal dalam penyesuaian tingkat kesulitan dan kematangan gameplay. Arx Fatalis (sekarang Libertatis) dan Ultima Underworld juga mirip
    • Ini mengingatkan pada Dwarf Fortress. Palu perak memberi kerusakan lebih besar karena perak lebih berat, dan furnitur kayu bisa terbakar. Hujan atau darah bisa membasahi pakaian dengan cairan, dan itu bahkan bisa diminum
      Dari aturan sederhana bisa muncul banyak kompleksitas yang sangat menarik
    • Dengan asumsi saya belum membaca tulisan aslinya, saya sudah terpesona selama beberapa tahun oleh penggunaan pemrograman relasional dalam mesin game. Pada akhirnya saya menyimpulkan bahwa, alih-alih membuat seluruh game dalam bahasa relasional umum, lebih baik menulis mesinnya dalam C++ lalu memakai solver khusus hanya untuk beberapa aspek yang memang ingin ditangani secara relasional
      Bukan berarti hanya algoritme solver yang diimplementasikan oleh bahasa logika/relasional umum yang mungkin dipakai; masalahnya, makin umum sifatnya, makin mungkin ia tidak efisien untuk masalah yang harus diselesaikan mesin game secara efisien. Sebaliknya, jika fungsi-fungsi seperti itu diperluas secara native ke bahasa logika, kita mungkin harus merusak asumsi penyederhanaan atau mengubah urutan evaluasi, sehingga bahasa menjadi lebih sulit diimplementasikan secara sederhana dan efisien
      Misalnya saya ingin menggunakan relasi logika bersama kendala linear. Sesuatu seperti A <= (B-10.0) .OR. B <= (A-10.0) untuk membatasi posisi pusat dua objek game yang lebarnya 10.0 agar batasnya tidak saling tumpang tindih, tanpa peduli yang mana berada di depan. Dengan pernyataan seperti ini, adegan atau objek game yang kompleks bisa disusun secara kualitatif, lalu solver kendala linear memilih koordinat yang tepat
      Masalahnya, menyelesaikan kendala linear seperti f(A) <= g(B) bisa memengaruhi semua variabel terkait. A atau B juga bisa memiliki kendala dengan C, D, E, dan F, sehingga jika sisi kiri atau kanan dari ekspresi logika prop(X) .OR. prop(Y) dieksekusi segera saat dipilih, proposisi lain yang sebelumnya sudah dipastikan bisa menjadi tidak valid
      Karena itu, daripada menafsirkan <= pada variabel linear sebagai tes yang menghasilkan nilai boolean, lebih baik menafsirkannya sebagai perintah untuk menambahkan f(A) <= g(B) ke penyimpanan kendala linear global lalu menjalankan solver nanti terhadap seluruh matriks variabel linear
      Lalu muncul pertanyaan desain seperti bagaimana bahasa tahu kapan penambahan kendala sudah selesai dan saatnya menyelesaikan, atau bagaimana menangani klausa logika yang benar-benar harus menguji nilai, bukan menambah kendala. Tetapi intinya, dalam konteks mesin game, kita perlu jauh lebih mengontrol kapan komputasi panjang dijalankan dan berapa lama ia berjalan, baik dalam penyelesaian kendala linear maupun pemrograman logika
      Artinya, bahkan jika dari sudut pandang bahasa logika fitur ekstensi itu dirancang agar bekerja dengan baik, dari sudut pandang sistem luar tetap ada masalah bahwa waktu pencarian untuk menyelesaikan sebagian program logika bisa tiba-tiba meledak, dan programmer tidak selalu mudah memprediksi kapan dan di mana itu akan terjadi. Dalam arti ini, kode imperatif yang ditulis tangan bahkan tidak harus lebih cepat; meski lebih lambat pun tidak masalah asalkan memiliki prediktabilitas
      Pada praktiknya, juga bukan berarti semuanya harus ditulis langsung sendiri. Intinya adalah apakah mesin aturan merupakan solver yang dijalankan dan bisa dipreempt oleh kode game imperatif dari luar, atau justru seluruh game berjalan di dalam solver, yaitu di dalam bahasa relasional. Membayangkan apa yang bisa dilakukan jika seluruh game bersifat relasional memang menarik, tetapi untuk benar-benar menerapkan teknologi itu pada keseluruhan game, dibutuhkan solver relasional ajaib yang dalam kenyataannya belum ada
  • Menarik karena ini pengantar pemrograman game dengan Prolog, tetapi langsung menuju game aksi. Aspek yang dibahas mencakup real-time, lini masa, 3D, ECS, dan event
    Biasanya buku pengantar pengembangan game dengan Prolog dimulai dari game petualangan, terutama text adventure klasik. Itu karena labirin dan puzzle inventaris sangat pas dengan fakta dan aturan Prolog, serta DSL-nya
    Game kartu atau board game juga bisa mengekspresikan aturannya dengan sangat nyaman di Prolog, dan seperti perencana Prolog yang dipakai di robotika, logistik, keuangan, industri, dan bidang lain, lawan game umum kombinatorial dasar pun bisa diperluas dengan relatif mudah

  • Saat mengambil kelas AI, hal pertama yang kupelajari adalah Prolog, dan tugas kami semuanya harus menulis game bergaya adventure/colossal cave. Prolog sangat cocok untuk pekerjaan itu, dan aku terkejut melihat betapa beragamnya game sederhana yang dibuat di kelas
    Aku sempat berpikir akan bagus kalau semua game buatan mahasiswa lain dikumpulkan. Setelah beberapa minggu, materi lalu beralih ke topik lain seperti CLIPS dan Lisp
    Untuk tugasku, aku membuat Bureaucratic Maze [1], dan itu juga terasa cukup intuitif di Prolog
    [1]. http://logicmazes.com/bureau/index.htm

    • Di Common Lisp, Land of Lisp memang memakai latihan seperti ini untuk pemula
      Tetapi di Inform6, tingkat kesulitannya turun drastis hingga hampir sepele berkat pemrograman berorientasi objek sebagaimana diterapkan pada desain game dan cara menangani langsung relasi antarobjek dalam game seperti ZMachine
    • https://amzi.com/AdventureInProlog/ juga mengajarkan Prolog dengan cara yang sama
    • Di Chrome/Firefox terbaru pada macOS, puzzle yang ditautkan dari halaman teratas memunculkan error JavaScript di terminal. Akan menyenangkan kalau bisa melihatnya benar-benar berjalan
      http://logicmazes.com/alice.html
      alice.html:353 Uncaught TypeError: Cannot read properties of undefined (reading 'play')
      at playSound (alice.html:353:30)
      at finalize2 (alice.html:347:1)
      at :1:1
  • Aku sudah menelusuri 12 tulisan, dan ini tampak bagus sebagai pengantar penggunaan Prolog, tetapi masih terasa terlalu dini untuk menyebutnya terkait dengan pemrograman game
    Mungkin nanti akan berkembang, tetapi sampai pelajaran ke-12 isinya kebanyakan soal mencoba memodelkan beberapa konsep berorientasi objek di Prolog
    Mungkin ada yang kulewatkan, tetapi interaksi pengguna yang tampaknya menjadi premis game itu sendiri belum dibahas. Ada bagian singkat tentang pengiriman pesan, jadi mungkin itu yang dimaksud

  • Dalam konteks serupa, aku pernah menikmati membaca buku pemrograman game berbasis pemrograman logika yang memakai CLIPS alih-alih Prolog
    Adventures in Rule-Based Programming: A CLIPS Tutorial https://a.co/d/7wVOcZp

    • Aku juga tadinya ingin menyebut buku itu. Aku membelinya setelah menelusuri dokumentasi gratis ketika di tempat kerja kami sedang mengeksplorasi kemungkinan memakai CLIPS atau sesuatu yang mirip untuk suatu sistem, dan itu buku yang menyenangkan untuk dibaca
      https://www.clipsrules.net/
    • https://ryjo.codes/ punya banyak materi bagus terkait CLIPS
    • Kelihatannya menarik. Aku penasaran apakah edisi Kindle-nya bagus
      Buku pemrograman sering kali buruk di Kindle, tetapi mungkin cukup bagus kalau dibaca di tablet Fire
  • Ada irisan menarik antara cara memandang status game sebagai kumpulan fakta dan relasi (Prolog) dan inti ECS, yaitu “ini adalah database” [1]
    Secara pribadi aku sedang bereksperimen memakai Datascript sebagai database status game, tetapi masih terlalu dini untuk menilai apakah ini berhasil atau tidak. Menyenangkan melihat ide dalam tutorial ini terpetakan 1:1 ke sudut pandang itu

    1. https://www.gamedevs.org/uploads/data-driven-game-object-sys...
    • Bagian yang menarik adalah irisan antara aturan dalam pemrograman logika dan aturan game. Terinspirasi dari karya Stanford tentang Game Description Language [1] berbasis pemrograman logika, kemarin aku mengimplementasikan tic-tac-toe dengan Datascript: https://github.com/kasbah/datascript-games/blob/e06a37025bf9...
      Aku masih belum yakin apakah definisi aturan yang lebih ringkas daripada yang kutulis sekarang itu memungkinkan. Di makalah Stanford, aturan bisa ditulis seperti (<= (column ?n ?x) ...), tetapi di Datascript ada jauh lebih banyak pekerjaan tambahan untuk memindahkan data
      Aku tidak tahu apakah ini karena keterbatasan Datascript/Datomic Datalog, atau karena pemahamanku yang masih kurang
      Aku penasaran bagaimana kamu mendekati eksperimen ini. Kalau ada hasil kerja yang bisa dibagikan atau saran tentang pendekatanku saat ini, aku akan sangat tertarik
      [1]: https://www.cs.uic.edu/~hinrichs/papers/love2006general.pdf
    • Kalau belum pernah lihat, mungkin kamu akan tertarik pada pendekatan yang merangkai aturan DataScript ini untuk menurunkan frame berikutnya: https://frankiesardo.github.io/minikusari/#!/minikusari.tuto...
  • Ini terasa segar sebagai cara menangani masalah mesin status dalam game yang sarat logika, misalnya simulasi kota. Aku belum pernah terpikir memakai Prolog seperti ini

  • Tampaknya ini bisa melakukan hal yang sangat keren dalam pembahasan kausalitas dan relativitas. Misalnya, sambil menghasilkan pertemuan acak dengan NPC, kita bisa membuat riwayat peristiwa NPC tersebut yang mencakup rantai kausal yang sebelumnya dipicu oleh pemain
    Karena semuanya adalah relasi, dan ada fakta bahwa NPC itu ada sekarang serta riwayat semua keadaan dunia dan tindakan yang telah diamati, kita bisa menelusurinya secara terbalik dan memberi NPC masa lalu yang sepenuhnya konsisten tanpa perlu menyimulasikannya terlebih dahulu

  • Saya tidak pernah terpikir bahwa model actor-world/entity-trait yang umum bisa sangat cocok dengan pendekatan relasional Prolog
    Namun, waktu eksekusi yang dapat diprediksi dan efisien juga penting. Prolog biasanya cenderung melakukan pencarian brute-force dengan mencocokkan term demi memenuhi kueri. Saya belum membaca seluruh serinya, tetapi penasaran apakah ini membahas masalah tersebut

    • Pencarian brute-force hanyalah cara naif untuk menemukan solusi. Seperti halnya kita bisa menambahkan indeks pada tabel SQL, kita juga bisa menambahkan indeks pada predikat Prolog untuk meningkatkan performa
    • Ini mungkin pertanyaan yang sangat dasar, tetapi bukankah banyaknya pencarian brute-force bergantung pada solver yang digunakan? Saya samar-samar tahu tentang hal seperti finite domain constraints, dan penasaran seberapa jauh Prolog memberi ruang untuk menggunakan solver yang berbeda di bagian-bagian berbeda dari codebase
      Tebakan awal saya, bentuknya mungkin seperti menuliskan kendala yang diketahui tentang solusi sebagai semacam “deklarasi tipe”