
Pada awal musim gugur, kompetisi untuk menulis bot Mini AI Cup # 3 (alias Mobil Gila) selesai, di mana para peserta harus bertarung dengan mobil. Peserta banyak berdebat tentang apa yang akan berhasil dan apa yang tidak akan berhasil, ide-ide diungkapkan dan diuji dari jika sederhana untuk melatih jaringan saraf, tetapi tempat-tempat teratas diambil oleh orang-orang dengan apa yang disebut "simulasi". Mari kita coba memahami apa itu, membandingkan solusi untuk tempat ke-1, ke-3 dan ke-4 dan berdiskusi tentang topik solusi lain yang mungkin.
Penafian
Artikel ini ditulis bekerja sama dengan Alexei Dichkovsky (Commandos) dan Vladimir Kiselev (Valdemar) .
Bagi mereka yang hanya ingin membaca tentang keputusan pemenang, saya sarankan Anda untuk segera mulai dengan item "Simulasi".
Pernyataan masalah
Kali ini, mekanisme dunia sangat mirip dengan game mobile Drive Ahead: para pemain diberi mobil dengan tombol yang terletak di sana; tugasnya adalah menekan tombol musuh lebih cepat dari yang dilakukannya. Jika tidak ada yang menang dalam 600 kutu game, kartu mulai tenggelam ke tumpukan sampah, yang juga dapat menekan tombol. Dengan kata lain, Anda perlu melindungi tombol Anda dari musuh, dunia di sekitar Anda dan banyak sampah (sangat, ya). Setiap pemain diberikan 5 nyawa, permainan berlangsung dari 5 hingga 9 putaran, sementara seseorang tidak mengakhiri hidup mereka. Setiap putaran diadakan pada peta acak dan mobil, sama untuk kedua peserta. Total ada 6 kartu yang berbeda dan 3 jenis mobil - total 18 kombinasi yang berbeda.
Setiap putaran dipecah menjadi kutu. Kutu adalah satu gerakan, seperti dalam catur. Satu-satunya perbedaan adalah bahwa kedua pemain pergi pada saat yang sama. Ada kompetisi di mana setiap orang bergiliran, atau Anda dapat melakukan tindakan hanya sekali setiap beberapa gerakan dan memilih unit sebagai bingkai .
Setiap tanda centang pada bot muncul keadaan damai dan diberi kesempatan untuk melakukan 3 tindakan:
,
,
. Tindakan ini membuat mobil masuk ke salah satu arah, dan jika pada saat yang sama tidak menyentuh roda bumi, maka mereka memberikan sedikit putaran ke seluruh tubuh (sedikit fisika arcade). Setelah kedua lawan memilih tindakan, simulasi dunia permainan dimulai, negara baru dipertimbangkan dan dikirim ke para pemain. Jika seseorang mengklik tombol, maka putaran berakhir dan yang berikutnya dimulai. Semuanya sederhana, tetapi ada nuansa.
Aturan yang lebih lengkap dapat ditemukan di sini . Dan lihat pertandingan final di sini .
Deskripsi Solusi Umum
Kebanyakan kompetisi penulisan bot sangat mirip: ada jumlah kutu yang terbatas (ada sekitar 1.500 maksimum untuk satu putaran), ada sejumlah tindakan yang mungkin terbatas, Anda perlu memilih urutan tindakan yang lebih baik daripada lawan Anda. Beberapa saat kemudian kita akan kembali ke apa artinya menjadi lebih baik, tetapi untuk sekarang kita akan mencari tahu bagaimana menangani masalah utama - sejumlah besar opsi: pada awalnya kita memiliki satu keadaan awal, maka setiap mesin dapat bergerak dalam tiga cara yang berbeda, yang memberi kita 9 kombinasi yang berbeda untuk dua mobil, pada langkah 1500 itu akan menjadi 9 ^ 1500 kombinasi yang berbeda ... Yang sedikit lebih daripada yang kita inginkan jika kita berencana untuk mengaturnya selama keberadaan Semesta.
Di sini kita sampai pada apa itu simulasi . Ini bukan semacam algoritma, tetapi hanya rekreasi dari aturan permainan dengan akurasi yang cukup atau lengkap sehingga dimungkinkan untuk memilah-milah solusi. Tentu saja, kita tidak akan melalui semua solusi, tetapi hanya sebagian saja. Algoritme pencarian akan digunakan untuk ini - di pohon status permainan kami sedang mencari yang terbaik untuk kami. Ada banyak algoritma (dari minimax ke MCTS), masing-masing memiliki nuansa tersendiri. Yang terbaik adalah membiasakan diri dengan keputusan yang ditulis peserta dalam kompetisi AI sebelumnya. Ini akan memberikan pemahaman dasar dalam kondisi apa algoritma bekerja, dan di mana tidak demikian. Ada banyak tautan untuk ini di repositori khusus .
Saat memilih suatu algoritma, Anda harus mempertimbangkan:
- batas waktu untuk 1 tick (di sini saya salah hitung banyak tahun ini, tetapi bisa tetap di posisi ke-3);
- jumlah pemain. Misalnya, jika ada tiga pemain, akan sulit untuk menggunakan minimax;
- akurasi simulasi, seperti ini memungkinkan penggunaan kembali perhitungan lama;
- "Percabangan" dari pohon negara (apakah mungkin untuk menghitung semua negara yang mungkin setidaknya 10 langkah di depan);
- akal sehat - jangan mulai menulis MCTS jika kompetisi berlangsung 4 jam.
Dalam kompetisi ini, 1 tick memberi sekitar 10-13ms (2 menit untuk seluruh pertandingan). Selama waktu ini, bot harus membaca data, membuat keputusan dan mengirim perintah untuk pindah. Ini cukup untuk merangsang sekitar 500-1000 gerakan. Iterasi semua negara bagian. Algoritma pencarian paling sederhana mungkin terlihat seperti perbandingan dari tiga pilihan gerakan: "50 ticks go left", "50 ticks go right", "50 ticks click stop". Dan betapapun sederhananya kedengarannya, tidak jauh dari keputusan pemenang.
Karena kita hanya menghitung 50 langkah ke depan, yang dalam kebanyakan kasus tidak dihitung sampai akhir permainan, maka kita membutuhkan fungsi evaluasi yang akan mengatakan seberapa baik dan buruk keadaan dunia bagi kita. Paling sering, itu dibangun di atas heuristik dan memahami apa yang penting untuk kemenangan. Misalnya, dalam kompetisi Piala Rusia Rusia 2014 ada balapan, tetapi Anda bisa menang jika Anda datang terakhir, jika Anda mendapatkan lebih banyak poin bonus. Oleh karena itu, fungsi peringkat harus merangsang pengumpulan poin pada saat yang sama dengan pergerakan cepat di sepanjang jalan raya. Skor hanya dapat dihitung untuk keadaan terakhir dari simulasi (setelah 50 ticks) atau sebagai jumlah dari perkiraan keadaan perantara. Seringkali, perkiraan "memudar" pada waktunya sehingga keadaan yang terjadi lebih awal lebih dipengaruhi. Karena kita tidak dapat secara pasti memprediksi musuh, maka opsi di masa depan kemungkinan kecil akan terjadi, kita tidak akan terlalu bergantung pada mereka. Juga, teknik ini membuat bot lebih cepat untuk menyelesaikan tugasnya, dan tidak menunda semuanya untuk nanti. Tetapi perlu dicatat bahwa bot akan mengambil risiko lebih sedikit demi manfaat selanjutnya.
Karena kita akan memprediksi keadaan dunia sebagai respons atas tindakan kita, kita perlu memodelkan perilaku musuh. Tidak ada yang rumit dan ada beberapa opsi umum:
- Rintisan atau heuristik
Logika perilaku sederhana ditulis di mana musuh tidak melakukan apa-apa, atau memilih tindakan berdasarkan heuristik sederhana (misalnya, Anda dapat menggunakan versi strategi Anda yang pertama atau cukup mengulangi langkah lawan sebelumnya). - Gunakan algoritma yang sama seperti untuk Anda sendiri
Pertama kita mencoba untuk menemukan tindakan terbaik untuk musuh (terhadap set tindakan terbaik kita dari langkah terakhir, atau terhadap rintisan), dan kemudian kita mencari tindakan terbaik untuk diri kita sendiri, menggunakan perilaku yang ditemukan musuh. Di sini bot akan mencoba untuk melawan musuh yang licik. Logika ini tidak berfungsi dengan baik pada awal kompetisi, karena banyak bot masih sangat lemah, dan keputusan Anda akan terlalu berhati-hati dengan mereka. - Lainnya
Minimax yang sama mengulangi semua gerakan pemain pada saat yang sama, dan dia tidak akan membutuhkan heuristik.
Jika Anda menerapkan semua langkah di atas, maka kemungkinan besar Anda akan mendapatkan bot yang sangat bagus, terutama jika Anda dapat mengambil fungsi peringkat yang baik. Tetapi, melihat melalui perkelahiannya, Anda dapat melihat bahwa dalam situasi tertentu ia berperilaku aneh. Memperbaiki fungsi evaluasi untuk situasi ini bisa sulit, atau ada risiko besar melanggar logika lain. Di sini kruk dan seandainya datang untuk menyelamatkan. Ya, hari-hari terakhir kompetisi sering berakhir dengan menulis kruk dan seandainya untuk memperbaiki kekurangan dalam kondisi spesifik apa pun. Secara pribadi, saya benar-benar tidak suka bagian ini, tetapi saya telah memperhatikan lebih dari sekali bahwa itu adalah kruk di final yang dapat mempengaruhi pengaturan tempat di sepuluh besar, yang berarti bahwa jika tidak tertulis dapat dikenakan biaya hadiah (hati saya sakit ketika saya menulis kata-kata ini, saya Saya juga suka algoritma dan solusi yang indah).
T: Apakah mungkin dilakukan tanpa simulasi sama sekali?
A: Ya, Anda dapat menggunakan solusi heuristik (pohon keputusan, sekelompok ifs, dll.). Ada artikel bagus dengan arsitektur AI tentang heuristik.
T: Seberapa jauh lebih baik penggunaan simulasi daripada pendekatan heuristik?
A: Itu semua tergantung pada tugas. Sebagai contoh, di sini beberapa kombinasi kartu dan mobil dapat dikodekan dengan seandainya dan selalu menang (atau seri). Namun, seringkali simulasi menemukan solusi yang sulit dipikirkan sendiri, atau sulit diterapkan heuristik. Dalam kontes ini, ketika Anda membalikkan mobil lain, solusi pada simulasi menempatkan roda mereka di atas roda musuh, yang mematikan bendera "di udara", yang berarti bahwa musuh tidak dapat menerapkan rotasi tubuh dan memutar kembali pada roda. Tetapi keputusan itu tidak memikirkan arti dari ini, hanya menemukan opsi di mana musuh akan jatuh lebih cepat di atap dan menekan tombolnya.

