18го ноября, в ГФМЛ №30 (Губернаторский Физико-Математический Лицей №30, он же 30ка, он же тридцатка) на дне наук, я, Саша, CGSG, при поддержки Yandex Cloud провели игровой хакатон для школьников.

Задачей ребят было за 2 часа написать бота для змейки на Lua. Они писали и отправляли стратегии, а в фоне постоянно шли матчи, в которых их стратегии и принимали участие.

Через 2 часа рейтинг сбросился, для каждой команды был взят последний отправленный алгоритм, и в финальной пачке матчей определился победитель.

Участники могли смотреть повторы матчей
Участники могли смотреть повторы матчей

И тут я хочу поделиться внутренней кухней. Как все это было приготовлено, с какими проблемами столкнулись, какие ошибки допустили, а что вышло хорошо. Будет много картинок, фоток и даже пару видео, надеюсь не переборщил)

С чего всё началось

Идея провести хакатон в школе появилась около года назад. Тогда мы потратили уйму времени на придумывание форматов разной степени извращенности. Варианты были от CTF до написания майнкрафт ботов. В итоге эти рассуждения ни к чему особо не привели.

В этом году у меня появилось навязчивое желание реализовать какой нибудь пет проект, который ну точно завершится (а пет проекты таким могут похвастаться не часто). Хакатон в школе - идеальный кандидат. С Сашей мы отправились к нашему школьному учителю информатики - Виталию Александровичу Галинскому, идею он принял с радостью и предложил провести ивент на дне наук.
Это круто избавило нас от задачи поиска участников - мы даже заранее представляли их количество - ~20 команд ~40 человек.

Откуда же появилась идея провести хакатон по написанию скриптов для змейки? На самом деле такая идея всплывала и год назад. Я вообще фанат примитивных клеточных игр (моя онлайн змейка) и совсем не против в 10й раз реализовать очередную game of life или змейку. Но именно этой осенью произошло ещё кое что интересное. В универе я хожу на курс по Rust от ШАДа. На одной из домашек мы писали ботов для paperio. И когда я с заданием справился, я понял, что затея то реально веселая и рабочая, и хакатона вполне заслуживает. А с тем, что змейка - лучший кандидат на баланс фана и сложности - думаю многие согласятся (для школьников паперио было бы все таки чересчур).

Paperio - персонажи захватывают территории, очерчивая их
Paperio - персонажи захватывают территории, очерчивая их

Я пошёл в Yandex Cloud (я тут работаю) с предложением нас проспонсировать. Пройдя не очень большую цепочку "кинь меня в твоего знакомого, близкого к данной теме", я дошёл до нашего деврела - Насти Масловой, и облако в её лице поддержало нас с удовольствием) Никакой бюрократии, мы просто обсудили формат, количество человек, количество и способ определения победителей, а затем выбрали призы, которые должны были зайти школьникам. От меня оставалось только принять посылку в офисе. Огромное спасибо Насте, без неё этого бы не случилось!

Нам дали стикеры для всех и призы для победителей
Нам дали стикеры для всех и призы для победителей
Шикарный имаджинариум был одним из призов
Шикарный имаджинариум был одним из призов

Правила игры

  • Съеденные яблочки дают длину - всё по классике.

  • На поле сразу несколько змеек, в противников можно врезаться.

  • Игра идёт до момента гибели всех, но ограниченна 1000 тиками.

  • Внутри матча +1 очко за каждое яблоко, +5 за убийство.

  • Глобальный рейтинг - среднее количество очков по всем матчам.

Что же сделали мы?

Дальше много технических деталей, весьма интересных, но можете скипнуть, пролистав до "Ещё немного про подготовку".

Скелет таков:

Сервер на Go (~85% кода написанного человеко). Для себя открыл huma, достойный аналог fastapi для go.

Фронт на react+vite (~5% кода написанного человеком) - Да, за это слегка стыдно, но фронт писать мы не умельцы, да и времени немного. Под конец фичи добавлялись через боль (даже что-то приходилось писать руками!). Дальше эта штука не особо расширяема. За начальный шаблон и укрощение агента спасибо Сане - без него эта штука бы развалилась не доехав до финиша.

Сайт выглядил прикольно, спасибо за Мите за идею стиля retroui
Сайт выглядил прикольно, спасибо за Мите за идею стиля retroui

Lua в качестве языка для ботов я выбрал без раздумий, давно хотел с ним поиграться. Язык очень красивый своей простотою. Считается супер встраиваемым, и инструментов под него написано немало. Есть gopher-lua на 6.8к звёзд, go-lua на 3.4к - это всё интерпретаторы Lua на Go.
То есть прямо внутри go кода можно выполнить код lua из условной строчки, ничего не компилируя и не плодя лишних процессов. Но не всё так гладко, как выяснилось позже...

Бета тесты и lua

За полторы недели до дня X мы решили провести бета тест среди своих знакомых. Набралось аж 15 человек. Был вечер субботы и все согласились, что думать лень и код будет писать ии. Главное было - протестировать нагрузку.

Во первых, бета тест выявил проблему - 1.5 часа невероятно мало. К счастью, после моей эмоциональной аргументации, нам увеличили время до 2.5 часов.

А вот про "во вторых" так кратко и не рассказать...

Немного про ограничения: скрипт должен выполняться не более 100 секунд суммарно за все тики (игра длилась максимум 1000 тиков). Получается, чтобы каждая команда участвовала в каком то матче раз в 2 минуты, ядер на сервере нужно столько же, сколько команд!

