Úvod

Takže tentokrat už konečně začneme s nějakým tím skutečným programováním. Pro začátek samozřejmě něco jednoduššího... Co by to asi tak mělo být... Nechte mě chvilku přemýšlet... Áááá, už to mám! Bude to jednoduchá hra na hádání čísel. Ti z vás, co již někde programovali, asi vědí, jak to bude probýhat. Náš prográmek si prostě vymyslí nějaké číslo, a na vás bude ho uhodnout. čím dříve ho uhodnete, tím jste lepší. (odměnu si dejte sami :) Sami si budete moci zvolit obtížnost, která bude dána maximálním číslem, které si náš počítač může vymyslet. Aby to nebylo tak snadné, počet pokusů bude omezený v závislosti na maximální velikosti náhodného čísla.


Než začneme

Měm bych popsat pár funkcí, které budeme v tomto programu používat. Předně jde o funkce WriteF, která nám vypíše do CLI jakýkoliv text. Tuto funkci již velmi dobře znáte, ale tentokrát se naučíte i něco o formátování textu (neplést s formátováním harddisku). Dále pak použijeme funkci ReadEStr, která z CLI načte vámi napsalý text, a uloží ho do proměnné. Další důležitou funkcí je Val, která z textu udělá číslo, pokud daný text nějaké obsahuje. Další funkcí, kterou v tomto prográmku upotřebíme, je Rnd, jenž nám vymyslí náhodné číslo. Pak jsou tu ještě další funkce, ale jejich význam vám vysvětlím až to bude třeba.


Scénář

Teď je na řadě vymyslet, co všechno tento program bude dělat. Zaprvé, bude se muset zadat maximální hodnota náhodného čísla, podle kterého vypočítáme maximální počet pokusů. Pak musí tento program vymyslet náhodné číslo. Potom se nás počítač zeptá na první pokusné číslo. Pokud uhodneme, program se nás zeptá, jestli skončit, nebo pokračovat. Pokud neuhodneme, řekne nám, jestli je jeho číslo větší, nebo menší, než to, co jsme zadali. A pak se nás zeptá na další pokusné číslo... Pokud vyčerpáme maximální počet pokusů, program nám oznámí, že jsme prohráli, a jestli chceme hrát znovu. To by mělo stačit.


Hurá na věc

Než s čímkoliv žačneme, musíme funkci Rnd nastavit nějakou výchozí hodnotu. Funkce Rnd nevymýšlí náhodná čísla, ona si pouze podle nějakého principu vypočítá pseudo-náhodné číslo. Prostě jde o to, že pokud chceme mít skutečně náhodná čísla, musíme této funkci nejdříve zadat nějaké skutečně náhodné číslo jako základ. Toto číslo musí být záporné, aby funkce Rnd pochopila, že ji teprve nastavujeme. Když této funkci jako argument zadáme kladné číslo, vrátí nám pseudo-náhodné číslo, které může nabývat hodnot od nuly do velikosti argumentu mínus jedna, takže třeba a:=Rnd(10) nám do proměnné "a" zapíše hodnotu od 0 do 9. Teď jde ještě o to, jak získat skutečně náhodné číslo... Co se v počítači stále mění... No přece čas! Takže pomocí funkce CurrentTime, která na adresy svých argumentů ukládá aktuální počet sekund a mikrosekund. A protože se tyto hodnoty ukládají na adresy, musíme jako argumenty zadat adresy našich proměnných. Více informací o funkci CurrentTime si můžete zjistit v AutoDocech, konkrétně intuition.library/CurrentTime. Pro nás to ale není důležité. Takže teď k vlastnímu programu. Jako obvikle si napište známé PROC main() a ukončovací ENDPROC. Mezi tyto dva řádky pak napište následující:
  DEF sekundy,mikrosekundy
  CurrentTime(&sekundy,&mikrosekundy)
  Rnd(-mikrosekundy)

