Игровой лог перестаёт пересказывать всё подряд
Один бросок кубиков печатал пять строк, две из которых называли одну и ту же клетку. Теперь лента читается как комментарий, а не как протокол, — и ради этого ничего не удалили.
Простыми словами
Панель рядом с доской записывала буквально каждое действие игры. Обычный бросок давал пять отдельных строк — бросил, переместился, попал на клетку, завершил ход и нередко ещё одну, — причём две из них называли одну и ту же клетку. Умножьте это на четырёх игроков и тридцать раундов, и лента превращается в стену, которую перестаёшь читать. Обидно, потому что те две-три строки, которые действительно важны, находились где-то внутри неё.
Теперь бросок и всё, что он повлёк, — одна строка. Попадание на клетку, завершение хода, объявление долга до его оплаты, отказ от покупки перед началом аукциона — всё это больше не проговаривается, потому что об этом уже сообщает сама доска или следующая строка. Серия построек на одном поле сворачивается в одну строку, аукцион без соперников перестаёт называть одну и ту же сумму дважды, а в Скорости отсчёт по закладной подаёт голос лишь тогда, когда на действие остаётся два раунда.
Ваши сообщения в чате тоже больше не выталкиваются за экран. Раньше панель держала одно окно истории на всё сразу, поэтому оживлённая доска могла тихо вытеснить то, что человек написал. Теперь активность и чат хранятся отдельно, и никакое количество кубиков не похоронит реально написанное сообщение.
Для тех, кому интересны детали
Фильтровать в источнике было нельзя в принципе. Воспроизведение партии — это свёртка полного журнала событий обратно в состояние, и именно так работают перезагрузка страницы, режим наблюдателя, экран повтора и генератор роликов. Выбросьте событие ради красоты ленты — и сломаете их все. Поэтому журнал остаётся целым, а сокращение живёт исключительно на уровне отрисовки, в одном общем построителе, которым пользуются живая доска, наблюдатель, повторы, ролики и офлайн-сборка.
То, что каждое событие делает с лентой, — это исчерпывающий переключатель по всем видам событий движка, а значит новый вид событий не соберётся, пока кто-нибудь не решит, как он должен читаться:
// lib/game/feedDigest.ts — an exhaustive switch over every engine event
case 'dice_rolled':
return 'move'; // the roll opens a line
case 'moved':
case 'passed_start':
case 'jail_attempt_failed':
return 'absorb'; // …and what it caused folds into that line
case 'landed': // names the cell 'moved' just named
case 'turn_ended': // the board already shows whose turn it is (14% of events)
case 'payment_due': // the intent; 'debt_paid' is the settlement, with the amount
case 'buy_declined': // always followed by 'auction_started', which says it better
case 'auction_passed':// carries no information, and outnumbers real bids 2:1
return 'hidden';Обнаружились две ошибки, которые не нашёл бы ни один тест, потому что обе — про то, как читается вывод, а не про то, что в нём есть. Аукцион без соперников объявлял одну и ту же сумму дважды («P1 ставит 2600k», затем «P1 забрал за 2600k»), поэтому закрывающая ставка теперь проглатывается — и только она, чтобы настоящая борьба ставок по-прежнему читалась как борьба. А событие, оказавшееся в середине броска, обрывало каждую строку перемещения раньше времени, пока построитель не научили через него переступать.
