Дверь, большой палец и путешествие во времени – история странного бага в Half-Life 2
Спустя более 20 лет после релиза легендарного шутера от первого лица от Valve фанаты продолжают узнавать новые подробности о Half-Life 2. Бывший дизайнер студии Том Форсайт поделился историей о баге, обнаруженном в 2013 году, который, как выяснилось, существовал с самого запуска игры в 2004 году, но проявил себя только спустя девять лет.
В подробном посте в Mastodon Форсайт рассказал, как вместе с программистом Valve Джо Людвигом работал над портированием игры на VR-шлем Oculus Rift. На ранних этапах прохождения дизайнер столкнулся с багом, который запирал дверь и блокировал продвижение по сюжету. Странность ситуации заключалась в том, что никто из разработчиков не помнил этой проблемы в оригинальной версии. Форсайт даже просмотрел видеозаписи вступительной сцены – бага там не было.
О нет. Такое нельзя выпускать. Я позвал других коллег, включая тех, кто изначально работал над HL2, и да – всё сломано. Причем, сломано даже когда вы не в VR – так что это не то, что сломали мы с Джо. Но никто не знает почему – соответствующий код не менялся.
Кто-то из команды Valve поднял историю исходного кода и скомпилировал оригинальную версию игры в том виде, в каком она вышла на релизе. К удивлению всех, баг присутствовал и там. Получалось, что ошибка, впервые обнаруженная в 2013 году, каким-то образом вернулась назад во времени и заразила оригинальные файлы 2004 года.
В первую очередь нужно было исправить баг перед выпуском игры на Oculus Rift, но разработчиков не меньше волновал сам факт путешествия ошибки во времени.
Как такое вообще возможно? На этом этапе люди начинают паниковать – это не обычный баг – похоже, что он путешествовал назад во времени и заразил оригинал!
В конце концов источник проблемы был обнаружен. Охранник, стоявший в недоступной комнате, находился слишком близко к двери. Его палец ноги сталкивался с дверью при открытии и заставлял её захлопнуться обратно. После обнаружения причины исправление оказалось "простым", хотя и потребовало много работы, так как разработчикам пришлось вспоминать, как работают инструменты отладки.
Но главная загадка оставалась нерешённой. Как баг из 2013 года пробрался в девятилетний код? И почему палец солдата не мешал двери открываться в 2004 году и все последующие годы до обнаружения ошибки?
Ответ крылся в "старом добром floating point". Форсайт объяснил техническую сторону вопроса: Half-Life 2 вышла в 2004 году, когда набор инструкций SSE хоть и существовал, но ещё не был повсеместным. Большая часть игры компилировалась с использованием старого набора математических инструкций 8087 или x87, который имел разную точность для разных операций – некоторые 32-битные, некоторые 64-битные, некоторые 80-битные.
Десять лет спустя, в 2013 году, SSE стал стандартом для всех x86 процессоров. Компиляторы по умолчанию использовали именно его, так как старый x87 код работал немного медленнее. SSE использует более определённую точность – либо 32, либо 64 бита в зависимости от запроса кода, что делает расчёты более предсказуемыми.
Именно эта новая точность и создала проблему. В оригинальном x87 коде было ровно столько "трения" в ботинке охранника, чтобы его нога повернулась достаточно для прохождения двери. Но новый SSE имел "множество крошечных точностей", которые были немного другими. Из-за комбинации трения об пол и массы объектов охранник всё ещё поворачивался от столкновения, но теперь поворачивался чуть меньше.
Так что на следующем кадре симуляции его палец всё ещё на пути двери. Двери не разрешено просто пройти сквозь палец, поэтому она делает единственное другое – отскакивает назад. По умолчанию она делает это полностью эластично, так что дверь отскакивает с той же скоростью, с которой открывалась, захлопывается и снова запирается. И вы застряли.
Это означало, что баг существовал в игре всё время. Охранник всегда стоял слишком близко к двери, но старый компилятор использовал другую точность с плавающей точкой, что создавало слегка иную физику. Эта мизерная разница и определяла, откроется критически важная дверь или нет.
И вот вам ответ. Два самых больших источника багов в геймдеве – двери и floating point – объединились, чтобы превратить простой баг размещения NPC в настоящее путешествие во времени.
Разработка игр – ну разве не чудо!?
- Если у вас есть VR-девайс, то вы обязаны сыграть в VR-версию Half-Life 2 – она ощущается совершенно иначе
- Художник Valve рассказал, что видел комнату, в которой разрабатывают Half-Life 3
- В бета-версии Half-Life 2 2003 года обнаружена река Сити-17, которая вела к подножию Цитадели