Mesin catur (chess engine) adalah program yang memberikan analisis posisi catur, contohnya berupa skor evaluasi (perkiraan besar keuntungan/kerugian bagi pemain yang bersangkutan) dan langkah balasan terbaik untuk posisi itu. Contoh mesin ini adalah Stockfish, Leela, Komodo, dan (mungkin sudah ada puluh) ribuan mesin lainnya. Sebagian besar, atau mungkin lebih tepatnya hampir semua, mesin-mesin ini adalah program berbasis teks, dan menggunakan protokol UCI untuk berkomunikasi. Sebagai contoh bentuk komunikasi, berikut (salah satu) cara menyuruh mesin menganalisis posisi yang dihasilkan dari 1.d4 d5 2.Nf3:
uci
ucinewgame
position startpos moves d2d4 d7d5 g1f3
go infinite
Setelah menuliskan itu, mesin akan memberikan analisisnya dalam baris-baris. Salah satu baris tersebut mungkin bertuliskan berikut
info multipv 1 depth 5 score cp -16 nodes 7825068 time 9914 nps 789294
hashfull 999 tbhits 0 pv e7e6 c2c4 g8f6 c4d5 e6d5
Terakhir ketika analisis dianggap sudah memuaskan, kita mengirim perintah stop, dan mesin akan menyampaikan teks yang kurang lebih seperti bestmove e7e6 ponder c2c4. Protokol UCI diterapkan untuk menyeragamkan format masukan/keluaran mesin-mesin catur, agar mereka lebih mudah digunakan dan dibandingkan satu sama lain.
Namun jujur, mengetik semua perintah-perintah itu dan mencoba membaca baris-baris analisis yang mengalir deras di layar, bukanlah pengalaman pengguna (UX, user experience) yang menyenangkan. Oleh karena itu, selanjutnya muncul antarmuka-antarmuka grafis catur (chess GUI) yang memperbaiki hal itu; membuat tampilan menjadi seperti apa yang diharapkan oleh pemain catur pada umumnya. Anda cukup menggeser-geser atau mengeklik-klik, dan analisis posisi akan tertampil rapi. Ada juga antarmuka dengan fitur-fitur tambahan, seperti bertanding melawan mesin, menonton mesin lawan mesin, melihat statistik permainan secara daring, membuat berkas analisis yang disertai teks komentar (misal, menjelaskan alasan suatu balasan dianggap cerdas), dan lain sebagainya. Contoh antarmuka ini adalah En Croissant, Nibbler, dan banyak lainnya (saya hanya menyertakan antarmuka yang sering saya pakai saja).
Malangnya, ada satu hal yang saya anggap sebagai kekurangan (setidaknya dari aspek pengalaman pengguna) di kebanyakan mesin maupun antarmuka catur: kemampuan untuk mengingat analisis posisi yang sudah dikerjakan. Ini maksud saya: misalkan Anda menganalisis posisi P dan membiarkan komputer bekerja setengah jam untuk menghasilkan analisis A yang memuaskan. Lalu Anda (secara tidak sengaja karena mouse-slip) memulai menganalisis posisi baru. Ini akan menyebabkan data analisis A hilang, dan Anda harus menganalisis P selama setengah jam lagi(!) untuk mendapatkan analisis A kembali. Anda juga harus melakukan hal yang sama jika Anda membuat sesi baru di mesin/antarmuka. Antarmuka dengan fasilitas "Simpan" juga tidak menyimpan informasi ini, atau menyimpannya dalam bentuk yang secara praktis sama saja dengan tidak disimpan. Tentu kekurangan ini tidak berlaku di semua mesin dan antarmuka; walau saya tidak bisa memastikannya, ada mesin (contohnya HIARCS dan BrainLearn, Rybka) dan antarmuka (Aquarium) yang menjawab masalah itu. Sialnya, solusi-solusi tersebut ad-hoc, dan tidak menyelesaikan keadaan ketika, contoh, saya ingin antarmuka Nibbler dapat menyimpan analisis oleh mesin Stockfish, dan simpanan itu dipakai di antarmuka En Croissant.
Ah, keadaan ini menyedihkan, dan itu memacu saya untuk membuat penyinggah (caching) untuk menyimpan analisis mesin. Secara lebih mendetail, penyinggah akan menjadi perantara komunikasi dengan mesin. Ketika mesin menganalisis posisi P, hasil analisisnya akan dibandingkan dengan hasil di pangkalan data, lalu penyinggah akan menyajikan data yang lebih berkualitas (misal, dengan nilai depth atau nodes yang lebih besar) dan memperbarui data di pangkalan (kalau diperlukan). Dari seig prakteknya, saya nantinya tidak perlu takut kehilangan hasil analisis karena mouse-slip.
Dari ide itu saya membuat prototipe program menggunakan Python, pangkalan data dengan SQLite, dan Nuitka untuk kompilasi kode menjadi executable. Gambaran umum pembuatan program kurang lebih seperti berikut. Pertama, menulis program yang bertindak sebagai perantara (man-in-the-middle) antara mesin dan apapun yang mencoba berkomunikasi dengannya. Lalu kita membuat cara memroses (parsing) teks yang dikirim dari/ke mesin. Selanjutnya kita tinggal membentuk pangkalan data, cara menyinggah hasil analisis, dan menampilkan versi analisis yang lebih baik (antara mesin dan pangkalan data). Saya pikir kode saya sama rapinya dengan kebanyakan kode-kode mesin catur di Internet; dengan kata lain, bisa dipahami tetapi hati akan sedikit memanas. Jika Anda penasaran cara yang saya lakukan, kode sumber utuh dapat diakses di /etc/share/chess_cache.py. Terakhir, kita bisa menggunakan Nuitka untuk mengompilasi kode menjadi berkas executable; berkas yang dihasilkan sekitar 50-60% lebih kecil daripada ketika menggunakan PyInstaller. Perintah yang saya gunakan adalah
python -m nuitka --standalone --onefile --lto=yes\
--python-flag=unbuffered --python-flag=no_asserts\
--python-flag=no_docstrings --python-flag=static_hashes\
--output-filename=chess_cache chess_cache.py`.
Untuk melihat program ini beraksi, Anda terlebih dahulu perlu membuat berkas settings.json di direktori yang sama dengan program chess_cache. Berkas JSON ini berisi letak mesin yang analisisnya ingin Anda singgah, dan nama berkas untuk menyimpan data singgahan. Sebagai contoh:
{
"engine_path": "/home/user/playground/stockfish",
"database_path": "/home/user/playground/chess.sqlite"
}
Lalu di Nibbler atau En Croissant (atau antarmuka yang Anda pakai), Anda tinggal menambahkan mesin baru dengan berkas binary/executable chess_cache. Antarmuka akan mengganggap mesin yang ditambahkan adalah mesin Stockfish (entah versi Stockfish apa yang Anda tetapkan di settings.json), dan Anda dapat berinteraksi seperti biasa. Yeay!
Tentu ini bukan hasil akhir. Untuk pengembangan selanjutnya, saya memikirkan cara-cara untuk: mengefisienkan penyimpanan data (info apa saja yang penting disinggah? apakah menyimpan bestmove sebagai INTEGER lebih efisien?), menyimpan metadata (mencegah pengguna tidak sengaja menggunakan pangkalan data yang sama untuk dua mesin berbeda), dan menggabungkan singgahan (sehingga pengguna dapat menikmati hasil singgahan yang dikumpulkan oleh pengguna-pengguna lainnya). Yeay! Ini menyenangkan, dan semoga saya bisa mengabarkan perkembangan selanjutnya.
Sampai jumpa!