První řádek vytváří dvě promenné, a sice "sekundy" a "mikrosekundy". Tady bych chtěl upozornit, ze třeba v jazycích basic (některých) se k rozpoznání používá jen několik prvních znaků názvu proměnné. To v Déčku neplatí, tady můžete používat proměnné jak dlouhé chcete s omezením maximální délky asi okolo 60 znaků. Na druhém řádku je ona funkce CurrentTime, jenž ná za argumenty adresy našich dvou proměnných. Jak jistě vidíte, první proměnná "sekundy" se již nikde jinde nepoužívá, a tudíž byste si mohli říct, že je zbytečná, a že ji můžeme vynechat. Ale není to tak, je sice pravda, že mi ji nikde nepoužíváme, ale v systému se musí dodržovat předepsané používání argumentů, jinak může volání takové špatně zadané funkce způsobit zhroucení systému. Přesné podmínky najdete ve výše popsaném návodu k této funkci (intuition.library/CurrentTime). Teď ale postačí, když mi budete věřit :) Takže tahle funkce zapíše aktuální stav sekund a mikrosekund do našich dvou proměnných. Sekundy nás nezajímají, protože ty se mění jen jednou za sekundu :) Nás vic zajímaji mikrosekundy, ty se mění častěji, přesně milionkrát častěji, takže je vetší šance, že číslo, které bude v proměnné "mikrosekundy" bude dostatečně náhodné. A na třetím řádku vidíte, že funkce Rnd má negativní argument "mikrosekundy". Tím nastavujeme výchozí hodnotu, podle které se nám pak bude vytvářet pseudo-náhodné číslo.

Nyní nás pocítač požádá o zadání maximálního čísla, které si může počítač vymyslet, toto číslo nesmí překročit, řekněme hodnotu 10000. Pokud tuto hodnotu překročíme, počítač náš vyzve k zadání opravy.
  DEF maximum,text[20]:STRING
zacatek:
  WriteF('Zadejte maximalni cislo (enter=konec): ')
  ReadEStr(stdout,text)
  maximum:=Val(text)
  IF StrCmp(text,'')
    JUMP konec
  ELSEIF maximum<5 OR maximum>10000
    WriteF('Chyba, cislo musi byt v rozmezi 5 az 10000\n')
    JUMP zacatek
  ENDIF

