Инженеры до сих пор не могут понять, как работает эта игра

techcult.ru — В далеком 1982-м для приставки Atari 2600 вышла занимательная игра «Entombed». В силу ограничений самой платформы она представляла собой образец программистской смекалки. Настолько, что современные специалисты по программному обеспечению до сих пор не могут понять, как она работает
Новости, Компьютеры | kielty 13:45 17.06.2020
48 комментариев | 12 за, 26 против |
#1 | 13:51 17.06.2020 | Кому: Всем
Фигня же.. Вотт Elite III - действительно натуральная загадка!
#2 | 13:52 17.06.2020 | Кому: Всем
>Тот просидел над задачей несколько дней и после ее решения на радостях так напился, что только чудом сохранил сам модуль, но вот объяснить его работу уже не мог.

Вотт, он знает толк в программироавании !
Интересно, как можно напрочь забыть решение самим собой же решенной задачи.
#3 | 13:53 17.06.2020 | Кому: Всем
> Настолько, что современные специалисты по программному обеспечению до сих пор не могут понять, как она работает

То - да! Нынешним "хуяк-хуяк-впродакшен"-специалистам оптимизированный код это прямо магия.
#4 | 13:59 17.06.2020 | Кому: Славянин
> Интересно, как можно напрочь забыть решение самим собой же решенной задачи.

Да лехко!
Помогает только реверс - инжиниринг с приведением себя в то же состояние.
#5 | 14:00 17.06.2020 | Кому: Всем
> Некоторые настолько парадоксально просты и в тоже время непонятны, что ставят в тупик даже современных специалистов.

Современных-то особенно.

Помнится, была демка в 3 Кб "Полёт над Марсом".
Vascosoft
интеллектуал »
#6 | 14:03 17.06.2020 | Кому: Всем
В чем проблема разобрать 4кб машинного кода? Люди многомегабайтные прошивки потрошат.
#7 | 14:03 17.06.2020 | Кому: Славянин
> Интересно, как можно напрочь забыть решение самим собой же решенной задачи.

Легко. Открой свои же исходники хотя бы полугодовой давности.
#8 | 14:04 17.06.2020 | Кому: Vascosoft
> В чем проблема разобрать 4кб машинного кода? Люди многомегабайтные прошивки потрошат.

Тогда на чистом асме писали и без всяких общих библиотек, которые можно в автомате сейчас восстановить.
#9 | 14:04 17.06.2020 | Кому: Склеп
> Открой свои же исходники хотя бы полугодовой давности.

Подобное поведение чревато запоем.
#10 | 14:06 17.06.2020 | Кому: Ummon
> > Открой свои же исходники хотя бы полугодовой давности.
> Подобное поведение чревато запоем.

[Меланхолично]
Я знаю...
Джон Ву
Резуноид »
#11 | 14:13 17.06.2020 | Кому: Всем
это всё потому что он нарушил основное правило(скорее всего он его просто не знал) - "напейся в любой непонятной ситуации!" а он напился после.
#12 | 14:13 17.06.2020 | Кому: Всем
> Игрок может перемещаться в четырех направлениях в пределах экрана, но он не может узнать строение лабиринта даже на шаг вперед. Потому что программа сама этого не знает.

Что означает "программа не знает"? Программа вообще никуя не знает. Она делает то, что ей сказано.

> Лабиринт в Entombed предельно простой, уровень состоит из блоков, которые имеют значение «стена» или 1 и «не-стена» или 0. В игре есть модуль, который обрабатывает участок 5х5 блоков и выдает три решения: сделать следующий уровень целиком из стен, пустым или случайной комбинацией стен и пустот. При этом должен сохраняться проход с предыдущего уровня и не возникать тупиков.


И в чём проблема?

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


А код посмотреть никак? Или они код не понимают? Тогда это говно, а не программеры, умеющие только клепать из готовых программных блоков.

> только чудом сохранил сам модуль, но вот объяснить его работу уже не мог.


То есть он не смог прочитать то, что сам написал? У него чердак сорвало?

> Старые программы и, в особенности, видеоигры могут быть ценным источником утраченных знаний.


Пичалька, да.

