← Дневник разработки

Класс переименовали — и герой разучился стрелять

Готовя эксперимент с украинским языком, мы перевели название класса: «следопыт» стало «слідопит». Ничего не упало. Мастер продолжал вести партию, текст читался нормально. Просто герой перестал получать бонус за привычное оружие.

Ошибки не было. Теста, который бы покраснел, тоже не было.

Имя было ключом

В сохранении у персонажа лежал не код класса, а его русское название. Правила, которые смотрят, какое оружие классу привычно, брали это название и искали в своей таблице. «следопыт» там был. «слідопит» — нет. Совпадения не нашлось, таблица вернула пустоту, а пустота означала «ограничений нет» — и проверка тихо перестала работать.

Таких мест в коде было десять. Поиск предмета по названию. Условие «тяжёлая броня», которое игра ставит сама и Мастеру ставить не даёт. Причина броска «обстановка». Список слов, по которому игра узнаёт, что Мастер говорит про группу людей, а не про одного человека. Всё это сходилось по русским строкам.

Общее у них одно: сломавшись, они не жалуются. Игра не падает и не выдаёт ошибку — она продолжает красиво рассказывать и при этом перестаёт соблюдать собственные правила. Броня не считается, класс не мешает надеть то, что мешать должен, толпа читается как один человек. Это худший вид поломки, потому что снаружи он выглядит как успех.

Поэтому порядок работ вышел обратный ожидаемому: сначала развести механику и язык, только потом переводить текст. Если сделать наоборот, получится игра, которая убедительно говорит по-английски и втихую не работает.

Разводили так: у каждого предмета появился латинский идентификатор, у каждого класса и состояния — латинский ключ. Название стало тем, чем и должно быть, — способом это показать человеку. Мастер по-прежнему читает и пишет слова, но сходится всё по ключам, поэтому переведённый каталог продолжает подчиняться своим правилам.

Заодно проверили старое решение

Пятью днями раньше мы решили, что описания в схеме, по которой Мастер отвечает, должны быть русскими: с английской схемой в русский текст лезли калькированные обороты. Из этого следовало, что каждый новый язык — это ещё одна копия схемы и системного промпта, навсегда.

Решили перемерить, прежде чем платить эту цену третий раз. Двенадцать живых прогонов, два языка, две модели, разная доля английского в инструкциях — и слепая оценка: сначала носитель языка, отдельно от него вторая модель.

Старое решение не подтвердилось. Английская схема с коротким блоком про язык даёт нормальный русский и украинский. Похоже, тогда помогло не то, что описания перевели, а две другие правки, которые уехали в том же изменении.

Так что дерево инструкций теперь одно, английское, а на язык пишется блок примерно на 1800 знаков — вместо переведённого промпта на 11 885 знаков и 13 554 знаков описаний. Экономия не в деньгах: английская схема длиннее в знаках и дешевле в токенах (36 015 знаков против 35 277, но 15 393 токена против 15 699). Про такие вещи нельзя рассуждать по длине текста — только мерить.

А потом мы открыли три языка, и тесты этого не заметили

Дальше честная часть. Мы включили английский и украинский, 1249 тестов были зелёными, и в первый же день нашлось вот что.

Стартовый набор класса приезжал на экран создания героя на русском, а магазин рядом с ним — на выбранном языке. Экран сводит одно с другим по названию, поэтому не сошлось ни разу: 17 строк из 17 в английской партии. Снаряжение выглядело неснаряжённым, деньги — нетронутыми.

Придуманный Мастером шлем в английской партии уезжал в слот корпуса. Шлем определялся по списку русских слов, который на сервере давно стал трёхъязычным, а в браузере остался русским.

Проиграв бой, герой получал шрам — и в английской партии получал его по-русски. Шрамы не снимаются, так что это остаётся в сохранении навсегда и потом возвращается Мастеру как факт.

Отдельно стоит проверка, которая должна была всё это поймать. Она перечисляла поля, которые смотрит: заголовок, описание, название класса, каталог. Поля, в котором лежала ошибка, в перечислении не было. Проверка была зелёной, стоя вплотную к дефекту.

Что мы поменяли в привычках

Не проверять по списку. Та же проверка теперь обходит весь ответ и ругается на любой русский текст, кроме нескольких заведомо технических полей; новое поле попадает под неё само, без чьей-то памяти. И ловить надо форму, а не алфавит: русский список слов проверка на кириллицу нашла бы, английский — нет, поэтому тест теперь запрещает браузеру вообще смотреть на название предмета.

И самое скучное: заходить в игру и смотреть. Из одиннадцати дефектов ни один не нашёл прогон тестов. Три нашли живые партии, два — взгляд на экран, где рядом оказались три кампании на трёх языках, остальные — обход кода парсером вместо grep.

Украинский текст мы пишем не как носители, и никакая проверка это не поймает: суржик собирается из букв, которые есть в обоих алфавитах. Поэтому качество украинского у нас проверяет человек, и так будет всегда. Если увидите неудачное слово — напишите, это ровно тот случай, когда сообщение от игрока ценнее ещё одного теста.