T: Jaringan saraf dan RL?
A: Tidak peduli seberapa populer ini, dalam kompetisi bot solusi seperti itu jarang berkinerja baik. Meskipun jaringan saraf tidak perlu simulasi, karena mereka cukup mengeluarkan tindakan berdasarkan parameter input dari keadaan saat ini, mereka masih perlu mempelajari sesuatu, dan untuk ini mereka sering harus menulis simulator untuk menggerakkan ribuan game secara lokal. Secara pribadi, saya yakin mereka punya potensi. Mungkin mereka dapat menyelesaikan sebagian dari masalah, atau menggunakannya dalam kondisi waktu respons yang sangat terbatas.
Catatan
Mengenai jumlah tindakan yang mungkin terbatas, perlu diperjelas bahwa kadang-kadang diizinkan untuk "dengan lancar" menyesuaikan beberapa parameter. Misalnya, tidak hanya memajukan, tetapi dengan persentase daya. Dalam hal ini, "keterbatasan" jumlah kesimpulan dapat dengan mudah dicapai hanya dengan menggunakan beberapa nilai, misalnya, 0%, 25%, 50%, 75% dan 100%. Paling sering, hanya dua yang cukup: "sepenuhnya aktif" dan "benar-benar mati".
Simulasi
Dalam kompetisi ini, kami menggunakan mesin fisika tupai siap pakai. Harapan penyelenggara adalah bahwa ia sudah tua, sudah teruji waktu dan memiliki banyak pembungkus sehingga semua orang dapat memasukkannya dalam keputusan mereka ...
Pada kenyataannya, mesin menghasilkan nilai yang berbeda setiap kali, yang membuatnya sulit untuk menyalakannya kembali untuk menghitung opsi untuk bergerak. Masalahnya diselesaikan "langsung" - pengalokasi memori ditulis dalam C dan sepotong memori dengan keadaan dunia sepenuhnya disalin. Pengalokasi seperti itu mengakhiri kemampuan untuk menulis solusi dalam bahasa selain C ++ (pada kenyataannya, itu mungkin, tetapi sangat padat karya dan pengalokasi masih harus ditulis dalam C). Selain itu, keakuratan prediksi dipengaruhi oleh urutan penambahan elemen ke dunia game, yang membutuhkan salinan kode yang sangat akurat yang digunakan panitia untuk menghitung game. Tapi dia sudah menggunakan Python. Sorotan terakhir dalam peti mati bahasa pemrograman lain adalah bahwa mesinnya sudah tua dan berisi banyak optimisasi yang tidak dapat dibuat ulang secara akurat selama kompetisi untuk mendapatkan versi simulasi fisika Anda sendiri.
Akibatnya, mesin, yang seharusnya memberi semua peserta kondisi yang sama untuk mensimulasikan gerakan, menjadi kendala paling sulit untuk ini. Lebih dari 10 orang dapat mengatasinya. 7 tempat pertama di papan peringkat diambil secara eksklusif oleh orang-orang yang membuat simulasi yang akurat, yang dapat berfungsi sebagai beberapa bukti pentingnya dalam kompetisi tersebut.
Dengan pengecualian beberapa peserta yang dapat masuk ke dalam chipmunk dan mengoptimalkan menyalin keadaannya, sisanya memiliki simulasi kinerja yang kira-kira sama (yang membuat kompetisi sedikit lebih menarik, karena Anda tahu bahwa perjuangannya adalah untuk algoritma keputusan, bukan "yang menghitung gerakan lebih banyak").
Algoritma untuk mencari dan memprediksi musuh
Dari titik ini, deskripsi terpisah dari solusi dimulai. Algoritma akan dijelaskan atas nama pengarangnya.
Vladimir Kiselev (Valdemar) tempat ke-4
Pencarian acak (Monte Carlo) digunakan untuk mencari ruang solusi. Algoritma adalah sebagai berikut:
- Kami menginisialisasi genom - urutan tindakan (kiri, kanan, berhenti) untuk 60 ticks - data acak.
- Ambil genom terbaik yang ditemukan
- Ubah salah satu tindakan secara acak
- Dengan menggunakan fungsi evaluasi kita mendapatkan angka - indikator seberapa bagus genom baru
- Jika Anda mendapatkan solusi yang lebih baik, maka perbarui solusi terbaik.
- Ulangi lagi dari langkah 2
Simulator saya menghasilkan ~ simulasi 100k dunia dalam 1 detik, mengingat ada rata-rata ~ 12 ms per tick, kami mendapatkan 1200 aksi per tick. Artinya, dalam 1 tick kita berhasil melewati siklus penuh sekitar 20 kali.
Untuk menemukan solusi optimal, jumlah iterasi ini jelas tidak cukup. Oleh karena itu, gagasan dengan tindakan "peregangan" diterapkan: alih-alih genom 60 gerakan, kami akan beroperasi dengan rantai 12 gerakan "peregangan" - kami percaya bahwa setiap tindakan berlangsung 5 kutu berturut-turut.
Plus: Meningkatkan kualitas mutasi dengan mengurangi panjang genom, simulasi juga dapat dijalankan setiap 5 kutu dan memeriksa 100 genom bukannya 20 (untuk menghindari jatuh dalam batas waktu, saya akhirnya berhenti di 70).
Lebih sedikit: aksi peregangan dapat menyebabkan solusi yang tidak optimal (misalnya, berayun pada bumper, bukannya rak yang stabil)
Perlu dicatat teknik yang telah secara signifikan meningkatkan kualitas algoritma:
- Kami melakukan inisialisasi acak hanya pada kutu pertama, sisa waktu kami menggunakan kembali solusi terbaik yang ditemukan dengan pergeseran 1 langkah (tindakan pada kutu 2 digeser ke 1, dll, tindakan acak ditambahkan ke akhir). Ini sangat meningkatkan kualitas pencarian, karena jika tidak, algoritma "lupa" apa yang akan dilakukan pada centang terakhir dan membuat tersentak tidak masuk akal di arah yang berbeda.
- Pada awal kursus, kami melakukan perubahan yang lebih intensif (kami mengubah genom 2 atau 3 kali alih-alih satu) dengan harapan dapat memecahkan maksimum lokal (kesamaan suhu dalam metode simulasi annealing).
Intensitas dipilih secara manual: 30 iterasi pertama membuat 3 mutasi, 10 berikutnya 2, kemudian oleh 1. - Yang sangat penting adalah prediksi aksi musuh. Untuk merugikan waktu untuk mencari solusi kami sendiri, kami meluncurkan pencarian acak dari sisi lawan, pada 20 iterasi, lalu 50 untuk diri kita sendiri, menggunakan informasi tentang gerakan optimal lawan.
Keputusan terbaik lawan juga digunakan kembali pada langkah selanjutnya dengan offset. Pada saat yang sama, ketika mencari solusi untuk musuh, genom dari langkah terakhir digunakan sebagai tindakan yang saya maksudkan.
Selama kompetisi, ia secara aktif menggunakan alat untuk pengembangan lokal, yang memungkinkan untuk dengan cepat menemukan bug dan fokus pada titik lemah dari strategi:
- arena lokal - meluncurkan banyak pertandingan melawan versi sebelumnya;
- visualizer untuk perilaku debug;
- skrip untuk mengumpulkan statistik pada pertandingan dari situs - memungkinkan Anda untuk memahami di peta dan mesin mana kekalahan paling sering terjadi.
mortido:
Menghitung setiap 5 tick terlihat berisiko, terutama jika musuh bergerak menjauh dari opsi yang Anda prediksi. Di sisi lain, di dunia game ini selama 5 kutu, tidak banyak yang terjadi.
Selain itu, dalam keputusan saya, saya menambahkan kombinasi acak setiap centang, tetapi saya pasti tidak akan mengatakan bagaimana ini mempengaruhi keputusan.
Commandos:
Mengubah beberapa tindakan dengan sejumlah simulasi tidak terlihat sangat berarti, karena sangat sedikit perubahan terjadi dalam satu tindakan. Tetapi ketika Anda merentangkan satu tindakan ke 5 kutu makna, tampaknya menjadi lebih.
Saya juga tidak menyukai ide itu sendiri - kami mengambil set terbaik dan mencoba mengeditnya di suatu tempat di awal. Tampaknya tidak masuk akal bahwa mengubah kutu pertama akan meninggalkan kutu berikutnya setidaknya cukup memadai.
Alexander Kiselev (mortido) tempat ke-3
Berbekal artikel oleh pemenang kompetisi lain, saya memutuskan untuk menggunakan algoritma genetika. Ternyata, sesuatu yang mirip dengan pencarian acak atau bahkan tiruan dari anil, tetapi lebih pada nanti.
Kami menyandikan solusi dengan array 40 angka, di mana -1, 0, dan 1 berhubungan dengan gerakan
,
dan
.
Pada awal setiap putaran, saya menghitung berapa banyak waktu yang telah saya habiskan untuk seluruh permainan, menghitung batas waktu baru berdasarkan berapa banyak putaran lagi, dan setiap putaran saya anggap 1.200 kutu. T.O. Awalnya, saya mencoba menghabiskan tidak lebih dari 11 ms per putaran, tetapi saya bisa "berjalan" sedikit di akhir jika putaran sebelumnya lebih cepat dari 1.200 kutu.
Valdemar:
Menariknya, chip ini memperburuk permainan bagi saya. Ternyata selalu lebih baik untuk menghabiskan 20-30ms dari 11 pertama, dan 60 di akhir
Sepertiga dari waktu ini saya sedang mencari langkah terbaik musuh, sisanya pergi untuk menghitung keputusan saya sendiri. Saat mencari langkah untuk musuh, perilaku saya dimodelkan sebagai yang terbaik dari langkah terakhir, digeser 1 tick. Yaitu seolah-olah aku terus bertindak sesuai dengan rencana yang dibuat dalam tanda centang terakhir, dan dia berusaha melawanku.
Pencarian solusi itu sendiri sama untuk lawan dan lawannya:
- Kami mengambil keputusan dari langkah terakhir dan menggesernya dengan 1 langkah (yang telah kami lakukan)
- Kami membuktikan pada populasi solusi acak sampai kami mengisi semuanya
- Kami mensimulasikan semua keputusan dan menetapkan kebugaran menggunakan fungsi evaluasi. Kami ingat yang terbaik.
- Sementara ada waktu untuk perhitungan
- Petunjuk, selalu tambahkan 1 mutasi dari solusi terbaik saat ini untuk populasi, ingatlah jika itu lebih baik
- Selama ada tempat di populasi baru dan waktu untuk perhitungan belum terlampaui (Anda bisa pergi ke lantai populasi yang dihuni)
- Kami mengambil dua individu yang berbeda dan pergi dengan kebugaran terbaik - ibu
- Kami mengambil dua individu yang berbeda dan pergi dengan kebugaran terbaik - ayah (tidak harus bertepatan dengan ibu)
- Lintasi mereka
- Bermutasi jika
RND <
- Kami mensimulasikan solusi dan mengingatnya, jika itu yang terbaik
Akibatnya, kami akan mengembalikan urutan tindakan yang dianggap optimal. Langkah pertama di dalamnya dikirim sebagai tindakan bot. Sayangnya, ada kekurangan serius dalam rencana saya, seperti jumlah simulasi yang dapat dilakukan dalam tick sangat kecil (termasuk karena fungsi evaluasi yang panjang), maka pada server kompetisi 4 poin dilakukan hanya 1 kali, dan untuk musuh itu tidak dilakukan sama sekali. Ini membuat algoritme lebih seperti pencarian acak atau simulasi anil (karena kami berhasil memutasikan solusi 1 kali dari langkah terakhir). Sudah terlambat untuk mengubah sesuatu, dan kami berhasil mempertahankan posisi ke-3.
Karena itu penting untuk menerapkan algoritma untuk menyeberang, bermutasi, dan menghasilkan solusi acak awal itu tergantung pada keputusan apa yang akan diuji, dan keputusan acak yang lengkap tidak sebaik kelihatannya pada pandangan pertama (itu akan berhasil, tetapi lebih banyak pilihan akan dibutuhkan).
Dalam versi final, keputusan acak dihasilkan dalam segmen, yang mengecualikan solusi "menyentak" di satu tempat:
- Tim acak dipilih
- Untuk seluruh panjang solusi (40 gerakan)
- Kami menulis perintah saat ini di sel
- Dengan probabilitas 10%, kami mengubah tim saat ini menjadi acak
Menurut teknologi yang sama, mutasi juga terjadi - segmen acak dari solusi diganti dengan perintah acak. Crossing terjadi dengan memilih titik pengambilan keputusan dari 1 orang tua, dan setelah dari 2.
Saya suka bahwa kami menggunakan semua waktu yang tersedia untuk menemukan solusi terbaik. Ini bukan masalah besar jika solusinya bukan yang terbaik - kami dapat memperbaikinya pada centang berikutnya, karena optimasi ternyata "kabur" pada waktunya. , . , - , . ,
Valdemar:
1 , , .
Commandos:
β - .
β , . , β¦ , . " β. -.
(Commandos) 1
( ), n m . 3^2=9 . m + n 40 .
:
|----------- n -----------|---------- m --------| | ... | ... |
: , , . ( ).
n m , . , .
:
- , ( , ):
- , , , .
- , , . . . , , , .
- . ; ( ).
- n m . , .1, , . - ( ) , β , ;
- . , β . , ( ).
Valdemar:
, 2 . . , .
mortido:
! , . . , 2 , 40-60 . , 3 .
n + m == const ?
. n + m != const
, . , . - .
(Valdemar) 4
, . , ( , , ..) [0..1].
. : , .
, , : , .
, :
- β 70 180 ( : ).
, . - 0..500
- β [2pi, pi/4] [0, 1]
- β , ( ), ( , , )
- β , , , .
, , . - β . .
- Y β .
, 2 , .
.
:
mortido:
, .. , .
Commandos:
, . -
(mortido) 3
, chipmunk. . , , , , . .
3 .
, ( , , ):
- . , , ( , );
- , β , ; , 1 ;
- ;
- ( , );
- ( β+β, β-β);
- ( β+β, β-β); , , , ;
30 , , ( ); - , .
, , (, , )
Valdemar:
. , β , , β , ( ..) .
, , . .
Commandos:
, , βββ¦ ? , ββ .
(Commandos) 1
SquaredWheelsBuggy
, .. , . Buggy , , ( /).
:
- ;
- ; β , , 1 0; .. ;
- . ; 10 ( );
- ( , );
- (, );
- β - , ;
- / ; , β ; .
1-5 , . 2 β β.
Valdemar:
, . , .
mortido:
, 10 .
IF'
(Valdemar) 4
, if'. 3 , , . , , -.
: , ββ β , - , ( , ) β .
:
- . , .
- β , .
- . β β .
, , .
, , .
, : . , , if' .
mortido:
, . .
Commandos:
if'. , , β¦ , , .
(mortido) 3
- .
3 . . . ββ, . , , .
, ββ . . , , , - . . , , .. .
, , , , , . β¦ . - β , ( , ).
Valdemar:
, . . ββ , if'. , β .
, + . , .
Commandos:
β¦ , - β , , . , , .
(Commandos) 1
. (, , ). ( ) /.
pill carcass map , , ( ). island map, , .
island hole buggy. / , , ( ). β . , , . SquaredWheelBuggy . , , , . , β¦ , , .
(Pill map, Bus) , ( / 100% ).
pill hubble map. , ( ), . .
β , ...
, . , . ( ).
Valdemar:
, β . , .
mortido:
, ββ .
Valdemar:
. , . ( ) .
. ββ, , , , :)
, mailru , .
mortido:
: , β¦ , , ( ). , 3 , , β¦ .
Commandos:
- , . , , , . β¦ . β , .
β ++. . , . 1 -.
, . , . , , .
Mail.Ru Group .
Valdemar
mortido