ЗЫ. Посмотрел на картинку. Это, видимо, скриншот игры? Вообще нихера не понимаю, в чём проблема. Примитивнейший лабиринт. Возможное решение: Каждый лабиринт описывается всего одним числом. Которое подставляется в генерирующую функцию с проверкой на проходимость. Если непроходим, или корректируем для проходимости или отбрасываем число, переходя к следующему.
Пока писал, ещё пара вариантов решения в голову пришла.

По-моему, статья про каких-то дебилов.
#13 | 14:18 17.06.2020 | Кому: Склеп
> Легко. Открой свои же исходники хотя бы полугодовой давности.

Да открывал недавно. Благо, я сильно мудрое не программирую. Недавно открывал свой же код, разбирался в одной задаче по оптимизации архитектурной акустики. Не все сразу вспомнил, минут за 20 разобрался. Ну вот чтоб всё отшибло - такого не бывало.
#14 | 14:24 17.06.2020 | Кому: Ummon
> Да лехко!
> Помогает только реверс - инжиниринг с приведением себя в то же состояние.

Ну, я не программист, мне программирование надо исключительно для численных методов Надо было решить один муторный интеграл, используя адаптивный шаг интегрированиях, получилось 3000 с лишним тысячи строк кода на C, это мой максимум. Вроде всё более или менее помню, а сколько надо написать строк, чтоб не помнить !? :-)
Vascosoft
интеллектуал »
#15 | 14:24 17.06.2020 | Кому: Склеп
> Тогда на чистом асме писали и без всяких общих библиотек, которые можно в автомате сейчас восстановить.

я сам на чистом асме писал для БК0010, и периодически ковырял машинные коды ее ПЗУ. И никаких особых проблем не испытывал с тем, чтобы понять о чем речь идет в том или ином куске. Вопрос времени и желания. Так что херня все это. А техкульт в топку.
Vertigo-One
надзор »
#16 | 14:28 17.06.2020 | Кому: Славянин
> Интересно, как можно напрочь забыть решение самим собой же решенной задачи

У журналистов и не такое возможно! У них то учёные рак вылечат, то по времени путешествуют....А на досуге - вообще страшно сказать чем занимаются!

В копилку: "Наука до сих пор не может ответить на эти 5 простых вопросов...". Обычно соседствует с "Чтобы похудеть без усилий достаточно перед сном принимать одну чайную ложку..."
Vascosoft
интеллектуал »
#17 | 14:40 17.06.2020 | Кому: Vertigo-One
> У журналистов и не такое возможно! У них то учёные рак вылечат, то по времени путешествуют....А на досуге - вообще страшно сказать чем занимаются!

"То у вас собаки лают, То руины говорят!" (с)

за это дебильный техкульт и топят - за неуемную тягу к кликбэйту.
#18 | 14:45 17.06.2020 | Кому: Ummon
> Да лехко!
> Помогает только реверс - инжиниринг с приведением себя в то же состояние.

Г.Каттнер - голова!
#19 | 14:46 17.06.2020 | Кому: Vascosoft
> за это дебильный техкульт и топят

Ну, и я пожалуй, топну.
Karhashim
надзор »
#20 | 14:52 17.06.2020 | Кому: Vascosoft
> В чем проблема разобрать 4кб машинного кода?

Все, кто пробовал, умерли мучительной смертью!
#21 | 14:58 17.06.2020 | Кому: Karhashim
> Все, кто пробовал, умерли мучительной смертью!

А к тем, кто разобрал, пришёл Чёрный кодер.
#22 | 15:01 17.06.2020 | Кому: Ummon
> > Все, кто пробовал, умерли мучительной смертью!
> А к тем, кто разобрал, пришёл Чёрный кодер.

И нажал Reset!!!
Джон Ву
Резуноид »
#23 | 15:02 17.06.2020 | Кому: aspav
> Примитивнейший лабиринт

[изнасилованные программистами журналисты] до сих пор не могут понять, как работает эта игра
#24 | 15:32 17.06.2020 | Кому: Vascosoft
> В чем проблема разобрать 4кб машинного кода? Люди многомегабайтные прошивки потрошат.

На примере ассемблера ZX Spectrum - весь код чтения и записи на магнитную ленту занимал меньше 100 байт.