Na prvním řádku opět definujeme proměnné, ale tentokrát už to není tak jednoduché. Doposud jsme používali proměnné pouze na čísla. K tomu nám stačí ta jednoduchá definice. Takže je jasné, že ta proměnná "text" nebude obsahovat pouhé číslo, ale jak už z názvu vyplývá, bude obsahovat text. A ti bystřejší z vás už pochopili, že tento text bude moci mít až 20 znaků. To klíčové slovo STRING je takzvaný typ proměnné (v tomto případě je to typ proměnné "text"). Ta hodnota mezi hranatýma závorkama nám říka, kolik bude mít tato proměnná místa v paměti. A protože tuto proměnnou definujeme jako typ STRING, tak bude mít tato proměnná pro sebe pameť velikou 20 bajtů, nebo chcete-li 20 znaků. Možná si řeknete, že je to dost málo, ale pro naše účely to postačí, protože my nebudeme potřebovat zadávat nic jiného, než číslo, takže by nám stačilo i méně znaků. Na druhém řádku je definice návěstí, kterou již známe z minulého tutoriálu, zde je jen proto, abychom se sem v prípadě potřeby mohli vrátit (skončit, či hrát znovu? B je správně). Pak následuje řádek s textem, který nám sdělí, abysme zadali maximální číslo, které si počítač může vymyslet. Na dalším řádku je již funkce ReadEStr, která má dva argumenty. První je argument "stdout", což je proměnná, která je předdefinována v PowerD automaticky. V tomto případě to znamená, že budeme načítat text z CLI. Druhým argumentem je naše proměnná "text", a to znamená, že do této proměnné budeme načítat to, co zadáme v CLI. ReadEStr je jakási obdoba příkazu INPUT A$ v basicu. Na dalším řádku je vidět funkce Val, která jak již bylo výše napsáno, zkonvertuje text na číslo. Takže pokud bude proměnná "text" obsahovat řetězec třeba "123", tak se nám do proměnné maximum uloží číslo 123. Tady je třeba vysvětlit, rozdíl mezi proměnnou, která obsahuje text, a která obsahuje číslo, či něco jiného. V basicu se to rozděluje snadno. Každá proměnná, která obsahuje text, končí pomocí znaku "$", třeba a$. Proměnná, která neobsahuje text, ale jen číslo je prostě jen písmeno, či název. V PowerD a ostatních podobných jazycích je tomu úplně jinak. Tady nezáleží na názvu promenné, tady záleží na jeho typu. Zjednodušeně řečeno máme typ "číslo", typ "text", a další. Výše jsme si ukázali, jak si nadefinovat proměnnou, která obsahuje text (typ STRING), obyčejné proměnné, které obsahují pouze čísla se nemusí definovat pomocí typu, což je také vidět výše. PowerD zná ještě mnoho dalších typů proměnných, než jen čísla a texty, ale to je na dlouhé povídání, a časem se k nim také dostaneme. Takže máme v proměnné "maximum" číslo, které jsme zadali. Nyní nás čeká podmínkový příkaz IF, o kterém jsme si něco málo řekli v minulém díle. IF v tomto případě není již tak jednoduché, jako v minulém případě, kde jsme potřebovali provést pouze jeden příkaz. Všimněte si odstavení řádku s IF a těch ostatních. Tam si všimnete, že řádek hned pod IF je odsunut o pár znaku dále, další pak řádek s ELSEIF je na úrovni IF, pak zase další odsazené, a nakonec ENDIF, které je také na stejné úrovni, jako IF a ELSEIF. Teď si vysvětlíme proč tomu tak je. V minulém případě jsme hned za IF a podmínkou použili klíčově slovo THEN, které signalizuje, že za ním následuje jediný příkaz, a tím se tento IF uzavírá. Tady ale musíme tento příkaz IF použít o něco složitěji. Pokud potřebujeme provést více příkazů, platí-li podmínka, nenapíšeme za tuto podmínku THEN, ale odřádkujeme, a napíšeme příkazů, kolik budeme chtít. Jakmile jsou všechny příkazy napsány, ukončíme tento podmínkový příkaz pomocí ENDIF, a nebo můzeme napsat jinou podmínku, která se bude testovat pouze v tom případě, že první podmínka nebyla splněna. Další podmínka se označuje pomocí ELSEIF a dále se používá úplně stejně, jako IF. Takových podmínek můžete napsat, kolik jich budete potřebovat. Nakonec uzavřete pomocí ENDIF. Vysvětlím na malém příkladu: Máme proměnnou "a", která obsahuje libovolné číslo od 1 do 5, a mi chceme, aby nám program toto číclo napsal slovy. K tomu použijeme právě vícenásobné použití IF/ELSEIF:
  IF a=1
    WriteF('jedna')
  ELSEIF a=2
    WriteF('dva')
  ELSEIF a=3
    WriteF('tri')
  ELSEIF a=4
    WriteF('ctyri')
  ELSEIF a=5
    WriteF('pet')
  ELSE
    WriteF('toto cislo neznam')
  ENDIF

Takže když to vezmu řádek po řádku, tak to bude probíhat asi takhle: Pokud se "a" rovná jedné, tak vypsat text "jedna", pokud ne, tak pokud se "a" rovná dvěma, tak vypsat text "dva", pokud ne, tak pokud se "a" rovná třem, tak vypsat "tri", pokud ne, tak pokud se "a" rovná čtyřem, tak vypsat text "ctyri", pokud ne, tak pokud se "a" rovná pěti, tak vypsat text "pet", pokud ne, tak vypsat text "toto cislo neznam". Davá to smysl? Snad ano. Určitě jste si všimli, toho "pokud ne" u každé podmínky. To znamená, že pokud neplatí žádná z předchozích podmínek v tomto příkazu IF, tak se může testovat další podmínka. A určitě jste si všimli, že na konci bylo pouze "pokud ne", a následovalo přímo vypsání textu. To znamená, že pokud nebyla splněna žádná z předchozích podmínek, provedou se příkazy, které jsou za klíčovým slovem ELSE, takže pokud proměnná "a" obsahuje cokoliv jiného, než čísla 1, 2, 3, 4 a 5, tak se vypíše text "toto cislo neznam". Pokud to není jasné, přečtěte si tento odstavec znova od začátku tolikrát, dokud to nepochopíte :)

