
Возможно, кто-то из читателей вспомнит свои самые первые шаги в программировании, в которых фигурировала книжечка по Бейсику с примитивными примерами, которые нужно было самостоятельно набирать, запускать, и через это постепенно понимать, как они работают. Когда-то именно так начинал «вкатываться в IT» и я.
Подобные брошюры издревле прилагались к домашним компьютерам, оснащённым встроенным интерпретатором Бейсика. В начале 1980-х годов в одной из них, входившей в комплект компьютера Commodore, была опубликована небольшая программка, рисующая на экране случайный лабиринт, составленный из диагональных чёрточек-слешей.
Пройдут десятилетия, и эта простая строчка кода превратится в настоящее культурное явление. Что это за строка, как работает, чем интересна, почему не забыта? Нет времени объяснять, срочно лезем в лабиринт разбираться!
Что за лабиринт?
Компания Commodore за время своего существования с 1976 по 1994 годы разработала и выпустила множество персональных компьютеров, сыграв значительную роль в популяризации самого формата этих устройств. Одним из главных ингредиентов её успеха стал встроенный интерпретатор языка Бейсик, готовый к использованию сразу после включения — золотой стандарт для «домашних» компьютеров 1980-х.

Интерпретатор был лицензирован у небезызвестной компании Microsoft уже в 1977 году, и под названием Commodore BASIC в различных своих ревизиях применялся во всех 8-битных машинах компании, начиная с учебно-делового PET, продолжая бытовым VIC-20, и включая главный хит — сверхпопулярный Commodore 64, проданный тиражом более 17 миллионов. Также его можно встретить и на менее известных моделях: Plus/4, C16/C116 или C128.
Если сдуть вековую пыль с любого из этих классических компьютеров, и набрать на клавиатуре одну не очень понятную, но довольно короткую строчку кода…
10 PRINT CHR$(205.5+RND(1));:GOTO 10
…можно увидеть интересный визуальный результат — диагональный узор, напоминающий классический лабиринт:

Простенький трюк, который едва ли удивит кого-то сегодня. Но представьте себе времена, когда компьютеры только-только превратились из артефакта научно-фантастических фильмов в доступное для приобретения бытовое устройство. Для человека, впервые увидевшего домашний компьютер и набирающего свои самые первые в жизни программы на Бейсике, это был весьма впечатляющий результат, навсегда отпечатавшийся в памяти момент.
Откуда взялся?
Прежде чем углубляться в дебри, попробуем выяснить, откуда вообще взялась эта строчка кода, и почему стала широко известной именно на Западе.
Во многих источниках тиражируется информация о том, что знаменитая программа случайного лабиринта содержит лишь одну строку, и впервые была опубликована в 1982 году в книжке-инструкции User’s Guide, прилагающейся к американскому домашнему компьютеру Commodore 64. На самом деле это не совсем так, а может быть, даже и совсем не так.
Действительно, в указанной инструкции есть эта программа. И, пожалуй, именно этот её вариант стал широко известен пользователям благодаря огромной популярности Commodore 64, которую он имел в основном в США. Выглядит эта страница так:

Внимательный читатель сразу заподозрит неладное. Строки здесь три, а не одна, а их нумерация непоследовательна — почему-то пропущена строка 30. Как будто программу отредактировали и убрали лишнюю строку, забыв изменить нумерацию. Ну а строка 10 содержит странную конструкцию. Впрочем, её разгадка проста: в Commodore BASIC до четвёртой версии отсутствовал привычный оператор CLS, и его заменяли таким вот образом, печатью спецсимвола, вызывающего очистку экрана.
Загадка же пропавшей строки не имеет объяснения — возможно, что-то было добавлено для демонстрации возможностей нового компьютера (звук или изменение цвета), а потом снова убрано для сохранения простоты. Но действительно, из-за неё программа выглядит отредактированной, а значит, это должна быть не первая её опубликованная версия. Искать гипотетический более ранний вариант долго не приходится: он есть в книге VIC-20 User’s Manual для предшественника Commodore 64, компьютера VIC-20. Первое издание этой книги было в 1981 году.

