Béton brut

10 PRINT

2022-01-15

Dyskusja na temat „czym jest sztuka, czym jest piękno” jest z nami tak długo jak długo istnieje klasa intelektualno-próżniacza, która mogła zadawać sobie takie pytania i szukać na nie odpowiedzi. Będąc bękartem tej klasy, odziedziczyłem tylko pół genotypu, jestem próżniakiem, dlatego na potrzeby dzisiejszego dnia zdefiniuję sztukę i piękno jako „to, co da się wyrazić jedną linijką w najgorszym1 BASIC-u”.

Najsłynniejszym przykładem „generowanej sztuki” jest 10 PRINT, jedna linijka w BASIC-u na C64, która generuje pseudolosowy labirynty. Jest możliwa tylko dzięki szczęśliwym zbiegom okoliczności. Prześledźmy ją krok po kroku.

10 PRINT CHR$(205.5 + RND(0)); : GOTO 10

PRINT nie trzeba nikomu tłumaczyć. Natomiast warto rozważyć dwa znaki interpunkcyjne. : pozwala na separacje poleceń, ; jest modyfikatorem dla PRINT i powoduje, że następne znaki nie będą wypisywane w nowej linii. CHR$() przyjmuje indeks i wypisuje znak znajdujący się pod nim w tabeli ASCII C642. Wartość 205 odpowiada /. RND() zwraca pseudolosową wartość w zakresie 0…1. GOTO zamyka pętle.

CHR$() jako parametr przyjmuje liczbę całkowitą. Jeśli podać mu liczbę zmiennoprzecinkową bezceremonialnie odrzuca wszystko po kropce bez zaokrąglania. To dla nas dobry zbieg okoliczności. Teraz rozważmy operację dodawania: 205.5 + [0…1] daje nam liczby z zbioru 205.5…206.5. Jak już ustaliliśmy CHR$() jest kompletnie nieczułe i widzi tylko dwie wartości. 205, które w tablicy ASCII odpowiada / i 206, kolejny szczęśliwy zbieg okoliczności, odpowiada \.

Ostatni pozytywny zbieg okoliczności? Piksele na 8-bitowych maszynach to materiał premium, twórcy komputera nie mieli luksusu martwienia się jak typografia „oddycha” na ekranie. Odstępy pomiędzy liniami nie są tego warte.

10 PRINT: wideo zrzucone z emulatora C64 demonstrujące efekt

I tyle: stawiamy znak \ lub / i pozwalamy naszemu mózgowi poukładać ten szum w kształty. Magiczne sztuczki wydają się głupie, gdy je wyjaśnić.

Dla zabawy „przeportowałem” ten kod na odpowiednik w Pythonie, niestety, Linuksowy terminal jest już bogaty w piksele i nie da się tak łatwo uzyskać jednolitych linii. Po ustawieniu fontu z C64 efekt był już całkiem zadowalający.

from random import choice
while True: print(choice(['/', '\\']), end='')

Szybka opowiastka o: random.choice zwraca losowy element z listy (tu dwuelementowa lista z \ i /, oczywiście), end='' do print() powoduje to samo, co średnik w BASIC-u, operacja nie kończy się nową linią.

10 PRINT: na Linuksie

Miałem w tym tygodniu opublikować inny tekst, ale chyba jestem kolejną ofiarą zarazy™ i nie mogę myśleć zbyt jasno. Widziałem wczoraj wideo w którym Robin optymalizuje 10 PRINT w asemblerze i pomyślałem, że to temat łatwy i przyjemny, a może ktoś z subskrybentów nie wie o fenomenie.

Kilka lat temu MIT wypuściło książkę o 10 PRINT, ma ona 324 strony, co jest pewną formą meta-sztuki nieosiągalnej dla zwykłych śmiertelników. Skłamałbym gdybym powiedział, że ją przeczytałem. Dość uważnie przekartkowałem ją spacją.

  1. TI/99 walczy zaciekle o koronę
  2. PETSCII, nie będę jednak dzielił włosa na czworo