10 PRINT ⌜ Technologia ⌟
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.
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ą.
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ą.