Игра Snake в 95 байт
История создания
Змейка (Питон, Удав), как ее называют в народе, одна из первых игр цифровой (компьютерной) эпохи середины 70-ых годов. В то время игры выпускались на отдельном игровом автомате с одной игрой, а сам автомат был под нее стилизован. Примерами таких игр, кроме Snake, являются Space Invaders, Pac-Man, Arkanoid и другие.
Игра Змейка имеет незамысловатый геймплей. Игрок управляет длинной линией с изгибами в 90 градусов с целью «поедания» все большего числа кроликов, представленых в виде точек на экране, от чего увеличивается длина Змейки. Сложность заключается в том, что Змейка не может пересекать саму себя.
С тех пор игра Змейка пережила множество воплощений на разных устройствах. Где-то вместо линии Змейка отображалась символами, так как технически вычислительное устройство не позволяло выводить произвольную графику. На более современных компьютерах Змейка получила возможность поворачиваться на произвольный угол, а не только на 90 градусов. Простая игра и ее идея были перенесены практически на все виды вычислительной техники, даже на программируемые микрокалькуляторы и микроконтроллеры, которые управляют холодильниками и другими бытовыми приборами. Идея Змейки популярна и сейчас, недавний бум пришелся на свежую реинкарнацию в виде сетевой игры slither.io.
Интересуясь программированием, в 90-е годы и после я читал множество литературы, где одной из учебных программ была игра Змейка. Также попадались статьи соревновательного характера: люди старались уложиться в какие-то технические параметры компьютера. Я же в свою очередь тоже практиковался в программировании и писал игру на разных языках и платформах. В электронном журнале на платформе ZX-Spectrum, мне попалась статья с описанием создания Змейки в 256 байт на языке Ассемблер. Автор статьи подробно описал свою работу и заявил, что вряд ли можно написать игру короче, чем 256 байт. Через некоторое время появилась другая версия в 121 байт, но за счет уменьшения размера пострадал геймплей.
Однажды, общаясь с начинающим программистом, я посоветовал написать хоть какой-то законченный проект, и речь зашла про игру Змейка. Я решил поддержать программиста тем, что пообещал написать свою реализацию игры, но не просто так, а на ZX-Spectrum и языке Ассемблер.
Первую версию змейки я написал за пару часов, и весила она чуть больше 150 байт. Я вспомнил про статьи в электронном журнале и захотел побить рекорд. Следующая версия уже весила 100 байт, но и потраченное время разработки перевалило за 6 часов. Остановившись на этом, показал свою версию игры, а начинающий программист — свою, и после я забыл об игре на некоторое время.
Разбирая папку со своими проектами и исходниками, я наткнулся на исходный код своей Змейки и понял, что код можно немного модифицировать и сократить еще на пару байт. Процесс оптимизации занял целый день, а сокращение составило только 5 байт. В итоге игра стала весить 95 байт.
Технические подробности
Технические подробности игры snake в 95 байт
- 59 строчек кода без комментариев
- Полная релоцируемость программы (размещение в любой адрес без перекомпиляции)
- Не используется стек
- Используется только основной набор регистров: a, b, c, d, e, h, l и r как генератор случайности
- Без использования процедур ПЗУ
- Честная инициализация экрана и бордера
- Классическое управление клавишами: 6,7,8,9 (Sinclair Joystick)
- Каждую инициализацию псевдослучайным образом расставляться кролики
Код состоит из 3 блоков
- Инициализация переменных и экрана
- Опрос клавиш на нажатие и изменение направления движения
- Обработка игровых событий
Регистры используются в основном как именные переменные, так:
- Регистр a — используется по как промежуточный результат и манипулятор с отдельными битами
- Регистровая пара bc — это направление движения принимает всего 4 значения за весь игровой процесс: #ffe0, #0020, #0001, #ffff
- Регистровая пара de — это текущий индекс обработки массива (атрибут)
- Регистровая пара hl — это текущие координаты головы змейки в адресном пространстве атрибут
В блоке инициализации de и hl, поменяны местами для сокращения логической операции распределения кроликов
В игре используются два глобальных цикла, от начала программы до конца (полная инициализация) и игровой цикл (после расстановки кроликов)
Код игры
org #8000
ld de,#598f;snake xy
ld hl,#5aff
ld b,l
ld c,l
;---
rabbit1 ld (hl),b
ld a,r
cp l
jr z,rabbit2
inc (hl)
rabbit2 dec hl
bit 3,h
jr nz,rabbit1
ex hl,de
;---
l1 xor a
out (#fe),a
clr ld (de),a
dec de
bit 6,d
jr nz,clr
;---
ld (hl),33
ld d,#5a
move1 ld a,(de)
dec a
cp 254
jr nc,move2
ld (de),a
move2 jr nz,move3
dec (hl)
move3 dec de
bit 3,d
jr nz,move1
;---
ld a,#ef
in a,(#fe)
rra
rra
jr c,$+5
ld bc,#ffe0
rra
jr c,$+5
ld bc,#0020
rra
jr c,$+5
ld bc,#0001
rra
jr c,$+4
ld b,e;ld bc,#ffff
ld c,e
;---
ld a,(hl)
and %00100000
add hl,bc
or (hl)
inc a
cp 7
jr nc,begin
ld a,h
inc a
and %00000011
jr z,begin
jr l1