Версия для VIC-20 идентична по коду, но строки имеют последовательную нумерацию. К сожалению, компания Commodore не указывала авторов своих книг, но вероятно, это были разные люди, так как оформление книг для C64 и VIC-20 довольно сильно различается. А так как у Commodore были и более ранние машины с почти таким же Бейсиком, вполне вероятно, что эту программу придумали не сами авторы книг.
Более того, один из пользователей Commodore PET некогда утверждал на одной из площадок в Интернете, что сам придумал подобную программу ещё в 1980 году, и поделился ей с единомышленниками на одной из сходок тех лет. Никаких документальных свидетельств этого, конечно, не сохранилось, но история звучит вполне правдоподобно: вполне возможно, что программа была придумана энтузиастами, и получила достаточно широкое хождение в их кругах, прежде чем попасться на глаза авторов книг.
Но откуда же взялась однострочная версия программы? Преобразование трёхстрочной версии в однострочную тривиально и напрашивается само собой — очистка экрана не сильно ей нужна, тем более с использованием труднонабираемого спецсимвола очистки. Разделение операторов по строкам также устраняется естественным образом. Наверняка многие пользователи проделывали это упражнение самостоятельно.
Остаётся последний вопрос: где же, в каком широко доступном публичном источнике, этот огранённый энтузиастами алмаз кода, его однострочный вариант, был зафиксирован документально, и таким образом внедрён в массовое сознание?

Такое место есть. Это американский журнал Run, выходивший в 1984-1992 годах и посвящённый компьютерам Commodore 64 и VIC-20. Одна из самых популярных рубрик журнала называлась «Magic». В ней публиковались короткие программы и различные трюки, присылаемые самими читателями. В седьмом номере, за июль 1984 года, в этом разделе под номером $93 была опубликована искомая однострочная версия лабиринта, присланная Дэном А. Крюгером. И уже здесь она была названа «одной из самых впечатляющих однострочных программ».
Эта версия немного отличается от классической: номер единственной строки в ней 8, а не 10. Место и время, где и когда он преобразовался обратно в канонический 10, цифровым археологам ещё предстоит раскопать. Ведь в современной ретро-компьютерной культуре эта программа стала широко известна именно под названием «10 PRINT».
Как работает?
Но довольно листания страниц старых книг и журналов. Теперь разберёмся, как это работает.

Идея очень проста: в наборе символов PETSCII, помимо прочей интересной псевдографики, в позициях 205 и 206 располагаются две диагональных черты, напоминающих стандартные «слеши», которыми мы разделяем уровни вложения в путях файловых систем, но занимающих знакоместо целиком, от края до края. К тому же они довольно толстенькие на вид.

Если случайным образом выбирать один из этих двух символов и печатать их друг за другом с постепенным переходом на строки ниже, они естественным образом сформируют геометрический узор, похожий на повёрнутый на 45 градусов лабиринт.
Для порядка бегло разберём и сам код:
10 PRINT CHR$(205.5+RND(1));:GOTO 10
10 — номер строки программы
PRINT — оператор печати
CHR$ — функция преобразования кода символа в сам символ
205.5 — код первой диагональной черты плюс 0.5
RND(1) — функция генерации случайного числа в диапазоне от 0 до 0.9 в периоде
; (точка с запятой) — для продолжения печати следующего символа в той же строке, с автоматическим переносом строк
: (двоеточие) — разделитель операторов в строке программы
GOTO 10 — переход на ту же строку программы, организующий бесконечный цикл
В целом всё просто и понятно. Пожалуй, некоторых пояснений требует лишь дробная часть в коде символа и RND.
Дело в том, что цифра в скобках RND(1) не является диапазоном, а лишь устанавливает режим генерации случайных чисел. Диапазон же всегда остаётся между нулём и единицей, никогда не достигая единицы. Получить другой желаемый диапазон можно только умножением на целое число. В нашем случае это могло бы быть множение на два — 205+2*RND(1). Но форма 205.5+RND(1) не содержит лишней арифметической операции и работает точно так же, с равным шансом выпадения каждого из символов: округление для CHR$ отбрасывает дробную часть.
Другие лабиринты
Оригинальный лабиринт построен всего из двух символов, диагональных слешей, что придаёт ему весьма специфический внешний вид. Но 8-битные компьютеры Commodore используют не стандартный набор символов ASCII, а щедро сдобренный псевдографикой набор PETSCII. Среди его символов есть достаточно интересные образцы, из случайных комбинаций которых можно построить другие визуальные паттерны, напоминающие лабиринт.
Например, очень легко получить «плетение», чередуя горизонтальные и вертикальные полоски с кодами символов 198 и 199:
10 PRINT CHR$(198.5+RND(1));:GOTO 10