Вывод на экран бы сложным - замороченная адресация, экран разбит на 3 части, в каждой части байт вывода на экран скомплектован в строки, которые идут сверху вниз с интервалами (можешь почитать в интернете) и отдельно цветовая закраска (квадраты 8 на 8 бит).

Так в ПЗУ был код для этой адресации, если не ошибаюсь - всего лишь в 16 байт - сплошные сложения, сдвиги, циклические сдвиги, сдвиги с переносом через регистр переполнения и ни одного условного перехода (при этом происходило деление/умножение/сложение). Вотт это было - охуенно! А не как сейчас говнокод раскопируют десять раз, подправят циферки в условиях - началнык, я сделаль!

P.S. Чтобы 4 кб ассемблера разобрать, где процентов 80 каждый байт - отдельная команда - крепко нужно попотеть. А если их делал ювелир, который пытался впихнуть невпихуемое...
#25 | 15:41 17.06.2020 | Кому: aspav
> Возможное решение: Каждый лабиринт описывается всего одним числом. Которое подставляется в генерирующую функцию с проверкой на проходимость.

Проверка на проходимость - это ещё одна функция?

> Если непроходим, или корректируем для проходимости


Корректировка - ещё одна функция?

> или отбрасываем число, переходя к следующему.


То есть перебором всех чисел подряд с неопределённым временем ожидания. На старом железе это долго.
Нет на всё это ни места, ни времени.
#26 | 15:48 17.06.2020 | Кому: глюкер
> А если их делал ювелир, который пытался впихнуть невпихуемое...

Еще могут быть неочевидные лайфхаки, которые например работали на живом железе, но в эмуляторе - не работают.
#27 | 16:06 17.06.2020 | Кому: amb
> Проверка на проходимость - это ещё одна функция?

Да. достаточно простая для такой маленькой матрицы.

> Корректировка - ещё одна функция?


Да. Меняем единичку на нолик.

> То есть перебором всех чисел подряд.


Каких "всех подряд"? При правильно подобранной функции, особых переборов не потребуется.

> На старом железе это долго.

> Нет на всё это ни места, ни времени.

Камрад, не нужно рассказывать мне про старое железо. Я слегка в курсе. Программирую с 1987.
Вполне достаточно и производительности и памяти для такой простой хуерги.

ЗЫ. На обдумывание этого варианта у меня ушло менее 2-х минут. Это вариант, стопудово реализуемый на чем угодно, с быстродействием большим, чем счёты.
Хоть на калькуляторе программируемом можно такое написать.
даже реалтайм игрухи писали для калькуляторов. С более сложными процессами, чем описанный.

И 2 возможных варианта возникло пока писал. За сутки можно кучу обдумать и исполнить оптимальный.
#28 | 16:23 17.06.2020 | Кому: aspav
> Каких "всех подряд"?

Сам предложил: "отбрасываем число, переходя к следующему." Где гарантия, что следующее подойдёт?

> При правильно подобранной функции, особых переборов не потребуется.


А лабиринт-то получится? Или просто забор?

> Вполне достаточно и производительности и памяти для такой простой хуерги.


Мы не знаем поставленную задачу. Может, ему там 500 байт выделили на лабиринт и 500 тактов. А может и меньше.
#29 | 16:44 17.06.2020 | Кому: Склеп
> > Подобное поведение чревато запоем.
>
> [Меланхолично]
> Я знаю...

А мне нравится.
#30 | 16:47 17.06.2020 | Кому: Всем
Каюсь, сходил по ссылке.
1. Лабиринт сдвигается только вперёд.
2. Если лабиринт непроходим, герой пробивает стену.
3. Монстры скачут сквозь стены.
4. Лабиринт симметричный отн-но вертикальной оси.
Вывод: каждая строчка лабиринта случайна, лишь бы из предыдущей в неё можно было попасть. Других проверок не треба. Генерить надо только пол-строки, вторая половина зеркальная.
Расходимся, нас нае$али.
Притопил
Vascosoft
интеллектуал »
#31 | 16:48 17.06.2020 | Кому: глюкер
> P.S. Чтобы 4 кб ассемблера разобрать, где процентов 80 каждый байт - отдельная команда - крепко нужно попотеть. А если их делал ювелир, который пытался впихнуть невпихуемое...

