Записано по байкам знакомого. Как человек, от программных материй далекий, не могу поручиться ни за правдивость, ни за точность, ни даже за правильность изложения. Но могу поручиться, что забавно)

Где-то в далеких 90-ых, группа энтузиастов-программистов делала игрушку — приключения героя в вампирском замке. Делали на достаточно примитивных возможностях, и в итоге так и не доделали, но работа шла довольно долго и даже с некоторой продуктивностью. И все бы было хорошо, но тут появилось оно.
Зеркало.
Огромное такое зеркало во всю стену, которое висело в холле замка. Программисты недовольно ворчали – мол, зачем оно вампирам, они ж не отражаются – но, поворчав, все же согласились…
Поскольку это были 90-ые, то создавать зеркала в видеоиграх приходилось дедовским методом: неразрушимая прозрачная стена, по ту сторону которой точно такая же комната. Когда игрок входил в холл, по ту сторону зеркала немедленно генерировалась его точная копия, повторяющая все его движения. Тяжело, занудно, объемно, но работало. А в данной ситуации даже и хорошо: поскольку вампиры в зеркале отражаться не должны, то и можно было ограничиться одной лишь копией игрока. Выходило атмосферно и даже где-то изящно.
ЗАЗЕРКАЛЬНЫЙ ВОР
Как уже упоминалось выше, зазеркальное отражение было точной копией персонажа игрока. И воспроизводило его со всеми переменными. Благо, перменных-то было не очень много: несколько видов доспеха, отличавшихся в основном цветом, и оружие в руках. Поэтому при генерации зазеркальной копии, игра просто выдавала ей такое же оружие и снаряжение, что и игроку.
И тут возникла проблема.
Некоторое оружие и снаряжение в игре были уникальными, существующими в единственном экземпляре. Игра вела учет положению такого вот снаряжения, и если игрок терял или бросал его, оно оставалось на прежнем месте.
Когда персонаж, несущий уникальное снаряжение, входил в зеркальный холл, игра, естественно, пыталась выдать такое же снаряжение его отражению. И тут возникало противоречие: уникальный объект в двух местах одновременно.
В лучшем случае, игра делала попытку вручить зазеркальной копии уникальное оружие, наталкивалась на наличие его в другом месте, не могла завершить процедуру, и крэшилась.
В худшем случае, игра вручала-таки зазеркальной копии уникальное оружие, затем проверяла его положение, и затирала старое. То есть отбирала уникальный предмет у игрока, и отдавала копии. И извлечь объект из зазеркалья не было уже никакой возможности.
После долгих мучений, проблему решили, создав копии каждого уникального предмета в игре, и всучив их зазеркальному двойнику. Теперь при генерации двойника, игра сначала проверяла наличие у игрока уникальных предметов, и вызывала их копии. Правда, периодически игра все равно путала где что находится, и у персонажа оказывалась копия (FLAMINGSWORDCOPY, например), но разработчики предусмотрительно сделали копии в точности соответствующими оригиналам.
АГРЕССИВНОЕ ЗАЗЕРКАЛЬЕ
Зазеркальный двойник игрока по сути своей был обычным монстром. Только уникальным, и с отключенной моделью поведения — ее заменили повторением действий игрока.
И тут возникла проблема. Время от времени, без всякой внятной причины, зазеркальный двойник озверевал и начинал проявлять агрессивность — пытался приблизиться к игроку, палил из оружия в зеркало, и всячески демонстрировал, как он свой оригинал не любит.
Расследование необычной агрессивности доппельгрангера выявило следующее: движения монстра в игре не соответствовали полностью движениям управляемого игроком персонажа. Близко, но не совсем. Из-за этого зазеркальная копия иногда оказывалась в ситуации, когда она просто не в состоянии полностью повторить действия персонажа. Например, если игрок персонаж вставал слишком близко к столу, то его зазеркальная копия могла оказаться в положении, когда для этого ей потребовалось бы пройти внутрь стола.
Столкнувшись с таким сбоем, программа повторения действий игрока зацикливалась и останавливалась. И поскольку свято место пусто не бывает — на ее место подключался «обычный» набор действий для монстра. Зазеркальный двойник внезапно обнаруживал, что он может двигаться, что он очень не любит игрока, и должен пытаться его убить.
Неоднократые попытки решить проблему застревания в мебели ни к чему не привели. Переделывать модели персонажей и монстров было слишком затратно. Поэтому проблему решили, переведя двойника в категорию «нейтральных» существ, которые не трогали игрока, пока сами не будут атакованы. Например, какая-нибудь корова игрока не атакует до тех пор, пока игрок сам не атакует ее, или другую корову из того же стада (той же суб-категории)
И все стало еще хуже.
С нововведением, агрессивность двойника возросла многократно. Немедленно после генерации, он бросался к зеркалу, и начинал яростно стрелять по персонажу. Все попытки выяснить причину такой предубежденности проваливались раз за разом. Код двойника перебрали буквально по букве, никакой ошибки не нашли, и уже готовились впасть в отчаяние, когда, наконец (совершенно случайно) правда не всплыла на свет.
Оказалось, что все дело было в суб-категориях, деливших нейтралы на группы. В своей субкатегории, двойник должен был быть одним-единственным. Но из-за небольшой ошибки, его «напарниками» по субкатегории оказались... разрушаемые чучела-мишени на стрельбище в начале игры. Атаки на мишени в начале игры настраивали против игрока всю суб-категорию, и к моменту появления зазеркального двойника, тот уже пылал мстительной яростью и мечтал поквитаться за невинно погубленных соломенных братьев. А поскольку ошибка была в мишенях, то, естественно, никакое исследование кода двойника ее не выявляло...
Эту ошибку удалось исправить легко, но вскоре нашлась еще одна: некоторые виды атак (проклятия и т.д.) действовали на всех в пределах видимости, и задевали и двойника. Который после этого терял свой «нейтралитет» и рьяно выступал против обидчика из-за прозрачной стены. Но так как проклятия были в игре вещью редкой, то программисты просто махнули на это рукой, и решили выдать баг за фичу: каждый раз, когда нейтральность двойника нарушалась, игра выводила сообщение «ПОХОЖЕ, ЭТО НЕ ПРОСТО ЗЕРКАЛО...»
ЗАЗЕРКАЛЬНАЯ ГЕОМЕТРИЯ
Как уже упоминалось ранее, зеркало в игру ввели не сразу, а уже на достаточно продвинутой стадии разработки. Естественно, это означало, что зазеркальный холл пришлось впихивать в уже частично готовый этаж замка. И, естественно, вышло это не больно-то удачно — попробуйте-ка в средневековом замке изыскать место под еще один зал, при этом не убирая других комнат!
В результате впихиваний и ужиманий, этаж замка разбух и растолстел, и весьма слабо соотносился с тем, как замок смотрится снаружи. Но это было еще мелочью. Настоящей проблемой оказалось то, что зазеркальный холл не везде удалось упихать правильно, и в некоторых местах он пересекался с другими комнатами. Пересечения, впрочем, были мелкие, провалиться сквозь них в зазеркалье было невозможно, и разработчики сочли, что особых проблем они не создадут.
К сожалению, координатную систему они об этом предупредить забыли.
В результате, в помещениях вокруг зазеркального зала, начали твориться странные (даже по меркам вампирского замка) дела. Торчащие (и невидимые) углы зазеркалья приводили к тому, что одни координаты накладывались на другие. И из-за этого геометрия замка перестала быть евклидовой, а его обитатели массово спятили с ума.
В деталях, все это выглядело примерно так: монстр-вампир видел персонажа, и начинал двигаться к нему. Программа приступала к просчету оптимального — кратчайшего - пути вампира, и в какой-то точке натыкалась на двойные, накладывающиеся координаты, согласно которым вампир должен был оказаться в комнате на другом конце замка. Такой путь явно не был оптимальным, программа пыталась изыскать новый, но поскольку вампир уже довольно слабо понимал, где он находится, результаты... как правило удручали. А то и пугали.
Некоторые вампиры начинали, забыв про персонажа, бешено бегать кругами, уставившись в одну точку. Другие, видя персонажа в двух шагах, разворачивались и выбегали из комнаты, оббегали по кругу весь этаж (пытаясь обогнуть зазеркальный зал в центре) и вбегали с противоположной стороны. Некоторые вообще решали, что находятся в зазеркалье, и пытались двигаться, строя маршрут по зазеркальному залу — бегать по несуществующим лестницам, огибать несуществующую мебель. Стрельба персонажа по вампирам выглядела не лучше — пули и стрелы выписывали странные траектории, кружились в воздухе, вылетали из комнаты.
В отчаянной попытке решить проблему, программисты не нашли ничего лучшего, как «заткнуть» точки пересечения координат различными непроходимыми препятствиями. Комнаты и коридоры вампирского замка заполонились стоящими в произвольных местах колоннами, шкафами, вазами с цветами и фонтанами. Такое решение хоть и не устранило проблему вампирского сумасшествия, но свело ее к допустимому минимуму...
no subject
Date: 2021-11-27 06:30 pm (UTC)Программировать и управлять государством, как известно, все умеют. Кроме программистов.
no subject
Date: 2021-11-28 06:13 am (UTC)no subject
Date: 2021-11-28 09:29 am (UTC)А если в зеркале отражается другое зеркало? А если два зеркала с переотражениями в третьем? А есл икривое зеркало отражается? А если часть объектов не должна отражаться? А если должна, но с незначительным преломлением или поглощением? А если неотражаемые объекты вдруг становятся отражаемыми — вампиру клык выбили или носовой платок потерял? А если объект частично отражаемый: вампир губы накрасил — помаду отражать? А пончик скушал — отражать? А пончик переварил — отражать? А кошку на его плече отражать — плывет себе скотинка в воздухе, да? А бездыханный труп вампира? А его одежда? А почему у вампира одежда неотражаема, а у человека-невидимки отражаема — сценарист точно решил? Не передумает?
Количество таких ситуаций бесконечно. Учесть их все невозможно, а потому бессмысленно.
Вы не туда посмотрели, проблема не в зеркале. Проблема (разработки) в том, что зеркало или другая фубля появляются неожиданно, в момент, когда к нему, зеркалу, никто не готов. Не закладывали возможность фубли в начальные планы. Или фубля настолько заковыриста, что имеющимся инструментарием ее не осилить. Или фубля требует масштабной переделки того, что уже сделано, а ресурсов на это нема — "ты как-нибудь выкрутись там, ты ж программист".
И переделки в лучшем случае оборачиваются анекдотом и бессонными ночами разработчиков. Сделать-то можно всё, даже к Альфа Центавра слетать. Но в реальности вопрос упирается не в абстрактное "можно", а в деньги и время, которое тоже деньги.
Главные враги по критерию время-деньги — это простые как армейский сапог заказчики и небитые жизнью программеры из породы "можно". Первые — абсолютное зло, чуть-чуть минимизируется только долгими и унылыми пытками на этапе ТЗ. Крепкие нервы нужны, чтобы в ответ на "заколебал ты, сделай как у ХХХ, чего проще?" не послать дятла, а допытать его и заставить подписать бумагу. Вторые — со временем вымрут, когда автоматизация разработки дойдет хотя бы до уровня нынешних CAD/CAM инженерных систем (САПР по-русски). Пока самый навороченный Visual Studio с прибамбасами даже рядом не стоял... хотя бы возле Fusion360, который простонародный, а не супер-профи.
no subject
Date: 2021-11-28 10:52 am (UTC)это всё бред, с точки зрения и ТЗ данного разрабам. более того в байке самой бред, ибо задача разрабам была тривиальная, даже со скидкой на очень старые движки типа билда (Build).
>Вы не туда посмотрели, проблема не в зеркале. Проблема (разработки) в том, что зеркало или другая фигня появляются неожиданно
такое происходит, но в игрушках в старые времена просто или рубили всё, что затягивалось, или затягивали донельзя, а в новые у уровня двадцать вариантов дизайна, которые обсуждаются до достижения одного и закрепляются, и ничего неожиданного не возникает.
сравнить же кады и написание кода, ну ок, интересное сравнение. как и все сравнения ложное.
ну и самая главная проблема конкретной байки — в том что она байка, а реальные проблемы разработки куда тоньше и сложнее ловятся.