Dimens 10 by Humberto Martinez Barbera
РАЗМЕРЫ 10
В прошлом году я представил программу на 10-м конкурсе BASIC 10 Liner Contest, и это был очень интересный и обнадеживающий опыт. Основная идея заключается в том, что вы разрабатываете игру на BASIC, используя не более 10 строк кода для устаревших 8-битных компьютеров. Существуют различные категории в зависимости от максимально допустимого количества символов в строке. После того, как я получил уведомление об объявлении 11-го издания BASIC 10 Liner Contest, я решил принять участие, на этот раз с сложной и технически сложной игрой (по крайней мере, для меня :-). В этом посте я опишу свое представление в категории EXTREME-256 для выпуска этого года (2022), которое я назвал Dimens10.
<р>Идея
Некоторое время назад я нашел часть кода игры с быстрой прокруткой, которую написал в 80-х. Это было очень просто и использовало какой-то машинный код для прокрутки, который я, к сожалению, не нашел. Он был назван Cuarta Dimensión (4-е измерение). Не так давно я начал писать программу для автоматической генерации кода BASIC для программ прокрутки лабиринта, которую я назвал aMazeing. С помощью этого редактора я закодировал простой мокап реинкарнации игры.
Для этого представления я хотел сделать что-то подобное, что было непросто, потому что лабиринт довольно большой и для его программирования требуется много кода. Базовая игра состояла примерно из 100 строк кода и занимала 14 КБ. Мне нужно было только сократить его до 10 строк кода, которые не должны превышать 2,56 КБ (то есть 256 байт на lчасть кода, включая номера строк). Не так просто.
В игре вы обычно начинаете с идеи, геймплея, некоторой графики, а затем начинаете писать код. В этом случае я начал программировать технические части, а затем создал игровой процесс, который мог бы уместиться в доступном пространстве. Как раз наоборот, хотя я считаю, что это не так уж и редкость.
Я реализовал игру для машины MSX-1 в режиме SCREEN 1, то есть в полуграфическом режиме: вы можете комбинировать текст и спрайты с несколькими ограничениями по цвету. Таблицу символов можно изменить, чтобы стандартные символы ASCII выглядели по-другому. Графика создается путем изменения таблицы символов и ее расположения на экране. Единственное, что мешает этой программе быть чистым MSX-1, - это необходимая дополнительная память VRAM (больше, чем базовые 16 КБ MSX-1).
Поскольку перемещение символов на экране для прокрутки в BASIC происходит довольно медленно, я решил попробовать MSX BASIC Kun. BASIC Kun (также известный как X-BASIC) — это компилятор BASIC, который практически является стандартом де-факто. Правила конкурса позволяют использовать скомпилированный код. Хотя это и не является строго необходимым (разработанная игра прекрасно работает без компилятора), некомпилированная игра довольно плоха.
Методология
Я использую aMazeing как для определения графики, так и для создания кода. aMazeing — это программа, разработанная на Java, которая позволяет автоматически генерировать код BASIC (в настоящее время только MSX SCREEN 1) для игр с вертикальной и горизонтальной прокруткой.Процесс выглядит следующим образом (ну, на самом деле это не так, это на самом деле итеративный процесс, вы знаете, но вы поняли идею).
Вы начинаете изменять таблицу символов, создавая шаблоны, которые станут частью графики игры, и таблицу спрайтов, их растровые изображения и их цвета. Я изменил 15 символов 8x8 и создал один спрайт 16x16.
<р>Следующий шаг — создание лабиринта, который закодирован как двумерный массив символов/шаблонов. Я создал массив 125x13 и заполнил его измененными символами из таблицы символов.
<р>Последний шаг — заполнение экрана символами, которые не будут прокручиваться (базовый экран).
<р>А теперь самое интересное: программирование. Я реализовал специальный модуль для генерации кода BASIC для конкурса 10-liner, в дополнение к стандартному кодированию BASIC. Поскольку написание 10-строчного кода — это очень итеративный процесс, в котором вы перемещаете фрагменты кода так, чтобы они соответствовали количеству строк (10) и максимальному количеству символов в строке (256), этот модуль включает счетчик строк и счетчик символов. Это очень удобно, чтобы узнать, сколько места доступно для каждой строки. Ниже отображается счет для Dimens10.
0 символов=255 1 символ = 255 2 символа=224 3 символа=247 4 символа=247 5 символов=253 6 символов=245 7 символов=212 8 символов=240 9 символов=221 -------------------- Всего строк=10 Всего символов = 2399И последнее, но не менее важное: генерация кода довольно сложна. Для стандартного BASIC это просто: вы генерируете строки ДАННЫХ со всеми определениями (паттерны, спрайты, лабиринт, экран и т. д.), а затем кодируете их все и модифицируете соответствующую графическую память (VRAM на языке MSX). Для 10-линейки нам нужно точно такое же, но все втиснуто в десять строк кода. Что совсем не прямолинейно. В этом случае, вместо создания шаблона кода BASIC и последующего ручного кодирования игровой логики, я встроил код для логики в код для генерации 10-строчного кода. Что делает «вау», так это то, что код BASIC параметризован кодом Java, например:
encodeLine (запись, "W!=W!-4*(S=4ORS=6)-0,75*(S=5)+4*(S=2ORS=8)+0,75*(S=1):K=" +confd.VDP_FREEEMEM+"+X+INT(U!/8+1)+(INT(W!/8+1)+"+MAZEOFF+")*"+mazed.mazex+":IFVPEEK(K)="+CHRTRG+ "THEND=D+1:F=1:BEEP:LOCATE10,22:PRINTD:VPOKEK,"+CHRSKY+ "ELSEIFVPEEK(K)<>"+CHRSKY+"THENVPOKEK,"+CHRSKY+":V=V1:F=1: LOCATE20,22:PRINTV:BEEP:IFV=0THENT#=4,8");Программирование
Если вы занимаетесь элементарной математикой, мне нужно написать следующее:
- лабиринт. 125х13 ячеек. Всего 1625 байт
- узоры. 15 символов (8x8 бит). Всего 120 байт
- спрайты. 1 спрайт (16x16 бит). Всего 32 байта
- экран. 32x24 символа. Всего 768 байт
Если мы добавим все это, мы получим в общей сложности 2545 байтов. Всего доступно 2560 байтов (10 строк x 256 байтов в строке). НИ ЗА ЧТО !!!!!. И это только длячасть данных. Чтобы усложнить задачу, код BASIC не может содержать некоторые из доступных диаграмм, например нуль (0) или символы удаления (127). Чтобы сделать это еще сложнее, я разрабатываю в OS X, которая создает другое кодирование для нестандартных символов ASCII. Все это подразумевает: нам нужно сжать данные, чтобы уменьшить размер кода BASIC, и нам нужно закодировать его, используя стандартные печатные символы ASCII. Требуются основные действия.
Шаблоны и спрайты требуют мало информации. Из-за этого сжатие не работает. Я закодировал эту часть в шестнадцатеричном формате, что означает, что для каждого байта мне нужно записать два байта на Бейсике. Всего 304 байта, коэффициент кодирования 200%. Чуть больше 1 строки кода BASIC. Не так много. Раскодирование очень простое и компактное, как показано ниже. Накладные расходы на кодирование данных компенсируются компактным кодом чтения.
10 ПРОЧИТАЙТЕ H$:FOR I=0 TO 119:VPOKE 768+I, VAL("&H"+MID$(H$,I*2+1, 2)):NEXT I 20 DATA FFFFFFFFFF000000FFFFFFFF7F3F3F1FFFFFFFFFFFFFFFFF000000000000000000808080E0F0F8FE000101010303071FF8E0C0C0808080007F1F0F07010101007F3F1F3F0F0F1F3FE0F0F8FCFCF8C080070F0F070F0F030180808080808080801C1C083E081C2222F8FCFCFEFFFFFFFFFFFFFFFFFEFCFCF8С экраном немного сложнее, потому что он довольно большой. В этом случае он сжимается, а затем кодируется. Одной из самых простых схем сжатия является RLE-16 (кодирование длин серий), которая довольно хорошо работает при наличии большогоколичество повторяющихся байтов, как это происходит на экране: есть большие области с одним и тем же символом. Каждая 16-битная запись RLE состоит из двух частей: счетчика (1 байт) и значения (1 байт). В основном вы кодируете количество повторений данного значения в смежных позициях. Фактическое кодирование экрана показано ниже.
<р>Как вы могли заметить, в необработанных данных (экране) есть большие области с одинаковыми значениями. Код очень компактный, с коэффициентом сжатия около 22%. Кодирование производится в шестнадцатеричном формате, как в случае шаблонов и спрайтов выше, что удваивает размер для реального коэффициента сжатия + кодирования 45%. Код чтения стал более сложным и большим, чем раньше, как показано ниже.
10 P=6144:ДЛЯ T=1 TO 2:ЧИТАТЬ H$:ДЛЯ I=1 TO LEN(H$) ШАГ 4:R=VAL("&H"+MID$(H$,I,2)) 20 O=VAL("&H"+MID$(H$,I+2,2)):FOR J=0 TO R:VPOKE P,O:P=P+1:СЛЕДУЮЩИЙ J,I,T 30 ДАННЫЕ 002000181B1700190120001600440049004D0045004E0053002000310030004C0049004E00450 ...Наконец мы добираемся до лабиринта, который еще более сложен из-за его размера. В этом случае лабиринт сжимается, а затем кодируется. Но вместо использования RLE-16 я использовал RLE-8, в котором запись RLE состоит из 8 бит: 4 бита для счетчика и 4 бита для значения. С помощью этой схемы мы можем закодировать до 16 различных значений. Это основная причина, по которой мы изменили только 15 записей таблицы символов. Фактическое кодирование лабиринта показано ниже.
<р>Код очень компактный, со степенью сжатия около 23%. Проблема в этом случае заключается в том, что если мы закодируем сжатые данные в шестнадцатеричном виде, мы получим 738 символов, что слишком много. Хитрость теперь заключается в использовании таблицы поиска. Мы находим различные коды RLE-8 и помещаем их в линейный массив. Мы кодируем каждый RLE-8, добавляя позицию в массиве к значению ASCII 32. Это создает печатные символы ASCII. Если количество кодов RLE-8 уменьшается, размер таблицы поиска становится небольшим, а значит, и накладные расходы на кодирование. Фактическая кодировка лабиринта показана ниже. Таблица токенов показывает код RLE-8 (tok), смещение в таблице поиска (off), закодированный символ (chr) и количество использований RLE-8 (cnt).
<р>Код компактный, степень сжатия около 28%. Хотя все эти символы можно распечатать, не все из них можно поместить в оператор DATA, например, символ кавычки ("). Конечно, схему кодирования можно изменить, чтобы избежать использования некоторых символов, но это подразумевает наличие больший и более сложный код.Есть альтернатива, которая кодирует все данные в операторе REM, в который вы можете поместить любой записываемый символ.Читающий код просто должен проходить через пространство памяти, где хранится программа BASIC, и читать символы после оператора REM (в MSX-BASIC оператор REM может быть записан также с символом апострофа ('). В этом случае комментарии размещаются в двух разных строках кода.содержимое первой строки BASIC начинается с адреса 0x8008. Код чтения намного сложнее, чем раньше, как показано ниже.
0 'F206730792A3B2536293633213A2B3030C428352223372E3705082020EF304C340433001120523090 A0D90C2 !"#$!%#&!'#(!)# (!*#+!,#-!.34,#0,#$!" 5#6!7#38*#6!)129:!5#3/0, 05#;05#1!20/0'#1=#3!'05#+>0?6!* #+@ABACD!"E3>/0F#4!=,#4!5E+>F#(>02#(2#D!=?E-G%0/0/0=/E 1 KEYOFF:DEFINTA-Z:SCREEN1 ,2:BLOAD"XBASIC.BIN",R:'35$>"#1!F0/0/0,D=.E+!F#4!%H(G?E(> F#$=,94)E ;I20,0/E+!==2E:>A#1!=2#D2E4AE-<=="0/E-==AED>0*+>FE$!A0,0,0FE1>=0E >= FE4>, EI*3>AE1>0E3!2J6>?E +>0=E:>5E6>/0/E-<='E$>% 6>0.E->/0E :I/0, 0,0F0F0,0/EK,0F0FE &>/0,0/0/E 2 P=16384:Q=&H8009+88:FORI=0TO368:G=PEEK(Q+I-37*(I>=164) ):K=&H8009+(G-32)*2: K=VAL("&H"+CHR$(PEEK(K))+CHR$(PEEK(K+1))):R=K\16:O= (KMOD16)+96:FORJ=0TOR: VPOKEP,O:P=P+1:NEXTJ,I:P=6144:FORT=1TO2:READH$:FORI=1TOLEN(H$)STEP4: R=VAL("&H "+MID$(H$,I,2)):O=VAL("&H"+MID$(H$,I+2,2 )):FORJ=0TOR:VPOKEP,O:P=P+1:NEXTJ,I,TВозможно, этот фрагмент кода нуждается в более подробном объяснении. В строке 0 первая часть оператора REM представляет собой кодировку таблицы поиска, содержащую 88 символов (кодирование 44 шестнадцатеричных значений). Тогда остальная часть тСтрока плюс оператор REM следующей строки (строка 1) содержат печатные ASCII-кодированные смещения таблицы поиска. Строка 2 содержит код для чтения лабиринта, который хранится в зоне VRAM, не используемой в режиме SCREEN 1. Переменная P является указателем на область VRAM и увеличивается на единицу в каждой ячейке лабиринта декодирования. Переменная Q является указателем на область ОЗУ, в которой хранятся смещения таблицы поиска, и она увеличивается на единицу для каждого символа в оставшейся части оператора REM в строке 0 с переходом (37 символов), необходимым для продолжения. оператор REM в строке 1. Когда символ читается из оператора REM, он сохраняется в переменной G. Затем переменная K вычисляется как указатель на соответствующую позицию таблицы поиска, полученная из G минус значение ASCII 32. Затем из рассчитанной позиции таблицы поиска мы читаем первый полубайт как R (который кодирует счетчик) и последний полубайт как O (который кодирует значение). Теперь нужно просто записать R-кратное значение O в память VRAM. Я знаю, что это немного запутанно, но уместить лабиринт из 1625 байт в 650 символов стоит затраченных усилий !!!!!
Состояние игры кодируется с помощью следующих переменных:
- X (Integer): горизонтальное смещение лабиринта, используемое для реализации прокрутки. Варьируется в диапазоне 1 .. 93
- F (целое число): ноль по умолчанию. Он принимает значение 1, когда лабиринт нужно перерисовать (обычно, когда требуется прокрутка,то есть, когда X изменил значение)
- У! (Плавающее): горизонтальное положение спрайта в пикселях. Он начинается в середине экрана. Когда лабиринт находится в начальном положении (X=1), его значение может быть в диапазоне 1 .. 128. Когда лабиринт находится в конечном положении (X=93), его значение может быть в диапазоне 128 .. 220.
- В! (Плавающее): вертикальное положение спрайта в пикселях. Его значение ограничено только формой лабиринта.
- T# (двойной): осталось время. Он также кодирует горизонтальное положение конца полосы времени и изменяется в диапазоне 27 .. 5. По мере уменьшения времени переменная времени перезаписывается символом пробела.
- D (Целое число): текущий счет игры. Каждый раз, когда спрайт сталкивается с персонажем-человеком, значение увеличивается.
- V (Целое число): количество оставшихся жизней. Уменьшается после каждого столкновения
Большая часть логики игры довольно проста. Единственная сложная часть — это движение спрайта. Поскольку прокрутка занимает некоторое время, сумма прибавляется или вычитается до U! и В! необходимо учитывать, если лабиринт прокручивается. Если клавиши курсора просто вверх или вниз (S=1 или S=5), есть только вертикальное движение и W! увеличивается или уменьшается на 0,75 пикселя. В другом случае W! увеличивается или уменьшается на 4 пикселя. Если нажаты горизонтальные клавиши курсора (отдельно или в сочетании с вертикальными) U! увеличивается или уменьшается на 1 пиксель, только если лабиринт находится в начале (X=1) или в конце (X=93). Этот кодпоказано ниже.
10 S=STICK(0):IFS>1ANDS<5ANDX<93ANDU!>120THENX=X+1:F=1ELSEIFS<9ANDS>5ANDX>1ANDU!<132THENX=X-1:F=1 20 U!=U!-1*(S>1ANDS<5AND((U!<128ANDX=1)OR(U!<220ANDX=93)))+1*(S<9ANDX>5AND((U!>3ANDX =1)ИЛИ(U!>128ANDX=93))) 30 Вт!=W!-4*(S=4ORS=6)-0,75*(S=5)+4*(S=2ORS=8)+0,75*(S=1). 40 ПОСТАВИТЬ СПРАЙТ 0, (У!,Ж!), 12Наконец-то я получил код размером 2,4 КБ в 10 строках BASIC со стандартной кодировкой символов ASCII. Хороший. Цель достигнута. Поскольку у меня есть свободное место, я оставил пасхалку в коде. Сможете найти? (да ладно, это не так сложно, найди!!!). Вы можете найти код, файл диска симулятора (DSK) и некоторые мультимедийные материалы здесь:
GitHub: https://github.com/humbertomb/mymsx/tree/master/dimens10.
Инструкции
По мотивам трилогии Лю Цысиня "Проблема трех тел". Если нет, ПРОЧИТАЙТЕ ЭТО.
Человечество находится на грани исчезновения. Трисолярианцы из системы Альфа Центавра оказывают давление после массового вымирания галактического флота. Оставшиеся в живых прячутся в подземной пещере, свободной от влияния шопонов. Ожидается, что фотоид, запущенный Трисоляном, столкнется с Солнцем через 22 единицы времени. После этого Солнечная система превратится в огромный огненный шар, без всякой надежды на жизнь.
Вы — могучий пилот (да, как могучие утки, ну, вроде того) летающегогорло. Ваша миссия состоит в том, чтобы вернуть как можно больше людей из пещеры до того, как фотоид достигнет Солнца. Используйте клавиши со стрелками, чтобы перемещать летающую тарелку по пещере, подбирая как можно больше людей и избегая контакта со стенами пещеры. Летающая тарелка спроектирована с пятью защитными барьерами. Барьеры теряются при каждом столкновении. Если время уменьшится до нуля или вы столкнетесь более пяти раз... игра окончена.
<р>Вы готовы? Сможете ли вы спасти человечество? Давай попробуем.
Как скачать Dimens 10 by Humberto Martinez Barbera через торрент
Всего несколько простых шагов:
- Устанавливаем программу μTorrent, через которую мы будем скачивать торренты
- Выбираем и скачиваем подходящий торрент-файл репака Dimens 10 by Humberto Martinez Barbera
- Двойным кликом открываем скаченный файл, программа μTorrent запустится автоматически и предложит выбрать место для сохранения дистрибутива.
- После того как репак скачается, запускайте его. Начнется установка и... это все, приятной игры!