Я сагрился на тупорылое утверждение "Инженеры до сих пор не могут понять...". Все, что сделал один человек, всегда сможет повторить/понять/разобрать кто-то другой. Вопрос мотивации.
#32 | 16:51 17.06.2020 | Кому: Пальтоконь
> > > Подобное поведение чревато запоем.
> > [Меланхолично]
> > Я знаю...
> А мне нравится.

Ну так тебе и погон на памятник не вешали!!!
#33 | 16:53 17.06.2020 | Кому: Склеп
> Ну так тебе и погон на памятник не вешали!!!

Это как связано? Я про запой. Проблема у меня: в запой физически войти не могу, сколько ни пей. Мечта. Ушел бы в запой лет на 700.
#34 | 16:54 17.06.2020 | Кому: Vascosoft
> Вопрос мотивации.

Вопрос квалификации. Мотивированных и тупых – стада.
#35 | 16:55 17.06.2020 | Кому: Пальтоконь
> Это как связано? Я про запой.

Прямо. Пить надо в меру, которую знаешь. Ибо сказано - мерить вас будут не мерой вашей, а мерой меряющих!!!
#36 | 16:57 17.06.2020 | Кому: Склеп
Не понимаю, ну да ладно. Мне и свой старый код нравится, если в нём нет Rx. И если это не плюсы. И не питон. И не... Так. Мне надо выпить.
#37 | 17:02 17.06.2020 | Кому: amb
> Сам предложил: "отбрасываем число, переходя к следующему." Где гарантия, что следующее подойдёт?

Всё зависит от правильно подобранной математической функции, которой описан лабиринт. Лабиринт несложен, судя по картинке. 5 входов - 5 выходов, извилины, ответвления, соединения. Более того, он ещё и симметричен! То есть, функция достаточно проста.

> А лабиринт-то получится?


Получится. Я думаю, из программеров того времени мало кто не занимался изготовлением всяких лабиринтов :)

> Мы не знаем поставленную задачу.


Ну, вообще никаких ресурсов не выделить не могли. :)

> Может, ему там 500 байт выделили на лабиринт


Это дохрена. Насчёт тактов ничего не скажу, нужно считать, а я сейчас не в той форме, но проги такого плана работали на всём, что считает.
Это реально простая задача. Если, конечно, не фантазировать, как талпайопы - журналисты, что эти лабиринты зачем-то нужно сохранять в памяти. Возможно, генерация "на лету" это для них какая-то магия, но только для них.
На том железе я умудрялся моделировать движение танка, погодные условия, движение цели и выстрел, разрабатывая танковый тренажёр стрельбы (похвастаюсь шматца, был с ним победителем всесоюзного конкурса военно-научных работ в 88-м).

Описанное же, это фигня фигнёвая. Никаких проблем не вижу от слова вообще.
#38 | 17:03 17.06.2020 | Кому: Ёхл
> Каюсь, сходил по ссылке.
> 1. Лабиринт сдвигается только вперёд.
> 2. Если лабиринт непроходим, герой пробивает стену.
> 3. Монстры скачут сквозь стены.

Там ещё и такие упрощающие условия?!!!
Вообще тогда непонятно что заинтересовало авторов статьи.
#39 | 17:06 17.06.2020 | Кому: Пальтоконь
> Так. Мне надо выпить.

[смотрит с уважением]

Наш челоконь!
#40 | 17:47 17.06.2020 | Кому: глюкер
> На примере ассемблера ZX Spectrum - весь код чтения и записи на магнитную ленту занимал меньше 100 байт.

(Меланхолично) Под ДОС могу написать программу из 1 байта. Работает.
#41 | 18:44 17.06.2020 | Кому: aspav
> Получится. Я думаю, из программеров того времени мало кто не занимался изготовлением всяких лабиринтов :)

Ну и я занимался )) Генератор квадратного лабиринта любого размера занимал строк 15 на паскале. Но пришлось доказать, что алгоритм обеспечивает наличие прохода в любом случае. Думаю, тут похожая история - нанятый чувак нашёл подходящий алгоритм, впихнул в заданный размер и на радостях напился.

> На том железе я умудрялся моделировать движение танка, погодные условия, движение цели и выстрел, разрабатывая танковый тренажёр стрельбы


На атари?!
#42 | 19:02 17.06.2020 | Кому: amb
> На атари?!