Время я ограничил без особого труда, но забыл про кое что ещё.
И один товарищ (спасибо ему большое) на бета тесте написал бесконечно растущий массив. Вся оперативная память машинки (а на тот момент это было 48гигов) - забилась.

Сервер убивает оперативку
Сервер убивает оперативку

Немало времени я потратил на решение задачи ограничения памяти... В канонической реализации Lua (на C) - такая возможность есть. Но ни в gopher-lua, ни в go-lua её не было. Теоретически можно было написать запуск скриптов на C, а потом использовать в Go через CGO, но к счастью до этого не дошло...

Нашёлся новый покемон - golua, киллер фичёй которого и была возможность ограничить и время и память. Звёзд на гитхабе было уже не так много, всего 100 штук, но интерпретатор проходил официальные тесты lua, и казалось бы - бояться нечего...

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

ошибки превышения ограничений
ошибки превышения ограничений

За дня три до хака я делал песочницу. В ней участники могли просимулировать матч прямо на сайте. Для этого go компилировался в wasm - бинарный формат, который может исполняться прямо в браузере. И тут всплыла проблема - новый интерпретатор lua отказывался компилироваться в wasm, так как имел системные зависимости. Интерпретатор пришлось форкнуть, чтобы это пофиксить. Но issue я завёл, и автор исправил ошибку.

А вот так выглядит песочница.

А за два дня до хака я решил пописать примеров кода на lua, чтобы добавить их в документацию. Тестировать в песочнице было просто и кайфово. И тут я наткнулся на реальную проблему - при определённых ключах в объекте lua итерация по этим ключам длилась бесконечно! Не без труда проблема была устранена, форк у меня уже был :) А после хака я разумеется сделал PR. Оказывается даже официальные тесты lua не гарантируют полную работоспособность...
И скрипты того товарища начали работать, спасибо Егору за лучшее тестирование!

Ещё немного про подготовку

Отдельно внимание стоит уделить GGSG и его бойцам. CGSG - Computer Graphics Support Group, кружок в 30ке, который существует уже больше 30 лет. Под руководством Виталия Александровича ребята делают невероятные проекты, связанные с компьютерной графикой. От собственного рейтрейсинга до софта для 3д очков, и всё это на C++, на собственных движках и собственной графике. Они сделали нам шикарную 3д визуализацию, и во время соревнования на большом экране (даже на двух!) транслировались последние матчи.

3д визуализация
3д визуализация
На большом экране
На большом экране

А за неделю до хакатона мы развесили вот такие плакаты. Язык был засекречен, нам это показалось интересной задумкой.

Плакаты, которые мы развесели в школе
Плакаты, которые мы развесели в школе

День Х (акатон)

Итак, 18 ноября мы провели хакатон. И что сказать? Это было не идеально, но это было отлично! Где то посередине сервер упал на 5 минут (nil dereference, который магическим образом не всплыл за часы тестов), но проблема быстро решилась.

Хакатон идёт, на переднем плане пилотская рубка
Хакатон идёт, на переднем плане пилотская рубка

Начнем с того, что стоило сделать по другому:

Большинство согласились с тем, что времени мало. На самом деле это радует, потому что доказывает, что ребята готовы кодить на протяжении длительного времени, а это позволяет давать более интересные задачи.

Обратная связь
Обратная связь

Засекречивать язык было ошибкой. Да, Lua простой, и похож на Python, который знало большинство (в документации были сравнения именно с ним). Но минут 40 на вникание ушло точно. А при двух часах на код - это критически много.

Постарались над докой
Постарались над докой

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

А что же прошло хорошо?

Да в общем самое главное: Все остались довольны! Большинство смогли написать стратегию победившую всех ботов. Отмечали красоту 3д визуализации и удобство сайта. Да и впринципе сказали, что учавствовать им понравилось!

Победители победили заслуженно, им действительно удалось написать достойную стратегию за отведённое время.

Немного из формы обратной связи:

Несмотря на то, что объяснения многие идеальными не посчитали, с задачей разобрались
Несмотря на то, что объяснения многие идеальными не посчитали, с задачей разобрались
Цифры, которые радуют
Цифры, которые радуют
И ещё немного хвастовства
И ещё немного хвастовства

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

Стоим с победителями, я слева, Саша справа
Стоим с победителями, я слева, Саша справа

Надеюсь в будущем мне ещё удастся поорганизовывать подобные мероприятия :)

Спасибо всем тем, без кого это бы не произошло!

Саше за укрощение ИИ и за то, что фронт не развалился впринципе. Ну и за совместную организацию разумеется.
Виталию Александровичу и бойцам CGSG - Саше и Тимофею за 3д визуал.
Вике за дизайн плакатов.
Yandex Cloud: команде HR-бренда, а также Оле за спонсирование мерчом и призами. Насте за то что помогла со всем разобраться. И облаку за машинку, на которой бежал сервер.
Паше Хохлюку за съёмку и монтаж ролика.
Мите за прототип редактора и идею использовать retroui
Всем 15 тестировщикам!

Да и мне, чего уж там :)

Обещанный клип

Комментарии (2)


  1. MrUssy
    24.11.2025 09:11

    Это было легендарно, Вань!

    Очень рад, что мы все таки справились и смогли организовать все это мероприятие!!


  1. kolzuk
    24.11.2025 09:11

    Лучшие))