А если чередовать символы, коды которых идут не подряд, можно получить и иной вид «прямоугольного» лабиринта. Для этого подходят разные символы, но приятный глазу упорядоченный узор хорошо получается с символами 181 и 184, содержащими знакоместо, закрашенное наполовину слева или сверху. Код для такого чередования нужен чуть похитрее:
10 PRINT CHR$(181+(INT(RND(1)+.5)*3));:GOTO 10

Другой «ортогональный» лабиринт можно получить, чередуя случайным образом шесть символов псевдографики, из которых обычно рисуют рамки: вертикальная и горизонтальная черта и четыре их варианта с ответвлением в сторону. Чтобы обойтись без условий и уложиться в одну короткую строчку, в коде используется функция MID$ для выбора символа с нужным номером из строки:
10 PRINT MID$("├┤┴┬─│",RND(0)*6+1,1);:GOTO 10

Есть и другие разновидности лабиринтов, часть из которых упоминается в книге, про которую я упомяну чуть ниже. Энтузиасты и по сей день продолжают искать новые интересные сочетания символов и случайности.
Но даже самый классический лабиринт с диагональными чертами таит интересную особенность. Если разбалансировать вероятность случайного выпадения символов 50:50 в одну из сторон, узор поменяется на вытянутый по одной из диагоналей:
10 PRINT CHR$(205.25+RND(1));:GOTO 10

Вне «Коммодора»
Разумеется, не Commodore 64 единым жив мировой ретрокомпьютинг. Популярность программы шагнула за пределы родной платформы, и сегодня аналогичные лабиринты можно увидеть на других компьютерах той эпохи.
Например, на семействе 8-битных компьютеров Atari, включающем модели Atari 400, 800, XE и XL, и обладающем родственным диалектом Бейсика, можно набрать очень похожую программку, в которой отличаются только коды символов (6 и 7 вместо 205 и 206), а также способ округления результата:
10 PRINT CHR$(6+RND(1));:GOTO 10
Сами символы здесь выглядят такими же толстыми и хорошо стыкующимися, как и на Commodore 64.
Или наш любимый ZX Spectrum — куда же мы без него? Правда, местный диалект Бейсика совершенно другой и требует иного подхода. В этой реализации используется трюк с возможностью обратиться к символу строки сразу же после её определения, не занося её в строковую переменную:
10 PRINT “/\”(INT(1.5+RND));:GO TO 10

К сожалению, с визуальной частью тут проблема: слеши маленькие, и не сливаются в единый узор. Это можно исправить, задав пару диагональных чёрточек в символах, переопределяемых пользователем (UDG). Но это потребует заменить в приведённой выше строке слеши на символы UDG A и B, и добавить ещё одну строчку:
5 FOR i=0 TO 7 : POKE USR “a”+i,2^i : POKE USR “b”+i,2^(7-i) : NEXT i

Так лабиринт выглядит значительно лучше!
Конечно же, случайный лабиринт можно реализовать и на современных компьютерах и языках программирования — хоть на C, хоть на JavaScript. Но к сожалению, как правило при этом теряется важный фактор оригинала: однострочность.
Тем не менее, что-то подобное сделать можно. Например, можно запустить вариант на Python прямо из командной строки:
python -c "import random; exec(\"while 1: print(random.choice('╱╲'), end='')\")"