Teď se vraťmě k našemu programu, tam je vidět, že pokud platí podmínka za IF, tak se provede příkaz "JUMP konec", a pokud tato podmínka neplatí, a zároveň platí podmínka za ELSEIF, vypíše se text, a provede se příkaz "JUMP zacatek". Teď si detailněji vysvetlíme ty samostatné podmínky. Zde používáme opět novou funkci, která se nazývá "StrCmp", což znamená "porovnat dva stringy" (=texty). Tato funkce má dva argumenty. (ona má tři, ale o tom třetím si povíme, až to bude třeba, teď nás nezajímá), oba musejí obsahovat proměnnou, která obsahuje text, či text samotný. Vy si můžete všimnout, že my používáme obě možnosti, první je proměnná "text" a druhý ja prázdný řetězec, což značí prázdný text (ohraníčený apostrofy). Takže funkce "StrCmp" porovná oba tyto texty, a nám sdělí, jestli jsou totožné, nebo ne. Pokud ano, tak podmínka IF platí, a to znamená, že se provedou příkazy rovnou za touto podmínkou, tedy "JUMP konec". Takže vzhledem k tomu, že porovnáváme proměnnou (od slova měnit se) s prázdným textem, tak pokud bude proměnná "text" obsahovat prázdný text, což znamená, že jsme nic nezadali a pouze odentrovali, skočí tento program na návěstí "konec". Toto návěstí ještě nemáme definované, k tomu dojdeme později. Takže pokud proměnná "text" obsahuje nějaký text, znamená to tedy, že v proměnné "maximum" máme nějakou hodnotu, a jak je napsáno v podmínce za ELSEIF, pokud je maximum menší než pět, a nebo pokud je maximum vetší než deset tisíc, napíšeme, že zadané číslo bylo špatné, a necháme zadat další. Tady musím ještě dodat, že funkce "Val" nám uloží do proměnné "maximum" nulu, pokud proměnná "text" neobsahuje číslo, ale text. I tato nula je zahrnuta v naší druhé podmínce (nula je menší, než pět), takže i tak nám napíše chybu, a vyzve k dalšímu zadání čísla.

Teď musíme dostat maximální počet pokusů, aby nebylo možné hádat do nekonečna. Je to velmi snadné, prostě odmocníme proměnnou "maximum" :)
  DEF pocet
  pocet:=Sqrt(maximum)

Toto je velmi jednoduché, a není k tomu moc co vysvětlovat. Snad jen, že od teď bude proměnná "pocet" obsahovat zbývající počet pokusů, po které ještě můžeme hádat. Řekl jsem "zbývající", protože tato proměnná bude měnit svou hodnotu od svého maxima k nule, a když dojde na nulu, znamená to, že už žádné další pokusy nejsou.

Teď přichází na řadu vlastně to nejdůležitější z tohoto programu, a sice vymyšlení našeho náhodného čísla. Jak jsem uvedl již výše, použijeme k tomu funkce "Rnd", která musí mít kladný argument a tím musí být maximum náhodného čísla, což je obsah proměnné "maximum", toto výsledné náhodné číslo si uložíme do proměnné "nahodne":
  DEF nahodne
  nahodne:=Rnd(maximum)

Takže teď k další části. Tady už začíná vlastní smyčka našeho programu. Totiž ta, kde my zadáme číslo, které si myslíme, že by to mohlo být:
  DEF cislo
smycka:
  WriteF('Zbyva vam \d pokusu.\nZadejte sve cislo (enter=konec): ',pocet)
  ReadEStr(stdout,text)
  cislo:=Val(text)

