Pull to refresh

Comments 13

PinnedPinned comments

Адрес SS:BP+SI указывает на голову змеи. Т.е. по этому адресу лежит "координата" головы (если точнее, то смещение адреса в сегменте DS, соответствующего цвету символа; для простоты я буду называть это координатой). После чтения скан-кода клавиши и преобразования его в смещение координаты (-2 / 2 / -80 / 80) мы добавляем к этому значению координату головы, получая т.о. новую координату. Далее эта координата записывается в SS:BP+SI, сдвигая всё остальное далее по массиву.

Например, длина (CX) = 5. В массиве (по адресу SS:BP+SI) были такие слова: [11] [13] [15] [17] [19] (на самом деле прямо таких значений не будет, но для простоты пусть будет так, можете мысленно прибавить к этим числам 64000). Мы нажали вниз (80), получили новую координату: 80+11=91, новый массив будет таким: [91] [11] [13] [15] [17].

При этом мы рисуем только голову (91) и затираем хвост (19). При съедании яблока после вышеуказанной процедуры длина увеличивается на 2, и на следующем кадре будет так: [171] [91] [11] [13] [15] [17] [мусор]. В этот раз мы затираем (один раз) "мусорную" координату. В теории, это может быть координата на экране, т.е. мы можем затереть какое-то яблоко, часть себя или даже нарисовать на экране более жирную точку, если координата окажется чётной (символ с кодом 7, т.к. мы затираем хвост цветом 7). Если присмотреться к скриншоту, то можно увидеть, что внизу есть более жирная точка. Этот артефакт — как раз результат такого "удаления" несуществующего хвоста с мусорной координатой, которая оказалась чётной и попала в экран.

Этот глюк можно убрать, добавив инструкцию mov [bp+si],cx после loop, но это +2 байта (хотя можно всё равно уложиться в 64 байта, убрав звуковой щелчок out $61,al). Но тут всё равно нет 100% гарантии, что первые 5 (начальная длина змейки) координат не попадут в экран (а эти координаты исходно мусорные). Нужно добавлять ещё несколько байт в начало кода для их очистки. Но и в этом случае можно уложиться в 64 байта, если прибавлять длину змейки на 1, т.к. мусорной координаты при увеличении длины не будет, и mov [bp+si],cx здесь уже будет не нужен + кол-во inc cx уменьшится на 1 шт + можно до кучи убрать удаление курсора.

P. S. Обычно сдвиг массива "вперёд" делается с конца назад (чтобы не затереть самого себя), но используя xchg можно делать это, двигаясь с начала вперёд (как здесь).

Добавлена 45-байтовая версия змейки (в спойлере в конце статьи) :)

Прекрасно сделано. Верните меня в детство

для вас я подготовил онлайн-версию, играйте на здоровье!

Поиграть можно в змейку и не только Online в KolibriOS
А, загрузив образ CD диска (30Мб) можно поиграть и в Quake, Doom и др. игры и не только.
(задержка, правда существует загрузки KolbriOS в браузере в отличии от "секундного" старта рабочего стола на реальном компьютерном железе)


P.S. Змейка в KolibriOS как и ядро самой системы и многие демо программы на дискетке 1.44 Мб написаны на ассемблере Fasm.



!(видео тоже есть возможность просмотреть :)

KolibriOS — тоже магия ассемблерного искусства.

| Важно: для игры нужно использовать стрелки на цифровой клавиатуре.

Эх, на ноутбуке не поиграешь. Вспомнил детство так как писать в видео память и приходилось в первых собственных играх на ассемблере, поэтому код довольно понятен.

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

Адрес SS:BP+SI указывает на голову змеи. Т.е. по этому адресу лежит "координата" головы (если точнее, то смещение адреса в сегменте DS, соответствующего цвету символа; для простоты я буду называть это координатой). После чтения скан-кода клавиши и преобразования его в смещение координаты (-2 / 2 / -80 / 80) мы добавляем к этому значению координату головы, получая т.о. новую координату. Далее эта координата записывается в SS:BP+SI, сдвигая всё остальное далее по массиву.

