Οδηγός βήμα προς βήμα για αρχάριους
Τι χρειάζεστε
- Έναν λογαριασμό FlipSight. Μπορείτε να εγγράψετε bot και να κατεβάσετε το πρόγραμμα σύνδεσης αφού συνδεθείτε.
- Μία φωτογραφία για το bot: αρχείο GIF, JPG ή PNG έως 5 MB, με πλάτος και ύψος τουλάχιστον 175 px.
- Ο δικός σας υπολογιστής για τη λειτουργία του bot Οι κινήσεις του bot σας υπολογίζονται στον υπολογιστή όπου τρέχει το πρόγραμμα σύνδεσης. Ακόμη και με την ίδια μηχανή, η δύναμη μπορεί να διαφέρει ανάλογα με την ισχύ του υπολογιστή και τις ρυθμίσεις της μηχανής, και αν αλλάξετε υπολογιστή ή ρυθμίσεις, η βαθμολογία μπορεί να κινηθεί ανάλογα.
- Python 3, ένα δωρεάν πρόγραμμα που εκτελεί το πρόγραμμα σύνδεσης. Λειτουργεί η έκδοση 3.9 ή νεότερη. Συνιστάται η 3.11 ή νεότερη. Θα το ελέγξετε στο βήμα 5.
- Η δική σας μηχανή bot. Το πρόγραμμα σύνδεσης περιλαμβάνει μια μηχανή εξάσκησης για δοκιμές.
1. Εγγράψτε το bot σας
Συνδεθείτε και ανοίξτε τη σελίδα bot (othelloclub.com/el/flipsight/bot). Στο πλαίσιο Εγγραφή του bot μου στο επάνω μέρος, γράψτε ένα όνομα στο Όνομα bot (2–24 χαρακτήρες). Στο Υποστηριζόμενα παιχνίδια αφήστε προς το παρόν επιλεγμένο μόνο το Κλασικό. Επιλέξτε μια εικόνα στο Μεταφόρτωση φωτογραφίας bot και μετά πατήστε το κουμπί Εγγραφή του bot μου.
Αν όλα πάνε καλά, θα δείτε αυτό: εμφανίζεται το πλαίσιο Διακριτικό σύνδεσης (εμφανίζεται μία φορά) με ένα μεγάλο κείμενο που αρχίζει με fsbm_.
2. Κρατήστε το διακριτικό
Αυτό το μεγάλο κείμενο είναι το διακριτικό, ένας κωδικός μόνο για το bot σας. Με αυτό το πρόγραμμα σύνδεσης αποδεικνύει στον διακομιστή ότι μιλά για λογαριασμό αυτού του bot. Αντιγράψτε το ολόκληρο και επικολλήστε το κάπου προσωρινά, για παράδειγμα σε έναν επεξεργαστή κειμένου. Μόλις κλείσετε το πλαίσιο, δεν μπορείτε να δείτε ξανά το ίδιο διακριτικό.
Φυλάξτε το διακριτικό όπως έναν κωδικό πρόσβασης. Μην το δείχνετε σε κανέναν και μη δημοσιεύετε στιγμιότυπο οθόνης του. Αν το χάσετε ή το δει κάποιος, ανοίξτε το Διαχείριση στη λίστα bot και πατήστε Δημιουργία διακριτικού. Μόλις πάρετε νέο διακριτικό, το παλιό σταματά αμέσως να λειτουργεί.
3. Κατεβάστε το πρόγραμμα σύνδεσης
Πατήστε Λήψη παραδειγμάτων Python για να κατεβάσετε το αρχείο ZIP και αποσυμπιέστε το. Αυτός ο οδηγός ονομάζει τον φάκελο που προκύπτει «φάκελο του bot». Βάλτε τον κάπου που βρίσκεται εύκολα, για παράδειγμα στην επιφάνεια εργασίας.
Αν όλα πάνε καλά, θα δείτε αυτό: ο φάκελος του bot περιέχει το αρχείο README.md και τον φάκελο tools.
4. Ανοίξτε ένα τερματικό στον φάκελο του bot
Το τερματικό είναι ένα παράθυρο όπου πληκτρολογείτε εντολές. Ανοίξτε το ως εξής, ανάλογα με το σύστημά σας.
macOS: πατήστε Command+Space, πληκτρολογήστε Terminal και ανοίξτε το. Πληκτρολογήστε cd και ένα κενό, σύρετε τον φάκελο του bot μέσα στο παράθυρο και πατήστε Enter.
Linux: στη διαχείριση αρχείων, κάντε δεξί κλικ στον φάκελο του bot και επιλέξτε «Άνοιγμα σε τερματικό» (Open in Terminal). Το όνομα του μενού μπορεί να διαφέρει ανάλογα με τη διανομή. Αν δεν υπάρχει τέτοιο μενού, ανοίξτε ένα τερματικό και χρησιμοποιήστε το cd όπως στο macOS.
Windows: ανοίξτε τον φάκελο του bot στην Εξερεύνηση αρχείων. Πληκτρολογήστε powershell στη γραμμή διευθύνσεων επάνω και πατήστε Enter. Ανοίγει ένα παράθυρο PowerShell σε αυτόν τον φάκελο.
Έλεγχος: πληκτρολογήστε την παρακάτω εντολή και πατήστε Enter. Αν στη λίστα εμφανίζονται τα README.md και tools, όλα είναι εντάξει. Η εντολή είναι ίδια σε macOS, Linux και Windows PowerShell.
ls5. Ελέγξτε την Python
Στο ίδιο παράθυρο, αντιγράψτε τη μία εντολή για το σύστημά σας, επικολλήστε την και πατήστε Enter. Μπορείτε να χρησιμοποιήσετε το κουμπί αντιγραφής πάνω δεξιά σε κάθε πλαίσιο κώδικα.
macOS / Linux
python3 --versionWindows PowerShell
py --versionΑν όλα πάνε καλά, θα δείτε αυτό: μια έκδοση που αρχίζει με 3, για παράδειγμα Python 3.11.9. Λειτουργεί η έκδοση 3.9 ή νεότερη. Αν η εντολή δεν βρεθεί, εγκαταστήστε την Python όπως παρακάτω, κλείστε το παράθυρο και ξεκινήστε ξανά από το βήμα 4.
macOS: κατεβάστε το πρόγραμμα εγκατάστασης για macOS (.pkg) από το python.org και εγκαταστήστε το. Μετά εκτελέστε μία φορά το Install Certificates.command από τον φάκελο Python στις Εφαρμογές. Έτσι ετοιμάζονται τα πιστοποιητικά που χρειάζονται για ασφαλείς (HTTPS) συνδέσεις.
Linux: εγκαταστήστε το python3 με το κέντρο λογισμικού ή τη διαχείριση πακέτων της διανομής σας.
Windows: εγκαταστήστε τη διαχείριση εγκατάστασης Python (Python install manager) από το python.org.
6. Εισαγάγετε το διακριτικό
Βάλτε το διακριτικό σε μια μεταβλητή περιβάλλοντος, δηλαδή σε μια προσωρινή ρύθμιση που υπάρχει μόνο μέσα σε αυτό το παράθυρο τερματικού. Το όνομά της είναι FS_BOT_TOKEN. Αντιγράψτε παρακάτω την εντολή μίας γραμμής για το σύστημά σας, επικολλήστε την και πατήστε Enter μία φορά. Τότε εμφανίζεται το Bot token και περιμένει να πληκτρολογήσετε. Τώρα επικολλήστε το διακριτικό που αντιγράψατε στο βήμα 2 και πατήστε Enter.
macOS / Linux
printf 'Bot token: '; read -r -s FS_BOT_TOKEN; printf '\n'; export FS_BOT_TOKENWindows PowerShell
$env:FS_BOT_TOKEN = [Net.NetworkCredential]::new('', (Read-Host 'Bot token' -AsSecureString)).PasswordΣε macOS και Linux το διακριτικό που επικολλήσατε δεν εμφανίζεται, ενώ στα Windows βλέπετε * αντί για τους χαρακτήρες του. Και τα δύο είναι φυσιολογικά. Επειδή το διακριτικό δεν γράφεται μέσα στην εντολή, δεν μένει στο ιστορικό εντολών. Η ρύθμιση ισχύει μόνο σε αυτό το παράθυρο. Αν το κλείσατε ή ανοίξατε νέο παράθυρο, επαναλάβετε τα βήματα 4 και 6.
Windows: στο PowerShell επικολλήστε με Ctrl+V ή με δεξί κλικ. Αυτή η εντολή μίας γραμμής χρησιμοποιεί σύνταξη που λειτουργεί τόσο στο Windows PowerShell 5.1, που περιλαμβάνεται στα Windows, όσο και στο νεότερο PowerShell 7, αλλά δεν έχει δοκιμαστεί ακόμη σε πραγματικό υπολογιστή με Windows.
Αν όλα πάνε καλά, θα δείτε αυτό: η προτροπή για την επόμενη εντολή επιστρέφει χωρίς σφάλμα.
7. Ξεκινήστε το πρόγραμμα σύνδεσης
Στο ίδιο παράθυρο, αντιγράψτε την παρακάτω εντολή όπως είναι, επικολλήστε την και πατήστε Enter. Μην αλλάξετε τα ονόματα αρχείων μέσα σε αυτήν. Το bot σας συνδέεται με τη μηχανή εξάσκησης. Είναι μια πολύ αδύναμη μηχανή που παίζει το νόμιμο τετράγωνο με τον μικρότερο αριθμό.
macOS / Linux
python3 tools/bot_match_client.py --engine 'python3 tools/bot_match_example_engine.py'Windows PowerShell
py tools/bot_match_client.py --engine 'py tools/bot_match_example_engine.py'Είναι φυσιολογικό η εντολή να μην εμφανίζει κείμενο και να μην επιστρέφει στη γραμμή εντολών όσο εκτελείται. Για να παραμένει το bot συνδεδεμένο, αφήστε αυτό το παράθυρο ανοιχτό με το πρόγραμμα σύνδεσης και τη μηχανή σε λειτουργία και αποτρέψτε την αναστολή λειτουργίας του υπολογιστή. Αν κλείσετε το παράθυρο ή πατήσετε Ctrl+C, τερματίζονται και τα δύο προγράμματα και το bot αποσυνδέεται. Εκτελέστε ξανά την παραπάνω εντολή για επανασύνδεση. Το πρόγραμμα σύνδεσης δέχεται αυτόματα αιτήματα άλλων bot.
Όσο το bot τρέχει με τη μηχανή εξάσκησης, δεν παίρνει αυτόματους αγώνες, και οι αγώνες του με άλλα bot, ακόμη και όσοι ζητάτε εσείς, δεν βαθμολογούνται. Ξεκινήστε το ξανά με τη δική σας μηχανή (βήμα 10) και από τότε αντιστοιχίζεται και βαθμολογείται.
Αν όλα πάνε καλά, θα δείτε αυτό: στη λίστα Εγγεγραμμένα bot της σελίδας bot, η κουκκίδα δεξιά από το όνομα του bot σας είναι πράσινη. Αν περάσετε το ποντίκι από πάνω της, εμφανίζεται το Συνδεδεμένο. Αν είναι γκρι (Αποσυνδεδεμένο), πατήστε Ανανέωση.
8. Δοκιμή με μια πρώτη παρτίδα
Στη σελίδα bot, επιλέξτε το bot σας στο Το bot μου που παίζει. Διαλέξτε οποιοδήποτε bot από τη λίστα Bot FlipSight, πατήστε Πρόκληση και επιβεβαιώστε στο παράθυρο που ανοίγει. Σε όλα τα είδη παιχνιδιών τις κινήσεις των bot FlipSight τις υπολογίζει ο διακομιστής, οπότε δεν χρειάζεται να κρατάτε ανοιχτό το δωμάτιο παιχνιδιού. Με την αυτόματη αντιστοίχιση ενεργή (προεπιλογή), ο ιστότοπος ορίζει επίσης αγώνες bot όσο τρέχει το πρόγραμμα σύνδεσης.
Αν όλα πάνε καλά, θα δείτε αυτό: το δωμάτιο παιχνιδιού δείχνει δύο ταμπλό και σε κάθε σειρά του bot σας τοποθετείται ένας δίσκος. Η μηχανή εξάσκησης είναι πολύ αδύναμη, οπότε είναι φυσιολογικό να χάνει.
9. Να συνεχίζει μετά το κλείσιμο του παραθύρου (προαιρετικό)
Αν ξεκινήσετε με την παρακάτω εντολή αντί για το βήμα 7, το bot συνεχίζει να τρέχει αφού κλείσετε το παράθυρο. Εκτελέστε την στο ίδιο παράθυρο όπου εισαγάγατε το διακριτικό (βήμα 6). Σταματά αν ο υπολογιστής κλείσει ή μπει σε αναστολή λειτουργίας. Αν το σταματήσετε κατά τη διάρκεια μιας παρτίδας, η παρτίδα αυτή χάνεται στον χρόνο ή λόγω αποσύνδεσης.
macOS / Linux
macOS / Linux: αφού εκτελέσετε την εντολή εκκίνησης, μπορείτε να κλείσετε το παράθυρο. Τα μηνύματα γράφονται στο αρχείο bot.log στον φάκελο του bot. Για να το σταματήσετε, ανοίξτε ένα νέο τερματικό και εκτελέστε την εντολή διακοπής. Αντιγράψτε μόνο το πλαίσιο που χρειάζεστε: αν επικολλήσετε και τα δύο πλαίσια μαζί, το bot σταματά αμέσως μόλις ξεκινήσει.
Εκκίνηση
nohup python3 tools/bot_match_client.py --engine 'python3 tools/bot_match_example_engine.py' > bot.log 2>&1 &Διακοπή
pkill -f bot_match_client.pyWindows PowerShell
Windows: εμφανίζεται ένα ελαχιστοποιημένο παράθυρο στη γραμμή εργασιών και το bot τρέχει μέσα σε αυτό. Μπορείτε να κλείσετε το τρέχον παράθυρο PowerShell. Για να το σταματήσετε, ανοίξτε το ελαχιστοποιημένο παράθυρο και πατήστε Ctrl+C ή κλείστε εκείνο το παράθυρο.
Εκκίνηση
Start-Process py -ArgumentList 'tools/bot_match_client.py --engine "py tools/bot_match_example_engine.py"' -WorkingDirectory $PWD -WindowStyle Minimized10. Περάστε στη δική σας μηχανή
Μετά τη δοκιμή σύνδεσης, αλλάξτε στη δική σας μηχανή: ειδικές επιλογές παρακάτω για Edax ή Egaroucid, --nboard για άλλες συμβατές μηχανές, JSON για δική σας μηχανή. Κρατήστε το ίδιο διακριτικό.
Επιλέξτε μια παραλλαγή (Anti, 10x10, Octagon, κλασικό Reversi) στο Υποστηριζόμενα παιχνίδια μόνο αν η μηχανή σας ξέρει τους κανόνες της. Άλλα bot και άνθρωποι μπορούν να προκαλέσουν το bot σας σε κάθε επιλεγμένο παιχνίδι. Για να το αλλάξετε, ανοίξτε το Διαχείριση στη λίστα bot, αλλάξτε το Υποστηριζόμενα παιχνίδια και πατήστε Αποθήκευση. Δεν μπορείτε να το αλλάξετε όσο παίζεται παρτίδα ή περιμένει μια πρόκληση.
Παραδείγματα αιτημάτων μηχανής ανά παιχνίδι
Σύνδεση μηχανής NBoard, όπως το Edax
Το NBoard είναι γραφική εφαρμογή Othello που μπορεί να χρησιμοποιηθεί με το NTest. Το πρωτόκολλο NBoard είναι η δημόσια μορφή επικοινωνίας της με μηχανές και λειτουργεί με μηχανές που το υποστηρίζουν, όπως τα NTest και Edax.
Τα παρακάτω παραδείγματα εγκατάστασης και εκκίνησης χρησιμοποιούν Edax 4.6 και Egaroucid for Console 7.8.2.
Το Edax 4.6 δεν περιλαμβάνεται στο πρόγραμμα σύνδεσης. Κατεβάστε το αρχείο για το λειτουργικό σας από το Assets στο Edax 4.6, βάλτε το στον φάκελο του bot και αποσυμπιέστε το με τις παρακάτω εντολές προετοιμασίας. Οι εντολές Windows και Linux αφορούν x86-64.
Windows PowerShell (x86-64): edax-4.6-MS-windows-x86.zip
Προετοιμασία (μόνο την πρώτη φορά)
Expand-Archive -LiteralPath edax-4.6-MS-windows-x86.zip -DestinationPath edax-4.6Εκκίνηση
py tools/bot_match_client.py --edax "edax-4.6\wEdax-x86-64.exe"Linux (x86-64): edax-4.6-linux-x86.tar.gz
Προετοιμασία (μόνο την πρώτη φορά)
mkdir -p edax-4.6
tar -xzf edax-4.6-linux-x86.tar.gz -C edax-4.6
chmod +x edax-4.6/lEdax-x86-64Εκκίνηση
python3 tools/bot_match_client.py --edax "edax-4.6/lEdax-x86-64"macOS: edax-reversi-4.6.tar.gz
Δεν υπάρχει επίσημο εκτελέσιμο Edax 4.6 για macOS. Κατεβάστε τα Source code (tar.gz) και edax-4.6-linux-x86.tar.gz της ίδιας έκδοσης. Μεταγλωττίστε το πρόγραμμα Mac από τον πηγαίο κώδικα· από το αρχείο Linux εξάγεται μόνο το κοινό αρχείο αξιολόγησης data/eval.dat. Απαιτούνται τα Xcode Command Line Tools. Οι εντολές προετοιμασίας μεταγλωττίζουν τον κώδικα.
Προετοιμασία (μόνο την πρώτη φορά)
xcode-select --installtar -xzf edax-reversi-4.6.tar.gz
mv edax-reversi-4.6 edax-4.6
mkdir -p edax-4.6/bin
tar -xzf edax-4.6-linux-x86.tar.gz -C edax-4.6 data/eval.dat
(cd edax-4.6/src && make build ARCH=native OS=osx)Εκκίνηση
python3 tools/bot_match_client.py --edax "edax-4.6/bin/mEdax-native"Το Edax συνδέεται και μόνο με τη διαδρομή του εκτελέσιμου μέσω --edax παρακάτω. Δεν χρειάζεται ξεχωριστός προσαρμογέας· ο σύνδεσμος κατανέμει τον χρόνο σκέψης ανά κίνηση από τον υπόλοιπο χρόνο παρτίδας.
Αντικαταστήστε τη διαδρομή στην εντολή με την πλήρη διαδρομή του προγράμματός σας. Διαδρομές με κενά μπαίνουν σε διπλά εισαγωγικά. Αν δεν βρεθεί αυτόματα το αρχείο αξιολόγησης, ορίστε το eval.dat με --edax-eval.
Μια σύνδεση NBoard παίζει μόνο κανονικές παρτίδες 8×8. Για αυτό το bot αφήστε επιλεγμένο μόνο το Κλασικό στο Υποστηριζόμενα παιχνίδια. Αν έρθει μια παραλλαγή, το πρόγραμμα σύνδεσης δεν ρωτά τη μηχανή, δεν παίζεται κίνηση και η παρτίδα ματαιώνεται ή χάνεται στον χρόνο.
Egaroucid: --egaroucid
Ετοιμάστε το Egaroucid for Console. Επιλέξτε το εκτελέσιμο κονσόλας και κρατήστε τον φάκελο resources στη θέση του. Σε macOS και Linux χρησιμοποιήστε πρόγραμμα μεταγλωττισμένο με τις επίσημες οδηγίες. Η θέση και ο υπόλοιπος χρόνος αποστέλλονται με setboard, settime και go χωρίς προσαρμογέα.
Windows PowerShell
py tools/bot_match_client.py --egaroucid "egaroucid\Egaroucid_for_console.exe"macOS / Linux
python3 tools/bot_match_client.py --egaroucid "egaroucid/bin/Egaroucid_for_Console.out"Και οι δύο τρόποι υποστηρίζουν μόνο κανονικό 8×8, με μία μηχανή ανά ταυτόχρονη παρτίδα. Το --max-think-seconds είναι το όριο ασφαλείας ανά κίνηση (προεπιλογή 10 δευτερόλεπτα). Αν το Egaroucid φτάσει στο όριο, η αναζήτηση σταματά, παίζεται εφεδρική νόμιμη κίνηση και η μηχανή επανεκκινείται στην επόμενη σειρά.
Δική σας μηχανή: σύνδεση μέσω JSON
Διαβάστε αυτό το μέρος μόνο αν θέλετε να συνδέσετε μια μηχανή που γράψατε εσείς. Αν χρησιμοποιείτε το Edax, το Egaroucid ή άλλη μηχανή NBoard, έχετε ήδη τελειώσει παραπάνω και μπορείτε να το παραλείψετε.
Κάθε φορά που είναι η σειρά του bot σας, το πρόγραμμα σύνδεσης εκτελεί το my_adapter.py μία φορά. Του δίνει την τρέχουσα θέση ως μία γραμμή (πού βρίσκονται οι δίσκοι, ποιος παίζει, ποια τετράγωνα είναι νόμιμα, πόσος χρόνος απομένει), το my_adapter.py απαντά με ένα τετράγωνο ως μία γραμμή και το πρόγραμμα σύνδεσης παίζει αυτή την κίνηση στον διακομιστή. Το my_adapter.py είναι ένα μικρό αρχείο Python που βρίσκεται ανάμεσα και ζητά την κίνηση από τη μηχανή σας. Το πρόγραμμα σύνδεσης αναλαμβάνει τη σύνδεση με τον διακομιστή, το διακριτικό και την υποβολή των κινήσεων, οπότε αυτό το αρχείο δεν ασχολείται ποτέ με αυτά.
bot_match_client.py→ my_adapter.pybot_match_client.py← my_adapter.pyΤι είδους είναι η μηχανή σας;
- Μηχανή που επιλέγει την κίνησή της με κώδικα Python: χρησιμοποιήστε το παράδειγμα A παρακάτω.
- Αρχείο προγράμματος που κάθε φορά που εκτελείται τυπώνει μία γραμμή απάντησης και κλείνει: χρησιμοποιήστε το παράδειγμα B παρακάτω.
- Ένα εκτελέσιμο που μένει ανοιχτό και ανταλλάσσει συνεχώς εντολές: αν υποστηρίζει NBoard, συνδέστε το με το --nboard παραπάνω. Για άλλο πρωτόκολλο, προσαρμόστε το παράδειγμα B σε αυτό και κάντε το my_adapter.py να κρατά τη μηχανή ανοιχτή και να ανταλλάσσει μία γραμμή τη φορά σε βρόχο.
Βήμα 1: ένα αρχείο που ελέγχει μόνο τη σύνδεση (my_adapter.py)
Στον φάκελο του bot (εκεί όπου βρίσκονται τα README.md και tools) δημιουργήστε ένα αρχείο με όνομα my_adapter.py, επικολλήστε τον παρακάτω κώδικα όπως είναι και αποθηκεύστε το. Αυτό το αρχείο δεν χρησιμοποιεί καμία μηχανή και απαντά απλώς με το πρώτο νόμιμο τετράγωνο. Υπάρχει για να επιβεβαιώσετε ότι η σύνδεση λειτουργεί πριν συνδέσετε τη μηχανή σας.
import json
import sys
def choose_move(position):
legal = position["legal_moves"]
return legal[0] if legal else -1
line = sys.stdin.readline()
position = json.loads(line)
move = choose_move(position)
print(json.dumps({"move": move}), flush=True)
Έλεγχος εισόδου και εξόδου πριν από τη σύνδεση
Η εντολή στο πλαίσιο 1 δίνει την παραδειγματική θέση κατευθείαν στον προσαρμογέα. Πρέπει να εμφανίσει μία γραμμή: {"move": 19}. Μόλις δείτε αυτή τη γραμμή, η εντολή στο πλαίσιο 2 ξεκινά το πρόγραμμα σύνδεσης με αυτόν τον προσαρμογέα, στο παράθυρο που έχει το διακριτικό από το βήμα 6. Εκτελέστε τα δύο πλαίσια χωριστά. Αν η μηχανή σας διαβάζει μόνη της αυτή τη μορφή JSON, μπορείτε να βάλετε την εντολή της κατευθείαν μετά το --engine.
1. Δοκιμή μόνο του προσαρμογέα
macOS / Linux
printf '%s\n' '{"board":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,1,0,0,0,0,0,0,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"color":1,"legal_moves":[19,26,37,44],"game_mode":"std","board_size":8,"blocked_squares":[],"placed":{"1":0,"2":0},"remaining_ms":60000,"match_id":123,"leg":0,"revision":0,"history":[],"round_no":null,"room_created_at":null,"budget_ms":10000}' | python3 my_adapter.pyWindows PowerShell
'{"board":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,1,0,0,0,0,0,0,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"color":1,"legal_moves":[19,26,37,44],"game_mode":"std","board_size":8,"blocked_squares":[],"placed":{"1":0,"2":0},"remaining_ms":60000,"match_id":123,"leg":0,"revision":0,"history":[],"round_no":null,"room_created_at":null,"budget_ms":10000}' | py my_adapter.py2. Εκκίνηση του προγράμματος σύνδεσης με τον προσαρμογέα
macOS / Linux
python3 tools/bot_match_client.py --engine 'python3 my_adapter.py'Windows PowerShell
py tools/bot_match_client.py --engine 'py my_adapter.py'Βήμα 2: αλλαγή σε αρχείο που καλεί τη μηχανή σας
Μόλις λειτουργήσει το βήμα 1, αντικαταστήστε όλο το περιεχόμενο του my_adapter.py με το παράδειγμα A ή B παρακάτω. Αλλάξτε μόνο τις γραμμές με τη σήμανση EDIT και αφήστε τα υπόλοιπα όπως είναι. Έπειτα εκτελέστε ξανά την εντολή δοκιμής 1 παραπάνω και ελέγξτε ότι εμφανίζεται μία γραμμή απάντησης. Την κίνηση την επέλεξε η μηχανή σας, οπότε είναι φυσιολογικό να βγει άλλο τετράγωνο από το 19.
Παράδειγμα A: μηχανή που επιλέγει την κίνησή της με συνάρτηση Python
Το παράδειγμα αυτό υποθέτει ένα αρχείο με όνομα my_engine.py που έχει μια συνάρτηση search η οποία επιλέγει την κίνηση. Στο EDIT 1 αλλάξτε το όνομα του αρχείου και το όνομα της συνάρτησης και στο EDIT 2 τις τιμές που της δίνονται, ώστε να ταιριάζουν με τη μηχανή σας. Η συνάρτηση πρέπει να επιστρέφει τον αριθμό του τετραγώνου (0 έως 63) ή μια συντεταγμένη όπως d3.
import json
import sys
from pathlib import Path
from my_engine import search # EDIT 1: your engine file and function name
def think_ms(position):
# Time for this move: share the remaining clock over my remaining moves.
my_moves_left = position["board"].count(0) // 2 + 1
share = position["remaining_ms"] / my_moves_left
return int(min(share, position["budget_ms"]) * 0.8)
def choose_move(position):
if not position["legal_moves"]:
return -1
# EDIT 2: pass what your function needs
return search(
board=position["board"],
color=position["color"],
legal_moves=position["legal_moves"],
time_limit_ms=think_ms(position),
)
position = json.loads(sys.stdin.readline())
legal = position["legal_moves"]
try:
move = choose_move(position)
except Exception as error:
# The engine failed: note why in my_adapter.log and play the first legal square.
with open(Path(__file__).with_name("my_adapter.log"), "a") as log:
log.write(repr(error) + "\n")
move = legal[0] if legal else -1
print(json.dumps({"move": move}), flush=True)Παράδειγμα B: μηχανή που είναι αρχείο προγράμματος
Το παράδειγμα αυτό υποθέτει ότι το πρόγραμμα διαβάζει μία γραμμή με 64 χαρακτήρες σκακιέρας, την πλευρά που παίζει και τον χρόνο σκέψης σε χιλιοστά του δευτερολέπτου, και απαντά με μία γραμμή συντεταγμένης όπως D3 (. = κενό, X = μαύρο, O = λευκό). Κάθε μηχανή έχει τη δική της μορφή, γι' αυτό αλλάξτε το όνομα του αρχείου προγράμματος στο EDIT 1, τη γραμμή που στέλνεται στη μηχανή στο EDIT 2 και το τμήμα που διαβάζει την απάντηση στο EDIT 3, ώστε να ταιριάζουν με τη μηχανή σας.
my_adapter.py → my_engine
...........................OX......XO........................... X 1777my_engine → my_adapter.py
D3import json
import subprocess
import sys
from pathlib import Path
# EDIT 1: your engine program file (kept in the same folder as my_adapter.py)
ENGINE = Path(__file__).with_name("my_engine.exe" if sys.platform == "win32" else "my_engine")
def think_ms(position):
# Time for this move: share the remaining clock over my remaining moves.
my_moves_left = position["board"].count(0) // 2 + 1
share = position["remaining_ms"] / my_moves_left
return int(min(share, position["budget_ms"]) * 0.8)
def choose_move(position):
if not position["legal_moves"]:
return -1
# EDIT 2: build the line your engine reads
board = "".join(".XO"[cell] for cell in position["board"])
color = "X" if position["color"] == 1 else "O"
reply = subprocess.run(
[str(ENGINE)],
input=f"{board} {color} {think_ms(position)}\n",
text=True,
capture_output=True,
check=True,
timeout=position["budget_ms"] / 1000 * 0.9,
)
# EDIT 3: take the square out of your engine's answer
return reply.stdout.strip()
position = json.loads(sys.stdin.readline())
legal = position["legal_moves"]
try:
move = choose_move(position)
except Exception as error:
# The engine failed: note why in my_adapter.log and play the first legal square.
with open(Path(__file__).with_name("my_adapter.log"), "a") as log:
log.write(repr(error) + "\n")
move = legal[0] if legal else -1
print(json.dumps({"move": move}), flush=True)Χρόνος σκέψης: στις παρτίδες bot κάθε bot έχει 1 λεπτό ανά παρτίδα, οπότε η πολλή σκέψη σε μία κίνηση οδηγεί γρήγορα σε ήττα στον χρόνο. Το think_ms στα παραδείγματα διαιρεί τον χρόνο που απομένει (remaining_ms) με τις κινήσεις που σας απομένουν, για να ορίσει τον χρόνο αυτής της κίνησης. Το budget_ms δεν είναι ο χρόνος που πρέπει να ξοδευτεί σε αυτή την κίνηση. Είναι ο μέγιστος χρόνος που το πρόγραμμα σύνδεσης περιμένει την απάντηση (10 δευτερόλεπτα από προεπιλογή). Αν η απάντηση έρθει αργότερα, το bot δεν μπορεί να συνεχίσει σε εκείνη την παρτίδα και τη χάνει στον χρόνο, γι' αυτό δώστε στη μηχανή σας το think_ms και όχι το budget_ms.
Όταν κάτι χαλάσει: αν η κλήση της μηχανής αποτύχει, τα αρχεία των παραδειγμάτων γράφουν την αιτία στο my_adapter.log και παίζουν στη θέση της το πρώτο νόμιμο τετράγωνο. Αν οι κινήσεις φαίνονται περίεργες, ανοίξτε πρώτα αυτό το αρχείο. Το πρόγραμμα σύνδεσης δεν εμφανίζει στην οθόνη τα μηνύματα σφάλματος του προσαρμογέα. Χρησιμοποιήστε το print μόνο για τη μία γραμμή απάντησης και γράψτε κάθε κείμενο αποσφαλμάτωσης σε αρχείο.
Ταχύτητα: το πρόγραμμα σύνδεσης κρατά το my_adapter.py σε λειτουργία για κάθε παρτίδα και στέλνει μία γραμμή ανά κίνηση. Ένα αρχείο που απαντά μία γραμμή και τερματίζει, όπως τα παραδείγματα, ξαναξεκινά στην επόμενη κίνηση, άρα και η μηχανή σας ξαναξεκινά κάθε φορά. Αν η μηχανή αργεί να ξεκινήσει ή πρέπει να κρατά τη δουλειά προηγούμενων κινήσεων, κάντε το my_adapter.py βρόχο: διάβασε μία γραμμή, απάντησε μία γραμμή, επανάλαβε. Μη διαβάζετε την είσοδο ως το τέλος και κάνετε flush μετά από κάθε απάντηση.
Το υπόλοιπο αυτού του μέρους είναι υλικό αναφοράς για το τι ανταλλάσσουν το πρόγραμμα σύνδεσης και το my_adapter.py. Αν χρησιμοποιείτε τα παραπάνω αρχεία παραδειγμάτων όπως είναι, δεν χρειάζεται να το διαβάσετε.
JSON εισόδου (σύνδεσμος → προσαρμογέας)
Αυτά είναι παραδείγματα δεδομένων που στέλνει ο σύνδεσμος, όχι εκτελέσιμος κώδικας. Μην τα αποθηκεύετε ως αρχείο Python. Κατά την παρτίδα, τα τρέχοντα δεδομένα στέλνονται αυτόματα σε κάθε γύρο.
Παρακάτω υπάρχει ένα παράδειγμα της κανονικής αρχικής θέσης 8×8. Στις πραγματικές παρτίδες το πρόγραμμα σύνδεσης συμπληρώνει την τρέχουσα θέση. Το board παραθέτει τα τετράγωνα από το a1 προς τα δεξιά, μετά την επόμενη σειρά. 0=κενό, 1=μαύρο, 2=λευκό. Το color=1 ζητά κίνηση για τα μαύρα. Το legal_moves παραθέτει τα τετράγωνα όπου μπορείτε να παίξετε. Το remaining_ms είναι ο υπόλοιπος χρόνος του ρολογιού της παρτίδας και το budget_ms ο μέγιστος χρόνος που το πρόγραμμα σύνδεσης περιμένει την απάντηση για αυτή την κίνηση, και τα δύο σε χιλιοστά του δευτερολέπτου (1000 = 1 δευτερόλεπτο). Τα πεδία και τα παραδείγματα για τις παραλλαγές βρίσκονται παρακάτω, στην ενότητα για τις παραλλαγές.
{"board":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,1,0,0,0,0,0,0,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"color":1,"legal_moves":[19,26,37,44],"game_mode":"std","board_size":8,"blocked_squares":[],"placed":{"1":0,"2":0},"remaining_ms":60000,"match_id":123,"leg":0,"revision":0,"history":[],"round_no":null,"room_created_at":null,"budget_ms":10000}JSON απάντησης (προσαρμογέας → σύνδεσμος)
Γράψτε μία από τις παρακάτω απαντήσεις ως μία γραμμή JSON που τελειώνει με αλλαγή γραμμής. Το move είναι αριθμός τετραγώνου ή συντεταγμένη, χωρίς διάκριση πεζών και κεφαλαίων. Στο 8×8, το d3 είναι (3−1)×8+3 = 19. Επιλέγετε πάντα από το legal_moves που λάβατε. Στα ζεύγη bot, όταν δεν υπάρχει νόμιμη κίνηση, στείλτε -1 ή pass. Στις παρτίδες με ανθρώπους τα υποχρεωτικά πάσο τα χειρίζεται ο διακομιστής. Γράψτε στο stdout μόνο τη γραμμή απάντησης, χωρίς άλλα μηνύματα.
{"move":19}{"move":"d3"}{"move":-1}Παραδείγματα αιτημάτων μηχανής ανά παιχνίδι
Παραδείγματα του πρώτου αιτήματος για τα μαύρα που στέλνει το πρόγραμμα σύνδεσης σε μια μηχανή --engine, δημιουργημένα με τον κώδικα κανόνων. Οι πραγματικές παρτίδες κάθε τύπου ξεκινούν από τυχαία θέση με 12 δίσκους, οπότε τα board και legal_moves διαφέρουν σε κάθε παρτίδα. Για να μένουν σταθερά αυτά τα παραδείγματα, οι αρχικές τους κινήσεις επιλέχθηκαν κοντά στο κέντρο του ταμπλό. Στις πραγματικές παρτίδες διαφέρουν επίσης το match_id και οι τιμές του ρολογιού.
game_mode: Ένα από τα std, anti, grand, octagon, reversi. Το XOT στις παρτίδες με ανθρώπους έρχεται ως std.board_size: 8, ή 10 για τα grand και octagon.board: Πίνακας μήκους board_size². Διαβάζεται από το a1 προς τα δεξιά, μετά η επόμενη σειρά. 0=κενό (μαζί με τα μπλοκαρισμένα τετράγωνα του Octagon), 1=μαύρο, 2=λευκό.blocked_squares: Τετράγωνα του Octagon που δεν χρησιμοποιούνται. Κενός πίνακας στα άλλα παιχνίδια.placed: Δίσκοι που έχει τοποθετήσει μέχρι τώρα κάθε χρώμα, μαζί με τις τυχαίες αρχικές κινήσεις. Τα κλειδιά είναι οι συμβολοσειρές "1" και "2". Χρησιμοποιείται για το όριο των 32 δίσκων του κλασικού Reversi.
Άντι (anti)
JSON εισόδου (σύνδεσμος → προσαρμογέας)
{
"board": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 1, 2, 2, 1, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
"color": 1,
"legal_moves": [2, 3, 12, 25, 42, 44, 45],
"game_mode": "anti",
"board_size": 8,
"blocked_squares": [],
"placed": {
"1": 4,
"2": 4
},
"remaining_ms": 60000,
"match_id": 123,
"leg": 0,
"revision": 0,
"history": [],
"round_no": null,
"room_created_at": null,
"budget_ms": 10000
}JSON απάντησης (προσαρμογέας → σύνδεσμος)
{"move":2}Μεγάλο (10x10) (grand)
JSON εισόδου (σύνδεσμος → προσαρμογέας)
{
"board": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 1, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
"color": 1,
"legal_moves": [13, 14, 25, 42, 63, 65, 66],
"game_mode": "grand",
"board_size": 10,
"blocked_squares": [],
"placed": {
"1": 4,
"2": 4
},
"remaining_ms": 60000,
"match_id": 123,
"leg": 0,
"revision": 0,
"history": [],
"round_no": null,
"room_created_at": null,
"budget_ms": 10000
}JSON απάντησης (προσαρμογέας → σύνδεσμος)
{"move":13}Οκτάγωνο (octagon)
JSON εισόδου (σύνδεσμος → προσαρμογέας)
{
"board": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 1, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
"color": 1,
"legal_moves": [13, 14, 25, 42, 63, 65, 66],
"game_mode": "octagon",
"board_size": 10,
"blocked_squares": [0, 1, 10, 8, 9, 19, 80, 90, 91, 89, 98, 99],
"placed": {
"1": 4,
"2": 4
},
"remaining_ms": 60000,
"match_id": 123,
"leg": 0,
"revision": 0,
"history": [],
"round_no": null,
"room_created_at": null,
"budget_ms": 10000
}JSON απάντησης (προσαρμογέας → σύνδεσμος)
{"move":13}Κλασικό Ρεβέρσι (reversi)
JSON εισόδου (σύνδεσμος → προσαρμογέας)
{
"board": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 2, 2, 1, 1, 0, 0, 0, 0, 2, 2, 1, 1, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
"color": 1,
"legal_moves": [18, 25, 33, 41, 42, 50, 51],
"game_mode": "reversi",
"board_size": 8,
"blocked_squares": [],
"placed": {
"1": 6,
"2": 6
},
"remaining_ms": 60000,
"match_id": 123,
"leg": 0,
"revision": 0,
"history": [],
"round_no": null,
"room_created_at": null,
"budget_ms": 10000
}JSON απάντησης (προσαρμογέας → σύνδεσμος)
{"move":18}Συνηθισμένα προβλήματα
| Σύμπτωμα | Αιτία και λύση |
|---|---|
| Το bot έχει γκρι κουκκίδα (αποσυνδεδεμένο). | Ελέγξτε ότι το παράθυρο του προγράμματος σύνδεσης τρέχει ακόμη. Σταματά όταν κλείσετε το παράθυρο, πατήσετε Ctrl+C ή όταν ο υπολογιστής μπει σε αναστολή λειτουργίας. Επαναλάβετε τα βήματα 6 και 7 και μετά πατήστε Ανανέωση. |
Λέει ότι η εντολή δεν βρέθηκε.command not found / is not recognized | Η Python λείπει ή το παράθυρο δεν άνοιξε ξανά μετά την εγκατάσταση. Δείτε το βήμα 5, ανοίξτε νέο παράθυρο και ξεκινήστε ξανά από το βήμα 4. |
Λέει ότι το αρχείο δεν μπορεί να ανοίξει.can't open file | Την εκτελέσατε έξω από τον φάκελο του bot. Μεταβείτε στον φάκελο του bot όπως στο βήμα 4 και ελέγξτε με το ls ότι εμφανίζονται τα README.md και tools. |
Λέει ότι λείπει το διακριτικό και τερματίζει.FS_BOT_TOKEN is missing or invalid | Αυτό το παράθυρο δεν έχει διακριτικό. Αν ανοίξατε νέο παράθυρο, επαναλάβετε το βήμα 6. |
Λέει ότι το διακριτικό απορρίφθηκε και σταματά.Bot credential rejected | Το διακριτικό επικολλήθηκε λάθος ή είναι παλιό. Αφού εκδώσετε νέο διακριτικό ή απενεργοποιήσετε το bot, το παλιό διακριτικό δεν λειτουργεί πια. Ξεκινήστε ξανά από το βήμα 6 με το πιο πρόσφατο διακριτικό. |
Η ίδια γραμμή σφάλματος εμφανίζεται συνέχεια.Connection/state error | Ελέγξτε τη σύνδεση στο διαδίκτυο. Σε macOS, ελέγξτε ότι εκτελέσατε το Install Certificates.command από το βήμα 5. Αν εμφανίζεται μόνο κατά τη διάρκεια παρτίδων, ο διακομιστής ίσως απορρίπτει την κίνηση της μηχανής σας ως μη νόμιμη. Το πρόγραμμα σύνδεσης στέλνει ξανά την ίδια κίνηση, οπότε πρέπει να διορθωθεί η μηχανή. |
| Το κουμπί πρόκλησης δεν λειτουργεί ή η πρόκληση δεν γίνεται αποδεκτή. | Και τα δύο bot πρέπει να έχουν πράσινη κουκκίδα. Ελέγξτε ότι το bot σας είναι επιλεγμένο στο Το bot μου που παίζει. Ένα bot που παίζει ήδη άλλη παρτίδα δεν δέχεται νέα πρόκληση. Μια πρόκληση που δεν γίνεται αποδεκτή λήγει μετά από 120 δευτερόλεπτα. |
Το bot δεν παίζει κίνηση και μετά χάνει στον χρόνο ή η παρτίδα ματαιώνεται.Engine failed for match | Η μηχανή δεν απάντησε εγκαίρως ή η απάντησή της είχε λάθος μορφή. Ελέγξτε την εντολή της μηχανής και την έξοδό της σε μία γραμμή JSON. Αν ένα bot δεν παίξει την πρώτη του κίνηση μέσα σε 30 δευτερόλεπτα από την έναρξη, η παρτίδα ματαιώνεται. |
| Δεν έρχονται προκλήσεις για παραλλαγές. | Το παράθυρο πρόκλησης δείχνει μόνο παιχνίδια που υποστηρίζουν και τα δύο bot. Ελέγξτε ότι το παιχνίδι είναι επιλεγμένο στο Υποστηριζόμενα παιχνίδια του bot σας και ότι το υποστηρίζει και το άλλο bot. Ένα bot που συνδέεται μέσω NBoard πρέπει να έχει επιλεγμένο μόνο το Κλασικό. |
Γλωσσάριο
| Όρος | Σημασία |
|---|---|
| API | Ένας συμφωνημένος τρόπος με τον οποίο τα προγράμματα στέλνουν αιτήματα και απαντήσεις. Το αναλαμβάνει για εσάς το πρόγραμμα σύνδεσης. |
| Διακριτικό | Ένας κωδικός μόνο για το bot σας. Με αυτόν το πρόγραμμα σύνδεσης αποδεικνύει στον διακομιστή ποιο bot είναι. |
| Τερματικό | Ένα παράθυρο όπου πληκτρολογείτε εντολές. Στα Windows χρησιμοποιήστε το PowerShell. |
| Μεταβλητή περιβάλλοντος | Μια προσωρινή ρύθμιση που δίνεται στα προγράμματα που ξεκινούν από ένα παράθυρο τερματικού. Χάνεται όταν κλείσει το παράθυρο. |
| JSON | Μια μορφή για να γράφονται δεδομένα ως κείμενο. Παράδειγμα: {"move":19} |
| Μηχανή | Ένα πρόγραμμα που εξετάζει μια θέση και επιλέγει κίνηση. |
| Προσαρμογέας | Ένα μικρό πρόγραμμα που μετατρέπει δεδομένα μεταξύ της μηχανής σας και του προγράμματος σύνδεσης. |
| NBoard | Το NBoard είναι γραφική εφαρμογή Othello που μπορεί να χρησιμοποιηθεί με το NTest. Το πρωτόκολλο NBoard είναι η δημόσια μορφή επικοινωνίας της με μηχανές και λειτουργεί με μηχανές που το υποστηρίζουν, όπως τα NTest και Edax. |
| Νόμιμη κίνηση | Ένα τετράγωνο όπου μπορείτε να παίξετε τώρα. Ο διακομιστής τα παραθέτει στο legal_moves. |
Λήψεις
Συνδεθείτε για λήψη. Το .zip περιέχει οδηγό, πρόγραμμα σύνδεσης και παράδειγμα μηχανής. Το .json είναι η προδιαγραφή API και το .md ο οδηγός.
Αναλυτικές προδιαγραφές
Το υπόλοιπο της σελίδας είναι αναλυτική τεκμηρίωση αναφοράς για προγραμματιστές που δουλεύουν απευθείας με μια μηχανή ή με το API.
Επιλογές του προγράμματος σύνδεσης
Επιλογές του tools/bot_match_client.py. Απαιτείται ακριβώς μία από τις --engine και --nboard / --edax / --egaroucid. Το διακριτικό δεν δίνεται ποτέ ως επιλογή. Διαβάζεται μόνο από τη μεταβλητή περιβάλλοντος FS_BOT_TOKEN. Κωδικοί εξόδου: 0 κανονική διακοπή, 2 απόρριψη διακριτικού, 3 συμπλήρωση του --max-runtime.
| Παράμετροι | Περιγραφή |
|---|---|
--engine "COMMAND" | Ξεκινά αυτή την εντολή μία φορά ανά παρτίδα και ανταλλάσσει μία γραμμή JSON ανά κίνηση χωρίς να κλείνει την είσοδό της. Μια μηχανή που απαντά μία γραμμή και τερματίζει ξαναξεκινά στην επόμενη κίνηση. |
--nboard "COMMAND" | Κρατά μία μηχανή NBoard ανά παρτίδα, δύο συνολικά. Μόνο κανονικό παιχνίδι (std). |
--edax PATH | Το Edax συνδέεται και μόνο με τη διαδρομή του εκτελέσιμου μέσω --edax παρακάτω. Δεν χρειάζεται ξεχωριστός προσαρμογέας· ο σύνδεσμος κατανέμει τον χρόνο σκέψης ανά κίνηση από τον υπόλοιπο χρόνο παρτίδας. |
--edax-eval PATH | Διαδρομή του eval.dat του Edax. Αν παραλειφθεί, αναζητείται data/eval.dat στον φάκελο του εκτελέσιμου ή στον γονικό του. |
--egaroucid PATH | Ετοιμάστε το Egaroucid for Console. Επιλέξτε το εκτελέσιμο κονσόλας και κρατήστε τον φάκελο resources στη θέση του. Σε macOS και Linux χρησιμοποιήστε πρόγραμμα μεταγλωττισμένο με τις επίσημες οδηγίες. Η θέση και ο υπόλοιπος χρόνος αποστέλλονται με setboard, settime και go χωρίς προσαρμογέα. |
--nboard-depth N | Στέλνει set depth N στη μηχανή NBoard. Από 0 έως 60. Το 0 κρατά την προεπιλογή της μηχανής. (--edax: 0 → 60). |
--max-think-seconds S | Μέγιστα δευτερόλεπτα αναμονής της μηχανής ανά κίνηση. Προεπιλογή 10, μέγιστο 300. Ποτέ περισσότερο από τον υπόλοιπο χρόνο του ρολογιού μείον 0,75 δευτερόλεπτα. Είναι όριο ασφαλείας του προγράμματος σύνδεσης. Ο διακομιστής δεν έχει όριο χρόνου ανά κίνηση. Με 0 καταργείται το όριο ανά κίνηση και ισχύει ο υπόλοιπος χρόνος παρτίδας. |
--engine-name NAME | Όνομα μηχανής που αναφέρεται στις πληροφορίες του bot (έως 120 χαρακτήρες). Μη βάζετε εντολές ή διαδρομές. |
--cpu-name NAME | Όνομα CPU προς αναφορά (έως 120 χαρακτήρες). Αν παραλειφθεί, εντοπίζεται αυτόματα. |
--once-match ID | Χειρίζεται μόνο αυτόν τον αγώνα και τερματίζει όταν εκείνος τελειώσει (finished, aborted, expired, rejected). Λειτουργούν και τα αρνητικά ID παρτίδων με ανθρώπους. Για δοκιμές, συνδυάστε το με το --max-runtime. |
--max-runtime S | Μετά από τόσα δευτερόλεπτα κλείνει τις μηχανές και τερματίζει (κωδικός εξόδου 3). |
--no-stream | Δεν χρησιμοποιεί τη ροή συμβάντων. Κάνει μόνο ερωτήματα. |
--api URL, --stream-url URL | Διευθύνσεις API και ροής. Κανονικά αφήστε τις προεπιλογές. Γίνεται δεκτό μόνο HTTPS, και επειδή μαζί στέλνεται το διακριτικό, η ροή πρέπει να βρίσκεται στον διακομιστή του API. |
Υλοποίηση του API μόνοι σας
Λαμβάνετε προκλήσεις και θέσεις με το agent_poll ή με την πιστοποιημένη ροή συμβάντων. Στείλτε agent_accept για εκκρεμείς προκλήσεις όπου είστε το bot_b και μετά υπολογίστε μόνο τις θέσεις όπου είναι η σειρά σας, σε κάθε παρτίδα ενός αγώνα σε εξέλιξη. Υποβάλλετε το πολύ μία φορά ανά match_id, παρτίδα και revision, και απορρίψτε την παρωχημένη δουλειά όταν αλλάζει η κατάσταση. Οι παρτίδες με ανθρώπους έχουν αρνητικό match_id και leg=0, και απαιτούν τα round_no και room_created_at ακριβώς όπως τα λάβατε. Στα κανονικά δωμάτια τα υποχρεωτικά πάσο τα χειρίζεται ο διακομιστής. Πάσο στέλνουν μόνο τα ζεύγη bot.
agent_poll / bot-stream → pending (bot_b = my_id)
→ agent_accept → running → legs[0] + legs[1]
→ agent_move(match_id, leg, revision, move) → finished / abortedΠαραλλαγές
Ένα bot λαμβάνει μόνο τα παιχνίδια που είναι επιλεγμένα στο Υποστηριζόμενα παιχνίδια. Το game_mode στα αιτήματα προς τη μηχανή και στην κατάσταση του αγώνα σας λέει ποιο παιχνίδι είναι. Ο διακομιστής υπολογίζει το μέγεθος του ταμπλό, τα μπλοκαρισμένα τετράγωνα και τα νόμιμα τετράγωνα, οπότε η μηχανή χρειάζεται μόνο να επιλέξει από το legal_moves που λαμβάνει. Μη δημιουργείτε κινήσεις 10×10 ή κλασικού Reversi με την κανονική παραγωγή κινήσεων 8×8.
| Παιχνίδι | game_mode | Ταμπλό | Αρχικοί δίσκοι | Ρολόι (ανά παρτίδα, ανά χρώμα) | Πρώτο legal_moves των μαύρων |
|---|---|---|---|---|---|
| Κλασικό | std | 8×8 | Τυχαίοι 12 δίσκοι | 60,000 ms | Εξαρτάται από τη θέση |
| Άντι | anti | 8×8 | Τυχαίοι 12 δίσκοι | 60,000 ms | Εξαρτάται από τη θέση |
| Μεγάλο (10x10) | grand | 10×10 | Τυχαίοι 12 δίσκοι | 60,000 ms | Εξαρτάται από τη θέση |
| Οκτάγωνο | octagon | 10×10 (88) | Τυχαίοι 12 δίσκοι | 60,000 ms | Εξαρτάται από τη θέση |
| Κλασικό Ρεβέρσι | reversi | 8×8 | Τυχαίοι 12 δίσκοι | 60,000 ms | Εξαρτάται από τη θέση |
Κοινοί κανόνες: τα μαύρα (1) παίζουν πρώτα. Και οι δύο παρτίδες ξεκινούν από την ίδια θέση με αντίστροφα χρώματα και παίζονται ταυτόχρονα. Στα ζεύγη bot, όταν δεν έχετε νόμιμη κίνηση, το legal_moves έρχεται ως κενός πίνακας και το bot πρέπει να στείλει μόνο του move=-1 (πάσο). Ο διακομιστής δεν κάνει πάσο για εσάς και το ρολόι σας συνεχίζει να μετρά. Το πάσο όταν υπάρχει νόμιμη κίνηση δεν επιτρέπεται. Μια παρτίδα τελειώνει όταν κανένα χρώμα δεν μπορεί να παίξει. Τα κενά τετράγωνα δεν δίνονται σε κανέναν. Αθροίζονται μόνο οι πραγματικοί δίσκοι και των δύο παρτίδων, και ίσα σύνολα σημαίνουν ισοπαλία. Όλες οι παρτίδες bot ξεκινούν από τυχαία θέση με 12 δίσκους. Σε κάθε τύπο παιχνιδιού, κάθε bot έχει 1 λεπτό ανά παρτίδα.
Anti: η τοποθέτηση και το γύρισμα δίσκων γίνονται όπως στο κανονικό Othello. Κερδίζει η πλευρά με τους λιγότερους δίσκους στις δύο παρτίδες.
10x10: κανονικοί κανόνες σε ταμπλό 10×10 (100 τετράγωνα). Η αρχική διάταξη είναι τα τέσσερα κεντρικά τετράγωνα. Τα ζεύγη bot προσθέτουν 8 τυχαίες κινήσεις και ξεκινούν με 12 δίσκους.
Octagon: ίδιο ταμπλό και ίδια αρχική διάταξη με το 10x10, αλλά τρία τετράγωνα σε κάθε γωνία, 12 συνολικά, δεν χρησιμοποιούνται (88 τετράγωνα για παιχνίδι). Τα μπλοκαρισμένα τετράγωνα έρχονται ως αριθμοί τετραγώνων στο blocked_squares και ως 0, την ίδια τιμή με το κενό, στο board. Ο πίνακας δεν είναι σε αριθμητική σειρά. Δεν μπορείτε να παίξετε σε μπλοκαρισμένο τετράγωνο και οι γραμμές δίσκων σταματούν εκεί.
Κλασικό Reversi: σύμφωνα με τους κανόνες, ξεκινά από κενό ταμπλό. Όσο κάποιο από τα τέσσερα κεντρικά τετράγωνα (27, 28, 35, 36) είναι κενό, τοποθετείτε μόνο εκεί και δεν γυρίζει κανένας δίσκος. Μόλις γεμίσουν και τα τέσσερα, ισχύουν οι κανονικοί κανόνες. Κάθε χρώμα τοποθετεί το πολύ 32 δίσκους, μαζί με τις τέσσερις πρώτες κινήσεις. Το placed μετρά τους δίσκους που έχει τοποθετήσει μέχρι τώρα κάθε χρώμα. Τα κλειδιά του είναι οι συμβολοσειρές "1" (μαύρα) και "2" (λευκά). Τα ζεύγη bot ξεκινούν αφού ο διακομιστής κάνει 12 τυχαίες τοποθετήσεις, μαζί με τις τέσσερις κεντρικές κινήσεις, οπότε στο πρώτο αίτημα οι δύο τιμές του placed έχουν άθροισμα 12 (συνήθως {"1":6,"2":6}). Ένα χρώμα που έχει τοποθετήσει και τους 32 δίσκους λαμβάνει κενό legal_moves και στέλνει -1 σε κάθε σειρά του.
Παραδείγματα αιτημάτων μηχανής ανά παιχνίδι
Παραδείγματα του πρώτου αιτήματος για τα μαύρα που στέλνει το πρόγραμμα σύνδεσης σε μια μηχανή --engine, δημιουργημένα με τον κώδικα κανόνων. Οι πραγματικές παρτίδες κάθε τύπου ξεκινούν από τυχαία θέση με 12 δίσκους, οπότε τα board και legal_moves διαφέρουν σε κάθε παρτίδα. Για να μένουν σταθερά αυτά τα παραδείγματα, οι αρχικές τους κινήσεις επιλέχθηκαν κοντά στο κέντρο του ταμπλό. Στις πραγματικές παρτίδες διαφέρουν επίσης το match_id και οι τιμές του ρολογιού.
Άντι (anti)
{"board":[0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,2,2,0,0,0,0,0,1,2,2,1,0,0,0,0,2,2,2,2,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"color":1,"legal_moves":[2,3,12,25,42,44,45],"game_mode":"anti","board_size":8,"blocked_squares":[],"placed":{"1":4,"2":4},"remaining_ms":60000,"match_id":123,"leg":0,"revision":0,"history":[],"round_no":null,"room_created_at":null,"budget_ms":10000}Μεγάλο (10x10) (grand)
{"board":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,2,2,0,0,0,0,0,0,0,1,2,2,1,0,0,0,0,0,0,2,2,2,2,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"color":1,"legal_moves":[13,14,25,42,63,65,66],"game_mode":"grand","board_size":10,"blocked_squares":[],"placed":{"1":4,"2":4},"remaining_ms":60000,"match_id":123,"leg":0,"revision":0,"history":[],"round_no":null,"room_created_at":null,"budget_ms":10000}Οκτάγωνο (octagon)
{"board":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,2,2,0,0,0,0,0,0,0,1,2,2,1,0,0,0,0,0,0,2,2,2,2,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"color":1,"legal_moves":[13,14,25,42,63,65,66],"game_mode":"octagon","board_size":10,"blocked_squares":[0,1,10,8,9,19,80,90,91,89,98,99],"placed":{"1":4,"2":4},"remaining_ms":60000,"match_id":123,"leg":0,"revision":0,"history":[],"round_no":null,"room_created_at":null,"budget_ms":10000}Κλασικό Ρεβέρσι (reversi)
{"board":[0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,1,0,0,0,0,0,2,2,1,1,0,0,0,0,2,2,1,1,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"color":1,"legal_moves":[18,25,33,41,42,50,51],"game_mode":"reversi","board_size":8,"blocked_squares":[],"placed":{"1":6,"2":6},"remaining_ms":60000,"match_id":123,"leg":0,"revision":0,"history":[],"round_no":null,"room_created_at":null,"budget_ms":10000}Πεδία αιτήματος μηχανής
| Πεδίο | Τύπος | Περιγραφή |
|---|---|---|
game_mode | string | Ένα από τα std, anti, grand, octagon, reversi. Το XOT στις παρτίδες με ανθρώπους έρχεται ως std. |
board_size | integer 8 | 10 | 8, ή 10 για τα grand και octagon. |
board | integer[board_size²] | Πίνακας μήκους board_size². Διαβάζεται από το a1 προς τα δεξιά, μετά η επόμενη σειρά. 0=κενό (μαζί με τα μπλοκαρισμένα τετράγωνα του Octagon), 1=μαύρο, 2=λευκό. |
blocked_squares | integer[] | Τετράγωνα του Octagon που δεν χρησιμοποιούνται. Κενός πίνακας στα άλλα παιχνίδια. |
placed | {"1": integer, "2": integer} | Δίσκοι που έχει τοποθετήσει μέχρι τώρα κάθε χρώμα, μαζί με τις τυχαίες αρχικές κινήσεις. Τα κλειδιά είναι οι συμβολοσειρές "1" και "2". Χρησιμοποιείται για το όριο των 32 δίσκων του κλασικού Reversi. |
legal_moves | integer[] | Τετράγωνα όπου μπορείτε να παίξετε τώρα. Αν είναι κενό, απαντήστε move=-1. |
color | integer 1 | 2 | Το χρώμα που παίζει. 1=μαύρο, 2=λευκό. |
budget_ms | integer | Χρόνος που επιτρέπεται για αυτή την κίνηση σε χιλιοστά του δευτερολέπτου: το μικρότερο από το --max-think-seconds και τον υπόλοιπο χρόνο του ρολογιού μείον 0,75 δευτερόλεπτα. Αν ξεπεραστεί, το πρόγραμμα σύνδεσης σταματά τη μηχανή. |
remaining_ms | integer | Ο υπόλοιπος χρόνος του χρώματός σας σε αυτή την παρτίδα, σε χιλιοστά του δευτερολέπτου, αφού αφαιρεθεί ο χρόνος που έχει ήδη χρησιμοποιηθεί σε αυτή τη σειρά. |
match_id | integer ≠ 0 | Αναγνωριστικό αγώνα. Αρνητικό (-αριθμός δωματίου) για παρτίδες με ανθρώπους. |
leg | integer 0 | 1 | Αριθμός παρτίδας 0 ή 1. Πάντα 0 για παρτίδες με ανθρώπους. |
revision | integer | Αριθμός κατάστασης αυτής της παρτίδας. Στείλτε τον αμετάβλητο με το agent_move. |
history | array | Κινήσεις που παίχτηκαν σε αυτή την παρτίδα. Αποφασίζετε με βάση το board. |
round_no | integer | null | Αριθμός γύρου μιας παρτίδας με άνθρωπο. null για ζεύγη bot. |
room_created_at | string | null | Ώρα δημιουργίας του δωματίου μιας παρτίδας με άνθρωπο. null για ζεύγη bot. |
Πρόκληση άλλου bot σε παραλλαγή
Προσθέστε το game_mode στο agent_challenge. Η προεπιλογή είναι std. Και τα δύο bot πρέπει να το έχουν στο supported_games. Διαβάστε τα παιχνίδια του αντιπάλου από το bots[].supported_games στην απάντηση του agent_poll. Αν κάποιο από τα δύο bot δεν έχει το παιχνίδι, η απάντηση είναι HTTP 409 με το παρακάτω σφάλμα.
{"action":"agent_challenge","target_id":2,"game_mode":"anti"}
{"action":"agent_challenge","target_name":"Opponent","game_mode":"grand"}HTTP 409
{"ok":false,"error":"unsupported game mode","server_now_ms":1800000000000}Αλλαγή του supported_games
Η φόρμα εγγραφής ξεκινά με επιλεγμένο το Κλασικό, και τα παλαιότερα bot χωρίς αποθηκευμένη λίστα υποστηρίζουν std. Μπορείτε να αλλάξετε τη λίστα μόνο στο Διαχείριση της ιστοσελίδας bot, ποτέ με το διακριτικό του bot (API). Η αλλαγή απορρίπτεται όσο ένας αγώνας είναι σε εξέλιξη ή περιμένει αποδοχή. Κενή λίστα δεν μπορεί να αποθηκευτεί.
NBoard και παραλλαγές
Μια σύνδεση --nboard υποστηρίζει μόνο το κανονικό παιχνίδι (std). Όταν έρθει μια παραλλαγή, το πρόγραμμα σύνδεσης δεν ρωτά τη μηχανή και παραιτείται από αυτή τη σειρά (μήνυμα Engine failed for match). Δεν στέλνεται κίνηση, οπότε η παρτίδα ματαιώνεται πριν από την πρώτη κίνηση ή η παρτίδα αυτή χάνεται αργότερα στον χρόνο. Δώστε σε ένα bot NBoard το κανονικό παιχνίδι ως μοναδικό υποστηριζόμενο.
Άνθρωποι εναντίον εγγεγραμμένων bot
Οι άνθρωποι μπορούν να προκαλέσουν το bot σας σε οποιοδήποτε παιχνίδι έχει δηλώσει. Αν υποστηρίζει το κανονικό, μπορεί να έρθουν και STD και XOT. Το XOT έρχεται με game_mode std και ξεκινά από ταμπλό όπου έχουν ήδη παιχτεί 8 κινήσεις (περιλαμβάνονται στο history). Ο άνθρωπος που προκαλεί επιλέγει το ρολόι και η παρτίδα δεν βαθμολογείται. Ένας αγώνας με άνθρωπο έχει μόνο μία παρτίδα (leg 0) και αρνητικό match_id. Ο διακομιστής χειρίζεται τα πάσο όταν δεν υπάρχει δυνατή κίνηση, οπότε μη στέλνετε -1. Τα εγγεγραμμένα online bot με ενεργή αυτόματη αντιστοίχιση συμμετέχουν και σε υποστηριζόμενους γρήγορους αγώνες STD/XOT. Αυτοί μετρούν στη βαθμολογία των μελών, αλλά όχι των επισκεπτών.
Μη νόμιμες κινήσεις και χρόνος
Μια μη νόμιμη κίνηση ή ένα παρωχημένο revision απορρίπτεται με HTTP 409 (illegal_move, stale_revision, not_your_turn) και το ταμπλό δεν αλλάζει. Στο μεταξύ το ρολόι συνεχίζει να μετρά. Το πρόγραμμα σύνδεσης ξαναστέλνει την ίδια κίνηση με το ίδιο revision, οπότε, αν δεν διορθωθεί η μηχανή, η παρτίδα αυτή τελικά χάνεται στον χρόνο. Ο διακομιστής δεν έχει όριο ανά κίνηση και ελέγχει μόνο τον υπόλοιπο χρόνο κάθε χρώματος. Τα 10 δευτερόλεπτα είναι η προεπιλογή του --max-think-seconds του προγράμματος σύνδεσης.
Έλεγχος ταυτότητας
Χρησιμοποιήστε HTTPS, JSON POST και Authorization: Bearer. Το διακριτικό αφορά ένα bot. Μην το βάζετε σε URL, δημόσιο κώδικα ή αρχεία καταγραφής.
Content-Type: application/json
Authorization: Bearer <FS_BOT_TOKEN>POST https://othelloclub.com/flipsight/bot_match_api.php
Κανόνες αγώνα
Όλες οι παρτίδες bot ξεκινούν από τυχαία θέση με 12 δίσκους. Δύο παρτίδες παίζονται ταυτόχρονα με αντίστροφα χρώματα. Κρίνει το σύνολο δίσκων· στο Anti κερδίζει το μικρότερο.
Όλες οι παρτίδες bot ξεκινούν από τυχαία θέση με 12 δίσκους. Σε κάθε τύπο παιχνιδιού, κάθε bot έχει 1 λεπτό ανά παρτίδα.
Αν ένα bot δεν κάνει την πρώτη του κίνηση μέσα σε 30 δευτερόλεπτα από την έναρξη, ο αγώνας ματαιώνεται και δεν βαθμολογείται. Αν κατά τον αγώνα η σύνδεση ενός bot χαθεί για πάνω από 30 δευτερόλεπτα ενώ το άλλο είναι συνδεδεμένο, κερδίζει το συνδεδεμένο bot (finish_reason: disconnect) και το αποτέλεσμα βαθμολογείται.
Τις κινήσεις των bot FlipSight σε όλα τα είδη παιχνιδιών τις υπολογίζει ο διακομιστής. Γίνονται δεκτές προκλήσεις και από τον ιστό και μέσω API (agent_challenge), και ο διακομιστής ξεκινά αμέσως τον αγώνα, οπότε δεν χρειάζεται να κρατάτε ανοιχτό το δωμάτιο παιχνιδιού. Αν ο υπολογισμός του διακομιστή σταματήσει για πάνω από 30 δευτερόλεπτα, ο αγώνας ματαιώνεται (finish_reason: technical) και δεν βαθμολογείται. Οι παραλλαγές είναι βαριές στον υπολογισμό, οπότε παίζονται ταυτόχρονα έως 2 αγώνες παραλλαγών με bot FlipSight. Όταν είναι γεμάτοι, παίρνετε HTTP 409 με site bot variant matches are full. Δοκιμάστε ξανά σε λίγο.
Αυτόματοι αγώνες bot: ο ιστότοπος κρατά πάντα ανοιχτά δύο δωμάτια αγώνων bot. Όσο ένα εγγεγραμμένο bot με ενεργή την αυτόματη αντιστοίχιση είναι συνδεδεμένο και δεν παίζει, δέχεται πρόκληση για κανονικό (std) αγώνα bot με bot παρόμοιας βαθμολογίας (πρώτα άλλο εγγεγραμμένο bot, αλλιώς bot FlipSight), ως bot_b. Το πρόγραμμα σύνδεσης τη δέχεται αυτόματα και ο αγώνας ξεκινά. Αν το bot δεν δεχτεί μέσα σε 120 δευτερόλεπτα ή απορρίψει, μένει εκτός αυτόματης αντιστοίχισης για 10 λεπτά. Οι αυτόματοι αγώνες βαθμολογούνται. Οι αυτόματοι αγώνες bot συνεχίζονται και κατά τη διάρκεια των παρτίδων της Αρένας. Η αυτόματη αντιστοίχιση είναι ενεργή από προεπιλογή και απενεργοποιείται από το Διαχείριση στη σελίδα bot. Ένα bot που ξεκίνησε με τη μηχανή εξάσκησης (environment.practice είναι true) μένει εκτός αυτόματων αγώνων, και οι αγώνες του με άλλα bot σε αυτό το διάστημα δεν βαθμολογούνται.
Μια άμεση πρόκληση ανθρώπου παίζεται ως μία παρτίδα σε κανονικό δωμάτιο με υποστηριζόμενο παιχνίδι και χρόνο. Ο διακομιστής ορίζει πάντα τις άμεσες προκλήσεις χωρίς βαθμολογία. Τα εγγεγραμμένα online bot με ενεργή αυτόματη αντιστοίχιση συμμετέχουν και σε υποστηριζόμενους γρήγορους αγώνες STD/XOT. Αυτοί μετρούν στη βαθμολογία των μελών, αλλά όχι των επισκεπτών. Ένα καταχωρισμένο bot δέχεται μόνο όσες παρτίδες επιτρέπει η ρύθμιση ταυτόχρονων παρτίδων (προεπιλογή 2). Μια παρτίδα με άνθρωπο και ένας αγώνας bot (δύο ταμπλό) μετράνε από 1.
pending → running → finished / aborted
pending → rejected / expired
kind=human: id=-room_id, legs[0], round_no, room_created_at
agent_move: move=19 / "d3" / "D3" (8×8)
10×10: "j10" = "J0" = 99
pass: -1 / "pass" / "PA" / "PS" / "--" (paired games only)
index=row*board_size+column (0-based)Εξέλιξη αγώνα
Όλες οι παρτίδες bot ξεκινούν από τυχαία θέση με 12 δίσκους. Δύο παρτίδες παίζονται ταυτόχρονα με αντίστροφα χρώματα. Κρίνει το σύνολο δίσκων. Στο Anti κερδίζει το μικρότερο.
Ο αριθμός συμμετέχοντα σας είναι 0 αν είστε bot_a και 1 αν είστε bot_b. Ο συμμετέχων 0 παίζει μαύρα (1) στο legs[0] και λευκά (2) στο legs[1], ενώ ο συμμετέχων 1 το αντίθετο. Είναι η σειρά σας όταν το leg.status είναι active και το leg.turn ισούται με το χρώμα σας. Μπορεί να είναι η σειρά σας και στις δύο παρτίδες ταυτόχρονα.
Αν δεν έχετε νόμιμη κίνηση, πρέπει να στείλετε μόνοι σας move -1 (πάσο). Ο διακομιστής δεν κάνει πάσο για εσάς. Σε παρτίδες με άνθρωπο, ο διακομιστής χειρίζεται τα πάσα όπως στα κανονικά δωμάτια παιχνιδιού.
Στη σειρά σας, υπολειπόμενος χρόνος = clocks_ms[χρώμα σας - 1] - (server_now_ms - turn_started_ms). Το clocks_ms ακολουθεί τη σειρά χρωμάτων (μαύρα, λευκά). Τα totals και winner ακολουθούν τη σειρά συμμετεχόντων (winner 0 ή 1, null για ισοπαλία).
Αριθμοί θέσεων
Αριθμός θέσης = γραμμή × 8 + στήλη, άρα a1=0, h1=7, a2=8 και h8=63. Για παράδειγμα, το 19 είναι d3 και το 37 είναι f5. Ο πίνακας board χρησιμοποιεί την ίδια σειρά, με 0=κενό, 1=μαύρο, 2=λευκό.
a b c d e f g h
1 0 1 2 3 4 5 6 7
2 8 9 10 11 12 13 14 15
3 16 17 18 19 20 21 22 23
4 24 25 26 27 28 29 30 31
5 32 33 34 35 36 37 38 39
6 40 41 42 43 44 45 46 47
7 48 49 50 51 52 53 54 55
8 56 57 58 59 60 61 62 63Στο 10×10 (grand, octagon), τετράγωνο = σειρά × 10 + στήλη. Οι στήλες είναι από a έως j, και η δέκατη σειρά γράφεται στις συντεταγμένες ως 10 ή 0. a1=0, j1=9, a2=10, j10=99 (ίδιο με j0). Η ίδια συντεταγμένη έχει διαφορετικό αριθμό σε κάθε μέγεθος ταμπλό: το d3 είναι 19 στο 8×8 και 23 στο 10×10.
a b c d e f g h i j
1 0 1 2 3 4 5 6 7 8 9
2 10 11 12 13 14 15 16 17 18 19
3 20 21 22 23 24 25 26 27 28 29
4 30 31 32 33 34 35 36 37 38 39
5 40 41 42 43 44 45 46 47 48 49
6 50 51 52 53 54 55 56 57 58 59
7 60 61 62 63 64 65 66 67 68 69
8 70 71 72 73 74 75 76 77 78 79
9 80 81 82 83 84 85 86 87 88 89
10 90 91 92 93 94 95 96 97 98 99Οκτάγωνο (octagon)
a b c d e f g h i j
1 ## ## 2 3 4 5 6 7 ## ##
2 ## 11 12 13 14 15 16 17 18 ##
3 20 21 22 23 24 25 26 27 28 29
4 30 31 32 33 34 35 36 37 38 39
5 40 41 42 43 44 45 46 47 48 49
6 50 51 52 53 54 55 56 57 58 59
7 60 61 62 63 64 65 66 67 68 69
8 70 71 72 73 74 75 76 77 78 79
9 ## 81 82 83 84 85 86 87 88 ##
10 ## ## 92 93 94 95 96 97 ## ##Ροή συμβάντων
Συνδεθείτε με το ίδιο διακριτικό Bearer στο GET https://othelloclub.com/flipsight_api/bot-stream για να λαμβάνετε ένα συμβάν JSON ανά γραμμή (NDJSON): το hello επιβεβαιώνει τη σύνδεση, το match σημαίνει ότι άλλαξε ένας από τους αγώνες σας (τα συμβάντα αγώνων μεταξύ bot περιέχουν ολόκληρο το αντικείμενο αγώνα) και το ping διατηρεί τη σύνδεση ενεργή κάθε 10 δευτερόλεπτα. Όταν λάβετε match, καλέστε μία φορά το agent_poll. Αν η σύνδεση πέσει, επανασυνδεθείτε με καθυστέρηση που αυξάνεται από 1 έως 30 δευτερόλεπτα και στο μεταξύ συνεχίστε τα ερωτήματα. Όσο η ροή είναι συνδεδεμένη, το bot σας εμφανίζεται online. Κάθε bot μπορεί να ανοίξει έως 3 ροές.
Παραδείγματα συμβάντων
curl -N 'https://othelloclub.com/flipsight_api/bot-stream' \
-H "Authorization: Bearer $FS_BOT_TOKEN"
{"type":"hello","bot_id":1,"server_now_ms":1800000000000}
{"type":"match","match":{"id":123,"bot_a":1,"bot_b":2,"status":"running","state":{...}},"server_now_ms":1800000000500}
{"type":"match","match":{"id":-45,"kind":"human","room_id":45},"server_now_ms":1800000003000}
{"type":"ping","server_now_ms":1800000010000}Προσαρμογέας μηχανής
Το πρόγραμμα σύνδεσης bot του FlipSight (Python 3.9+, μόνο τυπική βιβλιοθήκη) τρέχει σε Windows, macOS και Linux και συνδέει μηχανή με δύο τρόπους. Το --engine ξεκινά τη μηχανή μία φορά ανά παρτίδα, στέλνει μία γραμμή JSON σε κάθε κίνηση και διαβάζει μία γραμμή {"move": τετράγωνο}. Μια μηχανή που απαντά μία γραμμή και τερματίζει εξακολουθεί να λειτουργεί, επειδή ξαναξεκινά στην επόμενη κίνηση, αλλά μια μηχανή που διαβάζει την είσοδο ως το τέλος (sys.stdin.read() κ.λπ.) δεν απαντά ποτέ, οπότε διαβάζετε μία γραμμή τη φορά. Το legal_moves στο αίτημα απαριθμεί τα νόμιμα τετράγωνα· αν είναι κενό, απαντήστε -1. Το --nboard κρατά σε λειτουργία μια μηχανή NBoard, μία ανά παρτίδα· το βάθος ορίζεται με --nboard-depth.
Το Edax συνδέεται και μόνο με τη διαδρομή του εκτελέσιμου μέσω --edax παρακάτω. Δεν χρειάζεται ξεχωριστός προσαρμογέας· ο σύνδεσμος κατανέμει τον χρόνο σκέψης ανά κίνηση από τον υπόλοιπο χρόνο παρτίδας.
Ετοιμάστε το Egaroucid for Console. Επιλέξτε το εκτελέσιμο κονσόλας και κρατήστε τον φάκελο resources στη θέση του. Σε macOS και Linux χρησιμοποιήστε πρόγραμμα μεταγλωττισμένο με τις επίσημες οδηγίες. Η θέση και ο υπόλοιπος χρόνος αποστέλλονται με setboard, settime και go χωρίς προσαρμογέα.
JSON εισόδου (σύνδεσμος → προσαρμογέας)
Αυτά είναι παραδείγματα δεδομένων που στέλνει ο σύνδεσμος, όχι εκτελέσιμος κώδικας. Μην τα αποθηκεύετε ως αρχείο Python. Κατά την παρτίδα, τα τρέχοντα δεδομένα στέλνονται αυτόματα σε κάθε γύρο.
{"board":[0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,2,2,0,0,0,0,0,1,2,2,1,0,0,0,0,2,2,2,2,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"color":1,"legal_moves":[2,3,12,25,42,44,45],"game_mode":"std","board_size":8,"blocked_squares":[],"placed":{"1":4,"2":4},"remaining_ms":40000,"match_id":123,"leg":1,"revision":0,"history":[],"round_no":null,"room_created_at":null,"budget_ms":10000}JSON απάντησης (προσαρμογέας → σύνδεσμος)
{"move":2}Συγχρονισμός
Με συνδεδεμένη ροή, καλείτε το agent_poll όταν φτάνει συμβάν και κάθε 10 δευτερόλεπτα. Χωρίς ροή, ρωτάτε κάθε δευτερόλεπτο κατά τη διάρκεια αγώνα και κάθε 5 δευτερόλεπτα σε αδράνεια, ποτέ συχνότερα από μία φορά το δευτερόλεπτο. Ο χρόνος δικτύου αφαιρείται από το ρολόι σας. Αν χαθεί η απάντηση σε μια κίνηση, λάβετε τη νέα κατάσταση και ξαναστείλτε την ίδια κίνηση μόνο αν το revision παραμένει ίδιο.
Ενέργειες API
Τα παραδείγματα απαντήσεων δείχνουν τη μορφή. Το κουμπί αντιγραφής αντιγράφει μόνο το αίτημα και δεν καλεί το API.
POST agent_poll
Λήψη κατάστασης
| Παράμετροι | Τύπος | Υποχρεωτικό | Περιγραφή |
|---|---|---|---|
action | string "agent_poll" | Υποχρεωτικό | Όνομα της ενέργειας που καλείται |
environment | object | Προαιρετικό | CPU, λειτουργικό σύστημα και όνομα μηχανής του υπολογιστή σύνδεσης (έως 120 χαρακτήρες το καθένα, προαιρετικό) και practice (true ή false, προαιρετικό). Το practice true σημαίνει ότι το bot κάνει εξάσκηση: μένει εκτός αυτόματων αγώνων, και οι αγώνες bot που ζητούνται ή γίνονται δεκτοί σε αυτό το διάστημα δεν βαθμολογούνται. Το πρόγραμμα σύνδεσης το στέλνει μόνο του όταν ξεκινά με τη μηχανή εξάσκησης. Ο διακομιστής θυμάται την τελευταία τιμή, οπότε όταν τελειώσει η εξάσκηση στείλτε το χωρίς practice ή με false. |
Παράδειγμα αιτήματος
curl 'https://othelloclub.com/flipsight/bot_match_api.php' \
-H "Authorization: Bearer $FS_BOT_TOKEN" \
-H 'Content-Type: application/json' \
--data '{"action":"agent_poll","environment":{"cpu":"Apple M4","engine":"MyEngine","os":"Darwin"}}'Παράδειγμα απάντησης
{
"ok": true,
"bots": [
{
"id": 1,
"name": "Opponent",
"owner_id": "example",
"owner_name": "Example",
"owner": {
"player_id": "example",
"name": "Example",
"photo": "/img/no_profile.gif",
"country_code": "",
"country_name": "",
"country_flag_url": "",
"donor": false,
"verified_player_id": ""
},
"engine_level": null,
"rating": {
"rating": 1200,
"rd": 300,
"official": false,
"official_progress": {
"kind": "provisional",
"current": 0,
"required": 50
},
"color": "pz-rating-unofficial",
"high_rating": 1200,
"wins": 0,
"losses": 0,
"draws": 0,
"streak": 0,
"best_streak": 0
},
"supported_games": ["std"],
"auto_match": true,
"bio": "",
"registered_at": "2026-11-12 18:00:00",
"registered_at_ts": 1794474000,
"environment": {
"cpu": "Apple M4",
"engine": "MyEngine",
"os": "Darwin",
"practice": false
},
"is_builtin": false,
"online": true,
"disabled": false,
"deleted": false,
"photo": "/flipsight/bot_match_api.php?action=photo&bot_id=1&v=1794474000000"
},
{
"id": 2,
"name": "MyBot",
"owner_id": "example",
"owner_name": "Example",
"owner": {
"player_id": "example",
"name": "Example",
"photo": "/img/no_profile.gif",
"country_code": "",
"country_name": "",
"country_flag_url": "",
"donor": false,
"verified_player_id": ""
},
"engine_level": null,
"rating": {
"rating": 1200,
"rd": 300,
"official": false,
"official_progress": {
"kind": "provisional",
"current": 0,
"required": 50
},
"color": "pz-rating-unofficial",
"high_rating": 1200,
"wins": 0,
"losses": 0,
"draws": 0,
"streak": 0,
"best_streak": 0
},
"supported_games": ["std", "anti"],
"auto_match": true,
"bio": "",
"registered_at": "2026-11-12 18:00:00",
"registered_at_ts": 1794474000,
"environment": {
"cpu": "Apple M4",
"engine": "MyEngine",
"os": "Darwin",
"practice": false
},
"is_builtin": false,
"online": true,
"disabled": false,
"deleted": false,
"photo": "/flipsight/bot_match_api.php?action=photo&bot_id=2&v=1794474000000"
}
],
"record_bots": [],
"matches": [
{
"id": 123,
"bot_a": 1,
"bot_b": 2,
"game_mode": "std",
"time_limit_sec": 60,
"status": "running",
"state": {
"version": 1,
"game_mode": "std",
"time_limit_sec": 60,
"status": "active",
"revision": 1,
"started_ms": 1799999980000,
"last_now_ms": 1799999984200,
"finished_ms": null,
"opening_moves": [19, 20, 29, 34, 26, 11, 43, 37],
"opening_history": [
{
"color": 1,
"move": 19
},
{
"color": 2,
"move": 20
},
{
"color": 1,
"move": 29
},
{
"color": 2,
"move": 34
},
{
"color": 1,
"move": 26
},
{
"color": 2,
"move": 11
},
{
"color": 1,
"move": 43
},
{
"color": 2,
"move": 37
}
],
"legs": [
{
"board": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 1, 2, 2, 1, 0, 0, 0, 0, 2, 1, 2, 2, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
"turn": 2,
"black_participant": 0,
"placed": {
"1": 5,
"2": 4
},
"clocks_ms": [55800, 60000],
"turn_started_ms": 1799999984200,
"revision": 1,
"history": [
{
"color": 1,
"participant": 0,
"move": 44,
"at_ms": 1799999984200
}
],
"status": "active",
"discs": [5, 8],
"finished_ms": null,
"legal_moves": [18, 21, 22, 25, 30, 33, 38, 42, 50, 51, 52]
},
{
"board": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 1, 2, 2, 1, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
"turn": 1,
"black_participant": 1,
"placed": {
"1": 4,
"2": 4
},
"clocks_ms": [60000, 60000],
"turn_started_ms": 1799999980000,
"revision": 0,
"history": [],
"status": "active",
"discs": [3, 9],
"finished_ms": null,
"legal_moves": [2, 3, 12, 25, 42, 44, 45]
}
],
"totals": [14, 11],
"winner": null,
"finish_reason": null,
"board_size": 8,
"blocked_squares": []
},
"auto": false,
"expires_ms": 1800000080000,
"ranked": true,
"rating_applied": false,
"rating_before": [null, null],
"rating_after": [null, null],
"created_at": "2026-11-12 19:00:00"
}
],
"me": "example",
"bot": {
"id": 2,
"name": "MyBot",
"owner_id": "example",
"owner_name": "Example",
"owner": {
"player_id": "example",
"name": "Example",
"photo": "/img/no_profile.gif",
"country_code": "",
"country_name": "",
"country_flag_url": "",
"donor": false,
"verified_player_id": ""
},
"engine_level": null,
"rating": {
"rating": 1200,
"rd": 300,
"official": false,
"official_progress": {
"kind": "provisional",
"current": 0,
"required": 50
},
"color": "pz-rating-unofficial",
"high_rating": 1200,
"wins": 0,
"losses": 0,
"draws": 0,
"streak": 0,
"best_streak": 0
},
"supported_games": ["std", "anti"],
"auto_match": true,
"bio": "",
"registered_at": "2026-11-12 18:00:00",
"registered_at_ts": 1794474000,
"environment": {
"cpu": "Apple M4",
"engine": "MyEngine",
"os": "Darwin",
"practice": false
},
"is_builtin": false,
"online": true,
"disabled": false,
"deleted": false,
"photo": "/flipsight/bot_match_api.php?action=photo&bot_id=2&v=1794474000000"
},
"server_now_ms": 1800000000000
}Αντικείμενο αγώνα (matches[])
| Πεδίο | Τύπος | Περιγραφή |
|---|---|---|
id | integer | ID αγώνα (αρνητικό για παρτίδες με άνθρωπο) |
kind | string | human για παρτίδες με άνθρωπο |
bot_a | integer | ID bot του συμμετέχοντα 0 (0 για άνθρωπο) |
bot_b | integer | ID bot του συμμετέχοντα 1 (0 για άνθρωπο) |
game_mode | string | Παιχνίδι (std, anti, grand, octagon, reversi) |
time_limit_sec | integer | Δευτερόλεπτα ανά παρτίδα, ανά χρώμα |
status | string | pending, running, finished, aborted, rejected, expired |
expires_ms | integer | Προθεσμία αποδοχής (χιλιοστά του δευτερολέπτου) |
ranked | boolean | Αν ο αγώνας βαθμολογείται |
state.status | string | active, finished ή aborted |
state.game_mode | string | Παιχνίδι (std, anti, grand, octagon, reversi) |
state.board_size | integer 8 | 10 | Τετράγωνα ανά πλευρά, 8 ή 10 |
state.blocked_squares | integer[] | Τετράγωνα εκτός χρήσης (μόνο Octagon, χωρίς ταξινόμηση) |
state.legs | array | Παρτίδες (2 μεταξύ bot, 1 με άνθρωπο) |
state.totals | [integer, integer] | Σύνολα δίσκων και των δύο παρτίδων ανά συμμετέχοντα |
state.winner | integer | null | Νικητής συμμετέχων 0 ή 1, null για ισοπαλία |
state.finish_reason | string | null | discs, timeout, double_timeout, disconnect, no_first_move |
Αντικείμενο παρτίδας (state.legs[])
| Πεδίο | Τύπος | Περιγραφή |
|---|---|---|
board | integer[64 | 100] | 64 / 100 θέσεις, 0=κενό 1=μαύρο 2=λευκό |
turn | integer | Χρώμα που παίζει, 1 (μαύρα) ή 2 (λευκά) |
legal_moves | integer[] | Νόμιμα τετράγωνα για το χρώμα που παίζει. Κενό για ολοκληρωμένες παρτίδες |
placed | {"1": integer, "2": integer} | Δίσκοι που τοποθετήθηκαν ανά χρώμα, κλειδιά "1" (μαύρα) και "2" (λευκά) |
black_participant | integer | Συμμετέχων που παίζει μαύρα σε αυτή την παρτίδα |
clocks_ms | [number, number] | Βάσεις υπολειπόμενου χρόνου σε σειρά χρωμάτων (μαύρα, λευκά) |
turn_started_ms | integer | Ώρα διακομιστή κατά την έναρξη της τρέχουσας σειράς |
revision | integer | Αυξάνεται κατά 1 σε κάθε αλλαγή αυτής της παρτίδας |
status | string | active, finished, timeout, stopped |
history | array | Κινήσεις που παίχτηκαν (color, participant, move, at_ms) |
discs | [integer, integer] | Πλήθος δίσκων σε σειρά χρωμάτων (μαύρα, λευκά) |
result_discs | [integer, integer] (optional) | Προαιρετικό σκορ κατακύρωσης [μαύρα, λευκά] για παρτίδα που χάθηκε στον χρόνο. Στο σύνολο μετράει αυτό αντί για τους δίσκους. Σκορ για την πλευρά που έμεινε χωρίς χρόνο και για τον αντίπαλό της: std και reversi από 0 έως 64, grand από 0 έως 100, octagon από 0 έως 88, anti από 64 έως 0. Η άλλη παρτίδα συνεχίζεται και τον νικητή τον κρίνουν τα σύνολα αφού τελειώσουν και οι δύο παρτίδες. Παλαιότερες ολοκληρωμένες εγγραφές δεν υπολογίζονται ξανά. |
POST agent_challenge
Πρόκληση
Ορίστε target_id (αριθμός bot) ή target_name (όνομα bot), που υπάρχουν στη λίστα bots της απάντησης του agent_poll. Τα ενσωματωμένα bot FlipSight (is_builtin: true) δέχονται πρόκληση μέσω API σε όλα τα είδη παιχνιδιών, και ο διακομιστής ξεκινά αμέσως τον αγώνα. Αν γίνονται ήδη 2 αγώνες παραλλαγών με ενσωματωμένα bot, παίρνετε HTTP 409 με site bot variant matches are full.
| Παράμετροι | Τύπος | Υποχρεωτικό | Περιγραφή |
|---|---|---|---|
action | string "agent_challenge" | Υποχρεωτικό | Όνομα της ενέργειας που καλείται |
target_id | integer ≥ 1 | Προαιρετικό | ID του bot που προκαλείτε |
target_name | string | Προαιρετικό | Όνομα του bot που προκαλείτε (αντί για target_id) |
game_mode | string std | anti | octagon | grand | reversi | Προαιρετικό | Παιχνίδι για ζεύγος bot. Προεπιλογή std. Πρέπει να το υποστηρίζουν και τα δύο bot. Κλασικό / Άντι / Οκτάγωνο / Μεγάλο (10x10) / Κλασικό Ρεβέρσι |
Παράδειγμα αιτήματος
curl 'https://othelloclub.com/flipsight/bot_match_api.php' \
-H "Authorization: Bearer $FS_BOT_TOKEN" \
-H 'Content-Type: application/json' \
--data '{"action":"agent_challenge","target_id":2,"game_mode":"anti"}'Παράδειγμα απάντησης
{
"ok": true,
"match_id": 123,
"server_now_ms": 1800000000000
}POST agent_accept
Αποδοχή
| Παράμετροι | Τύπος | Υποχρεωτικό | Περιγραφή |
|---|---|---|---|
action | string "agent_accept" | Υποχρεωτικό | Όνομα της ενέργειας που καλείται |
match_id | integer ≥ 1 | Υποχρεωτικό | ID αγώνα (αρνητικό για παρτίδες με άνθρωπο) |
Παράδειγμα αιτήματος
curl 'https://othelloclub.com/flipsight/bot_match_api.php' \
-H "Authorization: Bearer $FS_BOT_TOKEN" \
-H 'Content-Type: application/json' \
--data '{"action":"agent_accept","match_id":123}'Παράδειγμα απάντησης
{
"ok": true,
"match": {
"id": 123,
"status": "running",
"bot_a": 1,
"bot_b": 2
},
"server_now_ms": 1800000000000
}POST agent_reject
Απόρριψη
| Παράμετροι | Τύπος | Υποχρεωτικό | Περιγραφή |
|---|---|---|---|
action | string "agent_reject" | Υποχρεωτικό | Όνομα της ενέργειας που καλείται |
match_id | integer ≥ 1 | Υποχρεωτικό | ID αγώνα (αρνητικό για παρτίδες με άνθρωπο) |
Παράδειγμα αιτήματος
curl 'https://othelloclub.com/flipsight/bot_match_api.php' \
-H "Authorization: Bearer $FS_BOT_TOKEN" \
-H 'Content-Type: application/json' \
--data '{"action":"agent_reject","match_id":123}'Παράδειγμα απάντησης
{
"ok": true,
"match": {
"id": 123,
"status": "rejected",
"bot_a": 1,
"bot_b": 2
},
"server_now_ms": 1800000000000
}POST agent_move
Υποβολή κίνησης
| Παράμετροι | Τύπος | Υποχρεωτικό | Περιγραφή |
|---|---|---|---|
action | string "agent_move" | Υποχρεωτικό | Όνομα της ενέργειας που καλείται |
match_id | integer ≠ 0 | Υποχρεωτικό | ID αγώνα (αρνητικό για παρτίδες με άνθρωπο) |
round_no | integer ≥ 0 | Προαιρετικό | Μόνο για παρτίδες με άνθρωπο: round_no από το αντικείμενο αγώνα |
room_created_at | string | Προαιρετικό | Μόνο για παρτίδες με άνθρωπο: room_created_at από το αντικείμενο αγώνα |
leg | integer 0 | 1 | Υποχρεωτικό | Παρτίδα 0 ή 1 (0 για παρτίδες με άνθρωπο) |
revision | integer ≥ 0 | Υποχρεωτικό | Revision της παρτίδας για την οποία υπολογίστηκε η κίνηση. 409 stale_revision αν η παρτίδα έχει αλλάξει |
move | integer -1..99 | string | Υποχρεωτικό | Θέση 0-(board_size²−1), -1 για πάσο / d3 / D3 / pass |
Παράδειγμα αιτήματος
curl 'https://othelloclub.com/flipsight/bot_match_api.php' \
-H "Authorization: Bearer $FS_BOT_TOKEN" \
-H 'Content-Type: application/json' \
--data '{"action":"agent_move","match_id":123,"leg":1,"revision":0,"move":2}'Παράδειγμα απάντησης
{
"ok": true,
"match": {
"id": 123,
"status": "running",
"bot_a": 1,
"bot_b": 2
},
"server_now_ms": 1800000000000
}Σφάλματα
Τα σφάλματα έχουν τη μορφή {"ok": false, "error": "…"}. Στο 401 σταματήστε και ελέγξτε το διακριτικό. Στο 409 λάβετε την τρέχουσα κατάσταση και ελέγξτε σειρά, revision και νόμιμες κινήσεις. Το 429 σημαίνει υπερβολικά πολλές ροές για ένα bot. Επαναλάβετε τα σφάλματα σύνδεσης και το 503 με αυξανόμενες καθυστερήσεις και μην ξαναστέλνετε ποτέ παράνομη κίνηση.
{"ok":false,"error":"stale_revision","server_now_ms":1800000000000}| HTTP | error |
|---|---|
| 400 | JSON object required / unknown action |
| 401 | invalid bot credential |
| 403 | access denied / invalid csrf |
| 405 | POST required |
| 409 | stale_revision / not_your_turn / illegal_move / leg_finished / match not running / match timed out / stale room revision / invalid move coordinate / move outside board / unsupported game mode / both bots must be connected / bot already has an active match / bot busy / challenge expired or answered / site bot variant matches are full / target bot not found |
| 413 | request too large |
| 429 | too many streams (bot-stream) |
| 503 | bot match storage unavailable |