První, a druhy řádek by měl být jasný, pokud tomu tak není, podívejte se zpět, na první definici proměnné a návestí. Třetí řádek je již mírně složitější, takže se na něj podíváme detailněji. Jak je vidět, jde o již běžně používanou funkci "WriteF", která nám vypíše text, ani teď tomu nebude jinak, pouze toho vypíšeme o trošku víc. Určitě si říkáte, k čemu tam asi tak je to podivné "\d", určitě vám je jasné, že na jeho místě by měl být počet zbývajících pokusů, ale jak ho tam jen dostat. Je to velmi snadné. Funkce "WriteF" toho umí více, než se zdá, ona totiž umí pracovat s mnoha argumenty. První argument musí být text, ale ostatní mohou být cokoliv. A právě to "cokoliv" nám umožňuje vypisovat i různé další věci, jako třeba čísla, či texty. Abyste to správně pochopili, zjednodušeně vysvětlím jak funkce "WriteF" pracuje. Takže ona si vezme text, a začne ho písmenko po písmenku vypisovat. Když narazí na znak "\n", tak odřádkuje, a píše dál, dokud nenarazí na konec textu, takže takhle si můžete vypisovat jedinou funkcí i mnohořádkové texty. Když ale narazí na formátovací znak, jímž je právě znak "\d", tak se začnou dít další věci. V případě "\d", se vezme číslo z dalšího argumentu, a vloží se na místo tohoto znaku. Pokud narazí opět na další znak "\d", tak vezme zase další argument, a jeho obsah zase vypíše jako číslo. Dalším formátovacím znakem je "\s", což je to samé jako "\d", ale nevypíše číslo, ale text. Takže pokud narazí na "\s", a dalším argumentem bude proměnná, která obsahuje text, vloží tento text na místo znaku "\s". Toto jsou zatím jediné dva formátovací znaky, které budeme potřebovat, takže to dál nebudeme rozvádět. Pro více informací se podívejte na dokument: d:docs/strings.html, kde jsou popsány všechny formátovací znaky. Takže v našem případě, když funkce "WriteF" narazí na znak "\d", tak na jeho místo dosadí číselný obsah následujícího argumentu, v našem případě tedy obsah proměnné "pocet". Pro zjednodušení, a zvýšení čitelnosti PowerD podporuje rozdělení jediného textu na více řádek, pro příklad ukáži právě tu výše volanou funkce "WriteF", kterou rozložím na dva řádky:
  WriteF('Zbyva vam \d pokusu.\n'+
         'Zadejte sve cislo (enter=konec): ',pocet)

Zde vidíte, jak je to snadné, vlastně stačí ukončit text, a za apostrof připsat znaménko plus, a pak můžeme na dalším řádku pokračovat dalším apostrofem. Ve výsledku jsou obě tyto možnosti úplně stejné, takže záleží pouze na vás, jestli si text rozdělíte na více řádek, nebo jestli ho napíšete celý do jediné řádky. To byl třetí řádek, nyní čtvrtý a pátý, tam používáme opět funkci "ReadEStr" a "Val", a používáme je témeř stejně, takže k nim není co dodat. Snad jen, že po těchto řádcích by proměnná "cislo" měla obsahovat číslo, které jsme zadali, pokud jsme ho zadali správně. O tom ale rozhodne následující, a nejsložitější podmínka celého tohoto programu:
  IF StrCmp(text,'')
    JUMP konec
  ELSEIF cislo<0 OR cislo>=maximum
    WriteF('Chyba, nevesli jste se do rozmezi 0-\d, opakujte pokus\n',maximum-1)
    JUMP smycka
  ELSEIF cislo<nahodne
    WriteF('Me cislo je vetsi\n')
  ELSEIF cislo>nahodne
    WriteF('Me cislo je mensi\n')
  ELSEIF cislo=nahodne
    WriteF('Spravne!!! Uhodl jsi me cislo, zbyvalo jeste \d pokusu.\n',pocet-1)
    JUMP hotovo
  ENDIF

