Содержание
Pong на C, который пересобирает собственный исходный код на каждом кадре, получил Ping Pong Prize на IOCCC29. Автор работы, Jonah Uellenberg, сделал не просто странную версию классики, а почти учебник по тому, как оптимизация кода превращается в обфускацию.
Механика звучит как шутка для людей, которые слишком долго смотрели в make-файлы. Каждый запуск программы печатает новый C-код. Внутри уже зашиты текущий кадр, положение ракеток, мяч и состояние игры. Компилируем этот вывод, запускаем — получаем следующий кадр.
То есть игра не рисует экран обычным циклом. Она каждый раз рождает новую версию самой себя.
Pong работает как модифицированный куайн
Куайн — это программа, которая при запуске печатает собственный исходный код. Версия Uellenberg идет дальше: она печатает не копию, а измененный исходник для следующего состояния игры, поэтому каждый новый бинарник двигает матч на один шаг.
Игрок управляет правой ракеткой через аргумент командной строки: «w» или «e». Против него играет компьютерный соперник. В комплект входит скрипт, который автоматизирует цепочку «скомпилировать — запустить — забрать новый исходник», чтобы матч шел в реальном времени.
После победы над компьютером программа переключается на вторую мини-игру. Это боковой раннер в духе динозавра из Chrome. Если пройти и его, программа возвращает пользователя обратно в Pong.
Обфускацию сгенерировал собственный компилятор Insert
Самый вкусный момент здесь в том, что Uellenberg не писал весь этот хаос руками. Он написал чистый и прокомментированный код на собственном языке Insert, а уже компилятор превратил его в плотный и трудно читаемый C.
В заметках к работе автор прямо формулирует парадокс: «isn’t really obfuscated. It never was». По его словам, конкурсная версия — это результат работы компилятора, а не ручная порча исходников ради красоты.
- Liveness analysis: убирает код и значения, которые больше не нужны.
- Constant folding: заранее сворачивает выражения с константами.
- Variable merging: переиспользует один слот переменной для разных значений.
- C preprocessor defines: упаковывает повторяющиеся последовательности токенов в макросы.
На выходе получается стена из односимвольных идентификаторов и массив данных. В нем смешаны константы и изменяемое состояние игры. Для человека это выглядит как классическая обфускация. Для компилятора — просто экономия байтов и агрессивная чистка.
И вот тут IOCCC снова попадает в нерв. Конкурс с 1984 года награждает странный, изобретательный и нарочно неудобочитаемый C. Но в этой работе неудобочитаемость выросла из нормальной инженерной логики.
IOCCC вернулся после паузы и сразу получил «проклятый» Pong
IOCCC29 стал вторым конкурсом после четырехлетней паузы с 2020 по 2024 год. Работы сезона 2025 организаторы показали 6 июня 2026 года, а затем выложили исходники в репозиторий конкурса.
Uellenberg получил именно Ping Pong Prize. В той же подборке Yusuke Endoh взял три награды. Uellenberg отдельно упоминает его самопереписывающиеся куайны как причину, по которой сам начал заниматься такими программами.
Судьи не удержались от просьбы к участникам следующего года. Они попросили не строить «Quine Doom» для IOCCC30. Шутка понятная: после Pong, x86-эмулятора на чистом CSS и Doom на чистом SQL планка абсурда уже опасно близко к продакшену.
Конкурс ведет Landon Curt Noll, а работы публикуют под лицензией Creative Commons. Организаторы планируют открыть IOCCC30 ближе к концу 2026 года.