1. Tyamka
  2. Девблог
  3. Як сервер перевіряє результат, переграючи партію

Як сервер перевіряє результат, переграючи партію

· 3 хв читання · Команда Тямки

Як таблиці лідерів Тямки перевіряють результат, відбудовуючи рівень і переграючи ходи гравця тим самим кодом гри, і чого ця перевірка поки не ловить.

Таблиця лідерів чогось варта, лише коли результати в ній справжні. Найпростіший варіант вірить будь-якому числу, яке надсилає гра, а таке число легко підробити. Для таблиць лідерів у вебі і в Telegram ми пішли іншим шляхом. Сервер не вірить рахунку. Він відбудовує рівень, переграє ходи гравця через той самий код гри і зберігає рахунок, який отримав сам. Цю частину написано і покрито тестами. Наживо вона ще не працює, бо сервер для неї поки не розгорнуто.

Чому той самий код працює на сервері

Усе йде від правила з першого дня коду. Правила кожної гри лежать у звичайному модулі на TypeScript без React усередині. Випадковість приходить як seed, а час як аргумент. Тож рівень повністю описують гра, номер рівня і seed, а партія — це те саме плюс список ходів із часом кожного.

Усі пʼятнадцять ігор описані в однаковій формі, а оболонка гри змінює стан гри тільки в одному місці. Тому одна функція перегравання покриває кожну гру. Ми планували під неї окрему роботу, і вона не знадобилася. Функція займає близько 40 рядків, а модулі ігор працюють на сервері під Deno без змін. Побудова найскладнішого рівня будь-якої гри в нашому замірі 26 вересня забрала щонайбільше 7,2 мс, тож перегравання майже нічого не додає до запиту.

Що надсилає гра

Під час партії оболонка записує кожен хід, який справді змінив гру, разом із часом. Ходи, що нічого не змінюють, не записуються. Наприкінці, якщо в гравця є акаунт, партія йде на сервер разом із грою, рівнем і seed. Сервер переграє її і порівнює. Якщо його рахунок відрізняється від надісланого, нічого не записується. Гру в слова переграємо на словнику тієї мови, якою в неї грали, тож англійські й українські слова ніколи не змішуються в одній таблиці.

Гості грають як раніше. Їхні результати лишаються на пристрої, і нічого не надсилається. Збереження на пристрої взагалі не залежить від мережі. Без зʼєднання партія чекає в черзі на пристрої і йде на сервер, коли застосунок знову відкривають, а екран результатів чесно пише, що надішле пізніше, і не вдає, ніби вже надіслав.

Чого перевірка не ловить

Перегравання доводить, що рахунок отримано в законній партії на цьому рівні. Воно не доводить, що людина зіграла її з такою швидкістю. Час ходів приходить із пристрою, тому скрипт, який надсилає ідеальні ходи, перевірку пройде. Ми записали цю межу в код поруч із перевіркою, а не замовчали її. Наступний крок у тому, щоб сервер сам видавав seed на кожну партію і ставив нижню межу правдоподібного часу реакції.

Як це перевірено

Перегравання має 27 власних тестів. Для кожної з пʼятнадцяти ігор, а для гри в слова обома мовами, бот проходить перший і останній рівень до кінця. Перегравання записаних ним ходів має дати той самий рахунок і той самий підсумок. Інші тести підсовують погані партії, як-от незакінчену гру, хід після кінця, час, що йде назад, чи забагато ходів, і кожну з них має бути відхилено.

Де ми зараз

Серверну частину і запис ходів у грі написано. Бракує живого сервера і екрана таблиці лідерів, дизайн якого чекає на затвердження. Доти перевірка живе в тестах. Та сама думка стоїть за правилом для таблиці Шульте та інших ігор, що рекорд на пристрої ніколи не вигадується. Якщо результат не зберігся, гра так і каже.