Stejně, jako u předchozí složitější definice IF, i tady nejdříve zkontrolujeme, zda jsme pouze neodřádkovali, a pokud ano, tak program ukončíme skokem na návěstí "konec". I druhá větev podmínkového příkazu IF je podobná té v předchozí definici. Je-li námi zadané číslo menší, než nula, znamená to, že jsme číslo zadali nesprávně, a tak ho zadáme znovu skokem na návěstí "smycka", což provedeme i v případě, že zadané číslo bude větší, než je dříve zadané maximum. Pro jistotu ještě před tím skokem vypíšeme rozmezí, v němž musíme naše číslo zadat, což je nula až maximum mínus 1. Jiné číslo nám totiž funkce "Rnd" stejně vrátit nemůže. Třetí větev IFu nám říká, že pokud je námi zadané číslo menší, než je počítačem náhodně vybrané číslo, tak nám tuto informaci sdělí, řekne nám tedy, že jeho číslo je větší. To samé, jen opačně nám říká čtvrtá větev IFu. Pátá a poslední větev IFu se provede pouze pokud jsou proměnná "cislo" a proměnná "nahodne" totožné. A pokud ano (a po neúspěšném otestování všech předchozích větví to ani jinak být nemůže) nám počítač sdělí, že jsme jeho číslo uhodli, a že nám zbývá ješte "počet-1" pokusů. Hned potom skočí na návestí "hotovo", které je definováno dále.

Teď následuje ta část programu, která se provede, jen pokud jsme program neukončili, vše jsme zadali správně, a i přesto jsme číslo zatím neuhodli:
  pocet--
  IF pocet=0
    WriteF('Je mi lito, ale nestihl jsi uhodnout me cislo v danem poctu pokusu.\n')
    WriteF('Me cislo bylo \d\n',nahodne)
    JUMP hotovo
  ENDIF
  JUMP smycka

První řádek je snadný, musíme odečíst počet pokusů, abysme nemohli hádat do nekonečna, takže pomocí "pokus--" odečteme od proměnné "pokus" jedničku. Na dalším řádku začíná další podmínkový příkaz IF. Tentokrát nám jde o zjištění, jestli jsme náhodou nevyčerpali všechny pokusy. Takže tato podmínka nám říka, že je-li obsah proměnné "pokus" roven nule, musíme tuto skutečnost sdělit hráči. Aby na nás hráč nebyl naštvaný, sdělíme mu, jaké, že číslo si počítač vymyslel, a pak už jen skočíme na návěstí "hotovo", jenž nám značí, že hádání je u konce. Po ukončení podmínkového příkazu IF klíčovým slovem ENDIF nám zbývá už jen skočit zpět na začátek smyčky a pokračovat v hádání. To provedeme příkazem "JUMP smycka".

A nyní následuje už jen dotaz, jestli chceme hrát znovu, pokud ano, tak skočit zpět na začátek, pokud ne, tak ukončit program.
hotovo:
  WriteF('Prejes si hrat znovu? (a/n): ')
  ReadEStr(stdout,text)
  LowerStr(text)
  IF text[0]="a" THEN JUMP zacatek

První tři řádky jsme tu viděli již několikrát, takže jen ve spěchu. Návestí, výpis otázky a načtení odpovědi do proměnné "text". Tady ale veškerá podobnost končí. Ve všech předchozích případech jsme se ptali na číslo. Tentokrát se ale ptáme na text, konkrétně na "ano", či "ne". Aby to bylo jednodušší, stačí nám pouze "a", jako kladná odpověď, a cokoliv jiného (třeba jen samotný enter) jako záporná odpověď. Ještě může nastat případ, kdy hráč napíše třeba "A" namísto "a", ale i na toto jsem pamatoval, a proto jsem použil funkci "LowerStr", která zmenší všechna velká písmena v proměnné, kterou jsme zadali jako její argument. Takže třeba "Ano" se změní na "ano". Na dalším řádku vidíte další podmínkový příkaz IF. Tentokrát na to jdeme trošku z jiného směru, abyste neopakovali pořád jen to samé. Proměnná "text" je proměnná typu STRING, což nám říká, že bude obsahovat nejspíš nějaký ten text. Taky jste si v její definici určitě všimli té její délky, tedy 20 bajtů. No, a pokud za název takovéto proměnné dáte hranaté závorky, a do nich napíšete číslo od nuly do devatenácti (pozor, počítáme od nuly, takže devatenáctka je vlastně dvacátý znak, pokud je nultý znak vlastně první v řadě). Tak výsledkem bude n-té písmeno tohoto textu. Pokud tedy zadáme "ano", tak text[0] bude roven "a", text[1] bude roven "n" a text[2] bude roven "o". Tady si dejte pozor na rozdíl mezi uvozovkami a apostrofy. Apostrofy uvádějí celý text, ale vracejí pouze jeho adresu, nebo-li ukazatel, zatímco uvozovky uvádějí písmeno přímo. Jak bych to jen vysvětlil, všechno v počítači jsou jen čísla. Tedy i písmena. Písmeno "A" vlastně reprezentuje číslo 65, a písmeno "a" zase číslo 97. No, a přesně tak to funguje i tady, takže pokud chceme zjistit, jestli proměnná text[0] obsahuje písmeno "a", mužeme napsat buď rovnou "a" nabo číslo 97, není v tom rozdíl, jen pro vás je to "a" čitejnější. Takže, pokud bude první písmeno proměnné "a", tak skočíme na návěstí "zacatek", a můžeme hrát znova.