Нет. Д3-28. Примерно той же мощности машинка. Проц только послабее, чем у Атари.
Vascosoft
интеллектуал »
#43 | 19:24 17.06.2020 | Кому: Пальтоконь
> Вопрос квалификации. Мотивированных и тупых – стада.

Вопрос квалификации - это в первую очередь вопрос мотивации. Личной.
votvot123
3 комментария в день »
#44 | 19:32 17.06.2020 | Кому: Всем
А вот вам баян из "Статского физкультурника". Если найти и исправить с десяток ошибок (я понятия не имею сколько раз это копипастилось), то это можно скомпилировать и запустить. Уверенные в своих силах - разбирайтесь!

========================Start of Chess.C========================
/*
* Вот программа, занявшая в свое вpемя первое место ("Best of Show"). Она
* вызывается с необязательным числовым параметром (по умолчанию 2) и играет
* в шахматы. Параметр определяет глубину просмотра (при глубине большей,
* чем 3, она будет думать очень долго). Ходы задаются двумя восьмеричными
* числами (откуда куда - см. доску в начале игры, например, "e2-e4" нужно
* будет вводить как "64 44"), в приглашении к приему указывается количество
* просмотренных ходов и оценка позиций - своей и противника, т.е. Вас).
*
* Правила игры несколько упрощены - пешки превращаются только в ферзей, нет
* взятия на проходе и длинной рокировки (мне и короткую сделать не удалось),
* а также контроля правил повторения позиций и 50 ходов.
*/

#include <stdio.h>
#include <stdlib.h>