Можно покороче?
Популярной дисциплиной среди компьютерных энтузиастов, в особенности на демосцене, является так называемый «size coding» — создание программ сверх-малого размера, объёмом в сотни и даже десятки байт.
И хотя эта мысль довольно странная, но всё же, почему бы и не задать вопрос: а можно ли сделать эту однострочную программу на Бейсике ещё короче?
Задача непростая. С изначальных трёх до одной строки её уже сократили пользователи, и самая знаменитая версия содержит примерно 35 символов, в зависимости от использования необязательных пробелов. Казалось бы, куда уж ещё меньше — 32-байтовые программки и так являются одним из самых суровых форматов в size coding.
И всё же, есть несколько интересных оптимизаций, которые можно рассмотреть. Из самых простых вещей: можно убрать пробел после номера строки и можно сократить длину номера строки до одной цифры — что, собственно, и было сделано в журнальной версии 1984 года.
Что же ещё? Commodore BASIC имеет интересную особенность: вместо оператора PRINT можно набрать знак вопроса, и после ввода строки интерпретатор сам заменит его на нормальный PRINT. Правда, это лишь сокращает количество набираемых руками символов и не влияет на размер программы в байтах (токены кодируются одним байтом).
Также Бейсик позволяет делать ещё две странных вещи одновременно: вводить номер строки 0, и не указывать номер строки для GOTO — в этом случае переход произойдёт на нулевую строку, если она присутствует в программе (иначе будет ошибка).
Таким образом мы можем получить конструкцию из 26 вводимых символов:
0?CHR$(205.5+RND(1));:GOTO
Которая после ввода и выполнения оператора LIST будет отображаться в классической форме:
0PRINTCHR$(205.5+RND(1));:GOTO
Но и это ещё не всё. Конечно, это формальность, и фактически символов в программе станет больше, но программу можно сделать вообще без строк, и не вводить оператор RUN для запуска. Ведь Бейсик является интерпретатором, и сразу исполняет введённые команды. Надо лишь найти способ зациклить строку, вводимую без номера:
FOR A=0 TO 1 STEP 0:PRINT CHR$(205.5+RND(1));:NEXT
Можно побыстрее?
Запустив заветную строчку на оригинальном Commodore 64, можно заметить, что программа работает не очень-то быстро. А если честно, работает она очень медленно. И здесь тоже есть где разгуляться мятущемуся уму ретро-программиста.
Наибольшая проблема оригинальной программы — скорость работы функции RND. Ведь ей приходится генерировать псевдослучайное число с плавающей точкой чисто программным способом на 8-битном микропроцессоре с тактовой частотой около одного мегагерца. И если на других компьютерах Commodore с этим мало что можно сделать, у наиболее привычного для программы Commodore 64 есть скрытые ресурсы. Например, звуковой чип SID.
Нет, под бодрую музыку программа быстрее не заработает. Но у звукового чипа среди прочих возможностей есть режим генерации шума, и есть возможность чтения значения регистра этого шума. Включить этот режим можно следующими командами:
POKE 54287,255 : POKE 54290,128
Теперь каждое выполнение команды PEEK (54299) будет возвращать случайное целое число в диапазоне 0…255, генерируемое аппаратным способом. Работает это значительно быстрее, чем вызов функции RND.
Следующая возможность ускорения — генерировать не одиночный случайный символ, а сразу несколько. У нас всего два случайных символа, один или другой, инь или янь, ноль или единица. То есть один бит информации. А в байте, читаемом из регистра SID — восемь бит. Достаточно заменить каждый 0 и 1 в символьном представлении бит этого байта соответствующими слешами, и мы получаем группы из 8 случайных элементов лабиринта.
Наиболее быстрый способ реализовать эту схему — предварительно построить в памяти массив из 256 символьных строк, где каждому целому значению 0…255 соответствует строка из восьми слешей, и просто печатать эти строки одну за другой.
10 DIM M$(256):POKE 54290,128:POKE 54286,255:R=54299 20 FOR B=0 TO 255 30 Y=128:PRINT"$"B" / 255" 40 FOR C=0 TO 7 50 IF (Y AND B)=0 THEN M$(B)=M$(B)+"/":GOTO 70 60 M$(B)=M$(B)+"\" 70 Y=Y/2:NEXT C,B 80 PRINT M$(PEEK(R))M$(PEEK(R))M$(PEEK(R))M$(PEEK(R))M$(PEEK(R));:GOTO 80
Здесь строки 10…70 генерируют массив строк со слешами, а основной цикл находится в строке 80. Конструкция M$(PEEK®) повторяется в ней пять раз, чтобы за один вызов PRINT печатались все 40 символов одной строки экрана.
Конечно, теперь программа состоит из нескольких строк кода, а построение символьного массива занимает довольно длительное время. Зато скорость работы этой Бейсик-программы практически упирается в скорость работы процедуры печати интерпретатора. Можно ли утрамбовать аналогичную программу в одну строку кода, длина которой на Commodore 64 ограничена 80 символами — вопрос пока открытый.
Подробно эти трюки рассматривает и наглядно демонстрирует The 8-Bit Guy в своём относительно недавнем видео:
Можно на ассемблере?
Можно! А зачем? Ведь исконная программа лабиринта знаменита именно тем, что написана на Бейсике. Её ценность в простоте и достаточно интересном визуальном эффекте: код легко набрать руками, увидеть результат, и достаточно легко понять, как он работает. Прекрасный обучающий материал, стимулирующий интерес к компьютерам и программированию.
Изучать же ассемблер на примере программы-лабиринта далеко не так эффективно, так как для её реализации требуются некоторые не самые простые манипуляции. Например, получение случайного числа и вывод символа. И тем не менее, написать её на ассемблере, конечно же, можно.
Вот простая для понимания и умеренно компактная версия для того же Commodore 64:
*= $1000 ; адрес компиляции LDA #$80 ; значение для инициализации STA $D40F ; запись в регистр SID, частота генератора шума STA $D412 ; запись в регистр SID, режим генерации шума LOOP: ; начало цикла LDA $D41B ; читаем из регистра SID случайное значение AND #1 ; оставляем только младший бит, A=0 или 1 ADC #$6D ; добавляем код PETSCII-символа \ JSR $FFD2 ; выводим символ на экран через процедуру в KERNAL BNE LOOP ; переход на цикл
В силу тривиальности этого варианта разбирать подробно его работу я не буду, ограничившись приведёнными в коде комментариями. Но более интересно увидеть не исходник, а бинарный код. Ведь его длина всего лишь 20 байт:
A9 80 8D 0F D4 8D 12 D4 AD 1B D4 29 01 69 6D 20 D2 FF D0 F4
Правда, ввести и запустить эти байты с помощью голого Commodore 64 не получится, так как он не оснащён встроенным отладчиком — разве что преобразовать в десятичные числа и вводить серией операторов POKE.
Но мониторы-отладчики для Commodore 64 были доступны в виде загружаемых программ картриджей. Также монитор встроен в популярный эмулятор VICE. Ввести в нём этот код можно, зайдя в монитор (Alt-M), набрав команду F 1000 1013 и потом приведённые выше 20 байт. Для запуска нужно ввести в мониторе команду G 1000.
Конечно, так как это ассемблер, а не Бейсик, поле для возможных оптимизаций для уменьшения размера здесь просто огромное. И, конечно же, энтузиасты этого дела нашлись. Их усилия привели к появлению варианта размером всего до 8 байт. Для работы этого варианта критично расположение в конкретных адресах памяти и запуск кода из Бейсика командой SYS 12032:
*=$2F00 ; адрес компиляции PLA ; забираем A со стека CMP ($F3),Y ; ??? ADC #$87 ; ??? JSR $E717 ; PROFIT!!!
Однако, для понимания происходящего в этих четырёх командах требуется очень глубокое знание особенностей устройства аппаратной и программной части Commodore 64. В силу нетривиальности этого варианта разбирать его работу я подробно не буду, а просто покажу HEX-код, который должен наглядно продемонстрировать, почему же некоторым людям интересен «size coding». Чистая бинарная магия:
68 D1 F3 69 87 20 17 E7
Но то буржуйский Commodore, в наших краях почти неведомый. А мы, по крайней мере, некоторые из нас, в юности вводили hex-коды игр со страниц журналов в наши РК-шки и аналогичные машины. Поэтому я решил пробросить мостик между странами и эпохами, и написать аналогичную программку для Апогей БК-01, на ассемблере процессора КР580ВМ80. Вот она:
ORG 0 ; адрес компиляции LOOP: MOV A,H ; берём старший байт HL ANI 07H ; обрезаем до 0..7 ORI 0F0H ; добавляем #F0 MOV H,A ; возвращаем в HL MOV A,M ; читаем байт из диапазона F000..F7FF (ПЗУ) INX H ; увеличиваем указатель RAR ; сдвигаем A вправо, лишний бит в флаге переноса MVI C,2FH ; ASCII-код слеша JC SKIP ; если был перенос, пропускаем выбор бэкслеша MVI C,5CH ; ASCII-код бэкслеша SKIP: CALL 0FCBAH ; вывод символа из регистра C на экран JMP LOOP ; переход на цикл
К сожалению, из-за того, что коды нужных символов в ASCII полностью разные, а не соседние, как на Commodore 64, а в качестве источника псевдослучайности у меня используется код Монитора в ПЗУ, мне не удалось сделать свой лабиринт короче 22 байт. Но для начала пойдёт. А вот и его HEX-код:
7C E6 07 F6 F0 67 7E 23 1F 0E 2F DA 10 00 0E 5C CD BA FC C3 00 00
Ввести его в реальный Апогей значительно проще, так как он оснащён встроенным Монитором, хоть и не отладчиком. Для ручного ввода нужно выполнить команду M. Далее на экране будет показываться текущий адрес памяти и лежащее в нём значение. Можно ввести новое HEX-значение и нажать Enter. Таким образом нужно набрать все байты и завершить ввод нажатием точки. Теперь командой G можно запустить введённый код:

Конечно, из-за особенностей местного шрифта и настроек высоты символов результат смотрится неубедительно — примерно такая же проблема наблюдалась и в варианте для ZX Spectrum. Но всё же, если знать, как это должно выглядеть, и как следует прищуриться — какой-никакой лабиринт есть!
Наследие
Несмотря на простоту и древность, программа случайного лабиринта до сих пор завораживает и не отпускает некоторых энтузиастов. К этой теме регулярно возвращаются в компьютерной прессе, а в Интернете можно найти десятки публикаций и видео.
Культурный феномен программы оказался настолько значимым, что в 2014 году была опубликована целая 300-страничная бумажная книга под названием «10 PRINT CHR$(205.5+RND(1)); : GOTO 10» (сокращённо «10 PRINT»). Написана она группой из десяти авторов и издана британским отделением MIT Press.

В книге подробно рассматривается сама программа, её история и устройство, множественные вариации, феномен компьютерной культуры, созданной программистами-энтузиастами и их творческими изысканиями. К книге прилагается образ дискеты для Commodore 64, содержащей разные версии лабиринта, и не только его. Книга также свободна доступна и в электронном виде на посвящённом ей сайте, при желании можно ознакомиться.
Деятельность вокруг лабиринта кипит и за пределами бумажных и текстовых полей. Например, на YouTube этому занятию уделяют внимание авторы каналов 8-Bit Show and Tell и упомянутый ранее The 8-Bit Guy. Автор же первого канала создал ряд интересных вариаций программы, и исследовал многие моменты, часть которых была отражена и в этой статье. Помимо прочего, он создал аркадную мини-игру, использующую паттерн случайного лабиринта в своём оформлении.
Признаться, я и сам своего рода такой энтузиаст. И хотя я исторически и географически весьма далёк от компьютеров Commodore — в наших краях они были редкостью — и потому не столь глубоко погружён в тему, в один момент времени, когда я копался в истории ранних компьютеров, феномен однострочного лабиринта захватил и меня.
В 2022 году я отразил это увлечение в моей собственной демке BACK TO THE PET для Commodore PET, где одной из первых сцен следует шуточная отсылка к знаменитому лабиринту.
Заключение
Возможно, самая знаменитая строчка кода на Бейсике в истории —
10 PRINT “HELLO, WORLD!”:GOTO 10
Но однострочный лабиринт, пришедший к нам с 8-битного компьютера Commodore, определённо является вторым по знаменитости. И теперь вы знаете, что можно напечатать на вашей футболке, чтобы показать, как глубоко вы погрузились в лабиринты восьмибитной кроличьей норы.
© 2026 ООО «МТ ФИНАНС»


