Programátoři z pekel zde za šat a stravu programují čipová pseuda. Nyní s favicon!

Programujeme v BASICu: Seriózní programy (3)

Osmibity nebyly snad nikdy chápány jako úplně seriozní počítače. V sedmdesátých letech, když se na americkém trhu objevily první mikropočítače, byly většinou postavené na procesorech Intel 8008, Intel 8080 či Motorola 6800, měly žádnou či velmi malou paměť ROM a podobně na tom byla i jejich RAM. Takový Altair 8800 neměl za 400USD ROMku žádnou, RAMky čtvrt kilobajtu a pokud jste ji chtěli rozšířit na 4kB, stálo vás to stejně jako celý počítač. Pak jste do těch 4kB nahráli BASIC od Microsoftu a on vám nechal volných 700 bajtů pro váš program. Takovému výpočetnictví se operátoři minipočítačů oprávněně smáli, protože ve stejné době měli k dispozici stovky kilobajtů paměti a multitasking. Mikropočítače nebyly dost dobré ani na to, aby se na nich dala hrát proslulá hra Star Trek, protože v pár kilech paměti solidní vesmír nevygenerujete.

Krátké období, kdy byly osmibity opravdu k něčemu užitečnémi používány, bylo na přelomu 70. a 80. let, tedy v době po příchodu systému CP/M a před příchodem IBM PC. Osmibit vybavený tímto standardním systémem bylo možné najít v nejedné kanceláři – vytvořit nějakou tabulku, napsat text a poslat ho na tiskárnu, udělat daně pro garážovou firmu s pěti zaměstnanci – na nic z toho není třeba superpočítač. Později v osmdesátých letech cena komponent klesla a z osmibitů staly počítače do každé domácnosti, čímž se povětšinou zvrhly v herní či v lepším případě výukové stroje. ‎Pokud někdo chtěl něco užitečného a seriozního dělat, měl už na poli mikropočítačů k dispozici železo lepší, vícebitové.

Jediným místem, kde si osmibity z důvodu nedostatku čehokoliv lepšího přičichly k pravému computingu, byl tábor míru a socialismu. Jen tady Sord M5 počítal dávkování infuzí v nemocnici, ZX Spectrum počítalo televizní antény, kreslily se na něm plošné spoje či sázely časopisy. Ačkoliv to jasně ukazuje rozdíl mezi tehdejším západním a východním světem, je to vlastně uzavření kruhu, protože BASIC obsažený v ROMce většiny osmibitů nebyl původně Jánosem Kemenym vytvořen k nahrávání R-Type či Akcionáře 2, ale k seriózní práci.

Před pár lety jsem chtěl nějaké takové programování ukázat, ale po druhém díle jsem přestal, neboť zájem čtenářstva se ukázal jako limitně se nule přibližující. Je mi ale skoro dvaatřicet, mám vysokou školu, relativně slušné zaměstnání a jsem čerstvým otcem od rodiny, takže nadešel čas se jednou pro vždy vykašlat na názory čtenářstva a dělat to, co mě baví.
05 cls
10 let cy0=50.914: let cx0=14.84: let cy1=50.671: let cx1=15.381
15 let dmy=128: let dmx=128: let mlen = int sqr(dmy*dmy +dmx*dmx)
20 let stepy = (cy1-cy0)/dmy: let stepx = (cx1-cx0)/dmx
25 input "Bod 1 - sirka (Y): "; gy0
30 input "Bod 1 - delka (X): "; gx0
35 input "Bod 2 - sirka (Y): "; gy1
40 input "Bod 2 - delka (X): "; gx1
45 let y0=int((gy0-cy0)/stepy)
50 let x0=int((gx0-cx0)/stepx)
55 let y1=int((gy1-cy0)/stepy)
60 let x1=int((gx1-cx0)/stepx)
65 let adr=49152: let a=1: let x=x0: let y=y0: dim h(mlen)
70 let m=(y1-y)/(x1-x)
75 if abs(m) < 1 then let sg=sgn(x1-x0): let n=m
80 if abs(m) >= 1 then let sg=sgn(y1-y0): let n=1/m
85 let h(a) = peek (adr+int(y+0.5)*128+int(x+0.5))
90 let a=a+1
95 if abs(m) < 1 then let x=x+1*sg: let y=y+n*sg: if x<>(x1+sg*1) then goto 85
100 if abs(m) >=1 then let y=y+1*sg: let x=x+n*sg: if y<>(y1+sg*1) then goto 85
105 let gy0=(90-gy0)*(PI/180)
110 let gy1=(90-gy1)*(PI/180)
115 let fi=acs(cos (gy0)*cos (gy1) + sin(gy0)*sin(gy1)*cos((gx0-gx1)*(PI/180)))
120 let max=a-1
125 let a=1: let dy=0: let y=0: let cp=cos (-fi/2): let ainc=2
130 for x=-fi/2 to fi/2 step fi/max
135 plot a, y
140 draw 0, h(a/ainc)
145 let dy=750000*(cos(x)-cp): let cp = cos(x)
150 let y = y + dy
155 let a = a + ainc
160 next x
Program potřebuje pro svůj chod datový soubor nahraný od adresy 49152 a malé vysvětlení:

Když takhle stojím na vrcholku Ještědu (nebo libovolného jiného kopce), položím si často otázku, zda je teoreticky možno dohlédnout na Smrk, nejvyšší vrchol Jizerských hor (nebo libovolné jiné místo). Vysílám totiž v pásmu UHF a to se šíří podobně jako světlo – po přímce, žádné extra ohyby či odrazy se s použitou frekvencí a výkonem čekat nedají. Kdyby počítače neexistovaly, jedinou možností by bylo koupit si mapu Klubu českých turistů, mezi vybranými dvěma body udělat úsečku a pak po ní jít a zjišťovat, zda některá z vrstevnic, kterou úsečka protíná není příliš vysoká.

Problematické je už ono „příliš vysoká“, neb to nezávisí jen na čísle, které je u vrstevnice napsáno. Z dvourozměrné mapy nevyčtete jak vysoko vaše úsečka ve trojrozměrném prostoru probíhá a nevidíte v ní ani zakřivení Země, díky kterému objekty mají tendenci s rostoucí vzdáleností mizet za horizontem. Ještě, že máme počítače! Tam lze totiž problém výškového profilu rozdělit na dvě části, z nichž pouze jedna je starostí uživatele a ta druhá se skládá z posloupnosti kroků, které za nás vyřeší procesor (nebo v některých počítačích čip označený jako MOS6502 či MOS6510 s procesoru podobnou funkcionalitou).

Mapy.cz
Zvolená mapová oblast

Uživatel musí zajistit pro počítač data, bez těch to nepůjde. Před třiceti lety by uživateli nezbylo než si koupit zmiňovanou mapu KČT, udělat si na ní čtvercovou síť, v každém čtverci zjistit nadmořskou výšku a naťukat ji do počítače. Na rozdíl od středověkých programátorů my máme dneska mocné mapové servry, které nám tuhle informaci poskytnou, stačí se jich jen šikovně zeptat. Výše zobrazenou mapovou oblast jsem rozdělil na 128×128 obdélníků a pomocí několika skriptů jsem z jednoho těchto mocných serverů získal výškovou mapu převedenou do škály 0 (nejnižší bod mapy) až 127 (nejvyšší bod mapy). V šesnácti kilobajtech je tak pokryto zhruba 1200km2 s tím, že jeden obdélník (=1 pixel výškové mapy = 1 bajt datového souboru) reprezentuje výšku oblasti o velikosti 310×230 metrů. Vypadá to nějak takhle:

Mapy.cz