Poslední, co nám schází, je definice návěstí "konec", kam skáčeme, pokud jakoukoliv otázku jen odentrujeme:
konec:
  WriteF('dekuji za vas cas!\n')

Myslím, že k tomu není co dál vysvětlovat. Po té nám zbývá doplnit už jen klíčové slovo ENDPROC, a tím program ukončit definitivně. Takže celý výpis programu vypadá takto:
PROC main()
  DEF sekundy,mikrosekundy
        CurrentTime(&sekundy,&mikrosekundy)
        Rnd(-mikrosekundy)

  DEF maximum,text[20]:STRING
zacatek:
  WriteF('Zadejte maximalni cislo (enter=konec): ')
  ReadEStr(stdout,text)
  maximum:=Val(text)
  IF StrCmp(text,'')
    JUMP konec
  ELSEIF maximum<5 OR maximum>10000
    WriteF('Chyba, cislo musi byt v rozmezi 5 az 10000\n')
    JUMP zacatek
  ENDIF

  DEF pocet
  pocet:=Sqrt(maximum)

  DEF cislo,nahodne
  nahodne:=Rnd(maximum)
smycka:
  WriteF('Zbyva vam \d pokusu.\nZadejte sve cislo (enter=konec): ',pocet)
  ReadEStr(stdout,text)
  cislo:=Val(text)

  IF StrCmp(text,'')
    JUMP konec
  ELSEIF cislo<0 OR cislo>=maximum
    WriteF('Chyba, nevesli jste se do rozmezi 0-\d, opakujte pokus\n',maximum-1)
    JUMP smycka
  ELSEIF cislo<nahodne
    WriteF('Me cislo je vetsi\n')
  ELSEIF cislo>nahodne
    WriteF('Me cislo je mensi\n')
  ELSEIF cislo=nahodne
    WriteF('Spravne!!! Uhodl jsi me cislo, zbyvalo Ti \d pokusu.\n',pocet-1)
    JUMP hotovo
  ENDIF

  pocet--
  IF pocet=0
    WriteF('Je mi lito, ale nestihl jsi uhodnout me cislo v danem poctu pokusu.\n')
    WriteF('Me cislo bylo \d\n',nahodne)
    JUMP hotovo
  ENDIF
  JUMP smycka

hotovo:
  WriteF('Prejes si hrat znovu? (a/n): ')
  ReadEStr(stdout,text)
  LowerStr(text)
  IF text[0]="a" THEN JUMP zacatek

konec:
  WriteF('dekuji za vas cas!\n')
ENDPROC

Možná vám to připadá, jako pěkně dlouhé, ale věřte, že to vůbec nic není! Sami jste se přesvědčili, že tu není nic složitého. A tak je to s každým programováním, složitý program se skládá pouze z mnoha jednoduchých částí. Věřím, že po této lekci si již dokážete dostatečně vyhrát s tím, co umíte, abyste si napsali svůj vlastní CLI program.

V příštím tutoriálu si pohrajeme s okny a vysvětlíme si jak fungují struktury, v nichž je ta největší síla celého systémového programování. Pokud máte nějaké dotazy, tak neváhejte a ptejte se mě přímo na adrese martinkuchinka zavinac seznam tecka cz. Přeji vám hezké programování.