#define m(x)(x<0?-1:!!x)
#define g tj()-J
#define a(x)(x<0?-x:x)
#define h(x)((x)<=K?x:N-(x))
#define f 9999
#define A return
#define H printf(
#define R double
#define U int
#define V for
#define b else
#define u while
#define B if
U v,w,Y= -1,W,J,p,F,o=f,M,N,K,X,YY,_,P[f],s(); typedef U(*L)(); L q[f];
tj(){
U S=m(v)+(m(w)<<K); B(!S)A J; V(v=W+S; v!=J&&!q[v]; v+=S); A v; } k(){ _=K;
A
v?a(v)>1||w-Y||!q[J]:(w-Y&&(w-Y*2||q[W+Y*(N+1)]|| (J>>K)-K+(Y-1)/
v?a(v)>2))||q[J];
} z(){ _=5; A v*w||g; } e(){ _= -2;
A(v*v*v-v||w*w*w-w)&&(J-W-2||(W&N)-4||(W>>K!=(Y-1?N:0))||
q[W+1]||q[W+2]||q[W+K]!=z||P[W+K]*Y<0); } R VR(){ int PZ=0x7fff;
A(R)(rand()&PZ)/(R)PZ; } l(){ _=K+1; A(v*w&&a(v)-a(w))||g; } R UC(){ R
i=0,d;
u((i+=d=VR())<1.0); A d; } c(){ _= -11; A a(v)-a(w)||g; } I(ur,n,x){ W=ur;
J=n; B(P[W]!=Y||P[J]==Y)A J+1; v=(J&N)-(W&N); w=(J>>K)-(W>>K); A
q[W]()||(x&&QL(W,J,s)); } TT(W){ v=w=0; A q[W]()+K; } s(){ U j= -1,i; Y= -Y;
V(i=0; i<M; ++i){ B(j<0&&P[i]== -Y&&TT(i)&&_== -2) { j=i; i= -1; } b
B(j>=0&&!I(i,j,0))A Y= -Y; } A!(Y= -Y); } bb(){ _=1; A a(v*w)-2; } uv(){
V(v=0; v<f; ++v){ B(h(v>>K)==0){ U S=h(v&N);
q[v]=!S?z:(S==1?bb:(S==2?c:(v&N>K?l:e))); } b B(h(v>>K)==1)q[v]=k; b q[v]=0;
P[v]=!!q[v]*(28-v); } } y(){ U G=Y,i; J=0; V(i=0; i<M; ++i){
i%8||H"\n%4o ",i); B((Y=P[i]=m(P[i]))&& TT(i))H"%c ",_+93+Y*16); b H"- "); }
H"\n "); do H"%2d",i++&N); u(i&N); Y=G; H"\n"); } O(W,J){
B((q[J]=q[W])==k&&h(J>>K)==0)q[J]=l; B(q[W]==e)B(J-W==2)O(J+1,J-1); b
B(W-J==2)O(W-1,W+1); P[J]=P[W]; q[W]=0; P[W]=0; } QL(W,J,D)L D; { U
HQ=P[J],YX; L AJ=q[J],XY=q[W]; O(W,J); YX=D(); O(J,W); q[J]=AJ; q[W]=XY;
P[J]=HQ; A YX; } C(){ U i,j,BZ=0; V(i=0; i<M; ++i){ L Z=q[i]; B(Z){ U
r=h(i>>K)+h(i&N),G=Y, S=Z==z?88:(Z==k?11 +r+(P[i]<0?N-(i>>K):(i>>K)):
(Z==l?124-((YY<8&&((i&N)!=K|| (i>>K)!=(P[i]>0?0:N)))?M:0):
(Z==c?41+r:(Z==e?f-r-r:36+r+r)))); Y=P[i]; V(j=0; j<M;
++j)B(!I(i,j,0))S+=(P[j]?5:1); BZ+=G==Y?S:-S; Y=G; } }
B(!(++X&M-1))write(1,".",1); A BZ; } PX(){ U i,Q=0,XP=0,JZ=M*M,E= -f,t,S=o;
B(!F--)A++F+C(); V(i=0; i<JZ; ++i)B(!I(i>>K+K,i&M-1,1)){ Y= -Y; o= -E; t=
-QL(i>>K+K,i&M-1,PX); Y= -Y; B(t>E){ ++XP; Q=i; E=t; B(E>=S) A++F,E; } }
B(!XP)E=s()?-f+1:0; p=Q; A++F,E; } RZ(){ U i,j,T=0; V(; ; ){ y(); o=f; do{
H"\n%d %d %d %s ",X,T,C(),s()?"!":">"); fflush(stdout); }
u(scanf("%o%o",&i,&j)!=2||I(i,j,1)); O(i,j); y(); X=0; ++YY; Y= -Y; T=PX();
i=p>>(K<<1); j=p&(M-1); B(I(i,j,1)){ H"Rats!\n"); A; } O(i,j); Y= -Y;
B(T>M*M)H"\nHar har.\n"); } } main(ac,av)char**av; { long
B(T>time(),j=time(&j);
R i=0; srand((U)j); V(M=0; M<=f; ++M)i+=UC(); M=i/100; B(M&3)++M; B(M&1)--M;
V(N=1; N*N<M; ++N); K= --N/2; F=ac>1?atoi(av[1]):2; uv(); RZ(); }
=========================End of Chess.C========================
#45 | 21:37 17.06.2020 | Кому: Peter Zuev
> > На примере ассемблера ZX Spectrum - весь код чтения и записи на магнитную ленту занимал меньше 100 байт.
>
> (Меланхолично) Под ДОС могу написать программу из 1 байта. Работает.

Что там сложно - ret поставить (возврат в операционную систему). Так практически на любом железе можно сделать.
#46 | 07:07 18.06.2020 | Кому: Peter Zuev
> (Меланхолично) Под ДОС могу написать программу из 1 байта. Работает.

А из 0 байт - слабО?
[censored]

Вот это уже довольно близко к сути сабжа, рисует, и неплохо рисует (правда, ОЧЕНЬ сильно хочет вычислительных ресурсов, но в плане процедурной генерации всего на свете - маленький шедевр):
[censored]
#47 | 09:16 18.06.2020 | Кому: Zzlo
> А из 0 байт - слабО?

Ну, формально говоря, код длиной 0 байт кодом не является. Ибо по определению не выполняет никаких действий. А что там при этом делает операционная система - это уже относится не к программе, а к операционной системе.
#48 | 14:40 18.06.2020 | Кому: глюкер
> Что там сложно - ret поставить (возврат в операционную систему). Так практически на любом железе можно сделать.

Это в первую очередь зависит не от железа, а от ОС. Тот же 1 байт на х86 под ДОСом пройдет, а под Виндой уже нет. Да и на Мотороле с PDP-11 это будет уже не один байт, ибо словное выравнивание.
Войдите или зарегистрируйтесь чтобы писать комментарии.