Nejkorektnějším postupem by bylo projít obdélník metr po metru a výšku oblasti stanovit jako vážený průměr. Méně korektní by bylo najít ve čtverci nejvyšší bod a tvrdit, že to je výška oblasti. Abych zvolený server příliš nehobloval a nedráždil, zvolil jsem bod přesně uprostřed obdélníku a použil jsem ten. Pravděpodobnost, že by se na těch pár desítkách či stovkách metrů našel naprosto zásadní výškový rozdíl je v českých pohořích malá.

Počítač po zadání dvou bodů mezi nimiž nás zajímá viditelnost musí udělat následující.
  1. Vytvořit spojnici mezi bodem A a bodem B. K tomu lze použít buď metodu Bresenhamovu nebo DDA. V podstatě jde jenom o „nakreslení čáry“ mezi dvěma body na mapě, tak jako kdyby to uživatel dělal pravítkem a tužkou. Jelikož BASIC ZX Spectra má číselné proměnné typu float (s desetinnou tečkou), neměl jsem důvod psát Bressenhama a zůstal jsem u DDA, které jsem vždycky intuitivně chápal lépe. Pokud by někdo zkoušel algoritmus například na Apple I, kde jsou proměnné pouze celočíselné, musel by volit opačně.
  2. Tuto spojnici vynést nad výškovou mapou a v každém jejím bodě zjistit nadmořskou výšku. V uvedeném zdrojáku obstarávají první dva kroky řádky 70100.
  3. Ke každému bodu je třeba ještě zjistit výšku zakřivení země. Spojnice mezi body A a B nakreslená nad dvojrozměrnou mapou by v zásadě měla být na trojrozměrné kouli ortodromou, takže můžeme zjistit středový úhel a ten buď dosadit do vzorce pro výšku kruhové úseče (pokud nás zajímá číselný výsledek), nebo vykreslit na obrazovku (pokud chceme grafické řešení).
  4. Uživateli vykreslit výškový profil jako součet nadmořské výšky a výšky dané zakřivením Země. Tento a předchozí bod zajišťují ve zdrojáku řádky 105160.
Rozdělení na dva samostatné bloky ve zdrojáku vzniklo převážně kvůli vykreslení zakřivení. Pokud nevím jak dlouhá je spojnice mezi body, těžko se mi bude kreslit úhel stejně dlouhý. Test jsem provedl mezi Ještědem a Smrkem, kterými jsem celé povídání o výškovém profilu začal:
Výškový profil bez zakřivení ZeměVýškový profil s zakřivením Země
gy0=50.733, gx0=14.985, gy1=50.888, gx1=15.273

Pro srovnání jsem vygeneroval nejdřív profil bez zakřivení a poté se zakřivením, aby bylo vidět, že na krátkých vzdálenostech to relativně není problém, ale jen za předpokladu, že někde uprostřed není nic vysokého. Pokud bych do paměti ZX Spectra dostal plochu větší a spojnice by byla v řádech stovek kilometrů, zakřivení by hrálo zásadní roli.
Počítač mi spočítal (respektive graficky ukázal), že z Ještědu na Smrk vidět je a měl bych se tam tedy i vysílačkou dovolat. Lze to nějak ověřit, tedy mimo toho, že dojedu na Ještěd, někoho vyšlu na Smrk a uděláme spojení? Naštěstí nejsem první, kdo takovouhle věc zkoušel:

Výškopis bez zakřivení ZeměVýškopis s zakřivením Země

Docela podobné, což? Vidíte, a vy jste na osmibitech hráli hry!

PS: Také věci rádi chápete a nemůžete pochopit konstantu 750000 na řádku 145? Vězte, že jsem k ní došel čistě experimentálně a odpovídá převodu výšky zakřivení Země na pixely tak, aby byl jeden pixel stejně vysoký, jako je jeden pixel z výškové mapy. Pravděpodobně by se dala spočítat při znalosti výšky nejnižšího a nejvyššího bodu v datovém souboru, ale nikdy jsem nebyl fanda implementační fáze a zjistit to pokusně mi přišlo rychlejší. Omlouvám se.