Например, длина (CX) = 5. В массиве (по адресу SS:BP+SI) были такие слова: [11] [13] [15] [17] [19] (на самом деле прямо таких значений не будет, но для простоты пусть будет так, можете мысленно прибавить к этим числам 64000). Мы нажали вниз (80), получили новую координату: 80+11=91, новый массив будет таким: [91] [11] [13] [15] [17].

При этом мы рисуем только голову (91) и затираем хвост (19). При съедании яблока после вышеуказанной процедуры длина увеличивается на 2, и на следующем кадре будет так: [171] [91] [11] [13] [15] [17] [мусор]. В этот раз мы затираем (один раз) "мусорную" координату. В теории, это может быть координата на экране, т.е. мы можем затереть какое-то яблоко, часть себя или даже нарисовать на экране более жирную точку, если координата окажется чётной (символ с кодом 7, т.к. мы затираем хвост цветом 7). Если присмотреться к скриншоту, то можно увидеть, что внизу есть более жирная точка. Этот артефакт — как раз результат такого "удаления" несуществующего хвоста с мусорной координатой, которая оказалась чётной и попала в экран.

Этот глюк можно убрать, добавив инструкцию mov [bp+si],cx после loop, но это +2 байта (хотя можно всё равно уложиться в 64 байта, убрав звуковой щелчок out $61,al). Но тут всё равно нет 100% гарантии, что первые 5 (начальная длина змейки) координат не попадут в экран (а эти координаты исходно мусорные). Нужно добавлять ещё несколько байт в начало кода для их очистки. Но и в этом случае можно уложиться в 64 байта, если прибавлять длину змейки на 1, т.к. мусорной координаты при увеличении длины не будет, и mov [bp+si],cx здесь уже будет не нужен + кол-во inc cx уменьшится на 1 шт + можно до кучи убрать удаление курсора.

P. S. Обычно сдвиг массива "вперёд" делается с конца назад (чтобы не затереть самого себя), но используя xchg можно делать это, двигаясь с начала вперёд (как здесь).

Добавлена 45-байтовая версия змейки (в спойлере в конце статьи) :)

Ностальгия, в молодости ковырял такую же змейку, это было в начале нулевых (т.е. за много лет до 2020 упомянутого в копирайте исходника в статье), и на masm (скорее всего), но принцип явно тот же. Пофиксил баги, оптимизировал по коду, добавил очки, размер емнип был в районе 100байт.

Здравствуйте.

Объясните, пожалуйста, как работает этот code golf:

x86, MSDOS, 16 bytes

I wrote this a while ago, to my knowledge the smallest routine for producing a dragon fractal. It uses no real iterations, rather plots every contained discrete pixel inside the fractal directly, showing the final image. It's included with many other tiny productions in this pack. The 16 byte version was the end of my effort to get the dragon fractal as small as possible, starting 2014 with this 32 byte production.

Hex

14 10 19 CA D1 FA 10 DE 01 D1 CD 10 B4 0C EB F0

Code

S: 
adc al,0x10
sbb dx,cx       
sar dx,0x01 
adc dh,bl
add cx,dx
int 0x10
mov ah,0x0C
jmp short S

Про алгоритм лучше спросить у автора. Он доступен в Discord (ссылка есть в статье про radar).

Могу сказать только, что после adc al,0x10 на первой итерации int 0x10 выполняет установку 16-цветового EGA видеорежима 640x320, а на следующих выводит точку через функцию ah=0x0C, цвет которой каждый раз меняется c помощью всё той же инструкции adc al,0x10.

Здравствуйте. Автор, как я понял, на Stack Overflow давно не активен. Меня он точно не знает, Вас знает. Я понимаю, что это наглость, но можно Вас попросить:

  1. узнать у автора алгоритм;

  2. написать об 14 10 19 CA D1 FA 10 DE 01 D1 CD 10 B4 0C EB F0 статью на habr.

Заранее спасибо :)

Sign up to leave a comment.

Articles