Сказ про то, как American Chopper сам восстановился

А я вот вчера вечером решил поностальгировать и поставил себе на домашний комп American Chopper. Не, на самом деле, конечно, я хотел кое что в нем посмотреть, но будем считать это простой ностальгией. Проект уже старенький, 5 лет прошло, к тому же он (сейчас это уже хорошо видно) цинично спортирован с PS2 версии с самыми минимальными переделками. Но речь сейчас не об этом.

В Крейтовском коде еще с прошлого века существовал блок функций SetIdle()/ClearIdle()/IsIdle(). Эти функции предназначены для работы с режимом паузы. SetIdle() увеличивает счетчик паузы, ClearIdle() – уменьшает. Если счетсик равен 0, игра находится в рабочем состоянии. Если > 0, игра находится в режиме паузы. Внутриигровое меню, например, на конструкторе ставит режим паузы, на деструкторе ее снимает. Железобетонно? Вроде как да.

Тем не менее, одновременно с этими функциями был сделан следующий код в момент начала загрузки каждого нового уровня:

if (m_idleCounter > 0)
{
Warning("Resetting pause mode");
m_idleCounter = 0;
}

Так вот. Играю я вчера в American Chopper, врезаюсь в очередную машину, меня в воздухе ловит камера, ставит паузу, показывает со всех сторон, я прерываю этот скрипт Enter’ом, и происходит чудо. Впервые за все время разработки в Крейте, за все время локализации в 1С (я заканчивал проект, уже работая тут), игровой скрипт не снимает режим паузы при прерывании показа. То есть скрипт отработал, а я лежу себе на дороге такой красивый загораю, а посадить себя в мотоцикл и поехать дальше не могу.

Впрочем, работает внутриигровое меню, я перезагружаю уровень, и несмотря на то, что в протокол ушло “Resetting pause mode”, следующий уровень начал играть нормально. Больше мне ни разу не удалось вызватьтакое поведение скрипта, я даже предположить не могу, с чем было связано такое поведение. Возможно, с быстрым 4-х ядерным процессором. Возможно, я попал Enter’ом в какую-то наносекунду, куда не мог попасть раньше. А возможно, скрипт также фатально прервал свою работу, потому что что-то случилось где-то еще в программе. Но самое главное, что программа восстановилась после такого сбоя и позволила пользователю продолжать работать дальше.

На самом деле здесь неработоспоосбность программы и ее восстановление являются визуально очевидными. Однако в вашем коде бывает огромное количество мест, когда наступившее рассогласование с реальностью проявится сильно позже, либо проявляется только на определенной конфигурации компьютера.

Я в следующей статье покажу, каким образом выражение вида
int a = 0;
...
a = 0; // на всякий случай

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

Мораль: если у вас есть переменная int alwaysZeroValue = 0; то иногда она будет ненулевой.

  • http://www.microsoft.com CEMEH

    К сожалению, шансы что он действительно после этого восстановится хрен оценишь.
    Что вся игра будет работать в совершенно необъяснимой ситуации, которая никогда не тестировалась – всегда чудеса.
    Дуновение ветерка на всем пути взаимодействий, хоть как-то связанных с этой alwaysZeroValue и привет.

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

  • dDIMA

    На самом деле действительно повышается. Как именно – расскажу сегодня вечером или завтра :)
    Я тут скорее удивился не тому, что программа заработает после перезагрузки уровня, а тому, что эту багу я увидел вчера впервые с момента начала работы над AC.

  • kasym

    Насчет первой половины поста:
    - разработчикам (программисты и тестеры) удобнее всего, когда ошибки воспроизводятся каждый раз, на каждом компьютере и при любых условиях;
    - а пользователям совсем наоборот, лучше, когда ошибки случаются раз в год непонятно почему, потому что если она случилась — просто загрузил сохранение и играешь себе дальше.

    А насчет второй – ну бля, да, я заинтригован :)

  • look4awhile

    GC уже накрылся, а корабль ещё плывёт

  • dDIMA

    :)