ICFPC 2020: день третий
Это четвёртая часть моей серии отчётов об ICFPC 2020. Остальные части ищите здесь:
- предисловие;
- день первый;
- день второй;
- день третий (это то, что вы сейчас читаете);
- день четвёртый;
- итоги и выводы.
19-е июля, воскресенье, Z-30:17. Обратно в бой!
Перечитывая с утра командный чатик, обнаруживаю, что pink-snow написал ещё одну «вычислялку», в этот раз на Haskell. Она полностью следует псевдокоду организаторов и, что самое важное, работает. Теперь portnov и pink-snow выделяют её в отдельное приложение, а ForNeVeR модифицирует свой проект на C#, чтобы GUI при каждом клике вызывал Haskell и рисовал результат.
unclechu тем временем закончил работу над демодулятором и ушёл спать. Соперники заваливают Дискорд картинками из игры, и страсти накаляются: нам уже совсем-совсем пора добраться до туториалов, которые многие команды прошли ещё вчера.
В Z-30:17 ForNeVeR наконец получает первую картинку:
Пообедав, он выкатывает новую версию GUI с масштабированием, и я отправляюсь исследовать Галактику — в смысле, galaxy.txt. После нескольких кликов по иконке галактики идёт десяток экранов, где нужно кликать в пересечение горизонтальной и вертикальной линий — некая калибровка. А потом отображается та самая картинка, которую недавно показали нам организаторы:
У некоторых рас есть «игры», и я погружаюсь в угадывание правил одной из них; portnov и Akon32, похоже, увлечены тем же самым. Один из только что проснувшихся сокомандников недоумевает:
<xxx> теперь у нас приложение на шарпе, а не на х-ле или питоне?
<yyy> Шарповый фронтенд с хаскельным бэкендом
<zzz> Да, планируем каждые восемь часов переписывать.
ForNeVeR и mr146 заняты улучшением GUI, а pink-snow помогает им, впиливая в «вычислялку» поддерживающие фичи.
Я тем временем делаю первые успехи в игре, где сверху показано инопланетное число, а внизу нужно собрать некий шаблон на поле 3×3 пикселя. При нажатии на любую клетку шаблона её цвет меняется с зелёного на оранжевый, при этом какая-нибудь другая клетка шаблона становится чёрной. При удачно подобранном шаблоне число вверху поля уменьшается, и поле снова заполняется зелёным.
Решения первых уровней похожи на разные повороты и отражения «глайдера» из игры «Жизнь» Конвея. Следующие уровни решаются каким-то странным шаблоном, уже не похожим на «Жизнь». Чатик тем временем подгоняет:
<xxx> первые четыре уровня прошли, осталось ещё 8 или 9
<yyy> из туториала в игре? <_<
<zzz> нет :(
<zzz> В игру мы пока не залогинились
<xxx> да, тут капча
<xxx> инопланетная
<yyy> её нужно прокликать
<xxx> yyy: я так и делаю!
Из-за каких-то изменений в GUI и «вычислялке» появляется забавный баг: если дважды быстро кликнуть в GUI, то второй клик не будет проигнорирован. Вместо этого он будет применён после первого и, возможно, как-то повлияет на состояние игры. Мне флегматично советуют не кликать так быстро. Люблю нашу команду, такие отзывчивые люди, ух! ^_^
Тут mr146 подвозит в GUI возможность сохранять, загружать и править состояние вселенной, и играть становится совсем удобно: больше не нужно «прокликивать» экраны калибровки, а в случае ошибки в игре можно откатиться на предыдущий ход.
Z-24:00. Мы снова вспоминаем про IngvarJackal-а
Так и не решив девятый уровень, я ухожу обедать. Вернувшись, обнаруживаю, что организаторы опубликовали описание команд, которые нужно слать по HTTP для управления космическим кораблём. Тут я снова вспоминаю про IngvarJackal-а, который последние сутки в одиночку удерживает нас в районе 20-го места лидерборда.
Лидерборд в этом году формировался необычно: сутки, оставшиеся до конца соревнования, были разделены на несколько этапов. Очки за каждый этап суммировались и формировали итоговый рейтинг команды. Таким образом, нам нужно было уже сейчас зарабатывать баллы; выкатить решение в последний момент и попасть в середину рейтинга было бы практически невозможно. Поэтому я бросаю решать загадки galaxy.txt и присоединяюсь к IngvarJackal-у.
Игра на орбите происходит следующим образом: два корабля оказываются рядом с планетой. Один из них нападает, второй защищается. Игра длится 256 ходов (позже лимит подняли до 384-х). Задача атакующего — сбить защитника. Защитник, в свою очередь, просто пытается пережить нападение.
Сразу же после старта игры корабли начинают падать на планету, поэтому IngvarJackal первым делом научился поддерживать круговую орбиту. Это требовало постоянных затрат топлива, но, по крайней мере, давало нашему кораблю пожить хотя бы сотню ходов. Теперь IngvarJackal ставил эксперименты, пытаясь выяснить, как именно в этом мире устроена гравитация.
Я же взялся за пушки. Все корабли оборудованы лазерами, которые мгновенно поражают цели на любом расстоянии. Нужно заметить, что организаторы описали команду для выстрелов, но не объяснили, как именно выстрелы действуют на противника. По всей видимости, узнать это можно было только из туториалов, до которых мы всё никак не могли добраться.
Команда выстрела требует трёх параметров: идентификатора стреляющего корабля, координат цели, и ещё какого-то неизвестного параметра. В визуализаторе, предоставленном организаторами, было видно, что после координат идут три числа, а не один параметр.
Я принялся за эксперименты, и чего только не попробовал:
стрелять не по прогнозируемым координатам противника, а и в ближайшие точки — на случай, если команда выстрела принимается только при попадании. Это не подтвердилось: по логу моего бота и по визуализации боя я видел, что сгенерировал ровно те координаты, в которых оказался противник, но выстрела не происходило;
поменять начальные параметры корабля (для которых не было документации, но мы догадывались, что первый параметр из четырёх — это количество топлива);
не стрелять на первом ходу, потому что это постоянно заканчивалось ошибкой;
передавать в последнем параметре не одно число, а список из трёх (потому что именно столько показывал визуализатор от организаторов);
вместо последнего параметра передавать три числа, которые я видел в визуализаторе организаторов.
Всё эти эксперименты закончились одинаково — ошибкой.
У остальных членов команды дела тоже шли с переменным успехом:
- pink-snow добавил какую-то обвязку для HTTP API;
- ForNeVeR, замучившись отлаживать (де)модулятор, посоветовал портировать тесты из Python на Haskell и отправился спать;
- portnov добавил в «вычислялку»
send
и даже добрался до какого-то из туториалов; - unclechu, добавив каркас для сабмишенов на Haskell, тоже уснул;
- у mr146 возник какой-то форс-мажор, и он отвалился до конца соревнования.
Спустя почти шесть часов возни с командой выстрела мы с IngvarJackal наконец решили проверить алгоритм модуляции — и обнаружили, что команды кодируются неправильно! Мы должны передавать список команд, где каждая команда кодируется отдельным списком, но получается какая-то ерунда:
-- так должно быть
4, 14, [[0, 1, [-1, 0]], [2, 1, [-16, -48], 4]]]
[-- так кодируем
4, 14, [[0, 1, [-1, 0]], 2, 1, [-16, -48], 4] ] [
То есть второй элемент списка не добавляется в него, а конкатенируется с ним. При этом демодуляция неправильной кодировки возвращает правильный, исходный список! IngvarJackal писал демодулятор, но ничего не может подсказать по модулятору. portnov, писавший модулятор, делал это по коду mr146. В общем, бардак. portnov уходит спать, а я закатываю рукава и погружаюсь в науку о преобразовании «космолиспа» в нолики и единички…
Какой баг я найду? Успеем ли мы хоть чего-то достичь за последние 16 с лишним часов? Читайте в отчёте о последнем дне соревнования ;)
Your thoughts are welcome by email
(here’s why my blog doesn’t have a comments form)