Diskuze o textových hrách

Tvorba Textových her => Programování => Téma založeno: gaspoda 17. Září 2015 - 10:34

Název: Seriál o programování textových her v TADS 3
Přispěvatel: gaspoda 17. Září 2015 - 10:34
Někteří asi víte, že Základna na asteroidu je naprogramovaná trochu jinak, než je u českých textových her zvykem. Vznikla v systému TADS 3, který jsem přeložil do českého jazyka. TADS je jeden ze dvou nejpropracovanějších systémů pro tvorbu interaktivní fikce ovládané příkazovým řádkem a jeho historie sahá až do roku 1988, kdy se objevila první verze, trojka je však zcela přepracovaná a slouží od roku 2006.

Když už jsem se do tak rozsáhlého projektu pustil, měl jsem od počátku v plánu víc, než jen naprogramovat textovou hru. Rád bych českým autorům přiblížil svět novodobé interaktivní fikce, která se na anglicky hovořící scéně rozvinula, a protože jsem především programátor, snažím se především pootevřít dveře k modernějšímu způsobu programování. Na serveru textovy.cz dnes začal vycházet seriál o programování textových her v TADS 3, který vás provede tím nejdůležitějším, s čím se při tvorbě her budete setkávat. V jeho sedmi dílech vydávaných zhruba po čtrnácti dnech se postupně podíváme na jednotlivé problémy, jako tvorba místností, předmětů, zpracování akcí a programování postav ve hře.

Seriál si určitě neklade za cíl stát se dokonale podrobnou učebnicí, na to máme k dispozici řadu knih, ale určitě získáte poměrně dobrou představu, jak se věci v TADSu řeší. V diskusi rád odpovím na jakékoliv dotazy, které by vás mohly napadnout, budete-li chtít vědět o některém tématu více, můžeme na něj navázat podrobnějším vysvětlením nebo dalšími příklady. Na konci seriálu pak dojde na (snad) největší lákadlo, chystám se vydat kompletní zdrojové kódy své hry pro zájemce, kteří by do nich chtěli nahlédnout a prozkoumat, jak je hra udělaná.
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: pedromagician 17. Září 2015 - 15:58
ty ma chces silou mocou dokopat k zverejneniu svojho enginu :-D

super už sa teším, večer si prečítam. klobúk dole pred takým projektom a ešte k tomu aj úspešne dotiahnutým do konca :-)
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: gaspoda 17. Září 2015 - 23:48
Chci cokoliv, o co bude zájem.

Chci ukázat problematiku z malinko jiného úhlu pohledu, možná trochu inspirovat nebo třeba i jen vyvolat zajímavou diskusi. Zkrátka chci trochu rozvířit stojaté vody! A když Pavel Tišnovský nezvedl hozenou rukavici a psal na rootu jen o Informu, tak jako kontrast chci ukázat ten druhý velký systém, který je úplně jiný, než Inform, a přitom se v obou tvoří velice podobně fungující hry.

Možná někde ve skrytu duše chci i trochu zaprovokovat, ale to spíš v reakci na adentův článek, který tu před časem odkazoval. Přišlo mi škoda, že je tak povrchní, že mluví jen o tom nejjednodušším způsobu programování, a ještě ho ani neukáže konkrétně, takže těm, kterým byl určený, asi moc nepomohl. A diskuse, zda předmět mimo mapu označovat -1 nebo 255, je o ničem. Přitom by se dalo diskutovat o spoustě zajímavých problémů, o programování parseru, o konverzačních systémech, o odvíjení příběhu atp.

Hlavně ale chci dát větší přidanou hodnotu zdrojovým kódům Základny a dopředu trochu vysvětlit, co v nich lidé uvidí, aby to pro ně bylo pak více přínosné, než kdyby do nich nakoukli bez jakékoliv předchozí znalosti.
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: SoulSoft 19. Září 2015 - 08:31
Tak to sa tesim aj ja. Dufam ze ta nalada na pisanie clankov neopusti a dokoncis to cim skor tym lepsie :).

Jedna zvedava otazka k tomu TADS3. To je IDE kde sa pise cisto len kod a kompiluje alebo sa tam daju naklikavat jednotlive objekty, miestnosti, akcie a k nim sa riesi kod? Nemal som este cas sa do toho poriadne pozriet tak aspon informativne pre moju predstavu. Dik.
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: gaspoda 19. Září 2015 - 10:11
Nemusíš se bát, já ve skutečnosti mám už připravených pět dílů ze sedmi (asi z 95 %), musím jen dopsat výživný díl o NPC postavách a závěr, ty jsem ještě nezačal. Chci to ale pouštět ven postupně, protože přeci jen je to poměrně dlouhé a náročné čtení, a pokud vzniknou otázky, tak bude lepší si nechat časový prostor a nemíchat jednotlivá témata dohromady, aby se udrželo soustředění. A pak to zajistí textovkám.cz trošku živosti po celý podzim.

TADS přistupuje k programování textových her (na rozdíl třeba od Inform 7) opravdu z čistě programátorského pohledu, takže i jeho vývojové prostředí se velice podobá vývojovým prostředím pro profesionální programátory. Základem je tedy textový editor, který zvýrazňuje syntaxi a má spoustu různých vymožností (záložky, hledání, skládání kódu, automatické odsazování atp.), debugger umožňující krokovat kód, vkládat breakpointy a prohlížet aktuální stav proměnných, objektů atp., správce a navigátor v projektu a také obsahuje integrovanou veškerou dokumentaci. Pár obrázků, jak prostředí vypadá, je na http://tads.org/ov_tools.htm (http://tads.org/ov_tools.htm).

Opravdu se tedy nejedná o naklikávání objektů, žádné vyplňování dialogů či průvodců, je to čistokrevné programování, kde výsledkem je zdrojový kód v textové podobě, jak bys ho vytvořil i bez jakéhokoliv vývojového prostředí. Já sám pracuji na Linuxu, takže Workbench používám jen zřídka, když potřebuji debugger, a celou Základnu jsem napsal ve svém olíbeném IDE pro C++ (v Qt Creatoru).

V prvním dílu jsem si zatím jen připravoval půdu pod nohami, ale už v příštím článku uvidíš reálné příklady, jak se vytvářejí místnosti ve hře a jak se spojují do mapy, a uvidíš, že to není zase až tak strašidelné. Vlastně možná budete překvapeni, že s barvičkami a hezkým odsazením zdrojáku to je i docela přehledné a hlavně hodně stručné, prim hraje skutečný obsah hry, tedy texty k zobrazení.
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: SoulSoft 19. Září 2015 - 20:08
Parada, je sa teda na co tesit. Zima je uz coskoro pred dverami tak bude aj viac casu straveneho u PC.
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: SoulSoft 21. Září 2015 - 20:31
Uz lamem TADS3 cez koleno. Objavuju sa prve zaciatocnicke problemy. Trebars tento kus kodu ukazuje chybu aj ked by mal byt spravny (sudim podla manualu a podla ineho tutorialu kde je to presne rovnake len iny nazov objektu)

Kód: [Vybrat]
pants: Wearable
    vocabWords = 'brown pants*pants clothes'
    name = 'brown pants'
    desc = "Pair of brown pants with pockets on the sides."
    location = room03
    dobjFor(Doff)
    {
        check()
        { // - tu hlasi chybu ze vyzaduje ; ale preco by tu mala byt?
            failCheck('You decided to leave them on yourself for now.');
        }
    }
;

Citace
Expected a semicolon ';' but found "{".  Please add the required semicolon.  If
a semicolon is already present, check for unbalanced parentheses or other
expression errors.

PS:Zapis sa da skratit ja viem. Tento sposob sa mi ale paci viac. Tu dobjFor cast nechce skompilovat IDE, je to divne. V com by mohol byt problem?
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: gaspoda 21. Září 2015 - 20:45
Ten kousek kódu, co jsi přiložil, je naprosto v pořádku (za předpokladu, že existuje někde room03, pokud by neexistovala, napsalo by to jiné varování). Myslím, že problém bude někde jinde ve zdrojáku, třeba někde ještě dříve. Zkontroloval bych, zda složené závorky jdou všude do páru atp.

Kdybys na to jó nemohl přijít, tak mi pošli mailem celý zdroják, já se ti na něj podívám. Můj mail je na úvodní stránce tads.cz dole.
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: SoulSoft 21. Září 2015 - 20:52
Vsetko ostatne ale funguje akonahle tu cast kodu zakomentujem

Kód: [Vybrat]
dobjFor(Doff)
    {
        check()
        { // - tu hlasi chybu ze vyzaduje ; ale preco by tu mala byt?
            failCheck('You decided to leave them on yourself for now.');
        }
    }

Ak tam v src toto nieje tak normalne spusti hru. Som v miestnosti. Mozem sa hybat do inej miestnosti. A vidim na zemi svoje 2 predmety s ktorymi mozem manipulovat. Tam fakt ine zatvorky navyse niesu. :-/
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: gaspoda 21. Září 2015 - 21:01
Já jsem si celý ten tvůj kousek hodil do svého zdrojáku a fungoval úplně v pořádku, takže kdo ví. Člověk pak podezírá, zda sis tam třeba nezkopíroval nějakou neviditelnou typografickou značku, pokud jsi základ bral z nějakého tutoriálu, či něco takového, co pak já ve fóru nevidím. Proto jsem nabízel, že mi můžeš poslat celý ten zdroják mailem (nejlépe v zipu), samotný úryvek je v pořádku. A nebo je opravdu něco nad tím.
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: SoulSoft 22. Září 2015 - 09:39
Uz som prisiel na problem. Je to tym ze som si rozdelil subory na viacero casti. Chcel som to tak ze v main subore su len definicie ohladom hry, pociatocnej pozicii, intro atd. A v ostatnych suboroch by bola mapa rozdelena na mensie kusy koli prehladnosti.

Problem sa vyriesil ked som do dalsieho suboru kde bola hlasena chyba vlozil riadok na zaciatok pre kniznicu #include <adv3.h>, pre istotu tam necham aj #include <en_us.h>

Code completition to IDE nema ze? To by sa zislo ako sol :-/.

Dalsi problem na ktory som narazil je ako obliect hlavnej postave nohavice hned od zaciatku. Ak definujem u nohavic vlastnost wornBy = me (je to vsade v manuali takto) tak engine sa sprava divne. Ako keby to bolo oblecene na postave ale zaroven to pri zobrazeni inventara nevidno zeby som to mal oblecene. Najlepsie mozno pochopit celu situaciu z logu kde mam dva predmety. Nohavice su wearable a wornBy = me, tricko je wearable a je len v miestnosti na zemi.

Citace
You see a brown pants (being worn) and a green shirt here.

>i
You are empty-handed.

>wear shirt
(first taking the green shirt)
Okay, you’re now wearing the green shirt.

>i
You are carrying nothing, and are wearing a green shirt.
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: gaspoda 22. Září 2015 - 10:23
No vida! Já věděl, že je problém někde jinde, než v tom kousku, který jsi posílal.

Rozdělení projektu na více souborů je naprosto v pořádku, já mám dokonce každou místnost a každou postavu v samostatném souboru, aby se mi v tom lépe hledalo. Na začátku každého soubou vždy uveď definici kódové stránky (#charset "windows-1250" apod.) i oba #include, bez nich by to nemohlo fungovat, každý soubor se totiž kompiluje zvlášť a potřebuje všechny definice všech maker, které se v souboru pak používají.

Konkrétně v tomto případě byla chyba nahlášena v daném místě proto, že hlavičkový soubor zavádí takzvané "propertyset", to je právě ta vymoženost zápisu dobjFor(Doff) { check() { ... }}. Interně se to totiž transformuje na méně přehledné, ale pro kompilátor stravitelnější definice samostatných funkcí, v tomto případě checkDobjDoff { ... }.

A teď ke tvé otázce s oblečením. Trochu předbíháš, ve čtvrtém dílu budu podrobně mluvit o kontejnerové hierarchii, takže nyní jen stručně. U objektu, který chceš, aby postava nesla, nastav location = me. Pokud je to oblečení (Wearable) a má ho mít postava obléknuté, nastav kromě location i wornBy = me, tedy obě(!) vlastnosti. Zkrátka oblečené olečení musí být také v inventáři postavy.
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: SoulSoft 22. Září 2015 - 13:24
Dik to je ono. Este ma napada jedna vec ci si to neriesil nahodou. Mas rozne objekty napr postel a tricko. Napisem prikaz wear all a logicky tym myslim len tie objekty ktore sa daju obliect. Hra ale zacne prechadzat aj postel a vypisovat "That isn’t something you can wear". Nejde tam prepnut aby tieto objekty proste ignorovalo a nevypisovalo? Obdobne je to u prikazov take, open, close, lock, unlock.
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: gaspoda 22. Září 2015 - 13:37
Ano, jde to, ale dá to trochu práci, takže se to vyplatí dělat jen tam a jen s těmi akcemi, kde to hráč nejpravděpodobněji bude zkoušet. Třeba v mé hře bylo několik kousků oblečení v úvodní lokaci, tak v ní (a ne jinde) jsem měl u ostatních objektů, jako třeba u dveří přidanou metodu hideFromAll, která právě řeší, zda se ten konkrétní objekt má ukrýt před kvantifikátorem "vše" v příkazu:

Kód: [Vybrat]
    hideFromAll(action)
    {
        return action.ofKind(WearAction)
            || action.ofKind(DoffAction)
            || inherited(action);
    }

Metoda má vrátit true, pokud má být objekt vynechán z "vše". Tedy v tomto případě jsem ukrýval dveře před "oblékni vše" a "svlékni vše". U jiných typů akcí se pak použilo výchozí zacházení, proto to inherited(action).
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: gaspoda 30. Září 2015 - 23:14
Zítra ráno vyjde druhý díl na téma programování lokací, tj. místností ve hře, jejich spojování do mapy ať už přímo nebo prostřednictvím dveří či jiných konektorů, programování bariér zabraňujících pohybu postavy konektorem a tvorbě atmosférických hlášek, které oživují hru.
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: pedromagician 12. Říjen 2015 - 21:32
zaujímavé poučné, už sa neviem dočkať ďalšej časti :-)
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: gaspoda 12. Říjen 2015 - 23:03
Jasně, zase ve čtvrtek ráno, konkrétně v 6.00 (to je takové to klasické Technoplanetí ráno ;-)) Tentokrát zaplníme místnosti spoustou nejrůznějších objektů, ať už přenosných předmětů či nepřenosných dekorací. Vysvětlíme si pojmenování objektu a zadání jeho slovníku i spoustu dalších užitečných vlastností. A nakonec v poslední pokročilé kapitolce dojde i na objekt "chrápání".
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: gaspoda 29. Říjen 2015 - 08:02
Tak dnes vyšel další díl o kontejnerech a jejich hierarchii. Na příště mám nachystaný díl o akcích, čímž se uzavře kolečo znalostí, které je potřeba znát pro každou hru. Poctivě však už chystám díl o NPC postavách, mám popsaný skoro celý mechanismus rozhovorů, akorát jsem narazil na malý zádrhel, že už teď je tak dlouhý, jako ostatní články, a potřebuji do něj ještě dostat samotné postavy, jejich stavy a agendu. Tak doufám, že to alespoň ti nejodvážnější z vás přečtou. Jo a najde se dobrovolník, který napíše Syrečky? :-)
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: tekket 6. Listopad 2015 - 01:24
Narazil jsem v knihovně na takovou skrytou podivnost u standardních odpovědi na CutWithAction ve VerbRule(CutWithWhat) - když napíšu uřízni strom - napíše mi zprávu(špatně) Co jím chceš uříznout, zatímco přeřízni strom napíše(správně) Čím ho chceš uříznout

Dost divné, tipuju na nějaký konflikt s VerbRule(CutWith), tam to dělá také - když zadám
uřízni nožem liánu - nožem nic nepřeřízneš - to je dobře
přeřízni nožem liánu - Čím chceš uříznout? - tohle ne

Také mě zaujalo, že existuje CutAction, ale nepoužívá jí žádné VerbRule a místo toho je zřejmě ono CutWithWhat, které prakticky pouze upozorňuje na absenci iobj
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: gaspoda 6. Listopad 2015 - 09:46
Ano, vidím chybu, že synonymum přezízni na rozdíl od uřízni bylo jen u akce CutWithWhat a ne u CutWith. Tím pádem došlo k tomu, že přeřízni nožem liánu bylo vyhodnoceno jako:

Kód: [Vybrat]
VerbRule(CutWithWhat)
    [badness 500] ('uřízni' | 'uříznout' | 'přeřízni' | 'přeříznout') singleDobj
    : CutWithAction
;

tedy "nožem liánu" bylo bráno jako singleDobj, tedy jako jediný objekt a to vedlo ke zmatku. Chceš-li si to opravit, přidej chybějící synonyma i do CutWith, které je hned pod tím v souboru cs_cz.t.

Nicméně na tomto místě je potřeba vysvětlit ještě jednu ošklivou záludnost českého jazyka, se kterou je potřeba pomoci parseru. Totiž akce CutWith je jedna z několika akcí, které nemají předložkami určenou roli objektů, jako v jiných příkazech (dej hrnek na stůl vs. dej na stůl hrnek). Hráč může stejně dobře napsat "uřízni liánu nožem" jako "uřízni nožem liánu" a TADS to neumí dost dobře odlišit, co je přímý objekt manipulace (liána) a co nepřímý (nůž). Tyhle případy je potřeba ve zdrojovém kódu pořešit a pomoci TADSu se rozhodnou, který objekt je iobj. Stačí noži přidat třídu PreferredIobj pomocí vícenásobné dědičnosti. Tím si pojistíte, že parser se nesplete a nebude si myslet, že chce hráč liánou uříznout nůž.

Pomohla tato odpověď, nebo ještě zbyl nějaký problém?
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: tekket 6. Listopad 2015 - 14:13
ještě jsem to nezkoušel, ale myslím, že přidání synonym by to zmatení parseru mohlo vyřešit.

To jsem si právě říkal, jak to funguje, když parser v podobném případě neví jestli jsem použil dobj iobj nebo iobj dobj, když příkaz akceptuje obojí. Vyzkouším to udělat dle tvého doporučení a přidám noži třídu PreferredIobj

Zatím si také nejsem jistý do jakého objektu dát akci, když se jedná o akci zahrnující přímý a nepřímý objekt.
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: gaspoda 6. Listopad 2015 - 14:22
Zatím si také nejsem jistý do jakého objektu dát akci, když se jedná o akci zahrnující přímý a nepřímý objekt.
V podstatě si můžeš vybrat. Obvykle je potřeba se buď řídit tím, jak je akce naprogramována v knihovně, pokud se snažíš upravit či změnit výchozí chování knihovny, nebo si vybereš ten objekt, kde je výsledek akce specifičtější. Tím myslím, že když máš pět provazů a přeříznout jdou jedním jediným objektem, tak akci naprogramuješ u něj. Když máš jeden provaz a přeříznout jde pěti různými objekty, naprogramuješ akci u provazu apod.
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: tekket 6. Listopad 2015 - 15:01
Jasně, to dává smysl. Takže v tomto případě by byl nejlepší nůž, i kdyby ve hře reálně fungoval příkaz jen na jeden objekt, protože by mohly existovat další situace, ve kterých by dávalo smysl, že chci něco uříznout, i kdyby to mělo hodit jen odezvu, že to nejde.

Sladění synonym u CutWithWhat a CutWith pomohlo. Jen odezva na uřízni lianu odpoví - Co jí chceš uříznout.

Ještě jsem přemýšlel, o takové vychytávce, že by ta akce pouze s přímým objektem automaticky vybrala vhodný objekt. Zjistilo by to např. jestli mám objekt odpovídající třídy a akci provedl s ním, případně by se zeptal, který pokud by jich bylo více. No, to už je taková pomalu zbytečnost.
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: tekket 6. Listopad 2015 - 18:50
Ještě pro úplnost k třídě PreferredIobj. Ještě by se mělo do VerbRule(CutWith) přidat: preferredIobj = PreferredIobj

Alespoň bez toho mi to nefungovalo.
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: gaspoda 6. Listopad 2015 - 19:43
Jasně, to dává smysl. Takže v tomto případě by byl nejlepší nůž, i kdyby ve hře reálně fungoval příkaz jen na jeden objekt, protože by mohly existovat další situace, ve kterých by dávalo smysl, že chci něco uříznout, i kdyby to mělo hodit jen odezvu, že to nejde.

V podstatě ano. Ale pro úplnost i zde platí, že je zároveň potřeba se řídit knihovnou. Akce CutWith je zakázaná verify metodou dobj i iobj, takže verify je nutné přetížit prázdným tělem v rámci dobj liány i iobj nože, čili na obou místech. Právě ty verify() metody zobrazují hlášku, že to nejde.

Sladění synonym u CutWithWhat a CutWith pomohlo. Jen odezva na uřízni lianu odpoví - Co jí chceš uříznout.

Mě to tu funguje, asi bychom se museli bavit o konkrétním testcase. Mám tu něco jako:

Kód: [Vybrat]
+ PreferredIobj, Thing 'nůž' 'nůž' *2
    iobjFor(CutWith)
    {
        verify() {  }
    }

    gcName = 'nože, noži, nůž, noži, nožem'
    gcVocab = 'nože/noži/nožem'
;

+ Thing 'liána' 'liána' *3
    dobjFor(CutWith)
    {
        verify() {  }
        action() { "{Kýmčím iobj} jsi přeřízl {kohoco dobj}."; }
    }

    gcName = 'liány, liáně, liánu, liáně, liánou'
    gcVocab = 'liány/liáně/liánu/liánou'
;

Ještě jsem přemýšlel, o takové vychytávce, že by ta akce pouze s přímým objektem automaticky vybrala vhodný objekt. Zjistilo by to např. jestli mám objekt odpovídající třídy a akci provedl s ním, případně by se zeptal, který pokud by jich bylo více. No, to už je taková pomalu zbytečnost.

To není problém, to tak funguje automaticky. Pokud je jen jediný nůž, tak příkaz "uřízni liánu" ho zvolí automaticky, pokud mám víc nožů, zeptá se "Čím ji chceš uříznout?"

S čím mám problém je příkaz "uřízni nožem", na to není TADS v anglickém originálu stavěný a já zatím nepřišel na to, jak v situaci s chybějícím objektem prohodit roli iobj a dobj, jinýmy slovy TADS předpokládá, že vždy chybí iobj.

Ještě pro úplnost k třídě PreferredIobj. Ještě by se mělo do VerbRule(CutWith) přidat: preferredIobj = PreferredIobj

Ano, už jsem si toho také všiml. Ono by to spíš mělo být tak, že v cs_cz.t by podmínka:

Kód: [Vybrat]
            if (preferredIobj != nil && dobjInfo.obj_.ofKind(preferredIobj))Měla být změněna na:

Kód: [Vybrat]
            if (preferredIobj != nil && dobjInfo.obj_.ofKind(preferredIobj)
                || dobjInfo.obj_.ofKind(PreferredIobj))

Ty akce bez předložek (MoveWith, TurnWith, BurnWith, CutWith, CleanWith, (Un)LockWith, (Un)ScrewWith) nemám zatím moc prozkoušené a doladěné.
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: tekket 6. Listopad 2015 - 21:24
Citace
Sladění synonym u CutWithWhat a CutWith pomohlo. Jen odezva na uřízni lianu odpoví - Co jí chceš uříznout.

Mě to tu funguje, asi bychom se museli bavit o konkrétním testcase.

Když jsem si s tím hrál, tak jsem ještě u objektů neměl dobjFor(CutWith). Nyní mám tedy objekty takto:
Kód: [Vybrat]
++ nuz: PreferredIobj, Thing 'japonský vojenský nůž' 'vojenský nůž' *2
    "Je to vojenský nůž japonské výroby, který jsi ukradl strážci. Je velmi ostrý, pozor! "

    gcName = 'vojenského nože, vojenskému noži, vojenský nůž, vojenském noži, vojenským nožem'
    gcVocab = 'vojenského japonského vojenskému japonskému vojenském japonském vojenským japonským
    nože/noži/nožem'

    iobjFor(CutWith)
    {
        verify() {  }
    }
;

+ liana: Hidden, Thing 'pevná pružná liána' 'liána' *3
    "Liána vypadá pevně a pružně. "
    initSpecialDesc = "Kousek od tebe visí liána. "

    gcName = 'liány, liáně, liánu, liáně, liánou'
    gcVocab = 'pevné pružné pevnou pružnou liány/liáně/liánu/liánou'

    dobjFor(Take)
    {
        check()
        {
            failCheck('Liána je příliš pevná a pružná, abys ji dokázal jen tak vzít. ');
        }
    }

    dobjFor(CutWith)
    {
        verify()
        {
            if(moved) { illogicalAlready('Nechceš liánu zbytečně řezat na menší kusy. '); }
        }
        action()
        {
            moveInto(gPlayerChar);
            "{Kýmčím iobj} jsi uřízl velký kus {kohočeho dobj} a omotal si ho kolem pasu. ";
        }
    }
;
akce s dobj i iobj proběhne vše správně. Když zadám pouze přeřízni liánu, tak dostanu:
(řežeš liánu)
Liánou nic nepřeřízneš

když už mám liánu v inventáři, tak je odezva: Co jí chceš uříznout?

Citace
To není problém, to tak funguje automaticky. Pokud je jen jediný nůž, tak příkaz "uřízni liánu" ho zvolí automaticky, pokud mám víc nožů, zeptá se "Čím ji chceš uříznout?"

To mi právě nejde, viz. výše. Je třeba ještě něco dopsat?

Jinak, nemám založit další diskuzi, abych to tady netapetoval?
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: gaspoda 6. Listopad 2015 - 22:00
Jo víš, co jsem ještě udělal? Já smazal z CutWith tu variantu s opačným pořadím, která nedávala smysl:
Kód: [Vybrat]
VerbRule(CutWith)
    ('uřízni' | 'uříznout' | 'přeřízni' | 'přeříznout') singleDobj singleIobj
    : CutWithAction
    verbPhrase = 'uříznout/řež{eš}/uřízl{a} (co) (čím)'
    askDobjResponseProd = singleNoun
    askIobjResponseProd = singleNoun
;

Co se týče diskuse, to je asi celkem jedno, on se stejně nikdo moc na seriál neptal, tak to ani moc nevadí. Samozřejmě pokud by vznikly dotazy k určitým tématům ve větším množství, tak by bylo užitečnější je mít v samostatných vláknech s titulkem vyjadřující to které téma, aby se v tom ostatním lépe hledalo, pokud by řešili stejnou věc.
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: tekket 6. Listopad 2015 - 22:30
Tak v tomhle byl problém. Je zajímavé, že i když se vymaže ta varianta s opačným pořadím, tak to příkaz s opačným pořadím pochopí.
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: gaspoda 6. Listopad 2015 - 23:28
Parser TADSu je pro mě zdaleka nejsložitější část, jejíž vrstvy loupu jen velice pomalu. Kdysi jsem si myslel, že musím ve VerbRule uvést obě možná pořadí dobj a iobj, aby si parser mohl vybrat tu správnou interpretaci odpovídající pořadí, v němž zadal objekty hráč.

Ale parser pracuje trochu jiným způsobem, jakoby ve dvou krocích nebo vrstvách. Nejprve vybuduje všechny možné syntaktické stromy, které odpovídají příkazu hráče. Nejen VerbRule, ale celé strukturální fráze, jejichž součástí někde uvnitř jsou VerbRule se svými sloty pro objekty. Matchuje jednotlivá slova z frází a slova ze slovníku, u kterých rozlišuje gramatické kategorie (podstatná jména, přídavná jména,...).

Může tak vzniknout celá dlouhá řada různých syntaktických interpretací příkazu zadaného hráčem, která se různě hodnotí a řadí podle nejrůznějších kritérií, aby se vybrala nejlepší interpretace. Důležité je pochopit, že výběr interpretace se stane dříve, než se resolvují slova v dobj/iobj slotech na konkrétní herní objekty a začne se zjišťovat, co příkaz znamená sémanticky a jaký smysl dává.

S příkazy, ve kterých není určena role objektů předložkou, jsem si dlouho lámal hlavu, až jsem problém nadhodil na anglickém fóru a Mikawa mi poradil řešení. Po resolvování slotů na herní objekty, kdy už je možné o objektech zjišťovat informace, jako třeba jejich třídu, se provede případné prohození slotů mezi sebou. Detaily jsou na: http://www.intfiction.org/forum/viewtopic.php?f=10&t=5480 (http://www.intfiction.org/forum/viewtopic.php?f=10&t=5480)
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: tekket 7. Listopad 2015 - 21:43
Teď si říkám, co se stane, když mám nůž s třídou PreferredIobj a chci hi použít v akci, kde ho chci mít jako dobj?
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: gaspoda 7. Listopad 2015 - 21:58
Pokud by měl být zároveň přímým objektem v nějaké akci, která vyžaduje přímé i nepřímé objekty, a proto nebylo vhodné, že se vždy prohazuje do role nepřímého objektu, tak je tu vždy možnost vykašlat se na mix-in třídu PreferredIobj. Místo toho můžeš nůž podědit z Thing do nějaké své třídy (řekněme class Knife: Thing; + knife: Knife;), aby byl snadno identifikovatelný a modifikovat akci CutWith tak, že ji nastavíš preferredIobj = Knife. Mrkni třeba na konverzační akce GiveTo, ShowTo. Ty mají nastaveno preferredIobj = Actor.
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: tekket 7. Listopad 2015 - 22:15
To je bezva řešení. Elegantnější, než PreferredIobj - kde vždy může nastat problém s tím, že se u každé TI akce přehodí na nepřímý objekt.
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: tekket 10. Listopad 2015 - 17:05
Mimochodem, kdy bude další díl seriálu?

Řeším teď nové VerbRule. Mám dle CutWith, CutWithWhat z knihovny vytvořené RepairWith, RepairWithWhat.

Normálně neúplný příkaz např. oprav nůž hra(přes RepairWithWhat) automaticky doplní vhodným objektem, pokud je přítomný. Já bych spíše chtěl, aby se v podobném případě parser pouze zeptal, pomocí čeho chci nůž opravit.

Když úplně odstraním RepairWithWhat, tak neúplný příkaz vede k tomu, že hra ho nepozná vůbec. Napadlo mě jediné řešení, že bych vytvořil obecnější TAction Repair, ale nejlepší by bylo mít pro příkazy zahrnující přímý a nepřímý předmět řešení s doplňujícím dotazem, ale u některých neumožnit automatické doplnění nepřímého předmětu.
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: tekket 10. Listopad 2015 - 17:07
Ve VerbRule se také často nastavují různé vlastnosti, ale nic, z čeho bych byl moudrý, jsem o nich nenašel. Možná jsem špatně hledal, ale třeba v Library Reference k některým je krátká věta, k některým nic.
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: gaspoda 10. Listopad 2015 - 18:51
Jako obvykle ve čtvrtek v 6.00 ráno. A jak je to s automatickým doplněním nebo naopak nedoplněním objektů v různých situacích a akcích bude vysvětleno ;-)
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: tekket 10. Listopad 2015 - 20:03
Tak, na to si rád počkám:)
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: tekket 12. Listopad 2015 - 22:56
Ok, takže nonObvious ve verify objektu to vcelku řeší. Další varianta je mít verzi akce pouze s dobj a vypsat u ní pouze nápovědu/upřesnění jak je příkaz třeba zadat.
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: gaspoda 13. Listopad 2015 - 07:53
Přesně tak, řeší se to pomocí nonObvious. Třeba v naší hře jsme měli tablet, který bylo možné >rozsvítit tablet, ale nechtěli jsme, aby se to stalo jen když hráč napíše samotné >rozsviť:
Kód: [Vybrat]
    dobjFor(Light)
    {
        verify() { nonObvious; }
        action() { replaceAction(Push, tabletButton); }
    }
U akcí se to pak řeší tak, že k jedné akci jsou dvě VerbRule, jedna s badness a místo slotu na iobj dělá v konstruktoru iobjMatch = new EmptyNounPhraseProd(), snadno to někde zahlédneš. Ale úplně do těchhle vnitřností zatím moc nevidím.
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: tekket 13. Listopad 2015 - 15:28
Jo, zkopíroval jsem si pro druhé VerbRule k opravit právě z CutWithWhat, které má badness 500 a řeší to, že když se příkaz nezadá celý, tak se parser hráče dotáže(nebo automaticky doplní, když nemám u akce v objektu nonObvious).

Jen mi přijde zvláštní, že kód v constructu se dle mého tváří, že doplní pouze chybějící iobj, ale podle hry doplní i dobj, pokud chybí.

Kód: [Vybrat]
VerbRule(RepairWithWhat)
    [badness 500] ('oprav' | 'sprav') singleDobj
    : RepairWithAction
    verbPhrase = 'opravit/opravuj{eš}/opravil{a} (co) (čím)'
    construct()
    {
        iobjMatch = new EmptyNounPhraseProd();
        iobjMatch.responseProd = singleNoun;
    }
;

Pořád mi není úplně jasné askDobjResponseProd a askIobjResponseProd (je např. v CutWith, mám podle něj RepairWith) - to má pochopit v jaké podobě očekává doplnění příkazu? Znamená to, že to nějak pracuje ve spojení s CutWithWhat, bez kterého se hra na doplnění vůbec ptát nebude a příkaz prostě nepochopí?
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: gaspoda 13. Listopad 2015 - 20:28
Jen mi přijde zvláštní, že kód v constructu se dle mého tváří, že doplní pouze chybějící iobj, ale podle hry doplní i dobj, pokud chybí.

Kdybys do toho chtěl více nahlédnout, tak je možné kdykoliv zapnout ladění parseru pomocí příkazu libGlobal.parserDebugMode = true; a pak se třeba o příkazu "uřízni", kterému chybí oba objekty, dozvíš, že byl zachycen oběma predikáty CutWith i CutWithWhat a to díky gramatice singleNoun(empty):

Kód: [Vybrat]
>uřízni
———-
firstCommandPhrase(commandOnly) [uřízni]
  commandPhrase(definiteConj) [uřízni]
    predicate(CutWith) [uřízni]
      singleNoun(empty) []
      singleNoun(empty) []
———-
firstCommandPhrase(commandOnly) [uřízni]
  commandPhrase(definiteConj) [uřízni]
    predicate(CutWithWhat) [uřízni]
      singleNoun(empty) []
—– Winner —–
firstCommandPhrase(commandOnly) [uřízni]
  commandPhrase(definiteConj) [uřízni]
    predicate(CutWithWhat) [uřízni]
      singleNoun(empty) []
    (provaz)
Čím ho chceš uříznout?

Z obou vyhrává CutWithWhat, protože má v součtu menší badness, než když se singleNoun(empty) doplnilo dvakrát. Ta gramatika singleNoun(empty) vypadá následovně, najdeš ji někde v hlubinách cs_cz.t:

Kód: [Vybrat]
/*
 *   An empty single noun is one with no words at all.  This is matched
 *   when a command requires a noun list but the player doesn't include
 *   one; this construct has "badness" because we only want to match it
 *   when we have no choice.
 */
grammar singleNoun(empty): [badness 500] : EmptyNounPhraseProd
    /* use a nil responseProd, so that we get the phrasing from the action */
    responseProd = nil

    /* the fallback responseProd, if we can't get one from the action */
    fallbackResponseProd = singleNoun
;

Proč je to takhle udělané, že je v gramatice prázdný slot na objekt i je varianta příkazu bez jednoho objektu, ti neřeknu, nerozumím tomu do takové hloubky. Možná by bez toho nebylo jasné, který objekt chybí, a proto se preferuje chybějící iobj před dobj, ale to opravdu jen spekuluji.

Pořád mi není úplně jasné askDobjResponseProd a askIobjResponseProd (je např. v CutWith, mám podle něj RepairWith) - to má pochopit v jaké podobě očekává doplnění příkazu? Znamená to, že to nějak pracuje ve spojení s CutWithWhat, bez kterého se hra na doplnění vůbec ptát nebude a příkaz prostě nepochopí?

Vlastnosti askDobjResponseProd a askIobjResponseProd ovlivňují to, jakým způsobem bude parser zpracovávat odpověď hráče na otázku ohledně chybějícího objektu. Při odpovědi na otázku "čím chceš liánu uříznout?" hráč asi odpoví "nožem". Některé příkazy ale mohou vybízet k odpovědi obsahující kromě samotného objektu i předložku, např. na otázku "na koho chceš zaútočit?" může hráč odpovědět "na Borise". Výchozí hodnotou obou vlastností je nounList a právě příkazy, u nichž je očekávána možnost, že hráč odpoví s předložkou, mají nastavenou některou z možností inSingleNoun, onSingleNoun a dalších, které jsou někde kolem řádku 6000 v cs_cz.t. U žádné z těchto variant není předložka povinná.
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: tekket 14. Listopad 2015 - 14:34
Citace
Kdybys do toho chtěl více nahlédnout, tak je možné kdykoliv zapnout ladění parseru pomocí příkazu libGlobal.parserDebugMode = true; a pak se třeba o příkazu "uřízni", kterému chybí oba objekty, dozvíš, že byl zachycen oběma predikáty CutWith i CutWithWhat a to díky gramatice singleNoun(empty):

Dobrý tip, vyzkouším. Asi si rovnou přečtu něco o ladění v Tads. Čtu vše víceméně podle aktuální potřeby na přeskáčku.

Citace
Vlastnosti askDobjResponseProd a askIobjResponseProd ovlivňují to, jakým způsobem bude parser zpracovávat odpověď hráče na otázku ohledně chybějícího objektu. Při odpovědi na otázku "čím chceš liánu uříznout?" hráč asi odpoví "nožem". Některé příkazy ale mohou vybízet k odpovědi obsahující kromě samotného objektu i předložku, např. na otázku "na koho chceš zaútočit?" může hráč odpovědět "na Borise". Výchozí hodnotou obou vlastností je nounList a právě příkazy, u nichž je očekávána možnost, že hráč odpoví s předložkou, mají nastavenou některou z možností inSingleNoun, onSingleNoun a dalších, které jsou někde kolem řádku 6000 v cs_cz.t. U žádné z těchto variant není předložka povinná.

To jsem víceméně odhadl dobře, jen mi to nesedělo s tím, že obě vlastnosti jsou definovány v CutWith, ale to pokládání upřesňujícího dotazu funguje díky CutWithWhat - no nechám to zatím být a budu předpokládat, že obě VerbRule prostě nějak pracují dohromady.

Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: gaspoda 25. Listopad 2015 - 23:18
Tak zítra následuje neobvykle dlouhý díl o NPC postavách. Doufám, že zaujme, protože konverzační systém v TADS je velice vychytaný.
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: gaspoda 24. Prosinec 2015 - 22:49
Tamtadadáá! Dnes konečně vyšel poslední díl a s ním jsem zveřejnil i kompletní zdrojové kódy Základny na asteroidu, první plnohodnotné české textové hry, která v TADS 3 vznikla.
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: tekket 10. Leden 2016 - 18:28
Super, už jsem si zdroják stáhnul, jen jsem to narychlo prosvištěl, je to hodně rozsáhlé. Na tads teď nějak nezbývá čas, tak snad mezitím všechno nezapomenu.
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: Kroužící orel 13. Březen 2017 - 17:40
Je to sice více, než rok od zveřejnění článku pro TADS a kódů pro Základnu, teprve nyní jsem se však dostal k tomu, abych si jej vytiskl a pořádně pročetl. Musím se přiznat, že návod je psaný perfektně a otevřel mi oči, možnosti TADSu jsou opravdu rozsáhlé a rozhodně stojí za to v něm textovku naprogramovat.

Zkoušel jsem nainstalovat kompletní prostředí TADS v Linuxu i Windows XP, poslední verze Workbenche 3.1.3 je alespoň na mých počítadlech dosti nestabilní a ani WINE v Linuxu na tom není jinak, s trochou trpělivosti se však použít dá. Naštěstí Frobtads funguje parádně a i v připraveném Debianu 9 je k dispozici v repozitářích, takže není co řešit. A mimo jiné mě donutí konečně se vrhnout na ovládnutí editoru VIM, poměrně nedávno vyšel balík pro zvýrazňování syntaxe pro TADS, tato kombinace mi umožní programovat i v příkazové řádce téměř na jakémkoliv počítadle.

Po přečtení článku jsem chca nechca musel přehodnotit svůj postoj k tvorbě příběhu i programování, poslední závěrečná kapitola parádně popisuje doporučenou možnost tvorby, je pravda, že jsem zatím žádnou cizojazyčnou textovku nehrál a neměl jsem tedy možnost srovnávání. Ale je to tak v pořádku, člověk se stále učí a bez přiznání svých chyb se zkrátka dále nedostanu.

Takže se vrhnu na to samé, co jsem měl v plánu před několika lety, v TADSu naprogramuji Exotera tak jak byl na Spektru a poté tu samou hru s využitím více jeho možností, následně Kroužícího orla, kde se ještě hodně zamyslím nad úpravou příběhu. Pedrův engine je prostě super a moc se mi líbí, cítím ovšem, že s TADSem budu moci využít nové možnosti plus se mnohé naučit, takže jdu na to.

Moc děkuji za článek, přesně ten jsem potřeboval.
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: gaspoda 14. Březen 2017 - 15:58
poslední verze Workbenche 3.1.3 je alespoň na mých počítadlech dosti nestabilní a ani WINE v Linuxu na tom není jinak, s trochou trpělivosti se však použít dá.

Nemohu moc posoudit, protože Workbench a obecně Windows téměř nepoužívám. Mám akorát virtuální prostředí na pracovním počítači a notebooku a nikdy jsem neměl pocit, že by nebyl stabilní, ale opravdu jsem to zapnul jen párkrát, když jsem potřeboval debugger, jinak používám jen FrobTADS a jako vývojové prostředí Qt Creator.

je pravda, že jsem zatím žádnou cizojazyčnou textovku nehrál a neměl jsem tedy možnost srovnávání.

To je škoda, to nějakou zkus, byť třeba s walkthrough po ruce, abyses nezasekával a prošel jí rychle. Vyplatí se kouknout, jak vypadají a fungují textovky známých autorů, kteří za ně kolikrát získali i ocenění.

Každopádně pokud nebudeš jen sršit přehnaným optimismem a skutečně se i pokusíš něco udělat, tak rád ve fóru zodpovím otázky, na které nevyhnutelně narazíš. Každopádně se snaž udržet na uzdě a nejprve zkoušej jednoduché věci, tedy deklarace místností a objektů, různé typy objektů a jak se chovají a až to budeš mít bezpečněji v ruce, tak teprve zkoušej různé akce a složitější interakci. Moje série článků je opravdu jen stručný přehled, ale ke skutečné práci to chce přečíst Learning TADS 3, alespoň kap. 1-9.
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: Kroužící orel 15. Březen 2017 - 09:20
Ano, s Workbenchem jsme na tom stejně. Já mám na notebooku staré Windows XP a Q4OS, do XP chodím spouštět pouze aplikace, které v Linuxu nedokážu stabilně emulovat a je odpojen od internetu, právě sem jsem instaloval poslední verzi TADS a krom toho, že jej nelze klasickým způsobem odinstalovat, padá tehdy, když zde založím nový projekt a vytvářím zdrojáky. Vyřešil jsem to jednoduše, zdrojový t soubor píši v linuxovém VIMu a debugguji ve Workbenchi spuštěným přes WINE, tam už mám vždy otevřený projekt a jen aktualizuji t soubor, zde alespoň zatím nemám problémy. Zvýraznění syntaxe funguje parádně, jediné, co chybí, je právě ten debugger, viz příspěvek jednoho uživatele také používacího QT Creator:

http://www.intfiction.org/forum/viewtopic.php?f=10&t=11378&start=10

Ve Q4OS používám Trinity, což je vlastně fork starého KDE3, syntaxe mi funguje i v Kate, Creator rozhodně vyzkouším.


Moc díky za informace, teď si projdu Learning TADS od Erica Eveho a prozkoumám volně dostupné zdrojáky her SampleGames.zip . Máš pravdu, jako neprogramátor musím nejdříve začít s deklarací předem připravených místností a objektů, to už jsem testoval minule právě na tom Exoterovi, ale dost ad hoc a vlastně jsem ani nechápal jaký kód vlastně píšu. A já bych rád programoval něco, co mě bude opravdu bavit a čím třeba potěším i ostatní, právě TADS vše krásně skloubí a díky Tvé sérii jsem pochopil jeho obrovské možnosti, jsem moc zvědav, co mi ukáže Learning TADS.

Díval jsem se na textovky, zkusím The Elysium Enigma od Eveho a Return to Ditch Day spolu s The Plant od Robertse, zde mám k dispozici i zdrojáky.

Jdu tvořit a určitě se budu ptát, už se těším...
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: Kroužící orel 22. Březen 2017 - 11:32
Tak jsem se pomalu pustil do práce, hlídám nemocnou dcérenku, ale ve volných chvílích studuji manuál od Eveho a několikrát ten Tvůj, připravuji zatím Exoteří lokace a jejich propojení. Ještě bych se rád zeptal na jednu drobnost, abych se vyznal v místnostech a jejich pojmenování, potřebuji si připravit mapu. V dokumentaci TADSu jsem nenašel, zda přímo Workbench něco podobného podporuje a zatím využívám Dungeon Crafter. Ve WINE spustím starší verzi 1.41 i zatím nejnovější 3 Silver, v první vidím paletu nástrojů, ale pod emulátorem mi nefunguje export výsledné mapy, naopak u 3 export funguje bez problémů, ale nevidím paletu nástrojů, ufff, tohle opravdu zamrzí. Zatím to řeším tak, že v jedničce udělám snímek obrazovky a ten oříznu GIMPem.

Jinak po aktualizaci Wine na dvojkovou řadu se Workbench zdá být stabilní, hurá.

Jak si u Základny řešil mapu pod Linuxem? Neznáš elegantnější řešení?
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: gaspoda 22. Březen 2017 - 12:39
Na rozdíl od Inform7, které má i nástroje pro vykreslení mapy (myslím automaticky ze zdrojáku), tak Workbench připomíná spíš běžné programátorské vývojové prostředí a tyto věci jsou mimo jeho oblast zájmu. Existuje program Trizbort (http://trizbort.genstein.net/ (http://trizbort.genstein.net/)), který je však windowsový. Měl by ale umět do jisté míry zpracovat log hry a mapu automaticky vytvořit. Ovšem asi jen v angličtině. Pak ještě vím o IFMapperu (http://ggarra13.github.io/ifmapper/en/start.html (http://ggarra13.github.io/ifmapper/en/start.html)), ale ani s ním nemám přímou zkušenost.

Já osobně jsem to totiž neřešil v podstatě nijak, mapu jsem měl natolik malou, že jsem si ji pamatoval. Stanovil jsem si, že budu cílit na zhruba dva tucty lokací, což pro mě byl rozumný rozsah hry, aby se i hráč v ní dobře vyznal. Pro kolegy jsem pak nakonec i jednoduchou mapu nakreslil v rámci nástrojů, které má OpenOffice, byla rozdělena na část lodi, základnu horní patro, spodní patro a koncovou část v tunelech. Kdybych chtěl něco hezčího, tak bych ji kreslil v Inkscapu.

Spíš co jsem řešil, tak že jsem organizoval zdrojáky tak, aby každá místnost měla samostatný soubor, aby se ve všem dalo rychle zorientovat a snadno přecházet mezi různými místnostmi. Totiž když je vše pohromadě v jednom souboru a je tam už hodně objektů, tak je to hodně rolování a blbě se hledá, kde člověk má nějaký objekt. Navíc TADS kompiluje jen nezbytně nutné soubory, ve kterých nastala změna, takže se šetří čas.
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: Kroužící orel 24. Březen 2017 - 12:30
Díky moc za info, Trizbort jsem vyzkoušel a ve WINE funguje, jen ten zpropadený export zlobí - v obrázku se zobrazí jen názvy lokací a ohraničení už ne. IFMapper je v tuto chvíli na serveru nedostupný, zkusím v pondělí. Takže zatím budu testovat Dungeon Crafter a Trizbort s využitím snímku obrazovky, je pravda, že u menšího počtu lokací to bude zcela dostačovat.

Já jsem si zatím vzal kostru zdrojáku Heidi.t, do které se snažím dosazovat místnosti, uznávám ale, že to asi nebude zrovna ideální řešení a Tvé rozdělení u Základny bude vhodnější. Připravím si tedy podobné soubory roomXXX.t jako máš ty a zkusím je zpočátku propojit, spolu s jednoduchou mapou bude pro mě vše parádně přehledné. Nemám holt alespoň zatím ty správné programátorské návyky, to ale přijde časem. Plus rychlost kompilace je pro mě důležitá, dělám teď na deset let starém armádním notebooku, takže to sakra ocením.

Přes víkend mám akci s řechtáky, ale dcérenka už je zdravá, takže se k TADSu konečně více dostanu a dám vědět jak se zadařilo plus určitě bude pár dotazů.

Příjemný víkend přeje Orel

Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: Kroužící orel 20. Duben 2017 - 12:36
V příloze zasílám svůj první výtvor. Celý původní Exoter jsem dohrál a veškeré popisy místností, předmětů a hlášek jsem připravil do souboru Exoter.t. Ještě mě čekají hlášky, které se objevují v některých místnostech, na ty se zaměřím až na konec. Zkusil jsem připravit konektory místností a doplnit i pár předmětů. Hnedle na počátku je třeba dostat se z první místnosti mříží, nevím, zda je mé řešení takto OK, trochu kostrbaté, ale funguje. Vše, co chybí, by mělo být v komentářích, nyní se zaměřím právě na jejich obsah. Místnosti jsou nyní již přístupné, čeká mě hlavně doplnění předmětů a omezení u dveří. Původně jsem plánoval udělat pro každou místnost samostatný soubor, jen mi to alespoň zatím přijde nepřehledné, takže zatím zůstanu u zdrojáku jediného.

Největší problém jsem měl s kódováním. Text vkládám v linuxovém GVimu a poté testuji debuggerem přes Workbench. Ze mě nepochopitelného důvodu jej GVim zobrazuje a na první pohled ukládá správně, po dalším načtení se ale znaková sada pokazila tak, že jsem soubor již nemohl otevřít ani v Linuxu ani ve Win. Můžeš se juknout na soubor Aktuální popis místností a lokací.txt, ke psanému textu jsem se nedostal ani pomocí UTF-8, ani žádného kódování pro DOS nebo Windows. Takže jsem všechna chybně se zobrazující nabodeníčka poctivě ručně přepsal, uff, hlavně, že jsem zatím jen u malého textu. Nyní edituji v Kate a vše raději ještě ukládám do pdf pro jistotu, naštěstí i on zná TADS syntaxi. Debugger však potřebuji, odhalil opravdu všechny syntaktické chyby a že jich bylo. Už vůbec nebudu pokoušet windows-1250, možná byl problém i zde, při utf-8 vše Workbench a především FrobTADS správně přeloží, i když se v něm u háčků a čárek zobrazují paznaky a např. znak "ř" nemohu vkládat vůbec. Měl jsi s kódováním taky takové bolesti?

Výsledný exe soubor jsem bez problémů spustil ve Wine a t3 zkompilovaný z Frobtadsu pomocí QTads, vše parádně funguje a s češtinou problém není. Konzolový frob také jede a pokud oželím nabodeníčka, funguje v ncurses režimu parádně a to i ve skutečné konzoli, nejen v terminálu. Čeština se mi v tomto režimu ani nezobrazuje, takže nevidím žádné blikající znaky, nyní jedu na Q4OS na svém armádním stroji. Právě jsem zkusil Tebou popisovaný přepínač -i plain -k utf8 a hurá, jako plaintext je vše v pořádku, tohle se mi moc líbí, určitě podobnou možnost využiji na Raspberry, ostatně dříve se takhle hrály BSDGames na terminálech serverů, pokud je pravda, co staří unixáci píšou.

Exoter bych moc rád nechal tak jak je, ještě si musím rozmyslet, zda i s tou otravnou smrtí, když vlezu do místnosti bez správného předmětu, chápu ale, že tohle "vylepšení" sloužilo ke ztížení jinak dosti krátké hry. Teď se zase vrhnu na Tvůj a Eveho manuál a budu si hrát s předměty plus jejich interakcí, zase dám vědět, až se dostanu o něco dále. Až se s principy TADSu více seznámím a zmáknu Exotera, rád bych se vrhnul na můj veleoblíbený Bad Night, ten už si ale lapnu jen jako inšpiraci a mám v plánu jej mohutně rozšířit včetně těch parádních atmosférických hlášek, tahle moje nej textovka na Spectrum si to určitě zaslouží. A text typu "jak do místnosti pronikají krásným mozaikovým oknem mihotavé paprsky světla" ze Tvého návodu zde využiji opravdu velmi často, moc se těším. No a poté zkusím prvního a konečně i druhého Orla... Ještě jednou díky za manuál, bez něj bych se do TADSu asi nikdy nepustil.

Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: gaspoda 20. Duben 2017 - 14:28
V příloze zasílám svůj první výtvor.
Proběhnul jsem to a pár postřehů posílám níže:

Řádka 34: Před "me" bys neměl mít plus, když zároveň nastavuješ location na kobku. Plus je totiž jen zkratka zastupující nastavení vlastnosti location. V tomto případě by plus znamenalo, že se location nastaví na gameMain, ale to by nedávalo smysl.

Řádka 44: Většinou se dává přednost nepsat otevírací a zavírací složenou závorku na úrovni objektu a místo toho ukončit definici objektu středníkem podobně, jako jsi výše definoval objekt Actora. Možné je oboje, ale není přehedné míchat styl v rámci jednoho zdrojáku. Také 'Kobka' můžeš napsat prostě v rámci šablony stejně, jako u chodby níže, tj. bez uvádění vlastnoosti roomName =. Podobně místo psaní desc = "" stačí naspat jen text ve dvojitých uvozovkách.

Řádka 51: Při výpisu zpráv pomocí dvojitých uvozovek je dobrým zvykem na konci věty po tečce nechat mezeru, jako to máš u desc výše. Je to proto, že TADS často hlášky kombinuje a doplňuje a mohl by vytisknout něco dalšího za tvým řetězcem a chyběla by pak mezera mezi větami. Ne, že by to byl tento případ, ale je to dobrý zvyk tak psát všechny zprávy.

Řádka 64: Objevení pilníku v mrtvole lze i méně otrocky, až budeš mít náladu, tak si prostuduj Hidden a PresentLater objekty. A asi by nebylo špatné použít RestrictedContainer, aby se do mrtvoly nedaly odkládat jiné objekty.

Řádka 89: Vlastnost noun nic neznamená. Nastavuj name a gcName pro zobrazené jméno a vocabWord a gcVocab pro slovník parseru. Nezapomeň, že správně a dokonale to bude fungovat až tehdy, když si dáš práci a zadáš všechno skloňování. Podobně u pochodně.

Na různých místech: Značka \n značí zalomení řádky, ale \b nebo <.p> je zalomení odstavce. Záleží, co chceš, ale přijde mi, že takové to zalamování řádek bez nového odstavce není přehledné a neodpovídá zbytku výpisu.

Původně jsem plánoval udělat pro každou místnost samostatný soubor, jen mi to alespoň zatím přijde nepřehledné, takže zatím zůstanu u zdrojáku jediného.

Pokud hra není příliš rozsáhlá, tak proč ne, ale hodilo by se místnosti oddělit třeba čarou vytvořenou z komentářových znamének, nebo tak. Já jsem to rozsypával do více souborů, protože objektů bylo hodně a měl jsem problém přecházet mezi a hledat, kde v souboru je určitá část.

Každopádně ale na sebe zkus být přísnější ohedně formátování zdojáku, aby byl jednotnější a přehlednější.

Největší problém jsem měl s kódováním. Text vkládám v linuxovém GVimu a poté testuji debuggerem přes Workbench. Ze mě nepochopitelného důvodu jej GVim zobrazuje a na první pohled ukládá správně, po dalším načtení se ale znaková sada pokazila tak, že jsem soubor již nemohl otevřít ani v Linuxu ani ve Win. Můžeš se juknout na soubor Aktuální popis místností a lokací.txt, ke psanému textu jsem se nedostal ani pomocí UTF-8, ani žádného kódování pro DOS nebo Windows. Takže jsem všechna chybně se zobrazující nabodeníčka poctivě ručně přepsal, uff, hlavně, že jsem zatím jen u malého textu. Nyní edituji v Kate a vše raději ještě ukládám do pdf pro jistotu, naštěstí i on zná TADS syntaxi. Debugger však potřebuji, odhalil opravdu všechny syntaktické chyby a že jich bylo. Už vůbec nebudu pokoušet windows-1250, možná byl problém i zde, při utf-8 vše Workbench a především FrobTADS správně přeloží, i když se v něm u háčků a čárek zobrazují paznaky a např. znak "ř" nemohu vkládat vůbec. Měl jsi s kódováním taky takové bolesti?

Ten .txt soubor má zmršené kódování, ve windows-1250 rozhodně není. Workbench bohužel neumí zobrazit a editovat Unicode, je to známá chyba, která nebude opravena, je to nějak moc složité. Zabudovaný editor Scintilla by utf uměl, ale zbytek workbenche ne. Debugovat se to dá, ale nesmíš to editovat.

Pro odhalení syntaktických chyb stačí překladač, debugger (krokování kódu příkaz po příkazu) je fajn, ale většinou není potřeba.
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: Kroužící orel 2. Květen 2017 - 13:07

Moc díky za postřehy, své poznámky posílám se znakem komentáře a na konci budou další dotazy a postřehy:

Řádka 34: Před "me" bys neměl mít plus, když zároveň nastavuješ location na kobku. Plus je totiž jen zkratka zastupující nastavení vlastnosti location. V tomto případě by plus znamenalo, že se location nastaví na gameMain, ale to by nedávalo smysl.

//Aha, sakra, myslel jsem si, že plus bylo i ve zdrojáku Heidi a bez přemýšlení jsem jej okopíroval, buď jsem jej viděl jinde nebo jsem si všiml, že je uvedeno u věcí, které má zpočátku na sobě a to mě zmátlo - jasné, pokud nastavuji lokaci, nemá smysl.

Řádka 44: Většinou se dává přednost nepsat otevírací a zavírací složenou závorku na úrovni objektu a místo toho ukončit definici objektu středníkem podobně, jako jsi výše definoval objekt Actora. Možné je oboje, ale není přehedné míchat styl v rámci jednoho zdrojáku. Také 'Kobka' můžeš napsat prostě v rámci šablony stejně, jako u chodby níže, tj. bez uvádění vlastnoosti roomName =. Podobně místo psaní desc = "" stačí naspat jen text ve dvojitých uvozovkách.

//Tady je vše jasné, místnost Kobka jsem zkopíroval ze šablony z manuálu, kde použili plný zápis a ty další místnosti už jsem si zjednodušil. Každopádně názvy i popisy místností musím sjednotit a hned si na to zvyknout. Nejprve jsem otevřené závorky zkusil vymazat, debugger ale nepochopil jak interpretovat mříž, takže jsem je vrátil na úroveň objektu, pokud je to takto správně.

Řádka 51: Při výpisu zpráv pomocí dvojitých uvozovek je dobrým zvykem na konci věty po tečce nechat mezeru, jako to máš u desc výše. Je to proto, že TADS často hlášky kombinuje a doplňuje a mohl by vytisknout něco dalšího za tvým řetězcem a chyběla by pak mezera mezi větami. Ne, že by to byl tento případ, ale je to dobrý zvyk tak psát všechny zprávy.

//Aha, stejný případ jako minule, desc u popisu Actora jsem zkopíroval ze šablony a jak vidím, u popisu mříže, pilníku a mrtvoly také, souhlasím, zvyknu si na tento zápis už zpočátku.

Řádka 64: Objevení pilníku v mrtvole lze i méně otrocky, až budeš mít náladu, tak si prostuduj Hidden a PresentLater objekty. A asi by nebylo špatné použít RestrictedContainer, aby se do mrtvoly nedaly odkládat jiné objekty.

//Rozumím, RestrictedContainer je určitě vhodnější, odkládat cokoliv do mrtvoly už nepůjde. Zkusil jsem použít hidden, více níže v dotazech.

Řádka 89: Vlastnost noun nic neznamená. Nastavuj name a gcName pro zobrazené jméno a vocabWord a gcVocab pro slovník parseru. Nezapomeň, že správně a dokonale to bude fungovat až tehdy, když si dáš práci a zadáš všechno skloňování. Podobně u pochodně.

//Pokusil jsem se doplnit skloňování, budu testovat přímo ve hře.

Na různých místech: Značka \n značí zalomení řádky, ale \b nebo <.p> je zalomení odstavce. Záleží, co chceš, ale přijde mi, že takové to zalamování řádek bez nového odstavce není přehledné a neodpovídá zbytku výpisu.

//Souhlasím, zalomení \b vypadá v textu lépe, upravil jsem tak všechny texty, kde toto dává smysl.

Citace: Kroužící orel  20. Duben 2017 - 12:36

    Původně jsem plánoval udělat pro každou místnost samostatný soubor, jen mi to alespoň zatím přijde nepřehledné, takže zatím zůstanu u zdrojáku jediného.

Pokud hra není příliš rozsáhlá, tak proč ne, ale hodilo by se místnosti oddělit třeba čarou vytvořenou z komentářových znamének, nebo tak. Já jsem to rozsypával do více souborů, protože objektů bylo hodně a měl jsem problém přecházet mezi a hledat, kde v souboru je určitá část.

Každopádně ale na sebe zkus být přísnější ohedně formátování zdojáku, aby byl jednotnější a přehlednější.

//Naprosto souhlasím, že sjednotit formátování zdrojáku je velmi důležité. Začal jsem světovými stranami a popisy východů z lokací, budu se držet směrů S, V, J, Z, N a D v celém textu. Zatím ponechám jediný zdrojový soubor, oddělení místností komentáři je super nápad, vyzkouším.

Citace: Kroužící orel  20. Duben 2017 - 12:36

    Největší problém jsem měl s kódováním. Text vkládám v linuxovém GVimu a poté testuji debuggerem přes Workbench. Ze mě nepochopitelného důvodu jej GVim zobrazuje a na první pohled ukládá správně, po dalším načtení se ale znaková sada pokazila tak, že jsem soubor již nemohl otevřít ani v Linuxu ani ve Win. Můžeš se juknout na soubor Aktuální popis místností a lokací.txt, ke psanému textu jsem se nedostal ani pomocí UTF-8, ani žádného kódování pro DOS nebo Windows. Takže jsem všechna chybně se zobrazující nabodeníčka poctivě ručně přepsal, uff, hlavně, že jsem zatím jen u malého textu. Nyní edituji v Kate a vše raději ještě ukládám do pdf pro jistotu, naštěstí i on zná TADS syntaxi. Debugger však potřebuji, odhalil opravdu všechny syntaktické chyby a že jich bylo. Už vůbec nebudu pokoušet windows-1250, možná byl problém i zde, při utf-8 vše Workbench a především FrobTADS správně přeloží, i když se v něm u háčků a čárek zobrazují paznaky a např. znak "ř" nemohu vkládat vůbec. Měl jsi s kódováním taky takové bolesti?

Ten .txt soubor má zmršené kódování, ve windows-1250 rozhodně není. Workbench bohužel neumí zobrazit a editovat Unicode, je to známá chyba, která nebude opravena, je to nějak moc složité. Zabudovaný editor Scintilla by utf uměl, ale zbytek workbenche ne. Debugovat se to dá, ale nesmíš to editovat.

Pro odhalení syntaktických chyb stačí překladač, debugger (krokování kódu příkaz po příkazu) je fajn, ale většinou není potřeba.

//Přesně tak, nyní využívám k editaci souboru KATE nebo GVIM s tím, že Workbench se vždy sám zeptá, zda chci změněný soubor aktualizovat. Pokud souhlasím, krokování kódu proběhne v pořádku ať už s chybami nebo bez nich, co naplat, hlavně, že o tom vím a nebude se opakovat ta nepříjemná zkušenost.

A nyní mé dotazy:

Při debuggování bych si potřeboval uložit pozici a testovat hru z konkrétní místnosti. Když ale hru ukončím a znovu zkompiluji, uložený soubor není kompatibilní. Je tu nějaká lepší možnost testování ve Workbenchi?

Zkoušel jsem použít na mrtovlu direktivu RestrictedContainer a Heavy, právě při použití Heavy není ve hře vidět, ale lze jí prozkoumat, dělám něco špatně? Po vymazání Heavy je zase vše OK.

Pokusil jsem se pilník definovat jako hidden, ale bez úspěchu, v takovém případě se sice zobrazí při zadání příkazu "koukni se do mrtvoly", ale následně prozkoumat ani sebrat nelze. Rád bych také místo otrockého příkazu "odemkni mříž" použil "přepiluj mříž". Pokud budeš mít chvilku, prosím koukni se na definici objektů mriz, mrtvola a pilnik, nyní si vůbec nejsem jist, zda tato definice není celá špatně. Prozkoumal jsem zdrojový kód Základny, hidden objektů je zde mnoho, nejpodobnější jsem nalezl v souboru roomAlien.t, po použití definice objektu sheet jsem se dál nedostal.

Kromě hidden objektů mě čeká nastudovat chování strážce a po jeho zabití manipulace s jeho předměty, podobné to bude i u draka a psa, rozsvícecní pochodně ve studni (o tom píšeš v návodu, takže by neměl být problém), naprogramování akce pádu do kupky sena nebo hráčovy smrti, pokud tam není. Dveře by měly být OK, ještě musím vyřešit omezení přechodu do lokace před jejich odemknutím, to nastiňuješ v manuálu, juknu se ještě na příklady v Heidi a u Eveho. Slovník předmětů jsem definoval, zatím jsem nepoužil pomnožný tvar. Mříž a pilník tedy zatím nechám být a budu se věnovat výše popsanému.
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: gaspoda 2. Květen 2017 - 21:15
Nejprve jsem otevřené závorky zkusil vymazat, debugger ale nepochopil jak interpretovat mříž, takže jsem je vrátil na úroveň objektu, pokud je to takto správně.

Jsou dvě možnosti, jak deklarovat objekt a Eric obě na začátku knížky popisuje. Buď se použije otevírací i uzavírací složená závorka na úrovni objektu, nebo se místo nich použije jen středník označující konec objektu. Druhý způsob je obvyklejší v praxi, protože je úspornější a přehlednější. Je dobré si na něj zvyknout, protože ho najdeš prakticky výhradně v dalších kapitolách knihy a a příkladech a rozšířeních stáhnutých z internetu. Tedy v tvém případě by to znamenalo první otevírací závorku vymazat a zavírací také vymazat a místo ní dát středník.

Pokusil jsem se doplnit skloňování, budu testovat přímo ve hře.

Jen u gcName na rozdíl od gcVocab musíš zadat pády, i když se opakují. Konkrétně v pořadí 2, 3, 4, 6, 7, tedy např. gcName = 'mříže, mříži, mříž, mříži, mříží'.

Při debuggování bych si potřeboval uložit pozici a testovat hru z konkrétní místnosti. Když ale hru ukončím a znovu zkompiluji, uložený soubor není kompatibilní. Je tu nějaká lepší možnost testování ve Workbenchi?

Při zkompilování hry vznikne vlastně "nová hra", která není co se týče uložených pozic kompatibilní s tou původní. Je to nutný důsledek toho, jak ukládání pozic a UNDO v TADSu funguje. Tyto funkce jsou vytvořené na nízké úrovni a pracují s binární reprezentací objektů v paměti virtuálního stroje. Uložená hra je vlastně obrazem paměti (tj. stav objektů), přesněji řečeno je to rozdíl oproti výchozímu stavu hry, který je uložený v samotném souboru s hrou.

Přímo Workbech má funkci, že když hraješ hru, tak nahrává jednotlivé příkazy do souboru a příště jedním dvojklikem můžeš celé sezení přehrát a podívat se, jak se hra změnila. Nebo příkazem >přehraj 'soubor' můžeš interaktivně přímo ve hře nechat přehrát soubor s příkazy. Já osobně ve Workbenchi běžně nepracuji, ale mám udělaný skript, který mi hru tímto způsobem otestuje a rovnou mi zobrazí změny oproti poslednímu průchodu, který považuji za správný:

Kód: [Vybrat]
#!/bin/sh

t3make -d
frob -i plain -k utf8 --no-pause -S -c -e 1000 -R testCommands.txt asteroid.t3 > testOutput.txt
diff -Nur testTranscript.orig testTranscript.txt > testTranscript.diff
kwrite testTranscript.diff

potom mám soubor s příkazy, do nějž postupně doplňuji cokoliv, co chci vyzkoušet, ten vypadá např.:

Kód: [Vybrat]
>zapni zápis
>testTranscript.txt
>restart
>a
>nápověda
>o hře
>kontrola překlepů
>zapni kontrolu překlepů

Na začátku hry jsme ve své kajutě.

>p sebe
>zhasni
>p dozimetr
>p ventily
>přemýšlej
>na 20
>přemýšlej o věčnosti

atd., u Základny má přes 2000 příkazů. Když jsem s výsledkem spokojený, tak překopíruji obsah souboru testTranscript.txt do souboru testTranscript.orig a tím vytvořím novou bázi pro hledání změn. Po každé úprave programu spustím ten výše uvedený skript, hra se přeloží a za chvíli mám před očima rozdíl v kwritu:

Kód: [Vybrat]
@@ -2138,8 +2182,8 @@
 >rozsvitit displej tabletu
 Zmáčkl jsi tlačítko a displej se rozzářil. Na obrazovce tabletu je zobrazena
 hra Dělostřelecký souboj. Na nádherně malované krajině v hyperrealistickém 2D
-zobrazení stojí dvě děla. Hra ukazuje, že děla jsou od sebe 10 km daleko a
-čeká, až zadáš úhel hlavně, pod kterým chceš vystřelit. (např. ZADEJ 45)
+zobrazení stojí dvě děla. Hra čeká, až zadáš úhel hlavně, pod kterým chceš
+vystřelit.

 Servisní šachta
 Jsi v servisní šachtě. Tudy vedou kabely z přední části lodi s řídicím

Sice je trochu otrava s náhodnými akcemi, ale i tak je to fajn a rychlé řešení, vlastně jsem při vývoji hru interaktivně skoro nikdy nehrál.

Zkoušel jsem použít na mrtovlu direktivu RestrictedContainer a Heavy, právě při použití Heavy není ve hře vidět, ale lze jí prozkoumat, dělám něco špatně? Po vymazání Heavy je zase vše OK.

Heavy je třída poděděná z Immovable a ta zase z NonPortable. Tyto třídy slouží typicky k reprezentaci různých pevných součástí lokace, jako je nábytek, lustr na stropě apod., které se nevypisují v rámci rozhlédnutí v místnosti, protože se předpokládá, že to není běžný objekt, který by si hráč mohl odnést.

Když pracuješ s nějakou třídou, kterou ještě moc neznáš, tak je fajn se podívat na její definici do referenční příručky: http://www.tads.org/t3doc/doc/libref/index.html (http://www.tads.org/t3doc/doc/libref/index.html) Po levé straně vyhledáš Heavy v seznamu tříd, klikneš a podíváš se na vlastnosti a metody, které třída definuje. Úplně nejlépe se pak můžeš prokliknout přímo do zdrojáku kliknutím na číslo řádky v pravém horním rohu, zde objects.t[2054]:

Kód: [Vybrat]
/*
 *   Heavy: an object that's immovable because it's very heavy.  This is
 *   suitable for things like large boulders, heavy furniture, or the like:
 *   things that aren't nailed down, but nonetheless are too heavy to be
 *   carried or otherwise move.
 *
 *   This is a simple specialization of Immovable; the only thing we change
 *   is the messages we use to describe why the object can't be moved.
 */
class Heavy: Immovable
    cannotTakeMsg = &cannotTakeHeavyMsg
    cannotMoveMsg = &cannotMoveHeavyMsg
    cannotPutMsg = &cannotPutHeavyMsg
;

Vidím, že se zde nastavují jen hlášky, tak zatočím kolečkem a podívám se výše (nebo najdu přes seznam) a podívám se na Immovable. Tam toho je trochu více, upravují se akce, ale když vyhledám ještě dalšího předka, tak najdu:

Kód: [Vybrat]
class NonPortable: Thing
    /*
     *   An immovable objects is not listed in room or container contents
     *   listings.  Since the object is immovable, it's in effect a
     *   permanent feature of its location, so it should be described as
     *   such: either directly as part of its location's description text,
     *   or via its own specialDesc.
     */
    isListed = nil
    isListedInContents = nil
    isListedInInventory = nil

Všimni si, že právě tady mají tyto objekty definováno, že na rozdíl od běžných přenosných objektů třídy Thing se nemají vypisovat ani v místnosti, ani v inventáři atp. A pokud bys chtěl, tak to můžeš zvrátit, nastavit některou z vlastností u své mrtvoly zpátky na true. Druhý mechanismus, který můžeš využít pro popis objektu, který je v místnosti důležitý a je potřeba ho zmínit, tak je nastavení vlastnosti specialDesc, viz příklady v Základně.

Pokusil jsem se pilník definovat jako hidden, ale bez úspěchu, v takovém případě se sice zobrazí při zadání příkazu "koukni se do mrtvoly", ale následně prozkoumat ani sebrat nelze.

Existují dva vzájemně se deoplňující způsoby, jak zacházet se skrytými objekty. Třída Hidden a PresentLater. Nevím, co přesně a jak jsi zkoušel, našel jsem ve zdrojáku zhruba tohle:

Kód: [Vybrat]
+ mrtvola : RestrictedContainer 'mrtvola' 'mrtvola' *3
;

pilnik : Key 'pilník' 'pilník' *2
;

Doporučil bych ti přidat Hidden třídu, tj. deklarovat pilník jako Key, Hidden. Tím způsobem bude objekt skrytý před zraky, jako by ve hře nebyl, dokud nebude objeven. Hidden má ještě jednu vlastnost a sice že takové objekty hráč automaticky nalezne, pokud prohledá kontejner (>podívej se do mrtvoly).

Aby ti to fungovalo, musíš udělat ještě jednu důležitou věc - musíš pilník umístit do mrtvoly. To uděláš tak, že přidáš dvojici znamének plus před deklaraci objektu. Dvě proto, že mrtvola má znaménko jedno a místnost žádné, tedy mrtvola je v místnosti a pilník v mrtvole. Když není znaménko žádné, tak pilník existuje, ale není nikde ve hře umístěn. Podobně by to fungovalo u PresentLater, jen bysis tam musel sám objekt zviditelnit při prohledání. Ale v obou případech platí to o nutnosti psát známénka plus. Podobně na konci zdrojáku nemáš provaz v truhle.

Zahlédl jsem ve zdrojáku také poznámku "nevím, zda má smysl dobjFor(Search) asDobjFor(LookIn)". Kdybys po tom pátral, tak najdeš, že u Thing je právě tohle udělané a Container to trochu mění v tom smyslu, že akce Search (>prohledej něco) na rozdíl od LookIn (>podívej se do něčeho) má malinko upravené podmínky a na rozdíl od nahlédnutí vyžaduje, aby se postava předmětu mohla dotýkat. Ale to je pro tebe nezajímavý detail, takže nemusíš přesměrovávat akci.

Rád bych také místo otrockého příkazu "odemkni mříž" použil "přepiluj mříž". Pokud budeš mít chvilku, prosím koukni se na definici objektů mriz, mrtvola a pilnik, nyní si vůbec nejsem jist, zda tato definice není celá špatně.

To je pak něco jiného. V tom případě by se asi hodilo přepilování modelovat jako samostatnou akci a vůbec nebrat pilník jako klíč ke dveřím. Co se týče "dveří", které se nedají otevírat hráčem jako běžné dveře, ale mají nějakou formu externího ovládání, tak to viz dveře přechodové komory v Základně. Co se týče přepilování, tak viz některou definici nového příkazu, ale to je trochu pakárna, tak bych si to schoval, až budeš jistější.

Stručně chce to definovat akci a k ní VerbRule. Potom modify Thing a definovat základní chování příkazu se všemy objekty (něco jako hlášku Tohle není něco, co bys mohl přepilovat) a selektivně povolit u žádaných objektů. Aby to bylo dokonalé, tak to chce TAction i TIAction, aby reagovalo na >přepiluj mříž, >piluj pilníkem i >přepiluj mříž pilníkem. U té poslední varianty je ještě problém s tím, že ji lze říci v obou pořadích slov, takže musíš pořešit, aby parser nepochpil, že má mříží přepilovat pilník, viz debata s Tekketem.

Slovník předmětů jsem definoval, zatím jsem nepoužil pomnožný tvar.

Pomnožné jsou např. typicky dveře, těm bys měl nastavit isPlural = true. Když to neuděláš, tak bude hra špatně reagovat, když napíšeš příkaz >prozkoumej dveře a vzápětí zkusíš >otevři je, tak parser nebude vědět, že slovem "je" se odvoláváš na dveře.

+ drahokam_1 : Thing 'drahokam č. 1' 'drahokam č. 1' *2
  "Je nádherný. "
    gcName = 'drahokamu č. 1, drahokamu č. 1, drahokam č. 1'
    gcVocab = 'drahokamu č. 1/drahokamu č. 1/drahokam č. 1'
;

Tady pozor, takhle nemůžeš zapsat slovník. Jednak si nejsem jistý, jestli parser rozdejchá tečku za "č", ale hlavně když se zapisuje několik synonym, tak nemůžeš psát delší frázi lomeno delší frází. Vždy to je ve formátu "přídavné přídavné podstatné/podstatné*množné", takže gcVocab = 'drahokamu' a nahoře v šabloně 'drahokam (č.) 1'. Závorky označují nespecifickou část slovníku, tedy slova, která když jsou použita samotná, tak nejsou brány jako shoda, protože jsou moc slabá.

Nicméně vřele bych se doporučil těmto problémům úplně vyhnout např. označením 'první diamant' apod.
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: Kroužící orel 4. Květen 2017 - 11:33
Citace: Kroužící orel   2. Květen 2017 - 13:07
deklarace objektu
//Ano, na straně 11 jsem tuto informaci našel přesně tak jak píšeš. Nyní již používám všude zkrácený zápis s ukončovacím středníkem. A právě zde jsem v příkladu s první hrou našel direktivu noun, kterou jsem dříve používal, aniž bych věděl, co znamená.

Citace: Kroužící orel   2. Květen 2017 - 13:07
Pokusil jsem se doplnit skloňování, budu testovat přímo ve hře.
Jen u gcName na rozdíl od gcVocab musíš zadat pády, i když se opakují. Konkrétně v pořadí 2, 3, 4, 6, 7, tedy např. gcName = 'mříže, mříži, mříž, mříži, mříží'.
// Rozumím, opakující se pády jsem zadat zapomněl, ale máš pravdu, v manuálu píšeš o nutnosti zadat všechny pády. Všude opraveno. Je to sice pracné, ale musím uznat, že pocit z parádní češtiny na Základně stál za to, nedivím se, že právě zde kladeš takový důraz. Jo, musím se přiznat, že jsem si pády musel pořádně zopakovat, už jsem pár let ve škole nebyl...

Citace: Kroužící orel   2. Květen 2017 - 13:07
debug a uložení pozice ve WB
// Tohle je moc zajímavé jak píšeš práci s pozicemi. Jestli dobře rozumím, využívá se zde malý virtuální stroj podobně jako v javě – uložená hra je tedy obraz aktuální paměti, který rekompilací ztrácím. Mě se hned od začátku seznámení se s TADSem líbila možnost UNDO, na kterou nejsem z našich textovek zvyklý, teď už vím odkud vítr fouká…
Pořádně jsem se podíval do manuálu k Workbenchi, v sekci Scripting and Auto-Scripting jsem našel přesně to, co jsem hledal. Nyní k testování využívám automaticky generované skripty s příponou cmd – ty mohu vyvolat i po překompilování hry a je to asi nejpohodlnější způsob, v samotném Workbenchi se zobrazují správně i s diakritikou na rozdíl od jejich ručního otevření v Linuxu. Skriptovací funkce naštěstí pod emulovaným WB fungují bezchybně a moc mi testování ulehčuje, hurá.
Ale Tvůj skript je taky bezva řešení, hnedle jsem si říkal, že ty soubory testTranscript a testPlay v Základně nebudou jen tak pro nic za nic.  Skoro 700kb textu, to by bez tohodle mechanizmu otestovat opravdu nešlo. Upravil jsem jej pro Exoter a funguje parádně, je to super možnost i pro příkazovou řádku. Zajímalo mě, zda testCommands.txt schroupne i češtinu, naštěstí výsledný testOutput.txt jí zobrazuje naprosto bez problémů, jasné, tady je opravdu potřeba direktiva frob -i plain -k utf8.

Citace: Kroužící orel   2. Květen 2017 - 13:07
Zkoušel jsem použít na mrtovlu direktivu RestrictedContainer a Heavy
// Aha, tady narážím na své limity, protože programování šlo prozatím zcela mimo mě. A přitom ve svém manuálu o TADS 3 Library Reference Manual píšeš. Je parádně zpracovaný, prozkoumal jsem kromě Heavy i další, super příručka, už se stahuje wgetem, ať nemusím být vždy závislý na připojení. Stále čtu o vlastnostech, metodách, třídách a objektech, ovšem abych plně vše pochopil, musím začít na příkladech a právě tento manuál je to pravé. Moc se mi líbí ta možnost proklikat se do zdrojáku – nemusím zdlouhavě procházet objects.t, ale hned vidím číslo řádky. Tady vidím class Heavy: Immovable – takže pokud to dobře chápu, Heavy je potomek třídy Immovable, kterou rozšiřuje dalšími parametry a zachovává si všechny její vlastnosti. A nad CustomImmovable nacházím class Immovable: NonPortable plus ouplně nahoře je hlavní třída Thing, teď už je to jasné.
Takže jsem upravil mrtvolu jako RestrictedContainer, Heavy a přidal direktivu isListed = true
Teď už se chová jak má, tohle je opravdu cenná praktická zkušenost.

Citace: Kroužící orel   2. Květen 2017 - 13:07
Pokusil jsem se pilník definovat jako hidden, ale bez úspěchu...
// Ano, zkoušel jsem před objekt pilník definovat dvakrát plus takto:

+ mrtvola : RestrictedContainer 'mrtvola' 'mrtvola' *3
++ pilnik : Key, Hidden 'pilník' 'pilník' *2

Ovšem situace je stále stejná, hráč po příkazu koukni se do mrtvoly sice pilník vidí, ale není možné jej sebrat. Po odstranění direktivy Hidden je vše v pořádku. Tady mě to docela mate, raději dopíšu celou definici:

+ mrtvola : RestrictedContainer 'mrtvola' 'mrtvola' *3
 "Je v pokročilém stádiu rozkladu. "
     gcName = 'mrtvoly, mrtvole, mrtvolu, mrtvole, mrtvolou'
     gcVocab = 'mrtvoly/mrtvole/mrtvolu'
   dobjFor(LookIn)
   {
      action()
      {
         if(pilnik.moved)
         {
            "Na mrtvole jsi neobjevil už nic zajímavého. ";
            exit
            ;
         }
            pilnik.moveInto(self);
                     "Bližší pohled na mrtvolu odhalil pilník schovaný v záhybech polorozpadlých šatů! ";
      }
   }
;

++ pilnik : Key, Hidden 'pilník' 'pilník' *2
       "Je šikovně upraven na přepilovávání mříží. "

       gcName = 'pilníku, pilníku, pilník, pilníku, pilníkem'
       gcVocab = 'pilníku/pilníku/pilník'
;

Laicky řečeno se mi zdá, že jsem v těle objektu mrtvola už pracuji se skrytým objektem pilník jiným způsobem a není tedy možné využít direktivu Hidden. Ovšem po jejím vymazání se jak jsem očekával v popisu místnosti zobrazí hláška Vidíš tu mrtvolu (která obsahuje pilník), což je také špatně. Takže jedině po vymazání dvou znamének plus vše funguje jak potřebuji, ale nerozumím jak, což není dobré – budeš po přečtení zdrojáku moudřejší? Jinak je dvojité znaménko jasné, doplnil jsem jej do provazu v truhle, kde samozřejmě nesmí chybět. Stejné je to např. u kupky sena, tam Tvůj návod funguje bez problémů. Tam ale budu potřebovat objevení jehly až po spálení sena, takže se podívám na změnu stavu objektu po konkrétní akci.

Se Search a LookIn je to jasné, u tohoto objektu nemusím tuto věc řešit.

Malá aktualizace – Tvé komentáře projíždím, testuji a snažím se vnímat postupně, vzpomněl jsem si na třídu Heavy a referenční manuál. Kouknul jsem se tedy na definici Hidden a nalezl zajímavou možnost „can be sensed“ na str. 906:

    canBeSensed(sense, trans, ambient)
    {
        /*
         *   If the sense is sight, and we haven't been discovered yet, we
         *   cannot be sensed.  Otherwise, inherit the normal handling.
         */
        if (sense == sight && !discovered)
            return nil;
        else
            return inherited(sense, trans, ambient);
    }

Pokud uvnitř if změním hodnotu nil na true, pilník je zase vidět, tato direktiva tedy upravuje vlastnost třídy Hidden a de facto jí neguje, jestli to dobře chápu. Tak jako tak se mi zatím nezadařilo objekt správně definovat, otázka zní, zda není zakopaný pes spíš v definici mrtvoly, než u pilníku.

Citace: Kroužící orel   2. Květen 2017 - 13:07
Rád bych také místo otrockého příkazu "odemkni mříž" použil "přepiluj mříž"...
// Rozumím, až se pohnu dále, juknu se na zdrojáky Základny, prozkoumám přechodové dveře a juknu do diskuze. Ohledně přepilování jak radíš raději počkám, až naberu více zkušeností, zatím podumám o elegantnějším řešení, v mrtvole může být třeba šperhák a na mříži zámek – sakra, tady ti naši autoři měli s příkazem použij sakra ulehčenou práci přesně jak píšeš v manuálu.

Citace: Kroužící orel   2. Květen 2017 - 13:07
Slovník předmětů jsem definoval, zatím jsem nepoužil pomnožný tvar.
// Paráda, zde jsem využil příklad z Heidi u dveří a použil na obě ve své hře, budu testovat.

Citace: Kroužící orel   2. Květen 2017 - 13:07
+ drahokam_1 : Thing 'drahokam č. 1' 'drahokam č. 1' *2...
// Naprosto souhlasím, sám jsem byl zvědav jak si s č. 1 interpretr poradí. Použil jsem označení první až čtvrtý drahokam, je to určitě lepší řešení.

---

Svůj projekt zase zasílám v příloze. Každopádně je paráda, že dokumentace k TADSu je tak rozsáhlá a je čeho se chytit, i když zpočátku je jí pro mě opravdu mnoho, člověk něco přečte a vzápětí zapomene, co naplat. Každopádně i u správy serverů ocením kvalitní dokumentaci, dříve jsem jí tak neřešil, ale u linuxu jsem bez ní nahraný, tady je parádní příklad wiki Archu nebo u světa BSD manuály k OpenBSD. Když projíždím zdrojáky Základny, zjišťuji, že jsem toho mnoho opomněl, je opravdu rozsáhlá a bezva zpracovaná.

Teď budu pokračovat dále, zkusím nadefinovat akci se strážcem a otestuji chování dveří, fakt nesmím nic uspěchat, ale snažit se pochopit co nejvíce jak tenhle bezva systém funguje. Jako neprogramátor to mám těžké, na druhou stranu skripty v pythonu a weby v php mě nikdy moc nechytly, raději vytvořím něco, co mě baví a to TADS beze zbytku splňuje.

Ale v první řadě oceňuji Tvojí pomoc, je paráda, že se mám koho zeptat a jak rychle reaguješ na mé  dotazy. Stejně se snažím reagovat i já, pokud se mě lidi zeptají na něco z oblasti Linuxu a umím jim pomoci. Dal jsi si obrovskou práci s překladem, se Základnou a teď i s vysvětlováním, tady je krásně vidět, že kvalitní systém je hlavně o lidech. Tím spíš se těším na další programování a objevování, textovky nestárnou a možnosti TADSu jsem\prozkoumal zatím jen povrchně. Taky mi pomohl v přehodnocení mého názoru na programování, stojí to za to.
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: gaspoda 5. Květen 2017 - 20:57
A právě zde jsem v příkladu s první hrou našel direktivu noun, kterou jsem dříve používal, aniž bych věděl, co znamená.

Ah, pardon. Zalistoval jsem zdrojáky a ono to opravdu funguje, je to nějaká pomůcka mimo vocabWords, která umožňuje také vložit slova do slovníku. Ale v podstatě se to skoro nikde nepoužívá, používej normálně vocabWords/gcVocab, jak máš ve zbytku programu.

Tohle je moc zajímavé jak píšeš práci s pozicemi. Jestli dobře rozumím, využívá se zde malý virtuální stroj podobně jako v javě – uložená hra je tedy obraz aktuální paměti, který rekompilací ztrácím.

Ano. Zdrojový kód v TADSu je přeložen do strojového kódu podobně, jako když se třeba program v C++ přeloží do spustitelného souboru. Rozdíl je ovšem v tom, že při překladu C++ vznikne strojový kód spustitelný přímo na procesorech, kdežto překladem TADSu vznikne bytekód spustitelný v softwarově simulovaném počítači. Ve zkompilovaném programu jsou objekty a jejich proměnné identifikovány pořadovými čísly, ne symbolickými názvy kvůli rychlosti zpracování. A tak i při malé změně programu dojde leckde k přetřesení číselných identifikátorů, některé objekty zaniknou, jiné přibydou a tím se ztratí kompatibilita s uloženou pozicí.

Zajímalo mě, zda testCommands.txt schroupne i češtinu, naštěstí výsledný testOutput.txt jí zobrazuje naprosto bez problémů, jasné, tady je opravdu potřeba direktiva frob -i plain -k utf8.

Jo, jasně, s diakritikou není problém. Jenom jsem zapoměl napsat, že na konci souboru s testovacími příkazy to chce >konec a >ano, aby nezůstal interpret viset.

Stále čtu o vlastnostech, metodách, třídách a objektech, ovšem abych plně vše pochopil, musím začít na příkladech a právě tento manuál je to pravé.

V LearningT3 jsou ze začátku kapitoly "coding excursus", které postupně základní pojmy vysvětlují. Stručně:

 

Tady vidím class Heavy: Immovable – takže pokud to dobře chápu, Heavy je potomek třídy Immovable, kterou rozšiřuje dalšími parametry a zachovává si všechny její vlastnosti. A nad CustomImmovable nacházím class Immovable: NonPortable plus ouplně nahoře je hlavní třída Thing, teď už je to jasné.

Ano, přesně tak.

Ano, zkoušel jsem před objekt pilník definovat dvakrát plus takto:

Kód: [Vybrat]
+ mrtvola : RestrictedContainer 'mrtvola' 'mrtvola' *3
++ pilnik : Key, Hidden 'pilník' 'pilník' *2

Ovšem situace je stále stejná, hráč po příkazu koukni se do mrtvoly sice pilník vidí, ale není možné jej sebrat. Po odstranění direktivy Hidden je vše v pořádku. Tady mě to docela mate, raději dopíšu celou definici:

Kód: [Vybrat]
+ mrtvola : RestrictedContainer 'mrtvola' 'mrtvola' *3
 "Je v pokročilém stádiu rozkladu. "
     gcName = 'mrtvoly, mrtvole, mrtvolu, mrtvole, mrtvolou'
     gcVocab = 'mrtvoly/mrtvole/mrtvolu'
        dobjFor(LookIn)
        {
                action()
                {
                        if(pilnik.moved)
                        {
                                "Na mrtvole jsi neobjevil už nic zajímavého. ";
                                exit
                                ;
                        }

                        pilnik.moveInto(self);
                        "Bližší pohled na mrtvolu odhalil pilník schovaný v záhybech polorozpadlých šatů! ";
                }
        }
;

++ pilnik : Key, Hidden 'pilník' 'pilník' *2
       "Je šikovně upraven na přepilovávání mříží. "

       gcName = 'pilníku, pilníku, pilník, pilníku, pilníkem'
       gcVocab = 'pilníku/pilníku/pilník'
;

Laicky řečeno se mi zdá, že jsem v těle objektu mrtvola už pracuji se skrytým objektem pilník jiným způsobem a není tedy možné využít direktivu Hidden. Ovšem po jejím vymazání se jak jsem očekával v popisu místnosti zobrazí hláška Vidíš tu mrtvolu (která obsahuje pilník), což je také špatně. Takže jedině po vymazání dvou znamének plus vše funguje jak potřebuji, ale nerozumím jak, což není dobré – budeš po přečtení zdrojáku moudřejší? Jinak je dvojité znaménko jasné, doplnil jsem jej do provazu v truhle, kde samozřejmě nesmí chybět. Stejné je to např. u kupky sena, tam Tvůj návod funguje bez problémů. Tam ale budu potřebovat objevení jehly až po spálení sena, takže se podívám na změnu stavu objektu po konkrétní akci.

Trochu upřesním - nejde sebrat, ani hráč pilník nevidí, protože je stále skrytý. Jen jsi vypsal hlášku o jeho nalezení, ale pro TADS je stále neviditelný.

Teď je trochu více možností, jak dál postupovat. Záleží na tom, jakého efektu chceš dosáhnout. Asi nejblíže k tvému pojetí bude manuální zviditelnění doprovázené hláškou. V podstatě můžeš vyjít z toho, co máš, jen místo pilnik.moveInto(self) použiješ pilnik.discover();

Tohle řešení bude fungovat. Ale když to vezmu kolem a kolem, vlastně se moc neliší od přemístění objektu, jako jsi ho měl. Když nedáš žádné plus, znamená to, že objekt "nikde není", tudíž je pro háče nedosažitelný až do okamžiku, kdy ho do mrtvoly přemístíš a zobrazíš hlášku.

Já jsem promýšlel ještě některé jiné souvislosti, ale je fakt, že pokud chceš dodržet hlášky, jak je máš napsané, tak je to asi nejjednodušší cesta, takže se toho přidrž. On TADS umí lecos, ale někdy je větší problém se automatických hlášek, které se nehodí, zbavit :-)

Protože jsem ale nakousnul to automatické zviditelnění pří prohledání kontejneru, tak pro úplnost vysvětlím. Aby se Hidden objekt zviditelnil automaticky, je potřeba nechat TADS dělat, co má naprogramováno v knihovně. A to je obecný princip, na který je potřeba si dát při programování pozor, protože se do něj začátečník může zamotat. Půjdu-li do referenční příručky a vyhledám-li RestrictedContainer, dozvím se, že dobjFor(LookIn) je poděděné z Containeru:

Kód: [Vybrat]
dobjFor(LookIn)
{
    verify() { }
    check()
    {
        /*
         *   If I'm closed, and I can't see my contents when closed, we
         *   can't go on.  Unless, of course, the actor is inside us,
         *   in which case our external boundary isn't relevant.
         */
        if (!isOpen
            && transSensingIn(sight) == opaque
            && !gActor.isIn(self))
        {
            /* we can't see anything because we're closed */
            reportFailure(&cannotLookInClosedMsg);
            exit;
        }
    }
    action()
    {
        /* show our fixed "look in" description, if any */
        lookInDesc;

        /* examine my interior */
        examineInterior();
    }
}

Když ty si u kontejneru predefinuješ příslušnou action(), tak zdědíš verify() a check(), ale původní action() nahradíš tím svým. O co jsi přišel? Můžeš sledovat cestu kódem a dojdeš k funkci examineInteriorWithLister(lister), ve které se provádí mj. zviditelnění ukrytých objektů:

Kód: [Vybrat]
/* if desired, reveal any "Hidden" items concealed within */
if (revealHiddenItems)
{
    /* scan our contents and reveal each Hidden item */
    foreach (local cur in contents)
    {
        /* if it's a Hidden item, reveal it */
        if (cur.ofKind(Hidden))
            cur.discover();
    }
}

Tedy pokud chceš, aby TADS konal správně svou práci, tak když přetížíš nějakou metodu ve své třídě, tak bys obvykle měl zavolat zděděné chování a to tak, že do své action() metody nějak umístíš volání inherited(). Výjimkou je situace, kdy víš, že chceš zděděné chování úmyslně potlačit.

Jinými slovy stačilo by vynechat úplně dobjFor(LookIn) kontejneru a pilník by se sám zviditelnil. Byla by ale trochu potíž, že doprovodná hláška by byla velice fádní a nudná. To by se dalo poladit, ale bylo by to zbytečně složité, řešení s přemístěním je výhodnější.

Malá aktualizace – Tvé komentáře projíždím, testuji a snažím se vnímat postupně, vzpomněl jsem si na třídu Heavy a referenční manuál. Kouknul jsem se tedy na definici Hidden a nalezl zajímavou možnost „can be sensed“ na str. 906:

Kód: [Vybrat]
canBeSensed(sense, trans, ambient)
{
    /*
     *   If the sense is sight, and we haven't been discovered yet, we
     *   cannot be sensed.  Otherwise, inherit the normal handling.
     */
    if (sense == sight && !discovered)
        return nil;
    else
        return inherited(sense, trans, ambient);
}

Pokud uvnitř if změním hodnotu nil na true, pilník je zase vidět, tato direktiva tedy upravuje vlastnost třídy Hidden a de facto jí neguje, jestli to dobře chápu.

Ano. To je právě jádro toho, jak Hidden objekty fungují. Zablokují možnost smyslově vnímat objekt, pakliže není ještě objevený. To se pozná podle vlastnosti discovered, do které je po objevení uložena hodnota true. Tu ale nenastavuj ručně, místo toho zavolej v programu metodu discover(), tedy v tomto případě např. pilnik.discover(); a objekt bude zviditelněn.

Svůj projekt zase zasílám v příloze. Každopádně je paráda, že dokumentace k TADSu je tak rozsáhlá a je čeho se chytit, i když zpočátku je jí pro mě opravdu mnoho, člověk něco přečte a vzápětí zapomene, co naplat.

Jo, docela dobrý. Prolítl jsem zdroják a vedeš si dobře, žádné zásadní problémy tam nevidím.
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: Kroužící orel 9. Květen 2017 - 14:48
Ohledně noun je vše jasné, budu používat vocabWords/gcVocab a zvyknu si na něj.

Znovu jsem pročetl Tvůj návod a ohledně virtuálního stroje našel informaci ohledně T3VM, dokonce popisuješ jeho podobnost s Javou, ha, tady jsme to pochopili oba podobně. Naštěstí je to prcek, takže žádné zpomalování se nekoná, i na první verzi RPi řádím ve Frobtadsu bez omezení.

Vidíš, u skriptu je dobré dát na konec příkazy >konec a >ano, díky za doplnění, já jsem jej vždy ukončil ručně.

Moc díky za lidské vysvětlení tříd, metod a objektů, tohle si mi opravdu hrozně těžko chápe bez skutečných příkladů, teď když je budu stále používat konečně budu moci zjistit více. Je mi fuk, že začínám hnedle s OOP, nezdržel jsem se ani u Pascalu, prostě mě programování do této doby míjelo. Ale na zdrojáku jsem četl, že programovat se dá naučit i ve čtyřiceti, tady mám ještě rezervu, hurá.

U pilníku jsem nakonec dle Tvého doporučení použil dvě znaménka plus a direktivu pilnik.discover(). Nyní vše parádně funguje, zkusil jsem mříž "odemknout" a zase "zamknout", po následném pokusu o odemknutí už je parser natolik chytrý, že vše udělá za mě. Jo, velmi trefné s těmi automatickými hláškami, těch se budu muset zbavit právě u dveří, už se těším...

Pečlivě jsem si našel ve třídě RestrictedContainer objekt dobjFor(LookIn), chápu, že pokud změním akci, tedy přesněji řečeno metodu action, metody verify a check podědím a zůstávají stejné. Přiznám se, že tohle je pro mě ještě dosti složité, metodu examineInteriorWithLister(lister) bych bez Tvého vysvětlení sám nenalezl. Každopádně jsem vyzkoušel vymazat celé tělo metody dobjFor(LookIn), vše v pilníkem je v pořádku, ale přesně jak píšeš, hláška není nic moc, takže ponechám první řešení. Je to ale cenná rada, s tímhle se ještě určitě mnohokráte setkám - musím hlídat, co má TADS uvedeno ve svých knihovnách.

Pilník jsem nakonec proměnil na šperhák, texty nyní vypadají realističtěji. Časem upravím mříž tak, že zde bude ještě jeden objekt např. s názvem zámek a hráč bude otevírat právě jeho. Nyní se posunu dále. Přemýšlím o kupce sena, tmavé místnosti, doplnění druhého názvu místností jako to máš např. u velínu, u mě 'kobka' 'do kobky', konektorech dveří a místnostech... A jak uvádím výše, stačí si ještě jednou projít Tvůj manuál, kde vše popisuješ. Jen ty Akce pro mě nebudou jednoduché, nechám je tedy až na konec - viz správná definice zbavení se strážce. Musím holt ty manuály číst stále dokola, vše se najednou pamatovat nedá, je to ale paráda.

Zítra se zase dostanu k úpravě zdrojáku, takže budu makat a o výsledek se rád podělím. Až se dostanu dále, určitě bude zase nějaká ta nová otázka, tuším, že s akcemi, už se těším...
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: gaspoda 9. Květen 2017 - 15:26
Moc díky za lidské vysvětlení tříd, metod a objektů, tohle si mi opravdu hrozně těžko chápe bez skutečných příkladů, teď když je budu stále používat konečně budu moci zjistit více. Je mi fuk, že začínám hnedle s OOP, nezdržel jsem se ani u Pascalu, prostě mě programování do této doby míjelo. Ale na zdrojáku jsem četl, že programovat se dá naučit i ve čtyřiceti, tady mám ještě rezervu, hurá.

Žádný problém, dej tomu čas, případně se zeptej. Ono to pomalu začne pomalu zapadat dohromady. Je to trochu těžké pochopit, protože tyhle věci vyžadují už poměrně dost abstrakní způsob uvažování a představivost. Proto je také snaha studentům přiblížit objektově orientované programování tím, že se připodobňují ty programátorské objekty k objektům z reálněho světa. To obvykle dobře funguje do té doby, než student potká něco jako:

http://geek-and-poke.com/geekandpoke/2014/1/2/games-for-the-real-geeks-part-2 (http://geek-and-poke.com/geekandpoke/2014/1/2/games-for-the-real-geeks-part-2)

Pečlivě jsem si našel ve třídě RestrictedContainer objekt dobjFor(LookIn), chápu, že pokud změním akci, tedy přesněji řečeno metodu action, metody verify a check podědím a zůstávají stejné. Přiznám se, že tohle je pro mě ještě dosti složité, metodu examineInteriorWithLister(lister) bych bez Tvého vysvětlení sám nenalezl. Každopádně jsem vyzkoušel vymazat celé tělo metody dobjFor(LookIn), vše v pilníkem je v pořádku, ale přesně jak píšeš, hláška není nic moc, takže ponechám první řešení. Je to ale cenná rada, s tímhle se ještě určitě mnohokráte setkám - musím hlídat, co má TADS uvedeno ve svých knihovnách.

Hlavní poselství je, že bysis měl zvyknout vždy při přetěžování knihovních metod volat inherited. Vyhledej si to slovíčko fulltextem ve zdrojácích Základny, abys viděl příklady, kde a jak se to používá, to bude asi nejvíce ilustrativní. Nezavolání inherited musí být vědomé rozhodnutí, ne opomenutí.
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: Kroužící orel 12. Květen 2017 - 13:46
Krásný pátek přeji,

konečně se dostávám k počítači, počasí se úplně otočilo, takže každý, opravdu každý den zde mám lidi na řechtáky a ani tento víkend a téměř celý týden příští nebude výjimkou. OOP skutečně nebude nic jednoduchého, jestli zmáknu abstraktní myšlení nebo ne se dozvím tak, že se do něj pořádně opřu, pamatuji si, že mi jeden vývojář řekl něco jako „řešení Tě někdy napadne jen tak třeba při cestě autobusem nebo u Tebe při jízdě na koni, dej tomu čas“, přesně tak je to i u textovek, večer jsem si s jedním problémem lámal škebli a druhý den ráno řešení přišlo samo.

Ten odkaz je super, dostala mě hlavně ta hláška ohledně suda v Geeks And Non-Geeks. Netušil jsem, že používáš i javovský Spring, tu už je asi jiná třída.

Grepnul jsem si klíčové slovo inherited ve všech souborech Základny a budu študovat, co nepoberu, na to se zeptám. Postupně budu pokračovat i v Exoterovi, je to teď půjde trochu pomaleji, čas si ale najdu vždy. Až se posunu dále, pošlu další zdroják.
Modrou oblohu nad hlavou a konečně už slunečný víkend přeje

Orel
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: Kroužící orel 16. Květen 2017 - 15:14
Tak dnes jsem se konečně dostal k pokračování a alespoň něco se zadařilo.

Řešil jsem dveře – měl jsem potíže s jejich odemykáním, hra psala následující:
-------------------------------------------------
>odemkni dveře svazkem
To není něco, co bys mohlo odemknout.
>odemkni dveře svazkem klíčů
To není něco, co bys mohlo odemknout.
>odemkni dveře svazek klíčů
To není něco, co bys mohlo odemknout.
>odemkni dveře
Čím je chceš odemknout?
>svazkem klíčů
Hotovo.
-------------------------------------------------
Upravil jsem dle vzoru u Heidi skloňování u svazku klíčů, nyní je vše funkční, akci s dveřmi tedy mohu uzavřít.

Zatím jsem nezvládnul použití lana, které potřebuji pro vstup do studny, bude to nějaká akce a jak píšeš, naprogramovat realisticky se chovající lano nebude jednoduché. Nikde v manuálech ani tutoriálech na webu jsem nenašel příklad s přivázáním lana, to by mi parádně pomohlo a ani v Základně podobná akce pokud vím není, takže zde budu ještě bádat. Oficielní manuály moc hezky popisují šplhání po skalách, škoda, že vynechali právě to lano.


Pád z výšky do sena / na dlažbu – zde bude nějaká konstrukce if else. Napadlo mě použít:
 dobjFor(Enter) - method of ThroughPassage in travel.t[2618],
případně přesměrování, zatím jsem však nebyl úspěšný. Budu dále studovat nebo zkusím metodu jinou.


Útok na strážce – zde se mi konečně podařilo donutit hráče, aby dokázal sekerou zneškodnit strážce. Jen u výrazu zabij získávám nesmyslnou hlášku:
-------------------------------------------------
>zabij strážce sekerou
Strážcem nemůžeš zaútočit.
>zaútoč na strážce sekerou
Jediným mocným úderem se ti podařilo poslat strážce do věčných lovišť.
-------------------------------------------------

Teď ještě musím vymyslet, aby se předměty objevily až po zneškodnění strážce, změnu textu pomocí if – else – end jsem už doplnil. Pokud vložím jediné plus, předměty lze sebrat, pokud dvě, jsou vidět jen před zabitím strážce – tady by možná byl vhodný kontejner, jen nesmím strážce nechat „zmizet“, na to se teď vrhnu. Pokud se mi vše podaří, podobnou situaci připravím u draka a psa.
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: Kroužící orel 17. Květen 2017 - 09:28
Tady jsem našel diskuzi ohledně řešení přivazování provazu a také zajímavou definici akcí TAction – přesně tu bych využil při definici nové akce typu „přivaž“, „přepiluj“ apod., pokud jí dobře chápu. Také uvedené příklady dobjFor se hodí. Budu studovat a juknu se zase do Library reference a definici tříd a objektů

http://rec.arts.int-fiction.narkive.com/zp9ZA3sU/tads-3-attaching-problem
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: gaspoda 19. Květen 2017 - 19:57
Zatím jsem nezvládnul použití lana, které potřebuji pro vstup do studny, bude to nějaká akce a jak píšeš, naprogramovat realisticky se chovající lano nebude jednoduché. Nikde v manuálech ani tutoriálech na webu jsem nenašel příklad s přivázáním lana, to by mi parádně pomohlo a ani v Základně podobná akce pokud vím není, takže zde budu ještě bádat. Oficielní manuály moc hezky popisují šplhání po skalách, škoda, že vynechali právě to lano.

Teď pár týdnů budu mít málo času, tak odpovídám po kouskách. Realistická lana patří k těm nejsložitějším věcem k simulování a já vlastně ani nevím, jak se lano v Exoterovi používá. Ale hodil jsem na web překlad jedné demonstrační hry Attachable třídy. Kdysi dávno jsem ji přeložil, ale byly tam po staru zadané názvy a slovníky objektů. Teď jsem ji oprášil a připravil k publikování, je na http://www.tads.cz/cs/demonstracni-hra (http://www.tads.cz/cs/demonstracni-hra).

Ten odkaz je super, dostala mě hlavně ta hláška ohledně suda v Geeks And Non-Geeks. Netušil jsem, že používáš i javovský Spring, tu už je asi jiná třída.

Né, nepoužívám, jen čtu Geek and Poke...
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: gaspoda 21. Květen 2017 - 22:08
Pád z výšky do sena / na dlažbu – zde bude nějaká konstrukce if else. Napadlo mě použít:
 dobjFor(Enter) - method of ThroughPassage in travel.t[2618],
případně přesměrování, zatím jsem však nebyl úspěšný. Budu dále studovat nebo zkusím metodu jinou.

Možnosti a způsoby přesunů postav jsou docela rozsáhlé, spíš bys mohl použít v místnosti metodu enteringRoom, která tě informuje o vstupu postavy:
Kód: [Vybrat]
    enteringRoom(traveler)
    {
        if(traveler == me && nejake dalsi podminky)
        {
            "Něco... ";
        }
    }

V ní si otestuješ, o jakou postavu se jedná a jakékoliv jiné podmínky a něco uděláš. Pokud postavu nezabiješ, tak se výstupy zobrazí před rozhlédnutím v nové místnosti.
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: Kroužící orel 22. Květen 2017 - 08:17
Krásné ránko přeji,

paráda, hru Attachable jsem si stáhnul, binárka je v pohodě, jen zdroják attachment-20170519-1.zip bude asi poškozený, po rozbalení vidím jen prázdný adresář Attachable, můžu poprosit ještě jednou o nahrátí na server? Na řešení toho lana se moc těším, snad najdu inspiraci.

Taky mám teď spoustu práce, celý víkend koně a dnes kroužky s dcérenkou, vždy se ale alespoň o něco posunu dále. Se strážcem zatím ještě bojuju, budu dále zkoušet a podívám se na ten pád do sena - v místnosti sv_nadvori přidám metodu enteringRoom s podmínkami, zda je/není seno v místnosti, až se pohnu, dám sem výsledek.
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: gaspoda 22. Květen 2017 - 20:18
Pardon, už je to spravené.
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: Kroužící orel 25. Květen 2017 - 12:16
Vrhnul jsem se na pád z výšky do kupky sena, přiznám se, že si nejsem jist, kde mám metodu enteringRoom(traveler) použít – zda ve druha_mistnost_vrchol_vez nebo v sv_nádvoří, u obou případů jsem nedosáhl kýženého výsledku. Ale po juknutí se do zdrojáků Heidi a Tvého Attachment mě napadlo ještě jedno, nevím zda ouplně správné systémové řešení:

druha_mistnost_vrchol_vez: Room 'Druhá místnost na vrcholu věže' 'do druhé místnosti na vrcholu věže'
    "Jsi v místnosti na vrcholu věže. \bMůžeš jít na východ, dolů. "
    east = mistnost_vrchol_vez
    down : TravelMessage
          {  ->sv_nadvori
              "Spadl jsi přímo doprostřed kupky sena, která ideálně ztlumila tvůj pád. "
                canTravelerPass(traveler) {return kupka_sena.isIn(sv_nadvori); }
              explainTravelBarrier(traveler)
         { "Zabil jsi se pádem z výšky. "; finishGameMsg(ftDeath, [finishOptionUndo] );}
    }
;

Pomocí metody  TravelMessage jsem dosáhl toho, že pokud se kupka sena nachází v sv_nadvori, hráči se nic nestane a v opačném případě zahyne přesně tak jako v Exoterovi.

Mimochodem teprve dalším studiem zdrojáků Heidi jsem se dozvěděl, že ve hře lze i křičet a tento křik může zanikat ve větru, to minimálně u předělávky a dalším pokračování Kroužícího orla musím využít. Opravdu bezva systém, líbí se mi čím dál tím více.
 
Na tomto místě jsem zjistil, že po smrti hráče hra vypisuje ZEMŘELO JSI. - u definice hráčovy postavy me však nemohu využít striktní definici rodu typu *1, setkal jsi se s tím také u tvorby Základny?

V místnosti se studnou jsem pomocí zdrojáku Attachment a výše uvedené kombinace  TravelMessage zkusil něco podobného, zatím ale bez kloudného výsledku:

jz_nadvori: Room 'Jihozápadní část nádvoří' 'do jihozápadní části nádvoří'
    "Stojíš na nádvoří. \bMůžeš jít na sever, na východ, na jih, dolů. "
    north = sz_nadvori
    east = jv_nadvori
    south = brana
    down : TravelMessage
          {  ->ve_studni
              "Sešplhal jsi dolů za pomoci přivázaného lana. "
//                canTravelerPass(traveler) {return provaz.moveinto(studna); }
        canTravelerPass(traveler) {!provaz.isConnectedTo(studna); }
              explainTravelBarrier(traveler)
         { "Studna je moc hlubová na to, abys do ní skočil jen tak. "; }
    }
;

+ studna : Attachable, Thing, Heavy 'studna' 'studna' *3
    @jz_nadvori
    "Hluboká studna, nyní však již zcela vyschlá. "
    specialDesc = "Je tu stará kamenná studna. "

    canAttachTo(obj) {return obj == provaz;}
    handleAttach (other)
    {   provaz.moveinto(studna);
       "Spustil jsi jej dolů. ";
     }

     gcName = 'studnu, studni, studna, studni, studnou'
     gcVocab = 'studnu/studni/studnou'
;

Také doprovodné hlášky zatím nejsou zrovna ideální:

>prozkoumej studnu
Hluboká studna, nyní však již zcela vyschlá.
Studna je připevněna k provazu.

>d
Je tu příliš velká tma, než abys vidělo na cestu.


Zde asi TravelMessage nepoužívám správně, zkusím si ještě jednou projet zdroják a v Library reference prozkoumat používané metody. Tak jako tak mi provaz zůstane po připevnění ke studni v ruce, takže zde budu muset upravit změnu stavu.

Každopádně uvázání provazu a boj se strážcem/drakem/psem jsou poslední dva zádrhele, až tyhle rozseknu, tvorba se bude chýlit ke konci.
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: gaspoda 25. Květen 2017 - 12:36
Abych nehádal, prosím napiš mi, jak má vypadat ideální výstup ze hry s provazem i kupkou sena, tj. příkazy hráče a odpovědi hry na ně.
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: Kroužící orel 25. Květen 2017 - 12:57
Sakra, ty jsi ale rychlík, ještě jsem zapomněl dát sem aktuální zdroják.

Projel jsem celou současnou hru tak, že napoprvé spadnu do sena, pak zkouším vlézt do studny pomocí provazu, seberu seno a druhým pádem na dlažbu hra končí.

A ještě mě napadlo upravit Tebou přeložené příkazy. U studny mohu použít "připevni provaz", ale ne už "přivaž provaz". Upravil jsem soubor cs_cz.t v adresáři /usr/share/frobtads/tads3/lib/adv3/cs_cz i v tom samém pod Wine a hurá, možnost "přivaž" už interpretr zná. Takže pokud se nepletu, mělo by zafungovat přidání slova "přepiluj" tam, kde máš uvedeno odemkni, to zkusím příště.

Vše potřebné zasílám v příloze. Teď za chvíli frčím pro dcérenku do školky, během zítřka nebo nejpozději o víkendu se zase dostanu k Exoterovi, baví mě to čím dál více.
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: Kroužící orel 26. Květen 2017 - 08:55
Dnes jsem ještě jednou v klidu juknul na soubory, které jsem Ti zaslal a jak vidno, spěch není to pravé, zase je tu problém s kódováním. Nyní posílám následující soubory v jednom archivu:

Pruchod_Exoter.txt a Pruchod_Exoter.pdf - to je přesný postup zkopírovaný z hraní hry ve Win verzi TADS3 Interpretr
Auto 318.cmd - nahraný průchozí skript pod Linuxem s nečitelným kódováním, ve Win verzi Workbenche plně funční
cs_cz.t - moje malá úprava s přivázáním provazu

Se senem je tedy vše OK, nyní se pokusím zprovoznit jeho spálení pomocí zapálené pochodně plus bude asi vhodnější, aby jej hráč nemohl sebrat. Budu ještě laborovat ohledně lana a studny. Až bude hra hotová, vrhnul bych se na doplnění souboru cs_cz.t a doplnil další slova, která se mi zdají být užitečná, pokud budeš souhlasit a je-li to správný postup, můžeme jej dát i na Tvůj web jako novou verzi, alespoň takto málo budu schopen i já pomoci v překladu TADSu.

Krásný víkend a modrou oblohu nad hlavou přeje

Orel
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: Kroužící orel 31. Květen 2017 - 09:40
Tak se zase dostávám k tvorbě, lano a strážce zatím nechám stranou a zaměřil jsem se na zapálení pochodně. Prozkoumal jsem v Library - extras.t třídu class Candle: FueledLightSource a pečlivě přečetl práci s baterkou v Heidi a především Tour Guide stranu 102 - Light and Fire. Parádně je tu popsána klasická svítilna na baterky jako OpenableContainer, olejová lampa a informace o tom, že pochodeň mohu definovat podle Candle & FireSource. Zkoušel jsem všechny příklady, posílám aktuální zdroják, kde mám na str. 181 pochodeň a str. 247 křesadlo. Ve všech případech dostávám po příkazu zapal pochodeň hlášku "{Tím iobj} nemůžeš nic zapálit.".

Až budeš mít čas, zkus se prosím juknout i na pochodeň, zatím budu dále zkoumat.
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: Kroužící orel 22. Září 2017 - 15:27
Máme po táborech a konečně budu mít více času a hlavně spoustu chuti pokračovat s parádním TADSem. Jen tak bastlit a zkoušet opravdu nejde, Exoter bych tímto způsobem nikdy nedokončil. Znovu jsem si pročetl Gaspodův návod a vidím, že programovat to chce opravdu systematicky a od začátku.

Vytisknul jsem si tedy všechna dostupná pdf plus to hlavní z technického manuálu, nyní musím kompletně projít Learning TADS 3, Heidi jako příklad pro neprogramátora opravdu nestačí. Kromě TADS mě jako linuxáka zajímá nejvíce C a C++, jak vidno, syntaxe je podobná, takže proč nezačít něčím, co mě opravdu baví, u her a hlavně textovek se budu učit s radostí. Třeba časem jako céčkař vyřeším i ten nešťastný problém s UTF-8 a mé oblíbené knihovny ncurses ve Frobtadsu, jůů, to by bylo něco... Tahle aplikace si o další vylepšování sama říká, jen škoda, že není zrovna v hlavním hledáčku tvůrců balíčů jednotlivých distribucí, aktivně využívám Arch a Debian 9/Q4OS, v prvním je pro úspěšný překlad nutno upravit PKGBUILD a v tom druhém se již ani nenachází, naštěstí upravená verze z nestabilní větvě funguje parádně.

Exoter se tedy trochu pozdrží, budu se snažit co nejlépe pochopit popsané příklady v manuálech, mimochodem ty návody pro TADS jsou opravdu profesionálně zpracované. Díval jsem se i na Inform, také se dnes již zrovna moc nevyvíjí, synaxe TADSu je ale narozdíl od něj podobnější klasickému C++, takže není co řešit.

Námětů na texovky mám spoustu, hotový scénář k druhému Orlovi a připravený třetí, mnohem rozšířenější a přepracovaný Bad Night, aztékové a májové, středověké hrady jako vystřižené z vondruškových románů, ruská občanská válka za Války velké, partyzání v Jusoslávii v té druhé... je toho moc, takže se programování holt nevyhnu, to je osud, který si musím prožít.

Jakmile něco nového zbastlím, další zdrojáky sem rozhodně hodím, všechny své textovky chci dávat k dispozici včetně zdrojáků jako ve většině linuxových aplikací. Plus testování nové textovky od Thoorina, mám se na co těšit.
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: gaspoda 23. Září 2017 - 10:47
Jo, jo, omlouvám se, já padl před prázdninami vyčerpáním a tak trochu jsem spoléhal na to, že budeš mít letní akce a nevzpomeneš si na to, že jsem neodpověděl. Musím tam něco opravit v knihovně.
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: Kroužící orel 25. Září 2017 - 09:18
Jasná věc, nic se neděje, já jsem se upřímně o táborech k textovkám taky vůbec nedostal, s dvaceti dětmi není žádný den zrovínka oddych. Pilně teď študuju Learning TADS3, dříve jsem dumal nad tím, kterým programovacím jazykem začít, teď ale začínám chápat, že je to fuk, třídy a objekty se budou používat i v C++ podobně jako zde a až pořádně pochopím syntaxi a algoritmy, bude mi v každém jazyce hej. Eve parádně vysvětluje objekty, jejich vlastnosti a metody a rovnou na příkladech, takové učení mě baví, některé nic mi zatím neříkající matematické úlohy např. v Pascalu nebo Pythonu mojí pozornost nedokázaly udržet.

Hnedle od začátku mluví také o dědičnosti a vícenásobné dědičnosti, tohle se na příkladech dá parádně vstřebat. Zatím jsem u mix-in třídách, nyní ještě netuším, proč Darkroom není mix-in, ale ShipboardRoom a FloorlessRoom ano, důvod tady ale určitě je a věřím, že jej naleznu později v textu nebo v Library, tyhle otázky pokud sám vyřeším, mě posunou zase dále.

Stále jezdíme a za měsíc tu mám podzimní prázdniny u koní, volná dopoledne ale dycinky najdu, takže můžu študovat, jdu na to. Pokud budeš cokoliv upravovat, prosím o info např. sem:

http://tads.cz/cs/novinky

tam často chodím a hnedle je vidět, co máme nového - už se těším na novou knihovnu.
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: gaspoda 25. Září 2017 - 11:38
dříve jsem dumal nad tím, kterým programovacím jazykem začít, teď ale začínám chápat, že je to fuk, třídy a objekty se budou používat i v C++ podobně jako zde a až pořádně pochopím syntaxi a algoritmy, bude mi v každém jazyce hej.

Nakonec je to jedno, já jen cítím určité problémy s pochopením, pokud se někdo začne učit programování v prostředí webových stránek, ať už PHP nebo JavaScript, tam je to hodně přiohnuté a pro pochopení základních principů opravdu ne moc vhodné.

Zatím jsem u mix-in třídách, nyní ještě netuším, proč Darkroom není mix-in, ale ShipboardRoom a FloorlessRoom ano

Mix-in třída je taková třída, která není určená k tomu, aby se použila samostatně, tedy aby se přímo od ní samotné vytvořil objekt. Je to proto, že sama nedědí žádnou kompletní fukcionalitu, je to jen malý doplněk, který lze k něčemu přidat. Obvykle se používá pro ty věci, které chceš přidat na více místech v základní hierarchii tříd. Typickou ukázkou je mix-in třída Lockable a její potomci, jako LockableWithKey. Ty definují samotnou funkcionalitu zamykání a odemykání, která je sama o sobě k ničemu, dokud se nezkombinuje s nějakým objektem, třeba dveřmi, nebo kontejnerem. Dveře a kontejner jsou dva hodně odlišné objekty, které jsou v základní hierarchii objektů odvozených od Thing dost daleko od sebe, zejména kontejner má pak i hodně různých potomků s různým chováním, ale sdílejí tu potřebu je občas učinit zamykatelnými. Proto je Lockable mix-in třída, která jde přidat k jednomu či druhému a jde tak vytvořit hodně různých kombinací chování.

U Shipboard i Floorless máš ve skutečnosti obě možnosti:
Kód: [Vybrat]
/*
 *   A shipboard room.  This is a simple mix-in class: it can be used
 *   along with any type of Room to indicate that this room is aboard a
 *   ship.  When a room is aboard a ship, the shipboard travel directions
 *   (port, starboard, fore, aft) are allowed; these directions normally
 *   make no sense.
 *   
 *   This is a mix-in class rather than a Room subclass to allow it to be
 *   used in conjunction with any other Room subclass.  To make a room
 *   shipboard, simply declare your room like this:
 *   
 *   mainDeck: Shipboard, Room // etc
 */
class Shipboard: object
    /* mark the location as being aboard ship */
    isShipboard = true
;

/*
 *   For convenience, we define ShipboardRoom as a shipboard version of the
 *   basic Room type.
 */
class ShipboardRoom: Shipboard, Room
;

Tedy třída Shipboard je mix-in třída použitelná s jakýmkoliv druhem místnosti (a musíš si ji sám s nějakým druhem místnosti namíchat) a pokud žádný speciální druh místnosti nechceš, tak můžeš použít přímo ShipboardRoom, která představuje základní místnost s Shipboard směry.

Proč není stejným způsobem udělaný i Darkroom nevím, zřejmě nepřišlo autorovi důležité to tak udělat. Asi předpokládal, že místnost bez osvětlení budou lidé zřídka kdy chtít kombinovat s něčím jiným (a když, mohou to něco jiného přimíchat k ní). Nehledal bych v tom nějaký hlubokomyslný důvod. Snad jen snahu mít co nejvíce samostatně použitelných tříd a co nejméně mix-inů, které vyžadují o krůček navíc k pochopení.
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: Kroužící orel 27. Září 2017 - 10:02
Výborně, já to cítím zrovna tak, je velmi lákavé naučit se např. PHP s Javascriptem a nějakým tím frameworkem, spousta z nás by poté mohla pracovat z domova, což by mi v minulosti moc pomoho, u síťařiny tohle nejde. Nyní už ale tuhle potřebu nemám a mohu se učit jazyk, který je mi blízký, TADS, C, C++ a Python v kombinaci s linuxem nebo unixem je přesně to, co mě láká nejvíce.

Learning TADS3 je psaný čtivě a se zajímavými příklady, už jsem u šedesáté stránky a mnohé jsem pochopil, je hezké vědět, že existuje třída, objekt, vlastnosti a metody, ale teprve zde vidím prakticky, k čemu jsou. Autor parádně ukazuje jednoduchou definici vlastností a využití šablon, poté mix-in třídy a vícenásobnou dědičnost, nevěděl jsem, že i třída může dědit z jiné třídy.

Taky už vidím rozdíl mezi
vlastností = statická data
a
metodou = blok kódu čekající na spuštění

a na všechny ty tajemné příkazy uvnitř složených závorek u Heidi i Základny se už budu dívat jinak.

Snad jsem i správně pobral rozdíl mezi metodou a funkcí
metoda = kód přiřazený ke konkrétnímu objektu
funkce = kód nepřiřazený

tohle bude určitě v C++ podobné.

V manuálu jsou i bezva příklady, např. prsten schovaný pod kobercem se dá definovat více způsoby, metodou discover nebo makePresent.  Už vím jak změnit název objektu po jeho změně, např.  zapálenou pochodeň a spoustu dalších věcí, s tímle se pohnu mnohem více dále. I v Exoteru využiji třídu Outdoorroom a více si s ním vyhraji, teď už snad pochodeň a studnu nadefinuji správně. Metody jsou krásně vidět i v Sample games, soubor LightFire.t mi hodně pomůže.

Jo, my lidi jsme holt líní, nedal jsem na Tvou i autorovu radu, že začít Getting started a hrou Heidi pro neprogramátora není ten nej nápad, ale nevadí. Teď už snad konečně získám i ty programátorské návyky, hurá...

---

Moc děkuji za parádní vysvětlení mix-in tříd, autor je posléze popisuje i v dalších tématech, mě hlavně zajímalo, proč právě Darkroom, u kterého bych mix-in očekával, takto připravený není. Teď už vím, že autor standardní knihovny se prostě tak rozhodl při implementaci TADSu, nakonec novou mix-in třídu si mohu nadefinovat i sám, proč ne, takové vychytávky ale až časem. Na Lockable se podrobněji podívám, se Shipboard je vše jasné, tu jako samotnou třídu nemohu využít, pak by samozřejmě mix-in ztrácel smysl.

Mimochodem, díval jsem se, že i v C++ se mix-in třídy používají a jak jsem předpokládal, má svojí Standard Library, to mě více, než těší, začít programovat s TADSem mě nenásilnou formou dostane i sem...

Za půl hodinky mě čeká vyjížďka, pak bude chvíli volno, takže budu študovat dále a zase něco upravím a přidám do zdrojáku.
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: gaspoda 28. Září 2017 - 09:21
...nevěděl jsem, že i třída může dědit z jiné třídy.

Že třída může dědit od jiné třídy a ta zase od jiné je úplně běžné, právě tak je vystavený celý strom dědičnosti v knihovně a mají to tak snad všechny objektově orientované jazyky. Co není úplně běžné, je vícenásobná dědičnost, tedy že třída dědí od více než jedné rodičovské třídy. V C++ to možné je, ale např. PHP se tomu zuby nehty brání a zavádí raději interfejsy a traity, které část vlastností vícenásobné dědičnosti přidávají, ale přitom nedávají plnou volnost.

Taky už vidím rozdíl mezi vlastností = statická data a metodou = blok kódu čekající na spuštění

Na slovo "statický" pozor, to má jiný význam. Vlastnost je prostě proměnná - pojmenovaná paměťová buňka, do které se dá uložit nějaká hodnota (a měnit, proto ne statická). Když jsou proměnné a funkce součástí objektu, tak se jim říká vlastnosti a metody, aby se zdůraznila jejich příslušnost k daným objektům. V C++ se používají stejné pojmy, akorát v C++ musíš vždy nejprve udělat třídu a pak teprve vytvořit objekt dané třídy, v TADSu můžeš psát už hotové objekty.

Mimochodem, díval jsem se, že i v C++ se mix-in třídy používají a jak jsem předpokládal, má svojí Standard Library, to mě více, než těší, začít programovat s TADSem mě nenásilnou formou dostane i sem...

To ano, TADS je navržen jako běžný moderní profesionální programovací jazyk. Principy, které si v něm osvojíš, tak jsou přenositelné dál. Tím se liší např. od informu, který je postaven na programování v anglickém jazyce, což je sice na první pohled neotřelé a zajímavé, ale v jiných oblastech jsou tyto znalosti zcela nepoužitelné. A zároveň i od různých klikacích prostředí, kde se dají gamebooky naklikat a sem tam napsat jednoduchý skript, což však je jen velmi omezená podmnožina skutečného programování.

Nevýhodou TADSu je, že právě díky tomu je dost těžký pro neprogramátory. Má strmou křivku učení - první schod, který lidé musejí překonat, je tak trochu jako menší horolezecká stěna. Na druhou stranu až na ní vylezeš, uvidíš mnohem dál.
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: Kroužící orel 3. Říjen 2017 - 09:15
Díky za parádní vysvětlení, já opravdu žil v domění, že třída od třídy nemůže nebo spíše není nutno, aby cokoliv dědila, na to přijdu až s vysvětlením od programátora nebo vlastní praxí. S tou vícenásobnou dědičností je to moc zajímavé, čím dál více se mi líbí kombinace TADS a C++. U PHP chápu, že OOP zde není ještě úplně dozrálé, přeci jen pokud se nepletu, opravdové objekty tam byly až od verze 5, na druhou stranu původní C také nic takového nemělo, jeho následník má ale historii samozřejmě delší.

A sakra, já jsem právě slovo „statický“ převzal z Eveho manuálu, kde na straně 23 vysvětluje rozdíl mezi daty vlastností a blokem kódu uvnitř medoy, jak vidno, definici jsem pochopil nesprávně. Spolu jsme se v minulosti bavili právě o proměnných a funkcích, psal jsi mi, že u OOP se jedná o vlastnosti a metody daného objektu, díval jsem se do historie zpráv.

Ano, četl jsem velmi zajímavé srovnání TADS a Inform, kde právě Tebou popsaný rozdíl v programování autor uvádí. Určitě nebudu spěchat a pořádně si vyzkouším všechny příklady v manuálu, ano, Eve píše, že práce s objekty je u TADSu zjednodušena, na to si v budoucnu u C++ musím dát pozor. Mimochodem velmi mě zaujaly tyto stránky:

http://www.sallyx.org/

Autor zde parádně popisuje začátek v jazyce C, přechod k C++, poté programování v Linuxu a popis mnou velmi oblíbené knihovny ncurses, také Postgresql se bude hodit. Je to spíše věc budoucnosti, pokud bys však měl čas a chuť a v rychlosti se juknul na popsanou látku, můžeš mi jako programátor sdělit svůj názor zda jsou tyto tutoriály vhodné na seznámení s těmito jazyky? Toto ale v žádném případě nespěchá, nejprve musím projet Learning T3, ten se mi jako manuál zdá naprosto parádní. A přečtu si jej několikrát, což dělám právě teď...

Ještě jednou si projedu mnou popisovanou část manuálu, ať je mi vše jasné. Tento víkend jsme jezdili a také tento týden mám téměř celý zaplněn jízdami na koních, takže se k počítači dostanu méně, ve volných chvílích budu dále studovat, OOP není žádná sranda. Už vím jak definovat metodu uvnitř objektu pochodeň, v Library i příkladu s názvem LightFire jsem nalezl vše potřebné plus následná změna názvu po změně stavu se také zadařila, ještě si projedu všechny příklady a příště sem snad už konečně hodím další kus exoteráckého kódu.
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: gaspoda 3. Říjen 2017 - 20:36
Díky za parádní vysvětlení, já opravdu žil v domění, že třída od třídy nemůže nebo spíše není nutno, aby cokoliv dědila

V praxi se poměrně běžně vytvářejí složitější hierarchie dědičnosti tříd. V TADSu to máš třeba právě na příkladu třídy Thing a jejich desítek potomků: http://www.tads.org/t3doc/doc/libref/object/Thing.html#_SubClassTree_ (http://www.tads.org/t3doc/doc/libref/object/Thing.html#_SubClassTree_) Od Thing dědí Actor, BasicLocation, BulkLimiter, od BasicLocation dědí Room, od ní zase DarkRoom a další. Ale v jiných jazycích a programech to máš také, třeba v Qt knihovně pro tvorbu uživatelského rozhraní zase máš třeba třídu pro Widget, od ní dědí tlačítko atd. (https://wiki.qt.io/Qt_for_Beginners#Qt_class_hierarchy (https://wiki.qt.io/Qt_for_Beginners#Qt_class_hierarchy)). Představi si to jako podobenství s fylogenetickým stromem živočichů (https://cs.wikipedia.org/wiki/Klasifikace_%C5%BEivo%C4%8Dich%C5%AF#Fylogenetick.C3.A9_stromy (https://cs.wikipedia.org/wiki/Klasifikace_%C5%BEivo%C4%8Dich%C5%AF#Fylogenetick.C3.A9_stromy)), který říká, které druhy živočichů jsou si příbuzné. Třeba člověk a šimpanz mají hodně společného. V programování je podobná motivace - hledat společné vlastnosti a metody a ty pak vkládat do společného předka, odkud jsou zděděny do všech potomků, které je potřebují. Důvod je, aby to společné bylo naprogramováno jen jednou na jednom místě.

A sakra, já jsem právě slovo „statický“ převzal z Eveho manuálu, kde na straně 23 vysvětluje rozdíl mezi daty vlastností a blokem kódu uvnitř medoy, jak vidno, definici jsem pochopil nesprávně. Spolu jsme se v minulosti bavili právě o proměnných a funkcích, psal jsi mi, že u OOP se jedná o vlastnosti a metody daného objektu, díval jsem se do historie zpráv.

Ná já tam nikde slovo statický nevidím, ale já reagoval hlavně na pojem "statická data" a vlastnost, to je vlastně proměnná a může svou hodnotu měnit, takže slovo statický není na místě. Ale to je detail, moc nad tím nespekuluj.

Mimochodem velmi mě zaujaly tyto stránky: http://www.sallyx.org/

Nevím, proč ne. Psal to někdo mladší, kdo se to sám učil, tak třeba ti to bude vyhovovat. Proběhl jsem část o postgresu a přišlo mi to celkem fajn, takový zestručněný manuál. Vytkl bych asi hlavně to, že učí spojování tabulek zápisem s čárkou (kartézský součin) a následnou filtraci ve WHERE místo aby rovnou vysvětlil syntaxi LEFT resp. INNER JOIN ... ON ...  a jaký je mezi tím rozdíl.

O tom céčku je to taky takový docela hezký manuál. Akorát já osobně, když učím, tak kladu menší důraz na šířku znalostí a větší na schopnost porozumět principu a schopnost prakticky znalosti použít a proto se snažím všechno motivovat nějakou praktickou situací. Hlavní je mít nějakou motivaci, nějaký cíl, který chceš dosáhnout a který tě bude pohánět vpřed.
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: Kroužící orel 9. Říjen 2017 - 07:07
Hierarchie dědičnosti tříd:
Ano, právě na třídě Thing je vše parádně ilustrativní, někteří její potomci jsou popisováni v Eveho manuálu a také v návodu od Tebe. Díky za zajímavý odkaz na strom živočichů, ten jsem neznal, přeci jen od školy už mám pár let za sebou, hledání společných vlastností a metody je mi sympatické, tady krásně na konkrétním příkladě vidím výhodu OOP. S podobnou třídou pro Widget jsem se setkal už s GTK tuším v Glade při návrhu uživatelského rozhraní, když jsem si s ním hrál, tehdy jsem ale samozřejmě netušil nic o stromu dědičnosti a nyní je vše mnohem jasnější. Ouplně lituji, že nejsem programátor, TADS potřebuje pořádný moderní workbench pro Windows i Linux, moc dobře se mi pracuje s klasickými DOSovými okny ála Turbo nebo FreePascal IDE, mít takový naprogramovaný v ncurses pro příkazovou řádku a klidně i v GTK a QT pro X nebo Wayland by byla paráda. Ale co naplat, zatím musí stačit Wine.

Programování v C:
Moc díky za reakci, kvalitu tutoriálů zatím nejsem schopen posoudit, takže je paráda, že jsi se na web podíval a zhodnotil, mě zaujal hlavně popis oblastí, které mě nejvíce lákají, především ke knihovně ncurses jsem nenašel v češtině příliš mnoho materiálů. Podobný zajímavý návod nejen na C/C++ jsem nalezl i na webu www.itnetwork.cz a příklady her se zdrojovými kódy mám v plánu pořádně prozkoumat hnedle po zvládnutí TADS. Mám k dispozici i zajímavý úvod do programování v C na Raspberry - Essentials_C_v1.pdf, kde v závěru odkazují na asi tradiční knihu tohoto jazyka s názvem “The C Programming Language” od Kernighana and Ritchieho. Zde se ale právě bojím ztráty motivace a právě proto mě TADS zaujal, protože jeho ovládnutím se mi otevře můj dávný sen naprogramovat textovou hru, motivace je tedy obrovská. A stejně mě láká prozkoumávat linux a bsd, k tomu se dostanu později.

Pokud učíš právě tímto stylem, je to paráda, nakonec, proč bychom se na nějaké výuce nemohli dohodnout, vůbec nejsem proti.

Zapálení pochodně:
Nyní řeším zapálení pochodně. Několikrát jsem si přečetl T3TourGuide od strany 102 do 109 plus pečlivě prozkoumal LightFireSource v Sample Games. Zde jsou popisovány nejrůznější metody kontrolující množství oleje v lampě nebo způsob zapálení dynamitu, prosté zapálení pochodně něčím jiným, než sirkami, jsem však nenalezl. Napadlo mě grepnout metodu "canLightWith" a "canLightWith(obj)" ve všech souborech včetně Základny, které mám na disku, žádný příklad tohoto typu však nebyl k mání. Ani google nepomohl, divím se, že není k nalezení možnost zapálit pochodeň křesadlem, že by něco takového žádný autor pro textovku nepotřeboval?

Zkoušel jsem pomocí tipu na straně 104 v T3TourGuide v souboru LightFireSource ze Sample Games uvedený příklad LIGHT CANDLE FROM TORCH, ten mi úspěšně funguje, ovšem k zapálení předmětu musím mít krom zápalek v takovém případě věc, která již hoří.

Jediné, co mě po několikadenním zkoušení napadlo, bylo využít objekt Matchstick - jen díky němu jsem schopen křesadlem pochodeň zapálit. Zde zasílám transskript hry:

--------------------------------------------------------------------------------------------------------------------------
Vítejte v konverzační hře Exoter, přesněji řečeno v její co nejvěrnější předělávce ze skvělého počítače ZX Spectrum a Didaktik Gama.

Kobka
Jsi v malé kamenné kobce. Je tu cítit mrtvolný zápach. Světlo sem proniká z jediného stropního otvoru, ve kterém je mříž.
Nemůžeš jít nikam.
Vidíš tu mrtvolu.

>koukni se do mrtvoly
Bližší pohled na mrtvolu odhalil šperhák schovaný v záhybech polorozpadlých šatů!

>vezmi sperhak
Hotovo.

>odemkni mriz
(šperhákem)
Hotovo.

>n
(nejprve otevíráš mříž)
Chodba
Stojíš na kamenné dlažbě středověké chodby. Nízká klenba Ti rozhodně nedodává pocit jistoty.
Můžeš jít na východ, na jih, dolů.
Nevidíš nic zvláštního.

>v
Chodba
Jsi v chodbě.
Můžeš jít na východ, na západ.
Vidíš tu pochodeň.

>vezmi pochoden
Hotovo.

>prozkoumej pochoden
Kdyby se Ti jí podařilo zapálit, jistě by vydávala hodně světla.

>v
Chodba
Jsi v chodbě. Vidíš strážce, naštěstí je k Tobě obrácen zády.
Můžeš jít na východ, na západ.
Vidíš tu svazek klíčů a křesadlo.
Strážce tu stojí.

>vezmi kresadlo
Hotovo.

>prozkoumej kresadlo
Snad by se s ním dal rozdělat oheň.

>v
Konec chodby
Jsi na konci chodby. Vidíš dveře.
Můžeš jít na východ, na západ.

>zapal kresadlo
Škrtnutím křesadla zapaluješ malý plamínek.

>i
Neseš šperhák, pochodeň a křesadlo (lit).

>zapal pochoden
(křesadlem)
Zapálená pochodeň příjemně praská a vydává hodně světla.

Křesadlo dohořelo a plamen mizí v obláčku dýmu.

>

- po několika příkazech hra vypíše: "Pochodeň už vyhořela až na konec a zrovna zhasíná.", toto chování předpokládám musím potlačit změnou metody objektu Candle. Právě se koukám do T3TourGuide na stranu 104, kde autor popisuje vytvoření nové třídy RedCandle a právě metoda dobjFor(BurnWith) bude nejspíše ta pravá:

dobjFor(BurnWith)
{
   check()
   {
      if(fuelLevel < 1) // tento if musím potlačit?
        sayBurnedOut;
      else
        inherited; //volání předka tohoto objektu, pokud dobře rozumím?
    }
}

--------------------------------------------------------------------------------------------------------------------------

Křesadlo se stále chová jako sirka, viz "Škrtnutím křesadla zapaluješ malý plamínek." Po zadání i se v inventáři objeví „křesadlo (lit)“, zde asi bude nepřeložený textový řetězec. Následně křesadlo dohoří stejně jako sirka v Sample games - LightFireSource.

Napadlo mě modifikovat jednu z metod objektu Matchstick tak, aby lépe odpovídal křesadlu - je tento mnou zamýšlený postup správný? Pokud ano, pokusím se přijít na to, kterou. Skutečně jsem zatím nepřišel na jinou možnost jak zapálit nehořícím objektem objekt hořící, při vyhledávání na internetu jsem ještě narazil na zjednodušenou knihovnu adv3lite, která pravděpodobně tuto situaci řeší elegantněji:

http://tads3.gerynarsabode.org/index.php?title=Thing_(adv3Lite)

--------------------------------------------------------------------------------------------------------------------------
canBurnWithMe    
Use this property to declare that a player can burn something with the object being defined. The default setting is that one cannot use objects to burn other things with. Can be either true or nil
canBurnWithMe = true
--------------------------------------------------------------------------------------------------------------------------

Rád bych se však alespoň zpočátku naučil knihovnu klasickou, protože výše popsané zjednodušení mi ve výuce programování určitě nepomůže. Dostupná dokumentace je dle mého názoru perfektní, to spíše já zatím ještě neumím dohledat všechny potřebné informace.
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: gaspoda 9. Říjen 2017 - 19:36
...divím se, že není k nalezení možnost zapálit pochodeň křesadlem, že by něco takového žádný autor pro textovku nepotřeboval?

Ono těch různých možných kombinací je hodně, takže TADS nemůže postihnout úplně každý případ a proto dává k dispozici jen obecný rámec, který si musíš podle situace trochu přizpůsobit. Jak jsi asi zjistil, existuje mix-in třída FireSource, která představuje hořící objekt který může něco zapálit. To není úplně tvůj případ, protože chceš křesadlo, které může zapálit, ale samo o sobě nehoří. Nicméně je je docela dobrý nápad se podívat do knihovny na definici třídy FireSource, abys viděl, jak je udělaná. Je v ní akorát definice iobjFor(BurnWith), tedy nepřímého objektu akce zapal (přímý je ten, co bude zapálen a nepřímý ten, který slouží jako pomůcka zapálení).

Pojdme tedy udělat obyčejný objekt (Thing) a dát mu iobjFor(BurnWith), jen ho trochu zjednodušíme, aby křesadlo samo nehořelo. Pochodeň je vzata víceméně ze sample games. PreferredIobje je tam proto, že zapal nepoužívá předložky a tak je pro parser neodhadnutelné, co zapaluješ čím, tak si to sám prohodí tak, aby to dávalo smysl.

Kód: [Vybrat]
+ PreferredIobj, Thing 'křesadlo/křesadla/křesadlu/křesadlem' 'křesadlo' *4
    "Snad by se s ním dal rozdělat oheň. "

    iobjFor(BurnWith)
    {
        preCond = [objHeld]
        verify()
        {
            /* don't allow using me to light myself */
            if (gDobj == self)
                illogicalNow(&cannotBurnDobjWithMsg);

            nonObvious;
        }
    }
;

+ FireSource, Candle 'pochodeň/pochodně/pochodni/pochodní' 'pochodeň' *3
    desc()
    {
        if(isLit)
            "Hoří plápolavým plamenem<<if fuelLevel < 3>>, ale ten už začíná dohasínat<<end>>. ";
        else
            "Kdyby se Ti jí podařilo zapálit, jistě by vydávala hodně světla. ";
    }
    fuelLevel = 7
    brightnessOn = 2

    dobjFor(BurnWith)
    {
        check()
        {
            if(fuelLevel < 1)
                sayBurnedOut;
            else
                inherited;
        }
    }
;

Křesadlo se stále chová jako sirka, viz "Škrtnutím křesadla zapaluješ malý plamínek." Po zadání i se v inventáři objeví „křesadlo (lit)“, zde asi bude nepřeložený textový řetězec. Následně křesadlo dohoří stejně jako sirka v Sample games - LightFireSource.

Napadlo mě modifikovat jednu z metod objektu Matchstick tak, aby lépe odpovídal křesadlu - je tento mnou zamýšlený postup správný?

Matchstick je objekt, který můžeš zapálit sám o sobě, tj. zapálíš a hoří matchstick a od něj můžeš zapálit něco jiného, takže to moc neodpovídá. To (lit) u sebe nemám, možná jsem to někdy přeložil později a není to ve zveřejněné knihovně a nebo je to někde, kde nevím kde. Candle dědí z FueledLightSource, takže časem dohoří. Kdybys to chtěl odrušit, tak viz:

Kód: [Vybrat]
    /*
     *   If the light source can burn forever, simply return nil as the
     *   fuel level. 
     */
    getFuelLevel() { return fuelLevel; }

Rád bych se však alespoň zpočátku naučil knihovnu klasickou, protože výše popsané zjednodušení mi ve výuce programování určitě nepomůže. Dostupná dokumentace je dle mého názoru perfektní, to spíše já zatím ještě neumím dohledat všechny potřebné informace.

Adv3lite má na svědomí Eric Eve. Totiž ono to bylo tak, že po uvedení TADS 3 spousta lidí léta remcala, že to programování je moc těžké a nebyli ochotni přejít z TADS 2 dál. A vznikla taková pověra, že kdyby to programování bylo snazší, že by to umožnilo mnohem snadnější vstup do této oblasti těm, kteří pro domělou snadnost dávají přednost Informu a dalším systémům.

Mike Roberts zkoušel něco udělat, napsal nový trochu jednodušší parser nazvaný Mercury, ale neměl už moc času dotáhnout celou situaci až do stavu alternativní knihovny, která by byla obtížností někde mezi TADS 2 a 3. Eric se toho tehdy ujal a naprogramoval Adv3Lite. Původní idea byla odstranit některé ze složitějších vlastností, které knihovnu komplikují (postoje postav, simulování smyslů, hru v reálném čase, tisk řetězců přes žurnál atp.), ty totiž hodně znesnadňovaly orientaci a málo kdo je využil. Původní plán byl udělat hodně jednoduchou knihovnu, která by sloužila jako mezikrok pro programátory, než se pustí do plnohodnotné Adv3. Skutečnost však šla kousek dál, došlo k mohutné redukci, knihovna má o hodně menší počet tříd, ale zároveň i přidává některé nové vlasntosti, třeba scény, takže nakonec není ani zdaleka tak lite, jak se někteří původně domnívali a remcalové remaci dál...

No z hlediska našeho je hlavní problém v tom, že k ní není k dispozici překlad a nebude.
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: Kroužící orel 12. Říjen 2017 - 12:27
1. Křesadlo a pochodeň
Nádherně vysvětleno, právě se dívám na mix-in třídu FireSource, která má jedinou podtřídu Matchstick a jedinou metodu iobjFor(BurnWith).  A pokud si třídu rozkliknu odkazem 1895, skutečně vidím „We don't provide any action handling - we leave that to the direct object.“ - tady autor přímo nabádá, abych si odvozený objekt upravil, přesně jak píšeš.

S „PreferredIobj“ jsem se zatím nesetkal nebo si jej nevšiml, vidím, že jej používáš ve svém překladu a konkrétně v demonstraci Attachable:

preferredIobj = nil
replace doActionMain()

Dívám se na třídu FueledLightSource, zde je jako jediná podtřída uvedena Candle. Direktivu getFuelLevel() { return fuelLevel; } jsem našel při rozkliknutí odkazu třídy i její podtřídy, odkaz extras.t 2079 i 2205.

Nyní vše v pochodní funguje, viz soubor Exoter_v2.t, jediný problém, který zatím vidím, je příkaz:

>zapal pochoden kresadlem
To není něco, co by mohlo hořet.

ale

>zapal pochoden
Čím ji chceš zapálit?

>kresadlem
Zapaluješ pochodeň.

funguje parádně, zatím to tak nechám, tyhle detaily si nechám na později.

Hledání ve třídách, vlastnostech, metodách apod. v knihovně už je mi jasné, teď se mi jen vše musí spojit dohromady, chápu, to chce čas, jo to vlastně „gró“ programování. Místo abych hledal v knihovně, snažil jsem se nalézt co nejvíce v příkladech, což je asi běžný postup programátorů začátečníků. Upřímně řečeno přes obrovský záběr TADSu jsem si ani neuvědomil, že tak triviální věc jako zapálení pochodně křesadlem, troudu ocílkou nebo obyčejné rozdělání ohně něčím jiným, než sirkami, zde není už jako hotové řešení, tady jsem dost ovlivněn našimi textovkami a příkazem použij – je ale jasné, že standardní knihovna bude popisovat jen obecné věci, vše obsáhnout nelze, chápu, že se s tím v budoucnu setkám i v C++ a jiných jazycích, asi proto existují knihovny rozšiřující, které se snaží nějakou konkrétní množinu problémů řešit. Na programátorovi je také to, aby tyto knihovny znal a ve svém projektu je uměl použít plus to, co jinde nenajde, dokončil sám, to mi stále více a více ukazuje praxe.

Teď když už se s Library reference manual více kamarádím a ještě jednou si prohlížím třídu FueledLightSource, napadá mě otázka, co znamená a k čemu slouží soubor  extras.t, na jehož definici se dívám? Když si přeložím popis „This module defines classes for specialized simulation objects. “, vidím, že se jedná o modul, který definuje třídy pro objekty specializující se na konkrétní simulaci. Jedná se tedy o hlavičkový soubor umístěný v podadresáři lib a když rozkliknu odkaz Source file, mimo celého bohatě komentovaného dokumentu vidím, že na začátku obsahuje direktivu:

#include "adv3.h"

To znamená, že odkazuje na standardní knihovnu adv3, okolo které se celý TADS točí, teď už mi to do sebe více zapadá.

Možná bude pro mě lepší, když budu více zkoumat Library reference manual a nejlépe zkoušet dostupné příklady, tak pochopím více, ostatně i Eveho manuál sem mnohokráte odkazuje. Definice místností a objektů je mi již víceméně jasná, rozhovory s NPC postavami si nechám na jindy, nyní mi jde hlavně o akce, o kterých píšeš i ve svém manuálu a k jejich definici potřebuji pořádně pochopit práci s metodami, o nic se, jak překpokládám, dozvím nejvíce zde. 

2. Nepřeložený řetězec "lit"
Ještě jednou jsem si zkusil projet moji původní verzi Exotera, zde se po zapálení pochodně křesadlem s tím, že jej definuji jako Matchstick, viz soubor Exoter_v1.t, objeví toto:

„Neseš šperhák, pochodeň (svítí) a křesadlo (lit).“

Následně jsem to samé zkusil po Tebou navrhované úpravě, viz soubor Exoter_v2.t:

Neseš šperhák, pochodeň (svítí) a křesadlo.

V souborech cs_cz.t a msg_neu.t je dle mého laického pohledu vše v pořádku, zde asi překladač k objektu Matchstick přiřadil chybný textový řetězec nebo je na místě, které jsem zatím nenalezl. Pokud budeš v budoucnu připravovat další verzi češtiny, prosím o kontrolu objektu Matchstick a přidání překladu, snad alespoň tímto svým testováním alespoň trochu pomohu k jeho zlepšení.

3. Knihovna Adv3lite a TADS Workbench
Moc děkuji za parádní popis této knihovny, chápu, proč lidi toužili po něčem jednodušším, upřímně řečeno jsem dle Tvého popisu nabyl dojmu, že TADS2 byl mnohem jednodušší na použití, než třetí verze, já jsem se setkal až s trojkou.
Sakra, nečekal jsem, že tato knihovna přidává i nové vlastnosti, na druhou stranu vidím, že dopadla podobně jako např. Wordpress nebo Nginx, původně štíhlé projekty vesele bobtnají a původní záměr mizí. I proto je mi velmi sympatická knihovna ncurses, mám rád jednoduché řádkové aplikace s rozhraním ála M602 nebo dosedit, které jsou určené k jediné konkrétní činnosti nebo mé oblíbené účetnictví Tichý – Ježek, které i po dvaceti letech zachovává stejné rozhraní a jen upravuje funkcionalitu, dnes podporuje i EET a existuje i snadný krok, jak jej plně integrovat do Linuxu.
Zatím jí tedy nechám na pokoji, pokud neexistuje překlad, není pro mě určena, takže se na ní podívám v budoucnu. Ta klasická mě stále více a více ohromuje tím, co vše dokáže, takové práce, kterou autoři věnují komunitě, si nesmírně vážím.
S tím Informem jsem si také trochu hrál, na root.cz vyšel i český článek tuším o dvou dílech, který základy popisuje, vypadá mnohem jednodušší, ale obávám se, že složitější problémy už nebude taková sranda realizovat a domnělá jednoduchost se rozplyne jak pára nad hrncem. Pro mě je tedy TADS výhodnější,  díky českému překladu a  především jako parádní příprava na C++.

Neodolal jsem a do google jsem zadal „TADS Workbench source“, napadlo mě, když je TADS otevřený, zda jsou i k WB k dispozici zdrojové kódy. V diskuzi:

https://www.intfiction.org/forum/viewtopic.php?f=10&t=4088

Jeden diskutující píše: „The Workbench source is available as part of the htmltads source release. It's all built directly on Win32 (no MFC or any other Microsoft class libraries are involved).“

Plus zde na github:

https://github.com/uliwitness/TADSWorkbench

Jsou k dispozici nějaké zdrojáky, zběženě jsem je prozkoumal a vypadá to, že jsou určeny pro MAC, ostatně pro něj je k dispozici i starší oficiální verze dostupná na stránkách.  Škoda, linuxový WB by byla paráda plus jak jsem minule psal ta verze ncurses/GTK/QT, jen ty zdrojáky mě zatím opravdu děsí, je jich nějak privela…
Takže zatím zůstanu u kombinace Frobtads/editor českého textu/WB ve Wine, sice trochu krkolomné, ale naštěstí funkční.

4. Lano a attachable obecně
Nyní po vyřešení pochodně bych se rád vrhnul na přivázání lana k temné studni a vše, co s tím souvisí. Využiji všechny dostupné znalosti, jak vidím, attachable je parádně popsaná v manuálu i v Library plus připravil jsi parádní demonstrační hru, pokusím se vše vyřešit sám, jedině tak se dostanu zase o krok dále.
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: Kroužící orel 12. Říjen 2017 - 12:28
... ještě ty přílohy...
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: gaspoda 12. Říjen 2017 - 23:23
1. Křesadlo a pochodeň
Nádherně vysvětleno, právě se dívám na mix-in třídu FireSource, která má jedinou podtřídu Matchstick a jedinou metodu iobjFor(BurnWith).  A pokud si třídu rozkliknu odkazem 1895, skutečně vidím „We don't provide any action handling - we leave that to the direct object.“ - tady autor přímo nabádá, abych si odvozený objekt upravil, přesně jak píšeš.

To není narážka na odvozený objekt, ale na něco trochu jiného. TADS je založený na objektově orientovaném programování a to znamená, že se k herním objektům píší různé metody, které něco dělají. K akcím, které používají dva objekty (přímý a nepřímý), jako zapal koho/co kým/čím, se váží hned dva objekty ve dvou rolích. Přímý objekt, který je manipulován (pochodeň) a nepřímý, který slouží jako pomůcka (křesadlo). Výsledek takové akce se dá naprogramovat na dvou místech. Buď v metodě dobjFor(BurnWith) u pochodně nebo v iobjFor(BurnWith) křesadla.

Na kterém místě reakci naprogramovat je na tvém uvážení. Je to zpravidla jedno. V tom se objektový přístup trochu liší od třeba Informu, který je založen na tabulkách s pravidly. Tam se prostě přidá pravidlo a nemusí se přemýšlet, ke kterému objektu ho přilepit, prostě se hodí na jednu společnou hromadu všech pravidel.

To, co se v manuálu píše tedy říká, že akce bude naprogramovaná u přímého objektu a tady u nepřímého tedy není nic.

S „PreferredIobj“ jsem se zatím nesetkal nebo si jej nevšiml, vidím, že jej používáš ve svém překladu a konkrétně v demonstraci Attachable:

Parser sám neumí poznat, co je přímý a co nepřímý objekt u akcí, které nemají předložku, např. můžeš napsat "podej kafovak Borisovi" i "podej Borisovi kafovak". Proto třída Actor je označkovaná jako PreferredIobj a podle toho, když parser vezme objekty obráceně, tak je před dalším zpracováním prohodím. Je to právě ta situace, kdy by hra řekla, že kafovaku nemůžeš Borise podat. Značka říká, který z objektů je nepřímý, aby se to prohodilo do správného pořadí. U kací s postavou je to automaticky v knihovně, ale u některých akcí nebo nových akcí se to nedá dopředu určit a tak to musí udělat autor hry. Co ještě musím udělat je opačnou variantu, PreferredDobj, protože to u některých akcí je potřeba.

Nyní vše v pochodní funguje, viz soubor Exoter_v2.t, jediný problém, který zatím vidím, je příkaz:

>zapal pochoden kresadlem
To není něco, co by mohlo hořet.

ale

>zapal pochoden
Čím ji chceš zapálit?

>kresadlem
Zapaluješ pochodeň.

funguje parádně, zatím to tak nechám, tyhle detaily si nechám na později.

Jo, já se podívám, jaká verze knihovny je zveřejněná a vyzkouším to.

Teď když už se s Library reference manual více kamarádím a ještě jednou si prohlížím třídu FueledLightSource, napadá mě otázka, co znamená a k čemu slouží soubor  extras.t, na jehož definici se dívám?

Knihovna je poměrně velká, čítá téměř 100 tis. řádek a proto je rozdělená do většího množství souborů, je jich kolem čtyřiceti. Snaha je, aby žádný nebyl extrémně velký. Některé třídy, jako např. Thing, které jsou základem všeho, tak jsou už tak dost velké. Zabírají jeden celý velký soubor jen s pár drobnostma navíc (thing.t). Všechny objekty, které od Thing dědí, jsou rozdělené do několika souborů. Většinu najdeš v objects.t (dveře, kontejnery a kde co), ale pár jich je i v souboru extras.t a tam jsou takové ty exotičtější, jako komplexní kontejnery, baťoh, klíč a další. Jsou to věci, které začínající programátor asi hned nepoužije a myslím, že je to taková sbírka kódu, který naprogramovali (nebo navrhli) pro TADS vesměs jiní lidé, když hledali, čím knihovnu ještě obohatit. Myslím, že nebyly součástí TADSu od úplného počátku.

Jedná se tedy o hlavičkový soubor umístěný v podadresáři lib a když rozkliknu odkaz Source file, mimo celého bohatě komentovaného dokumentu vidím, že na začátku obsahuje direktivu:

#include "adv3.h"

Hlavičkové soubory jsou ty s příponou .h a normální zdrojáky mají koncovku .t. Hlavičkový soubor je zjednodušeně něco, co jen učí kompilátor rozumět zdrojovému kódu v .t souboru. Proto se inkludují do každého .t souboru na začátku. Nic co je uvedeno v hlavičkovém souboru se nepřeloží do výsledné hry, nevznikne žádný program. Jsou v nich tedy hlavně definice maker, šablon atp., ale žádný příkaz, žádná proměnná.
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: gaspoda 14. Říjen 2017 - 21:10
Zveřejnil jsem poslední verzi knihovny, kterou mám. Je tam jen pár drobných oprav. To s tím (lit) nevím, já když to vyzkouším u sebe se zdrojákem, který jsi přiložil, tak mi to v inventáři normáně česky píše, že pochodeň (svítí). Nevrtal ses v knihovně sám? Nebo nemáš nějakou jinou verzi TADSu, než já? Já mám normálně TADS 3.1.3, to by měla být poslední zveřejněná verze.
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: Kroužící orel 16. Říjen 2017 - 11:34
1. Přímý a nepřímý objekt

Konečně se zase dostávám k programování, krásné počasí o víkendu jsme celé projezdili. Paráda, teď už je mi
konečně věta we "leave that to the direct object" jasná, s přímými a nepřímými objekty se zde aktivně setkávám právě až u pochodně, Ericův manuál studuji postupně, vidím, že o nich píše v sekci Actions a právě u třídy Attachable, o které se zmíním později. Metodu iobjFor(BurnWith) jsem využil u křesadla, vyzkoušel jsem si i dobjFor(BurnWith) u pochodně, kterou jsem nakonec zakomentoval, k tomuto řešení bych se přiklonil v případě, že bych chtěl řešit její postupné vyhasínání, čímž u Exotera hráče trápit zatím nechci. Vidím, že jsi studoval také Inform, ten jsem zatím nezkoušel, snad časem, ovšem vypadá to, že TADS je tak komplexní, že jeho možnosti ani nebudu schopen využít. Na ten kafovak u Borise se juknu do Tvých zdrojáků, ohledně PreferredIobj není samozřejmě v Learning TADS 3 ani slovo, je mi jasné, že jsi jej potřeboval vytvořit sám při přípravě překladu.

2. Knihovna, hlavičkové soubory, zdrojáky a historie TADS

Podíval jsem se na adresářovou strukturu frobtadsu, nyní je to krásně vidět, hlavičkové soubory vidím v /usr/share/frobtads/tads3/include, vidím, že i u nich existuje vnořené inkludy, např. hned ten první bignum.h inkluduje systype.h . A na stejné úrovni adrsář /lib vidím zdrojáky s příponou .t, jasně, zde je ten obrovský thing.t, objekty, eventy a v neposlední řadě knihovna adv3.h, o které jsme se bavili minule. Napadá mě jak byla vygenerována dokumentace, vím, že např. u Javy nebo PHP lze vygenerovat dokumentaci z komentářů, předpokládám správně, že webová Library reference vznikla podobně?

Dívám se, že zde mám nainstalovanou také starší verzi TADS2 s mnohem skromnější strukturou, jedná se krom dokumentace jen o 3 soubory:
/usr/share/frobtads/tads2/adv.t
/usr/share/frobtads/tads2/gameinfo.t
/usr/share/frobtads/tads2/std.t

jak vidno, posun ve třetí verzi a tedy i složitost, je obrovský.

Právě to mě nejvíce láká, časem díky znalosti jazyka C budu schopen zkoumat tyto soubory a chápat, o čem jsou a jak linux opravdu funguje. Teď se dívám na wikipedii, TADS2 byl psán nebo spíše jeho syntaxe vycházela z C a trochu z Pascalu, zatímco TADS3 je úplně jiný objektový model vycházející z C++ a z Javy plus využití VM, o tom píšeš i Ty ve svém manuálu.

Zdálo by se tedy a někteří diskutující programátoři jsou toho názoru, že učit se staré C je už přežitek stejně jako Pascal, na druhou stranu pokud chci jít do hloubky, bude lépe se věnovat právě starému C a teprve poté C++, cítím, že jedině tak mohu programování opravdu do hloubky pochopit, viz Tvůj názor na prvotní výuku pomocí skriptovacích jazyků. Jen nevím, zda to pro mě nebude trochu obtížné, když se nyní snažím pochopit objektový model a budu se vracet ke strukturovanému, když se ovšem dívám na C++, není to čistě objektový jazyk a některé konstrukce jsou převzané z C, tak to snad půjde. Pascal, i když jeho implementace FreePascal a Lazarus už je objektová, mi dnes asi nic nedá a skutečné využití pro mě nevidím.

3. Attachable a malé rozšíření překladu

Pečlivě jsem prozkoumal popis této třídy v Learning TADS3, T3TourGuide, Tvůj překlad a také knihovnu. A vypadá to, že hurá, pečlivost se vyplatila, vytvořil jsem objekt studna, ke které pomocí metody canAttachTo(obj) lze přivázat provaz. U provazu jsem s definicí jako Attachable pohořel, to jsem ale očekával, manuály popisují, že typický problém, kdy jej přivázaný táhnu sebou celou mapou není tak jednoduché řešit. Napadlo mě použít NearbyAttachable, který tuto bolístku zvládá, nyní vše funguje jak má. U lana a provazu mě první slovo napadne přivaž/odvaž, nikoliv připevni, přidal jsem jej tedy do souboru cs_cz.t z aktuální verze překladu, tam i v budoucnu budu dávat synonyma. Společně s aktuálním zdrojákem a průchodem hrou jej zasílám v příloze, třeba Ti cokoliv z toho pomůže u tvorbě dalších verzí.

Ukončení hry sebráním 4 diamantů už naprogramovat nebude problém, toto popisuje i manuál, nyní musím vyřešit snad již poslední bolístku, což jsou boje se strážcem, drakem a psem. Tady jsem dříve také zuřivě hledal na internetu, teď znovu prozkoumám knihovnu, pokusím se najít obecnou formulaci a vymyslet řešení, bude to podobné jako Tvůj příklad s pochodní a křesadlem. Začíná mě to stále více bavit, což je přesně to, co potřebuji.

4. Nová verze překladu

A vidím, že jsi zveřejnil novou verzi překladu, vše jsem vyzkoušel. Pokud vím, nic kromě souboru cs_cz.t jsem neupravoval a používám skutečně verzi 3.1.3, s tou jsem také před lety začínal. Nyní již je pojem křesadlo(lit) minulostí, tehdy jsem chybně definoval jeho metodu, pochodeň skutečně svítí jak je vidět v přiloženém transskriptu hry.

Zkusil jsem ještě jednou starší verzi definice křesadla:
+ kresadlo : FireSource, Candle 'křesadlo/křesadla/křesadlu/křesadlem' 'křesadlo' *4
a po jeho zapálení je vidět:
 Neseš šperhák, pochodeň (svítí) a křesadlo (svítí).

I tak je tedy vše v pořádku, je ale samozřejmě možné, že jsem si s překladem hrál více, než je zdrávo a upravil něco, co jsem neměl. 
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: gaspoda 16. Říjen 2017 - 20:36
Napadá mě jak byla vygenerována dokumentace, vím, že např. u Javy nebo PHP lze vygenerovat dokumentaci z komentářů, předpokládám správně, že webová Library reference vznikla podobně?

Ano, přesně tak, referenční příručka je generovaná z komentářů v knihovně.

Zdálo by se tedy a někteří diskutující programátoři jsou toho názoru, že učit se staré C je už přežitek stejně jako Pascal, na druhou stranu pokud chci jít do hloubky, bude lépe se věnovat právě starému C a teprve poté C++, cítím, že jedině tak mohu programování opravdu do hloubky pochopit, viz Tvůj názor na prvotní výuku pomocí skriptovacích jazyků. Jen nevím, zda to pro mě nebude trochu obtížné, když se nyní snažím pochopit objektový model a budu se vracet ke strukturovanému, když se ovšem dívám na C++, není to čistě objektový jazyk a některé konstrukce jsou převzané z C, tak to snad půjde.

Abych to upřesnil, můj názor se týkal především skriptovacích jazyků v prostředí webového programování, které  je natolik specifickou doménou, že neposkytuje dobré možnosti pro pochopení základů. Mezi C a C++ bych nutně dělicí čáru nedělal, pochopit OOP je přirozenou součástí. Když budeš o C++ uvažovat tak, že je to Cčko s objektama a pár drobnostma navíc, tak to sice nebude úplně přesné, ale to nevadí. Prostě když se ti bude na něco hodit udělat třídu, tak udělej, když postačí procedurální kód, tak taky dobře.

U lana a provazu mě první slovo napadne přivaž/odvaž, nikoliv připevni, přidal jsem jej tedy do souboru cs_cz.t z aktuální verze překladu, tam i v budoucnu budu dávat synonyma. Společně s aktuálním zdrojákem a průchodem hrou jej zasílám v příloze, třeba Ti cokoliv z toho pomůže u tvorbě dalších verzí.

Jo, synonyma jsem si u sebe přidal. Ale obecně to není správný  způsob, TADS je udělán tak, abys nikdy nemusel do knihoven zasahovat. Cokoliv z knihovny můžeš změnit ve svém vlastním kódu hry. Kdyby ses podíval do zdrojáků Základny, tak podobné změny tam jsou soustředěné v souboru componentMods.t. Všimni si, že každou knihovní třídu můžeš změnit pomocí klíčového slova modify či replace.

A třeba přidání nějakých synonym se dá udělat jednoduše tím, že si patřičnou VerbRule napíšeš u sebe. Buď přidáš další VerbRule ke stejné akci, jako jsem přidával slovo 'bodni' jako synonymum AttachTo v roomControl.t a nebo můžeš existující VerbRule nahradit pomocí klíčového slova replace. Tak jsem třeba v souboru s počeštěním spelling correctoru nahrazoval původní anglické příkazy.

Jo a dej si pozor, máš tam provaz.moveinto(studna), ale mělo by to být s velkým písmenkem moveInto. Při překladu na to dostaneš upozornění, chce ho to číst.
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: Kroužící orel 19. Říjen 2017 - 14:24
1. C a C++
Ano, podobnou definici jsem nalezl i na diskuzních fórech programátorů, tady bude asi jen opravdu malý rozdíl, někteří diskutující srovnávali C++ a Javu s tím, že Java je plně objektová, což asi nebude ve všech případech to pravé, nevím, toto zjistím až s dalšími zkušenostmi. Každopádně jsem si nainstaloval cppreference a cppman a zkouším jejich integraci s různými IDE a VIMem, to jistě využiji u různých tutoriálů, o kterých jsem psal v minulých dílech.

2. synonyma
Jasné, do knihovny raději už zasahovat nebudu, vlastní změny ve svém kódu určitě budou lepší řešení. Prozkoumal jsem componentMods.t a pokoušel se definovat synonymum dle roomControl.t. Ještě předtím jsou použil Tvůj překlad cs_cz.t a přepsal jím svůj upravovaný, jenže ouha, od té doby při hře vidím:

přivaž provaz
K čemu ho chceš připevnit?
>studna
(nejprve dáváš provaz na podlahu, potom ho uvolňuješ od studnu)
Provaz jsi spustil dolů.
>d
Studna je moc hluboká na to, abys do ní skočil jen tak.

a tohoto hlášení se nejsem schopen zbavit, i když jsem mnou upravenou češtinu zase nahrál zpět, hlášení je zde po kompilaci ve WB i Frobtadsu…
Musel jsem nebo možná Workbench nějakým příkazem přepsal definici AttachTo, budu hledat, sakra, tohle jsem nečekal.

3. chybové hlášení
No jo, máš recht, příkazu provaz.moveinto(studna) jsem si opravdu nevšiml, na debug ovšem používám Workbench s výchozím nastavením a o chybě píše pouze Frobtads:
Frobtads:
   compile Exoter.t -> obj/Exoter.t3o
Exoter.t(338): warning: undefined symbol "moveinto" - assuming this is a property name
   link -> Exoter.t3p
   preinit -> Exoter.t3
Errors:   0
Warnings: 1

---

Workbench – příkaz Compile for Debugging i Full Recompile for Debugging:

Tip: you can go to the source location of a compile error
by double-clicking on the error message in this window

----- begin build: Thu Oct 19 13:02:03 2017 -----
>t3make -Fy "Z:\home\wanbli\Plocha\TADS\Exoter\obj" -Fo "Z:\home\wanbli\Plocha\TADS\Exoter\obj" -o "Z:\home\wanbli\Plocha\TADS\Exoter_�s\Makefile_dbg.t3" -D "LANGUAGE=cs_cz" -D "MESSAGESTYLE=neu" -D "INSTRUCTIONS_MENU" -d -statprefix <@> -statpct "system.tl" "adv3\adv3.tl" "Exoter.t" -res
TADS Compiler 3.1.3  Copyright 1999, 2012 Michael J. Roberts
Build successfully completed.
----- end build: Thu Oct 19 13:02:04 2017 -----

Zkusím se poohlédnout po chybě v mém nastavení, s warningy jsem se ovšem v minulosti setkával, je zvláštní, že tuto chybu neodchytil. Také je mi divné, že metoda „moveinto“ projde, v knihovně je opravdu pouze moveInto, tady je asi překladač benevolentní.
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: Kroužící orel 19. Říjen 2017 - 14:29
A kruci, ani nevím jak mě napadlo vrátit se zpět a metodu provaz.moveInto přepsat zase zpět na provaz.moveinto a chyba se už neobjevuje…:

>prozkoumej studnu
Hluboká studna, nyní však již zcela vyschlá.
>přivaž provaz ke studni
(nejprve dáváš provaz na podlahu)
Provaz jsi spustil dolů.
>d
Sešplhal jsi dolů za pomoci přivázaného lana.
Ve studni
Jsi na dně studny. Je tu vlhko.
Můžeš jít nahoru.
Vidíš tu druhý drahokam.
>i
Neseš šperhák, pochodeň (svítí), svazek klíčů a křesadlo.
>n
Jihozápadní část nádvoří
Stojíš na nádvoří.
Můžeš jít na sever, na východ, na jih, dolů.
Je tu stará kamenná studna.
Vidíš tu provaz.
>polož pochodeň
Hotovo.
>d
Sešplhal jsi dolů za pomoci přivázaného lana.
Ve tmě
Je tu naprostá tma.
>n
Jihozápadní část nádvoří
Stojíš na nádvoří.
Můžeš jít na sever, na východ, na jih, dolů.
Je tu stará kamenná studna.
Vidíš tu provaz a pochodeň (svítí).
>vezmi pochodeň
Hotovo.
>vezmi provaz
(nejprve uvolňuješ provaz od studnu)
Hotovo.
>d
Studna je moc hluboká na to, abys do ní skočil jen tak.

Uff, tohle opravdu zatím nepobírám, ale nevadí, pořádně si prostuduji Tebou popsané části základny a pokusím se znovu definovat VerbRules.
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: gaspoda 19. Říjen 2017 - 15:07
Exoter.t(338): warning: undefined symbol "moveinto" - assuming this is a property name

Zkusím se poohlédnout po chybě v mém nastavení, s warningy jsem se ovšem v minulosti setkával, je zvláštní, že tuto chybu neodchytil. Také je mi divné, že metoda „moveinto“ projde, v knihovně je opravdu pouze moveInto, tady je asi překladač benevolentní.

Praktický rozdíl mezi warningem a errorem je v tom, že při varování může překlad pokračovat dál. I když kód asi není v pořádku, není to závada tak velká, aby kompilátor zastavila. V případě moveinto s malým písmenkem si všimni, že prohlásí, že to bude asi nějaká zatím nedefinovaná vlastnost a tak s ní i zachází, tj. nezavolá tu správnou metodu.

Protože varování nezastaví překlad a spustitelný soubor se vytvoří, tak opakovaný překlad beze změny ve zdrojáku už pak daný soubor znovu nepřekládá. To bude nejspíš důvod, proč jsi neviděl varování při překladu ve workbenchi, ono se píše, ale ne při opakovaném překladu bez provedení změn, takže ho lze snadno přehlédnout.

Kdyby sis přidal při překladu volbu -we tak se všechna varování převedou na chybu, tj. jakmile na ně kompiler narazí, tak odmítne pokračovat s překladem. Pak budeš donucen takové chyby opravit hned, což by bylo nejlepší.
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: gaspoda 19. Říjen 2017 - 15:11
Uff, tohle opravdu zatím nepobírám, ale nevadí, pořádně si prostuduji Tebou popsané části základny a pokusím se znovu definovat VerbRules.

Kdyžtak prosím upřesni.
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: Kroužící orel 20. Říjen 2017 - 14:22
Moc díky za vysvětlení s překladem, vyzkoušel jsem ve frobtadsu volbu -we a s definicí provaz.moveinto jsem opravdu pohořel.  A máš pravdu, vše jsem zkusil znovu a nyní již i WB píše:

TADS Compiler 3.1.3  Copyright 1999, 2012 Michael J. Roberts
Exoter.t(338): warning: undefined symbol "moveinto" - assuming this is a property name
Errors:   0
Warnings: 1

Zajímavé, včera jsem zkoušel WB restartovat a vše znovu kompilovat, druhý den vše funguje, nechce se mi věřit, možná že zafungoval „restart“ celého linuxu. Tak to je super, jen bych rád volbu -we využil i ve WB, zkoumal jsem jeho manuály, především The TADS 3 Debugger a zatím nenašel nic, co by mi pomohlo, ještě na to juknu.

Byl jsem nadmíru překvapen příkazem provaz.moveinto(studna) a vše jsem dnes ještě jednou otestoval a zasílám v příloze.

1. scénář – použil jsem svůj upravený soubor cs_cz.t, takže mi funguje příkaz přivaž zatím bez využití Tebou doporučovaného VerbRule, ve zdrojovém kódu je „chybný“ vnitřek metody provaz.moveinto. Takto vše v pořádku funguje a hra nemá problém s přivázáním provazu a vlezením do studny. V příloze jsou to soubory provaz_moveinto_Exoter.t, transskript_provazmoveinto.txt a cs_cz.t

2. scénář – stejně jako 1 bod, ale s využitím „správného“ vnitřku metody provaz.moveInto, zde hra píše nesmyslné hlášení:
(nejprve dáváš provaz na podlahu, potom ho uvolňuješ od studnu)
Provaz jsi spustil dolů.
// do studny se však nedostanu
>d
Studna je moc hluboká na to, abys do ní skočil jen tak.
V příloze jsou to soubory provaz_moveInto_Exoter.t, transskript_provazmoveInto.txt a cs_cz.t

3. scénář stejně jako bod 1, jen využívám Tvůj aktuální překlad cs_cz.t, který jsem si stáhnul na stránkách. Zde musím zatím místo „přivaž“ použít „připevni“, jinak ale vše funguje tak jak má.
V příloze je to soubor transskript_provazmoveinto_preklad_Gaspoda.txt

4. scénář stejně jako bod 2, jen využívám Tvůj aktuální překlad cs_cz.t, který jsem si stáhnul na stránkách. Zde dopadnu zase špatně, viz soubor transskript_provazmoveInto_preklad_Gaspoda.txt

Z toho jsem zmaten, zatím s využitím mého zdrojáku musím využít původní chybný provaz.moveinto, jinak nemohu provaz ke studni připevnit a dostat se dolů. Na druhou stranu se divím, že hra místo chyby vyhodí jen varování, v Library jsem našel jen moveInto.

Pokud se na to podíváš, budu moc vděčný, snad jsem se vyjádřil srozumitelně. Tady mi potíž přijde nelogická, spíš ale někde dělám chybu, o které zatím nevím.

Krásný víkend přeje

Orel
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: gaspoda 20. Říjen 2017 - 20:33
Tak to je super, jen bych rád volbu -we využil i ve WB, zkoumal jsem jeho manuály, především The TADS 3 Debugger a zatím nenašel nic, co by mi pomohlo, ještě na to juknu.

Ony to jsou úplně stejné nástroje, jako ve frobtads, jen přeložené do Windows a Workbench je k nim doplněný jako nadstavba. Možnost naklikat tuto volbu najdeš v menu Build - settings - diagnostics - treat warnings as errors. To propíše danou volbu do makefile.

2. scénář – stejně jako 1 bod, ale s využitím „správného“ vnitřku metody provaz.moveInto, zde hra píše nesmyslné hlášení:
(nejprve dáváš provaz na podlahu, potom ho uvolňuješ od studnu)
Provaz jsi spustil dolů.
// do studny se však nedostanu
>d
Studna je moc hluboká na to, abys do ní skočil jen tak.
V příloze jsou to soubory provaz_moveInto_Exoter.t, transskript_provazmoveInto.txt a cs_cz.t

Ano, tohle jsou už docela zapeklité situace, kdy je potřeba si dobře uvědomit, jak to tam funguje. Podíváš-li se na popis NearbyAttachable, tak uvidíš, že se snaží vynutit, aby provaz sdílel se studnou stejný nadřazený kontejner. Jinými slovy, aby mohl být provaz přivázán, tak musí být umístěn přímo v místnosti, protože studna je také přímo v místnosti.

Citace
A "nearby" attachable is a subclass of Attachable that adds a
requirement that the attached objects be in a given location.  By
default, we simply require that they have a common immediate
container,...

Tedy nesmí být přímo ve studni, což se právě pokoušíš dělat pomocí toho moveInto. On se položí na podlahu jako součást přivázání ke studni, ale pak příjde tvůj příkaz přemístění do studny a tak se provaz poslušně zase odváže, aby mohl být strčen dovnitř studny. (Ta špatná koncovka "uvolňuješ od studnu" je jen překlep ve tvém skloňování.)

Takže nejjednodušší řešení je žádné moveInto nedělat (ani to chybné s malým i). Budeš-li to chtít vylepšit a skutečně mluvit o provazu ve studni, tak to chce pár změn. Jednak udělej studnu také NearbyAttachable, ať je vztah symetrický. Dále z ní udělej kontejner, aby se daly věci do ní vůbec dávat. No a nakonec si pomocí getNearbyAttachmentLocs definuj, kde má být provaz a studna, když jsou k sobě přivázány. Tedy ne vedle sebe v lokaci, ale v sobě:

Kód: [Vybrat]
++ studna : NearbyAttachable, Container, Heavy 'studna' 'studna' *3
    "Hluboká studna, nyní však již zcela vyschlá. "
    specialDesc = "Je tu stará kamenná studna. "

    canAttachTo(obj) {return obj == provaz;}
    handleAttach (other)
    {
        "Provaz jsi spustil dolů. ";
    }

    getNearbyAttachmentLocs(other)
    {
        return [location, self, 0];
    }

     gcName = 'studny, studni, studnu, studni, studnou'
     gcVocab = 'studny/studni/studnu/studnou'
;

Potom dostaneš něco takového:

Citace
>přivaž provaz
K čemu ho chceš připevnit?

>studna
(nejprve dáváš provaz do studny)
Provaz jsi spustil dolů.

>podívej se do studny
Studna obsahuje provaz.

>p studnu
Hluboká studna, nyní však již zcela vyschlá. Obsahuje provaz.

Studna je připevněna k provazu.

>p provaz
Je pevný.

Provaz je připevněn k studni.

>d
Sešplhal jsi dolů za pomoci přivázaného lana.

To je už jistě lepší, akorát je to trochu problém, že "Studna je připevněna k provazu.". To by ti mohla vyřešit třída SimpleAttachable, kterou napsal Eric Eve a je k dispozici v SampleGames ve zdrojácích attachment. Ta umí určit, který předmět je tzv. hlavní objekt (major) a pak správně mluví, který je připevněn k čemu.

Na druhou stranu se divím, že hra místo chyby vyhodí jen varování, v Library jsem našel jen moveInto.

Programátorům se poměrně často stává, že použijí nějakou proměnnou a zapomenou ji deklarovat. V dynamicky typovaných jazycích často ani deklarace nejsou potřeba. TADS tedy v rámci přítulnosti k autorům předpokládá, že když použiješ nějaký název, který nezná, tak že to je proměnná, kterou jsi zapoměl deklarovat a tak ji promptně vyrobí a vyhodí jen varování. Nechce působit prudérně.

TADS ale zároveň na rozdíl od leckterého jiného jazyka nedělá velký rozdíl mezi proměnnou a funkcí. Totiž tam, kde se očekává nějaká proměnná v objektu, která má hodnotu, tak TADS rád připustí metodu, která hodnotu vygeneruje. Proto si o neznámé metodě tak snadno pomyslí, že jde o zapomenutou deklaraci proměnné.

I když v tomto případě je to zmatečné, tak je to důsledek vlastností, které jinde zase pomáhají šetřit práci. On tě na to upozorní, jen to nesmíš přehlížet ;-)
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: Kroužící orel 24. Říjen 2017 - 14:17
1. Debugger ve WB
Výborně, treat warnings as errors jsem všude nastavil a snad se podobným situacím už vyhnu. Je to na jednu stranu smůla, ale na druhou parádní ukázka toho, že dělám tradiční začátečnické chyby, netušil jsem, že „neznámý“ název systém bere jako proměnnou. Vidím, že kromě malého rozdílu mezi třídou a objektem je zde i minimální mezi funkcí a proměnnou. Je super, že je TADS v tomto benevolentnější, na druhou stranu jsem se jako laik dostal do pro mě nemožné situace, kdy mě nedefinovaná proměnná tak zmátla a jakoby fungovala a i když jsem provaz.moveinto v Library nenalezl, vše jakoby fungovalo tak jak mělo.
Všiml jsem si, že WB má v nastavení Diagnostics ještě volbu Pedantic, kterou si teď zapnu, zpočátku potřebuji znát i sebemenší chyby.
A nyní po rekompilaci stávajícího souboru provaz_moveInto_Exoter.t se dozvídám následující:

--------------------------------------------------------------------------------------------------------------------------
warning:
The symbol "executeCommand" is defined in the symbol file, but is already
defined.  This usually indicates that two symbol files that you're importing
both define this symbol as a function, object, or property name (the two files
might define the symbol as the same type, or as different types - it doesn't
matter, because the symbol can only be used once for any of these types).  You
must resolve the conflict by renaming the symbol in one or more of the source
files to make each name unique.
Errors:   0
Warnings: 1
t3make: error code 1
Build failed.
----- end build: Tue Oct 24 11:52:58 2017 -----
--------------------------------------------------------------------------------------------------------------------------

Varování executeCommand není ale definováno na konkrétním řádku, to chápu, když píše, že už je zavedeno v „symbol file“. Setkal jsi se už s touto chybou?

2. Attachable
Ano, tohle je opravdu zamotané, sakra, takovéhle chyby by měli autoři programátorských učebnic ukazovat jako parádní náročné příklady… Projel jsem třídu NearbyAttachable, ano, vidím zde informaci o nadřazeném kontejneru, upřímně řečeno ale až po Tvém vysvětlení chápu, oč skutečně jde. Skloňování jsem upravil a přidal definici kontejneru ke studni, jen jsem využil jediné plus, protože žádný jiný objekt zde v místnosti nemám, zkusil jsem i Tvůj příklad se dvěma plusy, který ale umístil místnost se dnem studny o místnost dále:
--------------------------------------------------------------------------------------------------------------------------
Severozápadní část nádvoří
Jsi na nádvoří. Na západě jsou dveře vedoucí do kamenné chodby.
Můžeš jít na východ, na jih, na západ.
Je tu stará kamenná studna.

>pripevni provaz ke studni
(nejprve dáváš provaz do studny)
Provaz jsi spustil dolů.

>d
Tímto směrem se pohybovat nemůžeš. Zřetelné směry vedou na jih zpátky do jihozápadní části nádvoří, na východ do severovýchodní části nádvoří a na západ.

>j
Jihozápadní část nádvoří
Stojíš na nádvoří.
Můžeš jít na sever, na východ, na jih, dolů.

>d
Sešplhal jsi dolů za pomoci přivázaného lana.

Ve tmě
Je tu naprostá tma.
--------------------------------------------------------------------------------------------------------------------------

Tomu snad již rozumím, ponechám tedy jediné plus. Třídu SimpleAttachable jsem podrobněji nezkoumal, přečetl jsem si o ní pouze v Learning TADS3 a studoval attachment.t ze Samples. 
Nakonec se zadařilo, podařilo se mi po malé úpravě charsetu inkludnout SimpleAttachable a takto definovat studnu i provaz, nyní je vše včetně češtiny v pořádku, viz soubory v příloze.
Plus jsem přidal nové VerbRule dle Tvého příkladu s bodni v Základně, nyní už nemusím upravovat nic v knihovně.

3. Malá otázka a poznámky
Přemýšlel jsem o definici

+ FireSource, Candle 'pochodeň/pochodně/pochodni/pochodní' 'pochodeň' *3

a přišla mi záhadná, objekt reprezentující předmět jsem zvyklý deklarovat spíše takto:

+ sekera : Thing 'sekera/sekerou/sekeru' 'sekera' *3

teď po pročítání Learning TADS3 se mi zdá, že je zde poprvé použit tzv. Anonymní objekt, je to tak správně?

Takže až na to malé varování u volby Pedant ve WB hra docela hezky hraje, nyní mě snad čekají už jen ty potvůrky typu strážce, drak a pes, po ukončení hry u brány bude Exoter na hrubo dokončen. Ještě jsem si všiml malé chyby při odvazování provazu od studny:

>odvaz provaz

(ke studni)
Hotovo.

Tady bude asi chyba v definici (co) (od čeho), ještě se s tím zkusím poprat. Příkaz  uvolni definovaný v knihovně funguje správně:

>uvolni

Co chceš uvolnit?

>provaz
Hotovo.

Ještě, že se s těmito potížemi setkávám, je mi jasné, že u C++ se stanou taky a budu zase o něco zkušenější. Zítra mi začínají podzimní prázdniny u koní, dorazí skoro dvacet řechtákomilců, takže k dalšímu vývoji se dostanu až po neděli.
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: gaspoda 24. Říjen 2017 - 20:57
Varování executeCommand není ale definováno na konkrétním řádku, to chápu, když píše, že už je zavedeno v „symbol file“. Setkal jsi se už s touto chybou?

Kompilovat to s volbou pendantic je už asi trochu přehnané. Nevím přesně, čím je to způsobené. Tedy vím, že executeCommand předefinovávám v českém překladu pomocí modify, ale to se mi zdá, že dělám správně. Takže sice se jedná o stejný symbol, ale ne o duplicitu, nýbrž o redefinici. Nemyslím, že by šlo o skutečný problém.

(Symbol file se vytváří před kompilací. Jedná se o takový katalog, jaké funkce, proměnné, třídy atd. jsou v každém souboru naprogramované. Slouží během samotného překladu.)

Skloňování jsem upravil a přidal definici kontejneru ke studni, jen jsem využil jediné plus, protože žádný jiný objekt zde v místnosti nemám, zkusil jsem i Tvůj příklad se dvěma plusy...

Promiň, to jsem tě zmátl neúmyslně. Já to kopíroval do fóra z diff souboru, protože jsem se koukal, co jsem nakonec ve tvém zdrojáku změnil. No a plus na začátku řádky znamená přidanou změnu. Ze zbytku zdrojáku jsem plusy a mínusy odmazal, ale tohle jsem přehlédl.

Nakonec se zadařilo, podařilo se mi po malé úpravě charsetu inkludnout SimpleAttachable a takto definovat studnu i provaz, nyní je vše včetně češtiny v pořádku, viz soubory v příloze.

Includovat? Ne, to sice bude fungovat, ale tak se to nedělá. #include je na hlavičkové soubory, to jsou ty s příponou .h. Přidej si SimpleAttachable do Makefile jako další zdroják a to před ten zdroják, ve kterém používáš. Třeba můj Makefile.t3m pro Frob vypadá takhle:

Kód: [Vybrat]
-o Exoter.t3
-D LANGUAGE=cs_cz
-D MESSAGESTYLE=neu
-D INSTRUCTIONS_MENU
-Fy obj
-Fo obj
-FC

-lib system
-lib adv3/adv3
-source Exoter.t

Tak bych prostě přidal -source SimpleAttachable.t před poslední řádek. No a ve Workbenchi se to udělá nějakým klikáním na stromečku vlevo, kde ti ukazuje soubory.

...teď po pročítání Learning TADS3 se mi zdá, že je zde poprvé použit tzv. Anonymní objekt, je to tak správně?

Ano, uložit referenci objektu do nějaké pojmenované proměnné musíš jen tehdy, pokud ji ty sám potřebuješ např. na to, abys někde jinde v programu něco s objektem provedl. Tak např. prakticky každou místnost člověk nějak pojmenovává, protože se na ni potřebuje odkázat z konektorů v jiných místnostech, aby je propojil do mapy. Nebo když mám nějaký objekt abudu s ním pak nějak interagovat pomocí programu, třeba ho někam přesouvat v nějaké akci, nebo se někde budu ptát, zda ho hráč drží apod.

Ale spousta objektů, zejména různé dekorace, ale i abstraktní věci, jako předměty rozhovorů, žádnou interakci nepotřebují, tak není důvod jm dávat jméno. Mimochodem když jsi v nějakém objektu, který je vložen kontejnerovou hierarchií do jinho objektu (tj. když seš v objektu s dvema plus), tak na nadřazený objekt (s jedním plus) se dostaneš pomocí vlastnosti location. Takže nemusíš třeba pojmenovávat objekt, na který se chceš dostat z potomka.

Ještě jsem si všiml malé chyby při odvazování provazu od studny:

>odvaz provaz
(ke studni)
Hotovo.

Tady bude asi chyba v definici (co) (od čeho), ještě se s tím zkusím poprat.

No schválně, jestli na to přijdeš:

Kód: [Vybrat]
VerbRule(UnStabTo)
    ('odvaž' | 'odvázat') dobjList
    ('k' | 'ke' | 'na' | 'do') singleIobj
    : DetachFromAction
    askIobjResponseProd = atSingleNoun
    verbPhrase
    {
            return 'odvázat/odvazu{ješ}/odvázal{a} (co) (k čemu)';
    }
;
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: Kroužící orel 2. Listopad 2017 - 10:28
1. Volba pedantic a znaménko plus u studny
Ano, já  jsem upřímně řečeno trochu tušil, že chyba vyvolaná přepínačem Pedantic bude asi způsobena českým překladem a je mi jasné, že tohle se sakra těžko odchytává. Takže nechám Standard plus detailnější vypisování chyb, to mi plně vyhovuje. Symbol file tedy mohu chápat jako index u databáze. U studny jsem za malou chybku se znaménkem vděčný, alespoň mě to nutí přemýšlet nad problémem a ne jen otrocky opisovat, bez toho se u vývoje nikam nedostanu.

2. Include
Aha, tady narážím na svojí nezkušenost, ale to je dobře, správné programátorské návyky potřebuji jako sůl. Máš pravdu, že v jiném zdrojáku jsem také nalezl pouze include xxx.h, ponechám tedy jen adv3.h a cs_cz.h. Mnou upravenou třídu SimpleAttachable jsem tedy přidal do projektu jako další položku TADS3 Adventure Library, Tvůj makefile si uložím na později, zatím mi práce s WB vyhovuje, škoda, že Frob nemá takový debugger jako WB, v takovém případě by mi plně dostačoval.

3. Odvazování provazu od studny
Zde jsem upravil definici, nyní již „odvaž od studny“ funguje. Mám jen jeden dotaz:

Přivaž:

VerbRule(privaz)
    ('přivaž' | 'přivázat') dobjList
    ('k' | 'ke' | 'na' | 'do') singleIobj

Odvaž:

VerbRule(odvaz)
    ('odvaž' | 'odvázat') dobjList
    ('od' | 'od' | 'od' | 'od') singleIobj

Prozkoumal jsem Tvé informace na adrese http://tads.cz/cs/definice-ceske-verbphrase, rád bych upravil slova 'k' | 'ke' | 'na' | 'do' také u VerbRule(odvaz), odvázat mohu od něčeho/z něčeho, můžeš mě nasměrovat ke správné definici? Odvázání od studny mi v Exoteru plně dostačuje, v další hře už ale může být problém.

4. Anonymní objekt
Jasné, s těmito se v manuálech setkávám poměrně často, máš recht, že u dekorací nemá smysl konkrétní objekt přímo pojmenovat – dekorace a Tebou popisovanou třídu Vaporous mám v plánu v plánovaném Bad Nightu, kde se původní hrou budu jen lehce inspirovat. Ano, location Eric také často využívá a jak vidím, i Ty u Základny.

5. Mříž a šperhák vs pilník:
Po akci s pochodní a provazem mě napadlo, že by podobná metoda měla zafungovat i u mříže. Zatím jsem rezignoval na pilník a situaci řešil šperhákem ve funkci klíče, teď už ale vím jak na to:

- pilník definuji metodou iobjFor(CutWith) jako předmět, kterým lze něco přeříznout
- spíše než přeříznout bych využil slovo „přepilovat“, využil jsem novou definici VerbRule jako minule
- u mříže jsem pomocí metody dobjFor(CutWith) zajistil možnost jejího přepilování

Takže šperhák vesele mažu, přiznám se, že je bájo pocit, když se s takovou věcí konečně mohu poprat sám, na to bych bez Tvé pomoci nepřišel. O to více se těším na další tvorbu.

6. Strážce a boj obecně
Nyní se konečně dostávám k poslední bolístce, k boji. Na internetu jsem moc informací k tomuto tématu nenalezl, zajímavý je boj se zombiemi:

https://www.intfiction.org/forum/viewtopic.php?f=10&t=753
Depending on what you actually want to happen to the zombie (does its body stay in the zombie lair after it has been killed?), you'll have to change the "moveIntoForTravel(nil)" bit.

Pokud využiji popsanou definici metody moveIntoForTravel z Library:

        action()
        {
          moveIntoForTravel(newContainer);

              {
                 mainMoveInto(newContainer);
             }

             "Jediným mocným úderem se ti podařilo poslat strážce do věčných lovišť. ";
        }

objeví se chyba:

The symbol "newContainer" is undefined, but appears from context to be a
property name.  The compiler is assuming that this is a property.  Check the
spelling of the symbol.  If this assumption is correct, you can avoid this
warning by explicitly declaring a value to the property in an object definition
rather than in method code.

V Library vidím:
moveIntoForTravel - method of Thing in thing.t[5465]
takže tuto metodu lze využít pro třídu Thing, strážce je Actor nebo v mém případě UntakeableActor, což jsou podtřídy, takže tuto metodu využít mohu.

Prázdná metoda moveIntoForTravel(nil) způsobí zmizení objektu, takže funguje dle očekávání. To si budu pamatovat pro příště, nyní ale potřebuji, aby mrtvola strážce v místnosti zůstala a já k němu konečně mohl přiřadit svazek klíčů a křesadlo, které zatím leží na zemi.

Nyní se dívám na: www.tads.org/howto/t3npcTravel.htm

a také jsem prozkoumal zdrojové kódy Základny, v souborech
actorCommander.t       
actorCaptain.t       
roomCorridors.t           
roomControl.t       
actorTechnician.t
se vyskytuje metoda moveIntoForTravel

Nyní se zaměřím právě na tuto metodu, abych jí správně pochopil, ta se mi bude hodit při každém boji v textovkách, i když jej budu využívat minimálně.

Tábory mám za sebou, teď mě čeká spravování věcí po vichřici, za pár dní se zase k TADSu vrátím za budu pokračovat.
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: gaspoda 3. Listopad 2017 - 00:31
3. Odvazování provazu od studny
Zde jsem upravil definici, nyní již „odvaž od studny“ funguje. Mám jen jeden dotaz:

Přivaž:

VerbRule(privaz)
    ('přivaž' | 'přivázat') dobjList
    ('k' | 'ke' | 'na' | 'do') singleIobj

Odvaž:

VerbRule(odvaz)
    ('odvaž' | 'odvázat') dobjList
    ('od' | 'od' | 'od' | 'od') singleIobj

Prozkoumal jsem Tvé informace na adrese http://tads.cz/cs/definice-ceske-verbphrase, rád bych upravil slova 'k' | 'ke' | 'na' | 'do' také u VerbRule(odvaz), odvázat mohu od něčeho/z něčeho, můžeš mě nasměrovat ke správné definici? Odvázání od studny mi v Exoteru plně dostačuje, v další hře už ale může být problém.

Je to jednoduché, při zapisování gramatiky parseru se do apostrofů dávají jednotlivá slova, která se v příkazu mohou vysktovat. V každých apostrofech vždy jen jedno slovo. Kromě těchto slov se vyskytují placeholdery pro přímé a nepřímé objekty.

Napíšu-li 'a' 'b', tak to znamená, že hráč může zadat příkaz >a b, tedy dvojici slov za sebou. Na samotné >a nebo >b nebude příkaz reagovat. Svislítko značí alternativy. Tedy když např. napíšu 'a' | 'b', tak to znamená, že hráč musí napsat buď >a nebo >b, ale ne oboje. Svislítko ale dělá alternativu neomezeně doleva a doprava, takže např. 'a' 'b' | 'c' 'd' znamená, že hra má reagovat buď na >a b nebo >c d, ale ne na žádnou jinou kombinaci.

Dosah alternace lze omezit závorkami. Když dám ('a' | 'b') 'c', bude to reagovat na >a c i na >b c. Takže jednoduše:

Kód: [Vybrat]
VerbRule(UnStabTo)
    ('odvaž' | 'odvázat') dobjList
    ('od' | 'z' | 'ze') singleIobj
    : DetachFromAction
    askIobjResponseProd = atSingleNoun
    verbPhrase
    {
            return 'odvázat/odvazu{ješ}/odvázal{a} (co) (od čeho)';
    }
;

Bude reagovat na příkaz >odvaž provaz od studny nebo >odvázat provaz ze studny apod. Nakonec to chce i vhodnou verbPhrase, která poskytuje slovíčka do otázek "od čeho chceš provaz odvázat?" apod.

6. Strážce a boj obecně
Pokud využiji popsanou definici metody moveIntoForTravel z Library:

Metoda moveIntoForTravel je určená na přemisťování postav z místnosti do místnosti či z místa na místo.

Ne, nemusíš si kopírovat, jak je metoda napsaná v knihovně. Stačí ji použít. Ta deklarace s proměnnou newContainer prostě jen znamená, že při volání funkce máš předat nějaký nový kontejner, do kterého chceš postavu přesunout. Tak např.:

Kód: [Vybrat]
action()
{
"Jediným mocným úderem se ti podařilo poslat strážce do věčných lovišť. ";
moveIntoForTravel(nil);
}

Tím postavu vyhodíš ze hry pryč. moveIntoForTravel je metoda postavy, takže když jsi přímo v action metodě dané postavy, tak zavoláš takhle, ale i kdekoliv jinde můžeš zavolat, pak bys specifikoval, se kterou postavou pracuješ. Např. me.moveIntoForTravel(sz_nadvori) by přesunulo hráče na nádvoří, spici_drak.moveIntoForTravel(chodba) zase draka na chodbu.

nyní ale potřebuji, aby mrtvola strážce v místnosti zůstala a já k němu konečně mohl přiřadit svazek klíčů a křesadlo, které zatím leží na zemi.

No jo, tak pokud postavu nechceš přemisťovat, tak ji tam nech. Nebo ji odsuň pryč a na její místo dej objekt reprezentující mrtvolu. Jestli chceš zviditelnit klíče, tak jako Hidden a zavolat discover().
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: Kroužící orel 7. Listopad 2017 - 11:43
1. VerbRule
Moc díky za detailní vysvětlení, definici nových VerbRule a vhodných verbPhrase budu určitě velmi často používat u dalších her – pokud bude textovku testovat kdokoliv jiný, než já, vždy poprosím o seznam synonym, hledat to správné slovo je šíleně otravné.

2. Strážce
Výborně, vyzkoušel jsem Tvůj příklad metody  moveIntoForTravel u zabití strážce, funguje parádně tak jako v příkladu se zombiemi.

Nyní se snažím o jeho zabití, změnu na mrtvolu a možnost odebrání předmětů. Při studiu Learning T3 je postava Boba definována jako OutOfReach a poté ještě jednou s využitím HermitActorState, zkusil jsem využít tuto definici, viz soubor Exoter_OutOfReach.t v příloze, zde však dostávám při pokusu o zabití strážce hlášku Nepřipadá Ti vhodné dotýkat se mrtvoly!

Ve druhém případě, kdy by strážce zmizel a vytvořil bych objekt nový, by dle Learning T3 měla fungovat třída PresentLater nebo Hidden s pozdějším využitím discover. Eve popisuje rozdíl ve svém manuálu na stranách 25 a 26. Přiznám se, že zatím netuším, která třída bude v dané situaci vhodnější, o PresentLater se dále nezmiňuje, zkusím prozkoumat SampleGames a vyzkouším obě. Zde pracuji se svým klasickým zdrujákem Exoter.t .

Teď mě ještě napadá, že bych tu samou metodu moveIntoForTravel mohl využít v místnosti druha_mistnost_vrchol_vez, odkud hráč spadne do sena, potřeboval-li bych postavu kamkoliv přemístit, zde se ale samozřejmě nabízí TravelMessage.
Tohle člověku docvakává až postupně, dostupných metod je mnoho a alespoň u klasických akcí, které se vyskytují v Exoterovi a ve spoustě dalších českých textovek mi alespoň zpočátku moc pomůže navedení na správnou metodu, než získám více zkušeností.

3. Verbrule u strážce

Zde je seznam příkazů, které jsem zkoušel:

>zabij strážce
Zaútočit na strážce holýma rukama není dobrý nápad.

Zde je malá potíž:
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
>zabij strážce sekerou
Strážcem nemůžeš zaútočit.
>udeř strážce sekerou
Strážcem nemůžeš zaútočit.
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

V pořádku:
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
>zaútoč na strážce
Zaútočit na strážce holýma rukama není dobrý nápad.
>zaútoč sekerou
Příběh tomuto příkazu nerozumí.
// je třeba přesná definice
>zaútoč na strážce sekerou
Jediným mocným úderem se ti podařilo poslat strážce do věčných lovišť.
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Prozkoumal jsem definice VerbRule(Attack), VerbRule(AttackWith) a VerbRule(AttackWithType2) ve Tvém překladu. Zkoušel jsem definovat nové dle Tvého vzoru, např.

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
VerbRule(zabij)
    ('zabij' | 'zabít') 'na' singleDobj singleIobj
    | ('zabij' | 'zabít') singleIobj 'na' singleDobj
    : AttackWithAction
    verbPhrase = 'zabít/zabíj{íš}/zabil{a} (na koho) (čím)'
    askDobjResponseProd = onSingleNoun
    askIobjResponseProd = singleNoun
;
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

umožňuje příkazy:

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
>zabij na strážce
Nevidíš nic neobvyklého ve strážci.
>zabij na strážce sekerou
Jediným mocným úderem se ti podařilo poslat strážce do věčných lovišť.
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

To už je o něco lepší, jen po vymazání slova 'na' z definice
('zabij' | 'zabít') 'na' singleDobj singleIobj jsem zase na začátku.

Ještě si s tím zkusím pohrát, tyhle české definice musím bezchybně chápat, takové chyby jsou pro hráče k uzoufání a tomu bych se rád v maximální míře vyhnul. Znovu jsem popsal Tebou podrobně popsanou definici VerbRule(UnStabTo), tady bude ale asi zádrhel v něčem jiném, u „zaútoč“ potřebuji napsat „na“, kdežto u „zabij“ nikoliv.
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: gaspoda 7. Listopad 2017 - 21:09
1. VerbRule
pokud bude textovku testovat kdokoliv jiný, než já, vždy poprosím o seznam synonym, hledat to správné slovo je šíleně otravné.

Při testování je nejlepší od testerů vyžádat kompletní přepis celé hry a projít si celé jejich snažení. Sám narazíš na mnoho drobností k doladění, nejen chybějící synonyma příkazů, ale i chybějící slovník objektů, chybějící objekty zmíněné v nějakém popisu, nefungující příkazy a kde co. Stačí na začátku hraní zadat příkaz >zapni zápis a celý průbeh se pak ukládá do souboru. Tester může hned během hry napsat i různé poznámky pro autora, stačí do příkazového řákdku zadat hvězdičku a za ní cokoliv, ve hře se to bere jako poznámka.

2. Strážce

Mohl by s prosím doplnit průchod hrou? Naposledy mám níže uvedené, ale asi to trochu nakynulo a nějak se ztrácím, jak se dostat ke strážci a mít sekeru. No jo, jsem línej...

Kód: [Vybrat]
>zapni zápis
>testTranscript.txt
>koukni se do mrtvoly
>vezmi šperhák
>prozkoumej šperhák a mříž
>odemkni mříž
>n
>v
>vezmi pochodeň
>v
>vezmi svazek a křesadlo
>v
>prozkoumej dveře
>otevři dveře
>odemkni dveře svazkem
>v
>zapal pochodeň křesadlem
>i
>v
>j
>n
>v
>n
>s
>z
>koukni se do truhly
>prozkoumej provaz
>vezmi provaz
>d
>j
>z
>prozkoumej studnu
>přivaž provaz
>studna
>podívej se do studny
>p studnu
>p provaz
>d
>n
>polož pochodeň
>d
>n
>vezmi provaz
>d
>konec
>a
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: Kroužící orel 8. Listopad 2017 - 10:42
Nádhera, takové testování ušetří čas hráči i mě, máš pravdu, že nepůjde zdaleka jen o synonyma, tady mě TADS zase jako obvykle příjemně překvapil. Vyzkoušel jsem i znak *, komentáře zaznamenány, vše funguje náramně.

Připravil jsem transkript obou situací, které jsem popisoval, nejprve pomocí definice OutOfReach a ve druhém případě s využitím třídy Hidden, kde si nejsem jist, zda bude lépe právě ona nebo PresentLater – vše zasílám včetně zdrojáků.

Ještě jednou si projedu příslušné kapitoly v manuálu a následně v Library, tohle mi zatím nepřipadá jednoznačné.
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: gaspoda 14. Listopad 2017 - 21:12
2. Strážce
Nyní se snažím o jeho zabití, změnu na mrtvolu a možnost odebrání předmětů. Při studiu Learning T3 je postava Boba definována jako OutOfReach a poté ještě jednou s využitím HermitActorState, zkusil jsem využít tuto definici, viz soubor Exoter_OutOfReach.t v příloze, zde však dostávám při pokusu o zabití strážce hlášku Nepřipadá Ti vhodné dotýkat se mrtvoly!

Jo, koukám, že je v manuálu chyba. Třída OutOfReach se primárně používá např. pro modelování police, která je vysoko na stěně a hráč na předměty na ní umísté nedosáhne. A ano, dá se použít i pro zamezení, aby hráč manipuloval s mrtolou. Chyba spočívá v tom, že OutOfReach rozlišuje, zda je mimo hráčův dosah jen obsah daného objektu (co je v něm/na něm, jako kniha na polici) nebo i samotný objekt. Metodou canObjReachContentsObj se určí, které objekty z obsahu budou nepřístupné. My ale potřebujeme omezit dosah především na samotnou mrtvolu, takže musíme opravit název metody na canObjReachSelf.

Ve druhém případě, kdy by strážce zmizel a vytvořil bych objekt nový, by dle Learning T3 měla fungovat třída PresentLater nebo Hidden s pozdějším využitím discover. Eve popisuje rozdíl ve svém manuálu na stranách 25 a 26. Přiznám se, že zatím netuším, která třída bude v dané situaci vhodnější, o PresentLater se dále nezmiňuje, zkusím prozkoumat SampleGames a vyzkouším obě. Zde pracuji se svým klasickým zdrujákem Exoter.t .

Lepší je modelovat stav postavy pomocí ActorState. Je to stále ta samá postava, jen se změní její stav a tím pádem popis. ActorState resp. potomek HermitActorState se vloží pomocí plus do postavy. Tam máš ve zdojáku chybu - postava má jedno plus, tak abys HermitActorState vložil do postavy, tak musíš dát dvě plus.

ActorState automaticky přidává svůj popis za základní popis postavy, proto je nevhodné mít to "chystá se zabít tě" v popisu postavy. To platí, jen než bude strážce mrtvý, takže místo popisu postavy vložíme ještě jeden HermitActorState, který představuje stav postavy na začátku hry. Proto je označen isInitState = true. Jakmile udělá hráč ten jedný mocný úder, tak pomocí setCurState(strazceDeadState); stav změníme a toho změněného stavu se chytne ten výše zmíněný canObjReachSelf a zamezí s mrtvolou manipulovat. Předměty pak třeba pohodíme do místnosti.

Teď mě ještě napadá, že bych tu samou metodu moveIntoForTravel mohl využít v místnosti druha_mistnost_vrchol_vez, odkud hráč spadne do sena, potřeboval-li bych postavu kamkoliv přemístit, zde se ale samozřejmě nabízí TravelMessage.

Často se stane, že je více možností. Současné řešení mi přijde ok.

3. Verbrule u strážce

>zabij strážce sekerou
Strážcem nemůžeš zaútočit.
>udeř strážce sekerou
Strážcem nemůžeš zaútočit.

>zaútoč sekerou
Příběh tomuto příkazu nerozumí.
// je třeba přesná definice
>zaútoč na strážce sekerou
Jediným mocným úderem se ti podařilo poslat strážce do věčných lovišť.
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Myslím, že jsem oba problémy (prohazování iobj/dobj i zaútoč sekerou) pořešil v nové verzi českého překladu, bylo tam pár chyb a nedodělků. Níže pak úpravy ve zdrojáku hry:

Kód: [Vybrat]
--- Exoter.orig 2017-11-08 19:52:07.000000000 +0100
+++ Exoter.t    2017-11-14 20:31:21.000000000 +0100
@@ -260,7 +260,6 @@

 + strazce: OutOfReach, UntakeableActor, RestrictedContainer 'stráž/strážce/strážný/strážného' 'strážce' *1
 //+ strazce: Person 'stráž/strážce/strážný/strážného' 'strážce' *1
-      "Chystá se zabít tě. "

       gcName = 'strážce, strážci, strážce, strážci, strážcem'
       gcVocab = 'strážci/strážci/strážce'
@@ -288,16 +287,25 @@
                         strazce.moveIntoForTravel(chodba_se_strazcem);

              "Jediným mocným úderem se ti podařilo poslat strážce do věčných lovišť. ";
+             setCurState(strazceDeadState);
+            kresadlo.moveInto(location);
+            svazek_klicu.moveInto(location);
 //                      moveIntoForTravel(nil); - v takovém případě zmizí z místnosti
         }
     }

-canObjReachContentsObj(obj) { return curState != strazceDeadState; }
+canObjReachSelf(obj) { return curState != strazceDeadState; }
 cannotReachFromOutsideMsg(dest) { return 'Nepřipadá Ti vhodné dotýkat se mrtvoly!'; }

 ;

+++ strazceGuardState: HermitActorState
+    noResponse = "Chystá se zabít tě. "
+    stateDesc = "Chystá se zabít tě. "
+    isInitState = true
+;
+
-+ strazceDeadState: HermitActorState
+++ strazceDeadState: HermitActorState
 noResponse = "Je mrtvý a nic už neslyší. "
 specialDesc = "Strážce leží mrtvý na podlaze. "
 stateDesc = "Strážce je mrtvý. "
@@ -310,7 +318,7 @@
 // po zabití vidíš mrtvolu strážce: "V obličeji má hlubokou krvavou ránu, kdo mu to asi udělal." - po prvním prozkoumání najd
 //  strazce.makePosture(sitting);   --- ze Základny, může si sednout, př. actorCommander.t

-++ PreferredIobj, Thing 'křesadlo/křesadla/křesadlu/křesadlem' 'křesadlo' *4
+++ kresadlo: PreferredIobj, Thing 'křesadlo/křesadla/křesadlu/křesadlem' 'křesadlo' *4
     "Snad by se s ním dal rozdělat oheň. "
     iobjFor(BurnWith)
     {
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: Kroužící orel 16. Listopad 2017 - 10:51
A sakra, neznalce malá chyba v manuálu dosti zmate. Vidím ale, že třída OutOfReach zde asi ideálním řešením nebude,  ActorState určitě vypadá lépe, se znaménkem je mi už vše jasné, je to podobná situace jako u kontejnerů. Chápu už také konečně použití  HermitActorState, které mi z manuálu jasné rozhodně nebylo. Teda tyhle na první pohled jednoduché záležitosti jsou alespoň pro mě dost komplikované, bez tebe bych akci se strážcem neměl šanci vyřešit.

Moc díky za další verzi překladu, vše jsem vyzkoušel a parádně funguje. Je super, že svojí tvorbou a hlavně otázkami alespoň trochu pomáhám ke zlepšování českého překladu, jak bys postupoval u chyby v manuálu s OutOfReach? Vím, že TADS se už pár let nevyvíjí a to samé bude i u manuálů, poslední verze např. Learning je z roku 2012,má ještě dnes smysl tyto chyby hlásit Ericovi na jeho email eric.eve@hmc.ox.ac.uk? Prozkoumal jsem diskuzní fórum TADSu, vypadá to, že:

https://www.intfiction.org/forum/viewforum.php?f=10

je stále živé a dotazy se zde řeší. Diskutující popisuji i své problémy, nenalezl jsem však, kam posílat zaslané chyby. Rád bych projektu stejně jako Ty pomáhal, TADS za to určitě stojí a pokud nás bude více, věřím, že vývoj bude zdárně pokračovat, už jen např. překlad dnes již nevyvíjeného frobtadsu pod novějšími kompilátory není úplně triviální a to je vzhledem k práci, kterou autoři v minulosti odvedli, obrovská škoda.

Při další tvorbě bych měl ještě dva dotazy, které spolu souvisí:

1. Popis místnosti u strážce potřebuji změnit tak, aby se po jeho zabití již neobjevil text „Vidíš strážce, naštěstí je k Tobě obrácen zády.“. Zatím mám ve zdrojáku toto:

    "Jsi v chodbě. <<if strazce.isIn(chodba_se_strazcem)>>Vidíš strážce, naštěstí je k Tobě obrácen zády. \b<<else>> <<end>>Můžeš jít na východ, na západ. "

Je jasné, že strážce, i když mrtvý stále v místnosti je. Pokusil jsem se o různé změny, např. logické mi přijde:

    "Jsi v chodbě. <<if curState != strazceDeadState>>Vidíš strážce, naštěstí je k Tobě obrácen zády. \b<<else>> <<end>>Můžeš jít na východ, na západ. "

Zde však větu „Vidíš strážce...“ vidím stále, zkusil jsem místo curState také ActorState, ale bez výsledku. Grepnul jsem si základnu, if zde běžně používáš např. u Borise nebo kapitána. Ani v manuálu jsem více k těmto if příkazům v souvislosti se změnou desc nenalezl, můžeš mě prosím blíže navést jak je správně používat? Eve uvádí v Learning T3 na straně 51 ohledně if – else podívat se do String Literals v System manual, to jsem udělal, příkladů je zde mnoho, např. if door is open, then…, jen u třídy Actor mi konstrukce nefungují a někde dělám chybu.

Existuje nějaká tabulka konstrukce if – else podobné např. té s operátory na str. 29 nebo stringů str. 39 z Learning T3? Změnu popisu místnosti po nějaké manipulaci s předmětem/postavou budu potřebovat u dalších her také a rád bych znal tu konstrukci, která se v praxi využívá.

2. Pokud strážce žije a hráč se chce přesunout na V, stejně jako v Exoteru bude zabit – strážce je ale otočen, takže na Z je vše v pořádku. Zkusil jsem využít konstrukci, kterou využívám u pádu z výšku do kupky sena upravenou na místnost se strážcem takto:

    east : TravelMessage
          {  ->konec_chodby
              "Opatrně procházíš kolem mrtvého strážce dál na východ . "
                canTravelerPass(traveler) {return !strazce.isIn(chodba_se_strazcem); }
              explainTravelBarrier(traveler)
         { "Strážce se na tebe se strašlivým řevem vrhl a celkem snadno ukončil tvůj život. "; finishGameMsg(ftDeath, [finishOptionUndo] );}
}

Nyní je jedno, zda strážce žije nebo ne a při průchodu na V vždy zemřu. Hra pomocí výrazu strazce.isIn pravděpodobně neřeší, je-li živ nebo ne, stále se nachází v místnosti. Podobně jako u prvního dotazu ani konstrukce:

                canTravelerPass(traveler) {return curState = strazceDeadState; }

nepomohla.

Teď mě ještě napadá, že u další hry budu potřebovat simulaci plížení, např. v jedné místosti si rytíř bude muset sundat brnění, aby se dokázal tiše proplížit okolo nějakého toho potvoráka, určitě podobnou konstrukci využiji i tam.
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: gaspoda 16. Listopad 2017 - 11:21
A sakra, neznalce malá chyba v manuálu dosti zmate. Vidím ale, že třída OutOfReach zde asi ideálním řešením nebude,  ActorState určitě vypadá lépe, se znaménkem je mi už vše jasné, je to podobná situace jako u kontejnerů.

Aby nedošlo k nedorozumění, OutOfReach (se správným názvem metody) je správným řešením. Použij oboje - HermitActorState se týká konverzace s postavou, když je postava v tomto stavu, tak s ní nejde komunikovat, tedy zeptat se, požádat apod. OutOfReach zajistí druhou část problematiky, aby s postavou nešlo manipulovat, tj. odpoví na všechny příkazy, jako vem, tlač, prohledej atd.

Jak bys postupoval u chyby v manuálu s OutOfReach? Vím, že TADS se už pár let nevyvíjí a to samé bude i u manuálů, poslední verze např. Learning je z roku 2012,má ještě dnes smysl tyto chyby hlásit Ericovi na jeho email?

Jo, já jsem to Ericovi minulý týden řekl a až/jestli bude nějaká nová verze, tak to v manuálu opraví. Jinak TADS má i databázi bugů, ale tam dávam spíše technické věci pro Mika Robertse. Ericovi jsem psal přímo. Ano, Mike je teď pár let poněkud zaneprázdněný a na TADS mu evidentně nezbývá čas. Po všech těch letech docela intenzivního vývoje se mu ani nedivím. Přímo jsem s ním nemluvil, tak nevím, jak vidí budoucnost, ale já osobně věřím, že se někdy zase k TADSu vrátí a chyby, které jsou hlášené opraví.

Rád bych projektu stejně jako Ty pomáhal, TADS za to určitě stojí a pokud nás bude více, věřím, že vývoj bude zdárně pokračovat, už jen např. překlad dnes již nevyvíjeného frobtadsu pod novějšími kompilátory není úplně triviální a to je vzhledem k práci, kterou autoři v minulosti odvedli, obrovská škoda.

To je zajímavé, pokud k tomu máš nějaké detaily, tak mi je klidně pošli mailem. Já už nějakou dobu neaktualizoval a nekompiloval Frobtads, ale v minulosti jsem žádné problémy nezaznamenal. Možná to souvisí s konkrétní distribucí, kdo ví. O frob se stará Nikos Chantziaras a je normálně pravidelně aktivní na fóru, určitě se dá mu problém nahlásit.

    "Jsi v chodbě. <<if curState != strazceDeadState>>Vidíš strážce, naštěstí je k Tobě obrácen zády. \b<<else>> <<end>>Můžeš jít na východ, na západ. "

Skoro dobře. Jen si musíš dát pozor, na čem vyhodnocuješ curState. Když programuješ nějaký objekt (zde chodbu) a napíšeš jméno nějaké vlastnosti, tak se ta vlastnost hledá v tom objekt, který programuješ. Ale chodba žádné stavy nemá, takže na ní curState neexistuje. Ale to není problém, prostě se odkaž na curState dané postavy, tj. do podmínky napiš <<if strazce.curState != strazceDeadState>>. U druhého dotazu to samé.

Teď mě ještě napadá, že u další hry budu potřebovat simulaci plížení, např. v jedné místosti si rytíř bude muset sundat brnění, aby se dokázal tiše proplížit okolo nějakého toho potvoráka, určitě podobnou konstrukci využiji i tam.

Pak se bude hodit podmínka ve stylu if(brneni.isWornBy(me)), která testuje, jestli nějaký Wearable předmět máš oblečený (nezávisle na tom, jestli ho máš v inventáři).
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: Kroužící orel 19. Listopad 2017 - 18:32
1. OutOfReach
Aha, takže ideální bude zkombinovat obě. Vyzkoušel jsem a hra správně na hráčovi příkazy tlač, prohledej, vezmi… odpovídá řetězcem „Nepřipadá Ti vhodné dotýkat se mrtvoly!“, výborně, tuhle konstrukci jsem si uložil do poznámek, protože jí rozhodně využiji také u předělávky Bad Night.

2. Hlášení chyb a aktuální stav Frobtads
Skvěle, myslel jsem si, že jakž takž ještě funguje fórum, moc jsi mě potěšil, že Eric i Nikos se stále angažují. Je pravda, že bych nalezené problémy související s programováním nepopsal asi ouplně přesně, lépe to bude od Tebe. Nová verze manuálu by moc pomohla, alespoň ostatní zájemci uvidí, že TADS stále žije a to je hlavní. Práci Mikeho si moc vážím, ano, stačí si jen projít Library a člověk žasne, mě se líbí, že jak to cítím, textovky nestárnou a hra v tomto systému bude stejně bezva hratelná i za deset let. Třeba když uvidí, že uživatelé a dotazy stále jsou, k TADSu se vrátí, necháme se překvapit. Pomoci ale mohu s instalací Frobtads, mám v učebně i virtuálu několik distribucí:

Frobtads funguje v současné době bez problémů v:
Ubuntu 16.04 – binárka je OK a bez problémů funkční
Freebsd 11.1- binárka i kompilace pomocí clang funguje, díval jsem se na jejich fórum a potíž viditelně vyřešili, vše tedy OK

Menší potíž je s Debianem:
Na jejich bugzille se problém s novějším kompilátorem už řešil
https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=871215

Pokud se dívám na debianí balíčky:
https://packages.debian.org/search?keywords=frobtads&searchon=names&suite=all&section=all
Zjišťuji, že Debian Jessie je vše OK, balíčky existují ve verzi 1.2.3-1 včetně potřebných závislostí
Debian Stretch – tady balíčky vůbec k dispozici nejsou, řeším to tak, že instaluji z unstable verze Sid – zde je upravená 1.2.3-1+b1, pomocí dpkg -i instaluji balíčky frobtads, tads3-dev a tads3-common, následně je vše plně funkční

Raspbian je to samé, v Jessie je možné balíčky zkompilovat pomocí deb-src, pro Stretch také neexistují a je nutna verze ze Sidu

Největší potíž má Arch Linux vzhledem k aktuálním balíčkům, v současné době s kompilátorem GCC 7.2 - řešení zde však je:
https://aur.archlinux.org/packages/frobtads/

Failed to build with fresh gcc. Fix:
diff --git a/PKGBUILD b/PKGBUILD
index 5c78bee..b1d0ec1 100644
--- a/PKGBUILD
+++ b/PKGBUILD
@@ -17,7 +17,7 @@ md5sums=('c6ed8cd6dac04b3ee6f4422cea688979')
build() {
cd "${srcdir}/${pkgname}-${pkgver}"

- ./configure --prefix=/usr
+ ./configure --prefix=/usr CXXFLAGS="-std=c++03"
make
}

Pokud dobře chápu, je nutno zajistit kompatibilitu se standardem c++2003, poté kompilace proběhne bez problému.

A nakonec můj oblíbený Slackware:
Ve verzi 14. 2 se nachází GCC 5.3, kompilace OK
V current se momentálně nachází GCC 7.2, zde kompilace vypisuje jinou chybu, než Arch:
bash-4.4# make
make  all-am
make[1]: Entering directory '/root/frobtads-1.2.3'
  CXX      tads3/tcprs.o
In file included from tads3/tcprs.cpp:39:0:
tads3/vmbignum.h: In static member function ‘static vm_obj_id_t CVmObjBigNum::create(int, const bignum_t<prec>*)’:
tads3/vmbignum.h:585:45: error: exception cleanup for this placement new selects non-placement operator delete [-fpermissive]
         new (vmg_ id) CVmObjBigNum(vmg_ prec);
                                             ^
<built-in>: note: ‘void operator delete(void*, unsigned int)’ is a usual (non-placement) deallocation function in C++14 (or with -fsized-deallocation)
tads3/vmbignum.h: In static member function ‘static vm_obj_id_t CVmObjBigNum::create(int, const bignum_t<prec>&)’:
tads3/vmbignum.h:596:45: error: exception cleanup for this placement new selects non-placement operator delete [-fpermissive]
         new (vmg_ id) CVmObjBigNum(vmg_ prec);
                                             ^
<built-in>: note: ‘void operator delete(void*, unsigned int)’ is a usual (non-placement) deallocation function in C++14 (or with -fsized-deallocation)
tads3/vmbignum.h: In member function ‘virtual void CVmMetaclassBigNum::create_for_image_load(vm_obj_id_t)’:
tads3/vmbignum.h:1640:36: error: exception cleanup for this placement new selects non-placement operator delete [-fpermissive]
         new (vmg_ id) CVmObjBigNum();
                                    ^
<built-in>: note: ‘void operator delete(void*, unsigned int)’ is a usual (non-placement) deallocation function in C++14 (or with -fsized-deallocation)
tads3/vmbignum.h: In member function ‘virtual void CVmMetaclassBigNum::create_for_restore(vm_obj_id_t)’:
tads3/vmbignum.h:1647:36: error: exception cleanup for this placement new selects non-placement operator delete [-fpermissive]
         new (vmg_ id) CVmObjBigNum();
                                    ^
<built-in>: note: ‘void operator delete(void*, unsigned int)’ is a usual (non-placement) deallocation function in C++14 (or with -fsized-deallocation)
make[1]: *** [Makefile:6599: tads3/tcprs.o] Error 1
make[1]: Leaving directory '/root/frobtads-1.2.3'
make: *** [Makefile:3011: all] Error 2
bash-4.4#
Na to se ještě podívám, zde je ale výhoda, že balíček kompilovaný pro starší verzi většinou funguje i v novějším Slacku.

Takže suma sumárum gcc verze 5 a snad i 6 je se současným frobtads 1.2.3 OK, od verze 7 jsou potíže a také u clang byla nutna úprava. Bude paráda, pokud Nikosovi pošleš tyto postřehy, pokud upraví zdrojáky pro aktuální gcc a ideálně i clang, bude to paráda. Plus pokud by se podíval na tu bolístku s utf-8 v konzoli, což zatím řeším pomocí Tebou doporučované volby -i plain -k utf8.

Vím, že je s českými znaky docela potíž, upřímně řečeno jsem plnou češtinu včetně problematických znaků ť, ú nebo ů zprovoznil pouze v příkazové řádce Slackware a Archu. U jinak skvělého a bezproblémového Debianu se zatím vůbec nechytám, ť přes nejrůznější nastavení zatím nerozchodím, ještě si s tím zkusím pohrát, původně funkční návod pro Wheezy mi v aktuální verzi nejede. V Ubuntu a OpenSUSE je zatím nutno ručně po spuštění pouštět příkaz sudo loadkeys cz-us-qwerty nebo sudo loadkeys cz, nepodařilo se mi toto zautomatizovat. BSD systémy na češtinu zvysoka kašlou, jedinou podporu má FreeBSD, ale jeho terminál zatím neumí české uft-8 znaky na konzoli a Open a NetBSD nemá ani české lokalizační balíčky, co se dá dělat.
Dnes už to samozřejmě není nutné, na druhou stranu byl dříve milovníkem GUI, ale nyní se mi vzhledem k práci s armádním notebookem nebo Raspberry hodí co nejméně náročný systém. A zjistil jsem, že většinu práce zvládnu i v příkazové řádce, nyní testuji Slackware v kombinaci s framebufferem, zde rozchodím „grafický“ links nebo netsurf, s nimi vůbec není problém prohlížet moderní web, přehrávat videa včetně youtube lze pomocí mplayer nebo cvlc, procesor Worgrinder dokáže nahradit LO Writer, ještě doladit tabulky a budu tak moci parádně pracovat – v tom by mohl pomoci Emacs, na který se vrhnu vzápětí. No a časem, pokud zvládnu Cčko, bych rád připravil nějaké ncurses aplikace, které by se hodily stejně jako v době DOSu.

No, trochu jsem se rozepsal, nyní je ale snad jasnější, jaký důraz dávám na české znaky a frobtads v konzoli, ostatně stejnou práci s překladem si dáváš i Ty, myslím, že si rozumíme. Na druhou stranu chápu, že nějaký terminál dnes už nefrčí, takže by se autoři mohli více věnovat HTML nebo třeba apk souborům pro Android, sám sice chytrý telefon nepoužívám a v dohledné době nebudu, budoucnost je ovšem právě tam - naštěstí přes prohlížeč by hra měla být hratelná, určitě jí v konečné podobně umístím na IFDB, ve svém manuálu píšeš, že existují veřejné servery, takže nebudu muset konfigurovat vlastní.

3.  curState, mé další postřehy
Paráda, teď už chápu, že konstrukci musím využít u objektu s vhodnou vlastností, v mém případě u strážce. První příklad funguje na jedničku, zkusil jsem stejnou konstrukci využít i v druhém, ale ouha, zde jsem narazil a nefunguje jak má. Trochu jsem laboroval, nakonec jsem z příkladu zde:

https://www.intfiction.org/forum/viewtopic.php?f=10&t=21744&view=previous

zjistil, že musím využít dvě rovnítka, správný příkaz na řádku 260 je tedy:
canTravelerPass(traveler) {return strazce.curState == strazceDeadState; }
Super, tyhle konstrukce si zapamatuji a mohu vesele využívat dále.

Zajímavé je, že u živého strážce: věci, které má viditelně na sobě, mohu prozkoumat, ale příkaz:
>vezmi kresadlo
Nepřipadá Ti vhodné dotýkat se mrtvoly!

Zkusil jsem dočasně zakomentovat řádek :
cannotReachFromOutsideMsg(dest) { return 'Nepřipadá Ti vhodné dotýkat se mrtvoly!'; }

ale ejhle, nyní dostávám příkaz:

>vezmi strazce
Strážce je příliš daleko.

No jo, v prvním případě je to jasné, věci jsou příliš daleko a pokud se jich snažím dotknout, hra vypisuje hlášení za return. Teď mě napadá, chtělo by tam vložit nějaký if – else s kontrolou, je-li strážce naživu.

Konstrukci jsem tedy připravil, se syntaxí jsem se inspiroval Tvým manuálem v sekci Akce bez objektu - modify JumpAction. Vše se zdá OK a překlad v pořádku proběhne, při pokusu o příkaz vezmi kresadlo Workbench vyhodí chybu Tads runtime – string value required a otevře se mi soubor cs_cz.t, kde žlutá šipka ukazuje na řádek match = rexSearch(patSpecial, str, idx);.

S podobnou chybou už jsem se v minulosti setkal, jen si nepamatuji, kde přesně, tehdy jsem ještě nic o systému nevěděl. Mohu poprosit o vysvětlení, nejen, zda je chyba v mé if – else konstrukci, ale také je-li to chyba sémantická nebo syntaktická, pokud se vyjadřuji správně, o těchto jsem v minulosti při svých pokusech s Pascalem slýchal. Transkript a zdroják zasílám v příloze.

Ještě jsem si všiml malé chybky v překladu nebo u mě v deklaraci postavy hráče, pokud tento umírá, objeví se chybný střední rod:
Strážce se na tebe se strašlivým řevem vrhl a celkem snadno ukončil tvůj život.
*** ZEMŘELO JSI ***
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: gaspoda 21. Listopad 2017 - 11:13
zjistil, že musím využít dvě rovnítka, správný příkaz na řádku 260 je tedy:
canTravelerPass(traveler) {return strazce.curState == strazceDeadState; }

No, to samozřejmě, to jsem si ani nevšiml. Ano, dvě rovnítka znamenají porovnání hodnot a výsledkem je logická hodnota true, pokud jsou hodnoty stené. Jedno rovnítko naproti tomu znamená zápis hodnoty do proměnné. To je oblíbená chyba.

Zajímavé je, že u živého strážce: věci, které má viditelně na sobě, mohu prozkoumat, ale příkaz:
>vezmi kresadlo
Nepřipadá Ti vhodné dotýkat se mrtvoly!

Ah, tobě jde o to, že prozkoumat křesadlo, které má u sebe strážce, stále ještě můžeš, i když jsi tomu zkoušel zabránit. To je normální. Příkaz prozkoumej (na rozdíl od prohledej, vem a dalších) totiž v interaktivní fikci znamená defakto jen zaměření pozornosti hráče. Tedy hráč se zdálky letmo podívá a řekne, co vidí, aniž by se tím myslelo, že by ke strážci přišel a s křesadlem nějak manipuloval. Prozkoumání proto na rozdíl od jiných manipulací není třídou OutOfReach nijak ovlivněno a je stále povolené. OutOfReach se pověsí na metodu checkTouchViaPath a tak ovlivňuje ty akce, které vyžadují dotek. Prozkoumání však vyžaduje jen viditelnost.

Co s tím? To záleží, čeho chceš dosáhnout. Tak např. pokud bys nechtěl, aby hráč o svazku klíčů a křesadle předem věděl, dokud strážce nezabije, tak by je strážce do té doby vůbec nemusel mít v inventáři. Pak bys klíče nedal pomocí plus do strázce, ani do místnosti, nechal je jen tak mimo svět a v okamžik, kdy je strážce zabit, tak kresadlo.moveInto(strazce) resp. využít Hidden/PresentLater.

A nebo pokud chceš, aby je měl, aby o tom hráč věděl a dávalo mu to motivaci strážce zabít, což dost možná chceš, tak pak bych spíš třeba změnil popisek. Dokud má křesadlo strážce, může být popisek ve stylu, že by se ti křesadlo mohlo hodit, tj. nějak motivačně formulovaný. Jakmile strážce zabiješ, může se změnit na současný, který říká, jak ho můžeš použít. Popisek můžeš snadno měnit tak, že si uděláš v něm <<if něco>>text1<<else>>text2<<end>>.

To už znáš, někde jsem viděl, že jsi to použil v popisu chodby. Btw. když není žádná <<else>> část, tak ji nemusíš psát, stačí jen <<end>>. A když se varianta táhne až do konce textu, tak ani nemusíš <<end>> psát. Ještě k tomu popisu chodby.

Zkusil jsem dočasně zakomentovat řádek :
cannotReachFromOutsideMsg(dest) { return 'Nepřipadá Ti vhodné dotýkat se mrtvoly!'; }

ale ejhle, nyní dostávám příkaz:

>vezmi strazce
Strážce je příliš daleko.

No jo, v prvním případě je to jasné, věci jsou příliš daleko a pokud se jich snažím dotknout, hra vypisuje hlášení za return. Teď mě napadá, chtělo by tam vložit nějaký if – else s kontrolou, je-li strážce naživu.

Koncept je takový, že je oddělen test a zpráva. O tom, zda něco půjde nebo ne rozhoduje metoda canNěco(). V té metodě by měl být jen test, tedy nějaká podmínka a metoda by měla vrátit logickou hodnotu. Pokud je test neúspěšný, tak bude vypsána zpráva. A právě její vygenerování (ale už ne testování) má obstarat metoda cannotReachNěcoMsg. Pokud žádnou zprávu neposkytneš, tedy nenaprogramuješ metodu cannotReachFromOutsideMsg, tak zdědíš tuto metodu z předka a ta vrací zprávu tooDistantMsg, to je ta o tom, že je příliš daleko. Příliš daleko je standardní odpověď OutOfReach třídy. Samozřejmě ty jsi tuto třídu využil pro jinou situaci, tak chceš zprávu jinou.

Vše se zdá OK a překlad v pořádku proběhne, při pokusu o příkaz vezmi kresadlo Workbench vyhodí chybu Tads runtime – string value required a otevře se mi soubor cs_cz.t, kde žlutá šipka ukazuje na řádek match = rexSearch(patSpecial, str, idx);.

To je jen důsledek toho, že jsi sice naprogramoval metodu cannotReachFromOutsideMsg, ale v určité situaci z ní nevracíš žádný řetězec. O kus dál v kódu, kdy se má řetězec použít, tak to spadne. Jak říkám, v této metodě bys neměl nic testovat, ale jen vrátit zprávu. Na testování je ta druhá metoda. (Tedy můžeš samozřejmě zde něco testovat a např. vybírat z více různých zpráv podle situace, ale nesmíš připustit, abys nevrátil žádnou zprávu.)

je-li to chyba sémantická nebo syntaktická, pokud se vyjadřuji správně, o těchto jsem v minulosti při svých pokusech s Pascalem slýchal.

Sémantická. Syntaktická chyba je taková, kdy kompilátor program nepřeloží, protože nerozumí zápisu.

Ještě jsem si všiml malé chybky v překladu nebo u mě v deklaraci postavy hráče, pokud tento umírá, objeví se chybný střední rod:
Strážce se na tebe se strašlivým řevem vrhl a celkem snadno ukončil tvůj život.
*** ZEMŘELO JSI ***

No protože jsi neřekl, jakého rodu postava je. Přidání gender = 1 k objektu me situaci spraví. No uznávám, že mužský rod by byl asi lepším defaultem, asi to časem změním.
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: Kroužící orel 22. Listopad 2017 - 22:09
Ano, s rovnítky taky dosti bojuju, v případě se strážcem potřebuji porovnat hodnoty, to bude stejné asi u každého programovacího jazyka. S rodem u hráče je to jasné, já tak nějak automaticky předpokládal, že hra bere hráče v mužském rodu a zapomněl jsem uvést gender, ve většině českých textovek je hlavní hrdina chlap a vlastně i ten Luxík je ten Luxík plus podobně u jiných potvůrek, proto se přimlouvám za výchozí mužský rod, holt dámy snad prominou a děti zapomenou…

Hmm, vidím, že příkaz prozkoumej stále beru tak jak jej interpretují klasické české textovky, tedy něco jako hlavní rozkoukávající se prostředek, který je často potřeba využít i několikrát, viz např. Kainovy hry ze Středozemě. Příkazu prozkoumání tedy stačí jen prostá viditelnost, jasné. Ano, teď si vzpomínám, že o třídě Hidden/PresentLater píše Eric v příkladě s prstenem pod kobercem, zde podobně jako Ty také nabízí dva způsoby jak situaci řešit.

Mé tři předchozí dotazy:

>vezmi kresadlo
Nepřipadá Ti vhodné dotýkat se mrtvoly!

>vezmi strazce
Strážce je příliš daleko.

Workbench vyhodí chybu Tads runtime – string value required

a Tvé podrobné odpovědi na ně mi tedy daly pořádně zabrat, to, co popisuješ, už je alespoň zatím pro mě velmi obtížné. Každopádně spolu docela souvisí a vše jsem pobral až tehdy, když jsem se je, tedy alespoň druhý a třetí, snažil uchopit v kontextu hry. Práci s
<<ifněco>>text1<<else>>text2<<end>>
už chápu, ano, využil jsem jí také u popisu místnosti a vymazání else v případě, že za ním nic neplánuji, krásně funguje. Také mi dost pomohl přeložený zdroják Heidi, testoval jsem metodu dobjFor(Take) popsanou u ptačíḧo hnízda u mnou využívaných předmětů křesadla a svazku klíčů. Ovšem v mém případě bez výsledku, díky Tvému popisu ale už chápu, proč.

Perfektně popisuješ metodu CanNĚCO, nyní je jasné, že musím definovat cannotReachFromOutsideMsg, abych se vyhnul zpětné zprávě tooDistantMsg. Zase jsem se parádně inspiroval u Heidi, která popisuje cannotReachFromOutsideMsg u příkladu větve na stromě. Jasně, pokud nevracím žádný řetězec, který hra očekává, dojde k chybě, proto ten string = chybějící návratový textový řetězec.
 
Ještě jsem se koukal na fórum TADSu, kde se právě tato dle mého názoru dost obtížná část, přirovnal bych jí k potížím s prací s provazem, řeší:

https://www.intfiction.org/forum/viewtopic.php?f=10&t=17443&start=10

Zde je také vše pěkně vysvětleno s odkazem na Learning TADS 3, strana 185. Ano, tu si pamatuji, právě zde jsem se setkal s popisem smrti Boba a seznámil se s HermitActorState, o čemž jsme si psali v jednom z minulých příspěvků. Autor zde kromě využití třídy OutOfReach u strážce, kterou tam již použitou mám, doporučuje také přidat:

canObjReachContents(obj) { return curState != strazceDeadState; }

nyní tedy využívám:

canObjReachSelf(obj) { return curState != strazceDeadState; }
canObjReachContents(obj) { return curState != strazceDeadState; }
cannotReachFromOutsideMsg(dest) { return 'Nepřipadá Ti vhodné dotýkat se mrtvoly!'; }

a v Library jsem se dozvěděl:
canObjReachContents - Determine if the given object can reach my contents. 'obj' is the object (usually an actor) attempting to reach my contents from outside of me.
By default, we'll return nil, so that nothing within me can be reached from anyone outside. This can be overridden to allow my contents to become reachable from some external locations but not others; for example, a high shelf could allow an actor standing on a chair to reach my contents.

Paráda, přesně to potřebuji a nyní vše funguje jak má, v příloze zasílám aktuální zdroják a transkript – hláška o tom, že mi živý strážce nedovolí vzít nic, co sám nese, je parádní a pro mé potřeby ideální. Sakra, ještě toho musím stále mnoho pobrat, jen díky Tvému vysvětlení se mi všechny ty třídy a metody začínají pomalu slévat dohromady. Vše, co jsem se naučil u strážce, nyní využiji také u psa a draka, poté ještě naprogramovat ukončení hry plus drobné nedodělky a mohu se vrhnout na závěrečné testování.

Po průzkumu fóra jsem nalezl zajímavý odkaz

https://www.intfiction.org/forum/viewtopic.php?f=10&t=24885

kde autor popisuje možnost využití TADSu jako prvního programovacího jazyka, paráda, pro mě přesně to pravé. Vytvořil prý nějaké výukové třídy vhodné i pro děti i dospěláky, moc rád bych na to juknul, odkaz ale zatím nefunguje – už jsem mu psal, co se s tím dá dělat. Také vyvinul plugin pro editory Atom a Sublime, určitě vyzkouším, časem také ten pro Emacs, když se takové věci dělají, TADS stále žije, hurá…

Ještě zítra a pozítří tu mám lidi na koně, poté bude trochu volněji a mohu vesele pokračovat v tvorbě, už se těším.
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: Kroužící orel 28. Listopad 2017 - 09:24
Komunikace na fóru funguje bezvadně, od Jeffa jsem získal zajímavé soubory, plánuje třídy pro výuku TADSu jako prvního progracovacího jazyka, což je velmi zajímavé, přečetl jsem si Python for Kids, tvorba textovek mě však samozřejmě zaujala více.

1. Unit testy
Díval jsem se na jeho soubory, pro zajímavost zasílám i v příloze, je zde sada TADS3 Unit Testů, zajímavé, v minulosti jsem se setkal s pojmem Programování řízené testy – TDD, což pokud dobře chápu bude jedna z metod programování podobně jako např. Scrum. Vím jak postupuješ ty pomocí transkriptu hry, využil jsi při své práci také něco podobného od Jeffa nebo Bizzarriho?

2. QT Creator
Fórum jsem trochu procházel, zaujal mě článek, kde krásně popisuješ své prostředí:
https://www.intfiction.org/forum/viewtopic.php?f=10&t=20899&sid=0bc3a9795ccf2d5ffea8ecfd35941195
a vysvětluješ automatické testy. Obrázek QT Creatoru v akci je velmi zajímavý, zkoušel jsem různé editory a IDE a v případě aplikací v prostředí KDE potěší integrovaná podpora syntaxe TADSu v Kwrite i KATE, což se mi opravdu snadno podařilo převést do QT Creatoru. Svojí další hru již plánuji rozdělit na soubory podobně jako u Základny, proto by se vhodné IDE hodilo. Přímá podpora TADS projektu zde samozřejmě není, mohu poprosit o osvětlení jak jsi postupoval u založení projektu – nestačil např. nový projekt v C++ a ručně přidat zdrojové t soubory? Kontrolu nad výstupy máš v tomto IDE parádní, sakra, kdyby byl nějaký programátor ochoten převzít debugger z Workbenche a naroubovat jej na Frobtads, bylo by takové IDE naprosto perfektní a závislost na WINE ukončena.
Také je zvláštní, že projekt KDE má dvě taková prostředí, Kdevelop a QT Creator, na fóru:
http://www.abclinuxu.cz/clanky/srovnani-kdevelop-a-qt-creator
jsem našel sice starší, ale zajímavý článek obě porovnávající a mnoho rozdílů zde není. Každopádně zvýraznění syntaxe funguje pod každým z nich, Kdevelop se zdá být cca o 50MB zabrané paměti úspornější. Tak jako tak je to oproti javovským IDE paráda, na mém ne zrovna výkonném stroji se jedná dosti zásadní rozdíl.
Používáš QT Creator i nyní a jsi s ním spokojen? Nyní mám na svém stroji Arch Linux a Q4OS, v obou tato prostředí parádně fungují a i když mám pod Archem GTKčkové MATE, není s integrací sebemenší problém, obecně mi Arch přijde velmi zajímavý a i přes čerstvé aplikace opravdu stabilní, jeho Rollback Machine jsem už nevyužil, ani nepamatuji.

3. Na fóru mě zaujala ještě jedna zajímavost:
https://github.com/anthonyirwin82/generator-tads
Yeoman Generator for TADS 3
Nevím, zda má pro vývoj smysl automaticky generovat projekty s využitím tohoto nástroje, zaujala mě však podpora node.js, kterou využívají i moderní aplikace pro linuxovou řádku, možná by prospěla budoucnosti TADSu právě s využitím webových technologií.

4. Na a zase zpět k tvorbě
Nyní potřebuji zapálit kupku sena křesadlem nebo pochodní stejně jako v původní hře a po jejím shoření se na zemi objeví jehla.
Již umím zapálit pochodeň, přemýšlel jsem jak nejvhodněji zapálit kupku sena. Napadlo mě využít Matchbook a Matchstick, zkusil jsem definovat právě kupku jako Matchstick a křesadlo Matchbook i obráceně, dostávám však nesmysly typu „zapaluješ kupku kupkou“, tady si nejsem jist, zda kombinaci sirky - krabička od sirek budu moci využít. Plus nesmím zapomenout nadefinovat pochodeň podobně jako křesadlo PreferredIobj s využitím metody iobjFor(BurnWith).
Pokud neuspěju se zápalkami, další možností by mohlo být využití objektu objBurning: PreCondition – jen si nejsem jist, zda není určen k něčemu jinému, v Library píší This can be used for matches, candles, and the like. Budu ještě testovat.

Druhá akce je rozbití skleněné koule sekerou, na zem se rozlije tekutina, do které mohu namočit jehlu a tou odstranit draka.
Zde mi přijde ideální metoda dobjFor(Break), prozkoumal jsem příklady ze Základny, kde jí hojně využíváš, zde jsou však pouze formulace využívající direktivu illogical a popisující, proč hráč něco nemůže rozbít. Ani Library moc nepomohla, je zde pouze:
   /* -------------------------------------------------------------------- */
    /*
     *   "Break" action
     */
    dobjFor(Break)
    {
        preCond = [touchObj]
        verify() { illogical(&shouldNotBreakMsg); }
    }

snažím se využít jednu konstrukci ze Základny:

   dobjFor(Break)
    {
        verify() { }
        action()
        {
            "Nepodařilo se Ti uvolnit jí. ";
            nestedAction(TypeLiteralOn, self, 'R');
        }
    }
    dobjFor(Attack) asDobjFor(Break)

a inspiroval jsem se mnou dříve definovanou metodou dobjFor(CutWith) u mříže. Je mi jasné, že se musím kouknout na strom dědičnosti v Library a využít popsané metody a funkce, právě definice těchto akcí je pro mě v současné chvíli to nejobtížnější, ještě jednou si projedu Tvůj manuál, kde o nich píšeš a také kapitolu 6 – Actions v Ericově manuálu, tohle cítím, že je gró programování obecně a nesmím nic uspěchat, protože bez důkladného pochopení akcí se nikam nedostanu.

Psa i draka už jsem nadefinoval, k jejich eliminaci mi stačí jehla a rozlitý jed, tyto předměty využiji jakmile pohnu s akcemi popsanými výše. Dále jen u brány ukončím hru po sebrání všech 4 drahokamů, doladím ještě pár nesrovnalostí u skloňování některých objektů a tvorba pomalu končí.
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: gaspoda 28. Listopad 2017 - 20:24
1. Unit testy
Díval jsem se na jeho soubory, pro zajímavost zasílám i v příloze, je zde sada TADS3 Unit Testů, zajímavé, v minulosti jsem se setkal s pojmem Programování řízené testy – TDD, což pokud dobře chápu bude jedna z metod programování podobně jako např. Scrum. Vím jak postupuješ ty pomocí transkriptu hry, využil jsi při své práci také něco podobného od Jeffa nebo Bizzarriho?

TDD podobně jako Scrum jsou metodologie, tedy řekněme sady doporučení, jak při programování postupovat. Každá se ale zaměřuje na jinou oblast problematiky, spolu nijak nesouvisí. Scrum je o tom, jak z týmu programátorů vyždímat co nejvíce práce (alespoň mi všechny ty obrázky trochu připomínaly odstředivku :-)) za pomoci spousty podivných anglických slovíček, jako agile, user story, epic apod.:

https://i.pinimg.com/originals/82/4c/56/824c5615fa75244710db8abe3c40bbce.jpg (https://i.pinimg.com/originals/82/4c/56/824c5615fa75244710db8abe3c40bbce.jpg)
http://geekandpoke.typepad.com/.a/6a00d8341d3df553ef017ee8123faf970d-pi (http://geekandpoke.typepad.com/.a/6a00d8341d3df553ef017ee8123faf970d-pi)
http://geek-and-poke.com/geekandpoke/2016/11/6/advanced-scrum (http://geek-and-poke.com/geekandpoke/2016/11/6/advanced-scrum)

TDD je názor, že při vývoji softwaru je vhodné používat automatické testování, protože pomůže předejít chybám a že vůbec nejlepší je napsat testy dopředu před tím, než vznikne kód:

https://img.scoop.it/wn9mwRFeFitxvyrTjNs4yDl72eJkfbmt4t8yenImKBVvK0kTmF0xjctABnaLJIm9 (https://img.scoop.it/wn9mwRFeFitxvyrTjNs4yDl72eJkfbmt4t8yenImKBVvK0kTmF0xjctABnaLJIm9)
http://geekandpoke.typepad.com/.a/6a00d8341d3df553ef0153925eca87970b-pi (http://geekandpoke.typepad.com/.a/6a00d8341d3df553ef0153925eca87970b-pi)
https://static1.squarespace.com/static/518f5d62e4b075248d6a3f90/t/58a830ece6f2e14f1951b58e/1487417607195/ (https://static1.squarespace.com/static/518f5d62e4b075248d6a3f90/t/58a830ece6f2e14f1951b58e/1487417607195/)

Tyhle věci se týkají spíš projektů vyvíjených ve větších týmech, kdy je plánování a komunikace důležitá, protože jinak by levá ruka nevěděla, co dělá pravá. Ale já osobně s tím žádné praktické zkušenosti nemám, většinu času pracuji sám. I když je pravda, že jsem před časem v práci povýšil z funkce "jediný programátor" na "šéfprogramátor" prostě proto, že je nás už jeden a půl.

Testování je v řadě případů docela užitečné, zvláště v situaci, kdy se příiš neřeší dokumentace, točí se lidi a nikdo pořádně neví, co se stane, když do něčeho dloubne. To je trošku zkratkovitý názor, testování určitě patří k "dobré kultuře", potíž je, že zdaleka není všespasitelné a zdaleka není zadarmo. V ideální situaci by člověk pomocí automatizovaného testování otestoval všechny mezi situace a alternativy, které mohou nastat, aby si byl jistý, že kód pracuje v pořádku.

Když však člověk někde jednotkové testování vidí, tak kolikrát jsou otestovány jen jednoduché triviální situace, tedy to, co programátor očekává, že by se mohlo zvrtnout. Programátoři se pak pochválí, jak jsou moderní, že provádějí testování, dokonce z toho některé nástroje vypočítají tzv. "pokrytí testy", tedy procento řádků programového kódu, ke kterému je nějaký test. Co na tom, že se může pokazit ve stejném kódu deset jiných věcí, které nikdo netestuje. Připomíná mi to cargokult.

Moje zkušenosti s chybami v softwaru jsou spíš takové, že většina chyb, které je pracné najít a opravit a mohou snadno zůstat skryté plyne spíš z komplexnějších interakcí větších celků, které by mě ani nenapadlo předvídat a to jsou věci, které jsou na testování podstatně náročnější. A jak říkám, protože nepracuji ve velkém týmu, tak pro mě a můj styl práce ten poměr cena/výkon není zase tak příznivý, jinými slovy vždycky po mě spoustu lidí chtělo spoustu věcí, tak když mám chvíli čas, tak ji investuji spiš do kvalitních univerzálních komponent, které mezi projekty sdílím.

2. QT Creator
Fórum jsem trochu procházel, zaujal mě článek, kde krásně popisuješ své prostředí:
https://www.intfiction.org/forum/viewtopic.php?f=10&t=20899&sid=0bc3a9795ccf2d5ffea8ecfd35941195
a vysvětluješ automatické testy.

Právě na rozdíl od pracovních projektů jsem při programování té své textovky a tvorbě překladu TADSu automatizované testování používal, ale ne ve stylu jednotkových testů, jaké ukazoval Jeff, ale právě přes transkript. A na uvedeném odkazu jsem se snažil poukázat na hlavní výhodu, kterou v tom vidím, byť to má své mouchy, a sice na ekonomičnost takového způsobu testování - s tak malou námahou lze provést tak komplexní testování, to je u jiného druhu softwaru nedosažitelné. Stačí jen přidávat příkazy do souboru a vždy si přečíst pár řádek, jak se změnil výstup.

Přímá podpora TADS projektu zde samozřejmě není, mohu poprosit o osvětlení jak jsi postupoval u založení projektu – nestačil např. nový projekt v C++ a ručně přidat zdrojové t soubory?

Já vždy vyberu "importovat projekt" a "importovat stávající projekt". A to i tehdy, když projekt doposud neexistuje, prostě si při tom vytvořím prázdný adresář. Qt Creator pak funguje jako obyčejný textový editor a nijak mi do samotného projektu a způsobu jeho sestavení nezasahuje. Jen si v něm přidám, které soubor se mi mají zobrazovat v levém sloupečku a jak se volá překladač si nastavím v záložce projekty (ikona v levé šedivé liště).

Konkrétně mám dvě varianty sestavení (výběr v "upravit nastavení sestavování") a to normální, kdy poštím příkaz "t3make" s argumentem "-d" a druhou předvolbu mám sestavení na web, kdy pouštím ten samý příkaz s argumentem "-f Makefile.web.t3m". Pro web mám samostatný makefile, viz zdrojáky Základny. Když neřeknu t3make přepínač -f, tak automaticky bere Makefile.t3m.

Pro spouštění mám variant několik. Jednak spuštění automatického testu, tam mám v konfiguračním dialogu nastaven spustitelný soubor testPlay.sh v patřičném adresáři, dále mám spuštění frobu, to mám spustitelný soubor "frob" a command line arguments "-i plain -k utf8 -c -p asteroid.t3". Pak mám možnost spustit qtads, to je příkaz "qtads" a argument "asteroid.t3", pak spustit webové hraní s lokálním serverem, kde mám spustitelný soubor zase frob a argument "-i plain -k utf8 -p -N 00 -w 192.168.1.2 -W tomasb asteroid-web.t3 -storagesid=tomasb" a webové hraní s lokálním úložištěm má argument "-i plain -p -N 44 asteroid-web.t3"

Kontrolu nad výstupy máš v tomto IDE parádní, sakra, kdyby byl nějaký programátor ochoten převzít debugger z Workbenche a naroubovat jej na Frobtads, bylo by takové IDE naprosto perfektní a závislost na WINE ukončena.

To by teoreticky možné bylo, jednou jsem do toho nakukoval dovnitř. Qt Creator má poměrně univerzální kód, uživatelské prostředí je hotové, takže by stačilo "jen" napsat rozhranní a propojit. Bohužel i tak je to obrovská práce, muselo by se toho spousta nastudovat, takže neočekávám, že něco takového vznikne. Navíc Qt Creator je příliš živý projekt, často se mění.

Druhá možnost by byla vytvořit webové IDE a jít vstříc budoucnosti. To by mělo některé výhody a některé nevyhody.

Používáš QT Creator i nyní a jsi s ním spokojen? Nyní mám na svém stroji Arch Linux a Q4OS, v obou tato prostředí parádně fungují a i když mám pod Archem GTKčkové MATE, není s integrací sebemenší problém, obecně mi Arch přijde velmi zajímavý a i přes čerstvé aplikace opravdu stabilní, jeho Rollback Machine jsem už nevyužil, ani nepamatuji.

Qt Creator pochází od toho, kdo zrovna vlastní Qt knihovny, mění se to příliš rychle, než abych si pamatoval, kdo to je nyní. KDevelop je od komunity. Já qtc používám, tedy resp. používáme ho v Kapse na kroužku. Používám ho rád, protože má několik vlastností, které ho činí pro výuku ideální. Před drahnou dobou, co skončilá éra Borland Cčka jsem dlouho hledal něco použitelného pro výuku a ani Dev-C++, abu Code::blocks mi nevyhovovaly. Jednak jsem chtěl multiplatformí prostředí, aby bylo stejné na linuxu i windows, druhak jsem chtěl prostředí, které se příjemně používá. O Dev-C++ se nikdo nestaral, devpaky se SDL byly staré a ručně tam proniknout přes vrstvu konfiguračních dialogů projektů k fungujícímu projektu s nějakou cizí knihovnou bylo pro mě peklo a nedařilo se mi. Druhý zmíněný pak vypadal, jak když člověk nasype hromadu ikonek do mixéru, chyběla v tom nějaká vstřícnost a přehlednost. Navíc jsem také moc nepochodil s konfigurací projektů. QtC bylo vysvobození. Navíc nesnáším editory, které otevírají více souborů jako nahodile uspořádané záložky v záhlaví, já chci abecedně seřazený seznam po straně :-)

Yeoman Generator for TADS 3

Nemyslím, to je jen šum. Na založení projektu, tj. vytvoření dvou souborů není potřeba nic víc, než Ctrl+C, Ctrl+V. Učit se pět nových obskurních technologií, děkuji pěkne...

Již umím zapálit pochodeň, přemýšlel jsem jak nejvhodněji zapálit kupku sena. Napadlo mě využít Matchbook a Matchstick.

Matchstick je samozápalný objekt, tj. můžeš ho zapálit bez čehokoliv dalšího. To nevím, jestli chceš, nechceš zapálit seno od hořící pochodně? Každopádně Matchbook vůbec nepotřebuješ. To je krabička na zápalky a řeší úplně jiný problém a sice jde o to, když je v krabičce hodně stajných zápalek, aby hráč vytáhnul jakoukoliv bez ptaní, kterou z desítek sirek má hráč na mysli. Nemá se samotným zapalováním nic společného.

Pokud neuspěju se zápalkami, další možností by mohlo být využití objektu objBurning: PreCondition – jen si nejsem jist, zda není určen k něčemu jinému, v Library píší This can be used for matches, candles, and the like. Budu ještě testovat.

Precondition se používá pro automatické akce. Toho si také nevšímej. Nejjednodušší je udělat u sena dobjFor(Burn) a jednak pomocí verify s prázdným tělem povolit a v action napsat, co se stalo.

Zde mi přijde ideální metoda dobjFor(Break), prozkoumal jsem příklady ze Základny, kde jí hojně využíváš, zde jsou však pouze formulace využívající direktivu illogical a popisující, proč hráč něco nemůže rozbít. Ani Library moc nepomohla, je zde pouze:
   /* -------------------------------------------------------------------- */
    /*
     *   "Break" action
     */
    dobjFor(Break)
    {
        preCond = [touchObj]
        verify() { illogical(&shouldNotBreakMsg); }
    }

Tak to je přesně ono, to je úryvek z knihovny. Tak podobně, jako výše zmíněného zpálení. Vidíš, že na objektu je by default verify, které akci zakazuje. Tudíž přetěž verify tak, že ho uděláš s prázdným tělem, tím vyřadíš to illogical, takže akce bude s tím objektem povolená. No a pak zadefinuj action, ve kterém něco napíšeš a uděláš. Tedy asi odstraníš skleněnou kouli ze hry - moveInto(nil) a přidáš objekt střepy, tekutinu, nebo něco takového, takže tekutina bude třeba Hidden objekt v místnosti a zavoláš tekutina.discover(). Jen prosím vynechej to nestedAction(TypeLiteralOn, self, 'R'), to vyvolalo zmáčknutí klávesy R na ovládacím počítači v základně, kterou se zobrazí reporty o těžbě. To na tvém hradu nebude :-)
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: Kroužící orel 29. Listopad 2017 - 18:58
1. Metodiky programování
Paráda, rozepsal jsi se zajímavě a podrobně, moc díky za Tvůj čas. Teď už konečně chápu, co to opravdu znamená agilní programování, bude to něco jako tah na branku v požadavcích na firemní uchazeče. Jak vidno, po agilní snídani opravdu netoužím, tfuj… Pokud je metodika TDD vhodnější spíše pro větší týmy, zatím se jí podobněji zabývat nebudu, každopádně testy, které provádíš v QT Creatoru a o kterých jsme se bavili při mých začátcích s TADSem mi připadají komplexní, transskript s úspěchem používám i já a pokud uživatel-tester opravdu Zapne zápis, měli bychom společně odchytit téměř vše. Což jak chápu používáš, uvádíš, že testuješ především při TADS tvorbě. S univerzálními kvalitně napsanými komponenty, které sdílíš s ostatními, zcela souhlasím, zde si představuji např. komponenty starého Delphi a snad i novějšího Lazarusu, díky nimž programátor spoustu času ušetří a měly by být otestovány, vím, že vývojáři účetních programů a prvních IS tento nástroj s úspěchem využívali a někteří si dnes stěžují na Visual Studio, kde jim chybějí.

Máš recht, že takové testování v QT Creatoru, které jsem měl možnost vidět na obrázku v diskuzi, je velmi jednoduché a účinné, unit testy jsou možná pro TADS trochu zbytečné. Ale každopádně je budu využívat u C/C++, takže až dokončím hru, juknu na ně podrobněji a srovnám s těmi céčkovými. Tvrzení, že u jiného SW je takové jednoduché testování nedostažitelné, je velmi zajímavé, opravdu jsi mě překvapil. Hmm, pokud se v TDD netestuje vše potřebné, ale provádí se hlavně proto, aby se naplnily měřitelné parametry testování, nedá se nic dělat, připomíná mi to tzv. timesheety, které jsem denně vyplňoval v práci, ufff, pracovat na sebe má opravdu nesmírné výhody.

Sakra, nesmím to s tím programováním tak přehánět, manželky těchto individuí to opravdu nemají jednoduché… kór když je vývojář ještě nadšený koňák a dříve, než kobylku nauzdí, provádí testy výkonnosti...

2. QT Creator
Super, vše jsi parádně popsal, podařilo se mi naimportovat prázdný projekt, přidal jsem všechny soubory Základny a nastavil sestavení a spuštění. Hru se mi podařilo spustit pomocí interního qtcreator_process_stub. Lokální práce je tedy OK, tímto způsobem si založím nový projekt Špatné noci velmi volně inšpirované Bad Nightem, ještě si výhledově zprovozním lokální webový TADS server, to je myslím dobře popsané v dokumentaci. Zatím tedy budu používat klasický WB debugger, přiznám se, že se bez něj neobejdu s kombinaci s QTC. Důvody, proč QTC používáš, jsou jasné, mě se nejvíce líbí to, že ze mnou známých skutečných IDE, nejen „lepších“ textových editorů, patří mezi ty nejméně paměťově náročné plus je určen pro C a C++, pořádně se na něj juknu. Pokud se příliš živě vyvíjí, nevadí, i Arch je takový, vždy mám možnost výměny za Kdevelop nebo cokoliv jiného, ještě, že máme na výběr. DevC++ si pamatuji před mnoha lety z Windows, naštěstí pod Linuxem je výběr obrovský, zaujal mě např. jednoduchý juCi++, nejedná se ovšem o IDE, které pokud člověk správně uchopí, určitě pomůže.

3. Zapálení sena
Aha, já tušil, že Matchstick a Matchbook jsou předem připraveny pro konkrétní akci, v tomto případě samozápalný objekt, to u sena nevyužiji. Precondition si taky všímat nebudu, automatické akce nechám na později. Metoda dobjFor(Burn) funguje parádně, ještě jsem hráči znemožnil seno vzít, ať hra vypadá trochu reálněji.

4. Skleněná koule
Aha, budu si pamatovat, že k vyřazení akce rozbij je třeba přetížit verify. Použil jsem metodu dobjFor(Break) s tím, že pokud mám sekeru u sebe, hráč automaticky kouli rozbije. Následně se objeví kaluž, u které jsem ještě musel definovat  cannotTakeMsg a protože nebyla vidět, ale šlo jí prozkoumat, ještě bylo třeba isListed = true. Teď celá akce funguje parádně.
Jediná malá bolístka je v tom, že hráč musí napsat „rozbij kouli“, ovšem příkaz „rozbij kouli sekerou“ vrací „Nic takového jako „kouli sekerou“ tu nevidíš.“

Metoda dobjFor(AttackWith) útok sekerou povoluje, „zabij strážce sekerou“ je OK.

U skleněné koule jsem se pokusil použít místo původního
if (!sekera.isIn(me))
příkaz
if (gIobj != sekera)
zde však pohořím:

>rozbij kouli
Kouli holýma rukama nerozbiješ.
>rozbij kouli sekerou
Nic takového jako „kouli sekerou“ tu nevidíš.
>zabij kouli
Kouli holýma rukama nerozbiješ.
>zabij kouli sekerou
Skleněnou koulí nemůžeš zaútočit.
>zaútoč na kouli
Kouli holýma rukama nerozbiješ.
>zaútoč na kouli sekerou
Na ni nemůžeš zaútočit.

Využívám metodu dobjFor(Attack) asDobjFor(Break)

Napadlo mě změnit metodu dobjFor na:
dobjFor(AttackWith) asDobjFor(Break)

poté získávám:
>rozbij kouli
Kouli holýma rukama nerozbiješ.
>rozbij kouli sekerou
Nic takového jako „kouli sekerou“ tu nevidíš.
>rozbij kouli sekera
Nic takového jako „kouli sekera“ tu nevidíš.
>zaútoč na kouli
Na ni nemůžeš zaútočit.
>zaútoč na kouli sekerou
Rozbil jsi skleněnou kouli sekerou, kapalina vytekla na zem.

Jasně, zde je převzata metoda z definice strážce, metoda rozbij je však definována jinak a pokud uvažuji správně, musel bych jí přeprogramovat dle svých potřeb a nazvat jí např. DobjFor(BreakWith).

Ale nebudu situaci komplikovat, asi bude lepší vůbec hráči nedovolit zaútočit na kouli, pouze jí rozbít, takže jsem dobjFor(Attack) asDobjFor(Break) zakomentoval. Napadá mě, že těchto situací si v budoucnu určitě při tvorbě užiji dosytosti, je možné hráči na konkrétní příkaz, např. v mém případě:

rozbij kouli sekerou, rozbij kouli pochodní …

automaticky odpovědět např. textem „To nemůžeš udělat.“ - tedy přepsat standardní knihovní hlášku? Dost by to podobné situace zjednodušilo.

Podobně je to se zapálením sena:
>zapal kupku pochodní
{Tím iobj} nemůžeš nic zapálit.
// to chápu, pochodeň není definována přímo jako věc, která umožňuje něco zapálit
>zapal kupku křesadlem
To není něco, co by mohlo hořet.
>zapal kupku
Zapálil jsi seno. Bylo tak dobře proschlé, že za několik sekund zbyla jen docela malá hromádka popela.

Možná bych využil informace z Tvého manuálu, kde píšeš o Nepřenosných objektech - Fixture představuje pevný objekt, který na pokus o sebrání, pohnutí a položení někam reaguje chybovými zprávami cannotTakeMsg, cannotMoveMsg a cannotPutMsg. Pokud na objektu tyto vlastnosti nenastavíte na svůj jednoduchými uvozovkami ohraničený řetězec, použije se standardní knihovní hláška.
Bylo by možné takové řešení využít?

5. Namočení jehly v kaluži
Chvíli jsem se trápil s namočením jehly v kaluži, hra samozřejmě příkaz namoč nezná a již tradičně jsem žádný vhodný příklad na internetu ani v dostupných hrách nenalezl. Nakonec mě napadlo definovat kaluž jako RestrictedContainer, dlouho jsem uvažoval o vhodné metodě, s dobjFor(PutIn) jsem úspěšný nebyl, iobjFor(PutIn) ale funguje k plné spokojenosti. Uff, tak snad už se konečně do té tvorby dostanu. Definoval jsem také nové slovo „namoč“ pomocí:

VerbRule(namoc)
    ('namoč' | 'namočit')
    dobjList 'do' singleIobj
    | ('namoč' | 'namočit')
    'do' singleIobj dobjList
    : PutInAction
    verbPhrase = 'namočit/namá{číš}/namočil{a} (co) (do čeho)'
    askIobjResponseProd = toSingleNoun
;

a po kompilaci ve WB fungoval příkaz „namoč jehlu v kaluži“ kromě klasického dej nebo polož jehlu do kaluže naprosto bez potíží. Ale ouha, teď jsem překompiloval Exoter.t pomocí t3make a „namoč jehlu v kaluži“ už nefunguje, polož nebo dej naštěstí ano, viz transkript. Setkal jsi se někdy s něčím podobným?

Dokonale jsi mě rozřechtal tou hláškou ...to vyvolalo zmáčknutí klávesy R na ovládacím počítači v základně, kterou se zobrazí reporty o těžbě. - a její kombinací s prostorami hradu, díky, tak krásně už jsem se pár dnů nazasmál.

Draka a psa už mám připravené, nyní mě čeká vymyslet jak mrtvému drakovi useknu hlavy sekerou, dívám se na DefineTIAction(CutWith) a především dobjFor(CutWith) a tyto následně hodím psovi, zde se pokusím využít stejnou definici jako při namočení jehly do kaluže. Prozatím zasílám aktuální zdrojový kód a transkript, zítra nebo pozítří budu vesele pokračovat.
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: gaspoda 29. Listopad 2017 - 21:29
1. Metodiky programování
Teď už konečně chápu, co to opravdu znamená agilní programování, bude to něco jako tah na branku v požadavcích na firemní uchazeče.

Agilní na rozdíl od skrumáže znamená to, že se neplánuje vývoj a analýza celého projektu detailně dopředu, ale že se programuje po menších částech, které se pravidelně ukazují zákazníkovi a na základě zpětné vazby se pak průběžně mění plán a další zadání.

Tvrzení, že u jiného SW je takové jednoduché testování nedostažitelné, je velmi zajímavé, opravdu jsi mě překvapil. Hmm, pokud se v TDD netestuje vše potřebné, ale provádí se hlavně proto, aby se naplnily měřitelné parametry testování, nedá se nic dělat, připomíná mi to tzv. timesheety, které jsem denně vyplňoval v práci, ufff, pracovat na sebe má opravdu nesmírné výhody.

TDD jako teorie je pěkné, ale v praxi to občas trochu pokulhává. Ale to tak bývá se vším, třeba s dokumentací. Např. hrozně rozšířený zlozvyk je psát komentáře alespoň k hlavičce funkce a vygenerovat z toho pak HTML dokumentaci. Potíž je, že ve většině případů to bývá tak, že když bys z takového komentáře vymazal všechna slova obsažená v názvu funkce a všechna obsažená v názvu třídy, tak ti z komentáře zbydou jen předložky a spojky. Mnoho lidí se snaží o různé vývojářské postupy, ale málokdo to dělá pořádně.

Pokud se příliš živě vyvíjí, nevadí, i Arch je takový, vždy mám možnost výměny za Kdevelop nebo cokoliv jiného, ještě, že máme na výběr.

Jo, mě tím pěkně derou, protože se snažím udržovat na webu návod k instalaci Qt Creatoru spolu se SDL knihovnami do Windows a každou chvíli mi tam něco předělají a já pak musím přefocovat screenshoty a vyřezávat je z celého snímku a to je tak ubíjenící činnost...

4. Skleněná koule
Aha, budu si pamatovat, že k vyřazení akce rozbij je třeba přetížit verify.

Obecně si spíš pamatuj se na každou akci podívat do referenční příručky, jak je na tvém žádaném objektu zadefinovaná. A u těch exostičtějších akcí je běžné, že nemají žádné definované chování a jen pomocí verify říkají, že to nejde. Konec konců tak je zadefonovaná většina akcí na Thing, že nic nedělají (kromě těch úplně univerzálních, jako seber, polož apod. Koukni třeba na náhodný koušíček Thng:

Kód: [Vybrat]
    /* -------------------------------------------------------------------- */
    /*
     *   "PutBehind" action
     */
    dobjFor(PutBehind)
    {
        preCond = [objHeld]
        verify() { }
    }

    iobjFor(PutBehind)
    {
        preCond = [touchObj]
        verify() { illogical(&cannotPutBehindMsg); }
    }

    /* -------------------------------------------------------------------- */
    /*
     *   "Wear" action
     */
    dobjFor(Wear)
    {
        verify() { illogical(&notWearableMsg); }
    }

Tady třeba vidíš, že jakýkoliv objekt, který držíš nebo můžeš vzít (dobj) je možné umístit za jiný objekt (třeba klíč za obraz). Ale zároveň vidíš, že všechny objekty mají nastaveno, že zrovna za ně se nedá nic dát (iobj), takže dokud se u nějakého objektu neudělá výjimka, tak je akce polož něco za něco připravená, ale nejde s žádným objektem udělt.

Podobně je v základu zakázaná akce wear, tedy obléci objekt tím, že je zde naprogramované verify s illogical makrem. A to je právě to - když u objektů třídy Wearable chtěl autor tuto akci povolit, postupoval takto:

Kód: [Vybrat]
    dobjFor(Wear)
    {
        preCond = [objHeld]
        verify()
        {
            /* make sure the actor isn't already wearing the item */
            if (isWornBy(gActor))
                illogicalAlready(&alreadyWearingMsg);
        }
        action()
        {
            /* make the item worn and describe what happened */
            makeWornBy(gActor);
            defaultReport(&okayWearMsg);
        }
    }

Vidíš, že je přetížené verify, aby se vyřadilo původní illogical. I když v tomto případě tam jedna podmínka je přidaná. Pak je tu také precondition, že musí hráč objekt nejprve vzít, než ho bude moci obléknout. No a nakonec je tu akce, která obleče a zobrazí výchozí hlášku, že se tak stalo.

Smyslem tedy není si pamatovat nazpaměť, že zrovna při akci rozbij je potřeba předělat verify. U různých akcí to může být různé, někdy je potřeba upravit verify, jindy check. Vždy je tedy potřeba se podívat, jak je to dělané a co to pak v action() doopravdy udělá.

Následně se objeví kaluž, u které jsem ještě musel definovat  cannotTakeMsg a protože nebyla vidět, ale šlo jí prozkoumat, ještě bylo třeba isListed = true. Teď celá akce funguje parádně.

Kaluž se nevypisuje, protože jsi zvolil Immovable, což se obvykle používá na objekty, které jsou pevnou součástí lokace a předpokládá se, že jsou posané v popisu místnosti. Tvé řešení je jedno z možných. Také bys mohl přidat specialDesc předmětu a napsat tam podrobnější popis kaluže, jak se má v místnosti napsat. Jinak když používáš Immovable, měl bys napsat celkem tři různé hlášky pro různé manipulace cannotMoveMsg, cannotPutMsg a cannotTakeMsg. Pokud stačí na vše odpovídat stejně, stačí zadat jen cannotTakeMsg a místo Immovable použít třídu CustomImmovable.

Jediná malá bolístka je v tom, že hráč musí napsat „rozbij kouli“, ovšem příkaz „rozbij kouli sekerou“ vrací „Nic takového jako „kouli sekerou“ tu nevidíš.“

Metoda dobjFor(AttackWith) útok sekerou povoluje, „zabij strážce sekerou“ je OK.

Zkus u koule dobjFor(AttackWith), protože ta koule je to, na co se útočí, tedy dobj. Pak si dej ten prázdný verify (tedy pokud prozkoumáš implementaci dobjFor(Attack) v třídě Thing, tak zjistíš, že nemusíš, že akce zakázaná není), a ta podmínka if (gIobj != sekera) v checku by měla být ok. Já myslím, že možná jen narážíš na to, že jsi nic neudělal resp nevypsal v action(). Výchozí chování je mainReport(&uselessToAttackMsg);

Využívám metodu dobjFor(Attack) asDobjFor(Break)

To je v pořádku. To zajistí, že zaútoč na kouli se bude chovat stejně jako rozbij kouli.

Napadlo mě změnit metodu dobjFor na:
dobjFor(AttackWith) asDobjFor(Break)

To ne, myslím, že nemůžeš přesměrovávat akce se dvěma objekty na akci s jedním objektem. A beztak by to nedávalo smysl, protože akci s jedním objektem beřeš jako útok holma rukama a vyzýváš hráče říci akci se dvěma objekty.

Jasně, zde je převzata metoda z definice strážce, metoda rozbij je však definována jinak a pokud uvažuji správně, musel bych jí přeprogramovat dle svých potřeb a nazvat jí např. DobjFor(BreakWith).

Než programovat celou akci s celým chováním, tak bych asi jen přidal VerbRule se slovíčky rozbiij něco něčím ke stávající akci AttackWith.

automaticky odpovědět např. textem „To nemůžeš udělat.“ - tedy přepsat standardní knihovní hlášku? Dost by to podobné situace zjednodušilo.

Jasně. To je podobné, jako když jsi napsal cannotTakeMsg u toho Immovable. Koneckonců když mrkneš na ActionMessages.PDF v http://users.ox.ac.uk/%7Emanc0049/TADSGuide/QRefs.zip (http://users.ox.ac.uk/%7Emanc0049/TADSGuide/QRefs.zip), tak tam máš u každé akce na konkrétní třídě napsáno, jaké zprávy můžeš na objektu předefinovat.

Podobně je to se zapálením sena:

Přídej senu dobjFor(BurnWith) a zadej prázdné verify, aby se akce povolila. V action pak reaguje podobně, jako u Burn.

5. Namočení jehly v kaluži
Nakonec mě napadlo definovat kaluž jako RestrictedContainer, dlouho jsem uvažoval o vhodné metodě, s dobjFor(PutIn) jsem úspěšný nebyl, iobjFor(PutIn) ale funguje k plné spokojenosti. Uff, tak snad už se konečně do té tvorby dostanu. Definoval jsem také nové slovo „namoč“ pomocí:

Jasně, proč ne, to tak klidně můžeš udělat. Samořejmě si dej pozor na dobj vs. iobj. Iobj je vždy cíl nebo pomůcka a dobj to, co manipuluješ. Tady namáčíš jehlu (dobj) a kaluž je cílem (iobj).

Jen když k tomu využiješ akci PutIn, tak to znamená, že hráč tu jehlu dá do kaluže a zůstane v kaluži. To ti tady nevadí, protože jí zahodíš a místo toho mu dáš otrávenou, ale aby tě to jinde nepřekvapilo.

VerbRule(namoc)
    ('namoč' | 'namočit')
    dobjList 'do' singleIobj
    | ('namoč' | 'namočit')
    'do' singleIobj dobjList
    : PutInAction
    verbPhrase = 'namočit/namá{číš}/namočil{a} (co) (do čeho)'
    askIobjResponseProd = toSingleNoun
;

a po kompilaci ve WB fungoval příkaz „namoč jehlu v kaluži“ kromě klasického dej nebo polož jehlu do kaluže naprosto bez potíží. Ale ouha, teď jsem překompiloval Exoter.t pomocí t3make a „namoč jehlu v kaluži“ už nefunguje, polož nebo dej naštěstí ano, viz transkript. Setkal jsi se někdy s něčím podobným?

Hm, já vidím že jsi naprogramoval jen předložku 'do' a nikoliv předložku 'v'. Jo a drobnost, když píšeš verbPhrase, tak koncovky pravidelných sloves jsou eš neš ješ íš áš ne číš.

Jo a zkontroluj si tu podmínku, isLit, kterou kontroluješ na senu, takže to je nepravda. Dál Candle s vekám Cé je název třídy. Chceš-li konkrétní objekt, musíš si ho pojmenovat přes nějakou proměnnou. A nakonec mám pocit, že místo && isLit jsi spíš chtěl opak, tj. || !candle.isLit:
Kód: [Vybrat]
if (!Candle.isIn(me)&&(isLit) || !kresadlo.isIn(me))
        failCheck('Seno sám od sebe nezapálíš. ');
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: Kroužící orel 1. Prosinec 2017 - 13:08
1. Ještě jednou k metodikám a rychlým aktualizacím
Tak tady jsem špatně propojil skrumáž s agilním programováním, pokud jej dobře chápu, setkal jsem se právě s agilním stylem u doprogramování modulů IS – systém byl hotov, účetní, logistici apod. měli určité požadavky, které jsem já předával vývojářům a společně s oběma stranami testoval. Na základě této vazby jsme pak klidně změnili zadání, protože ne vždy se účetnímu podařilo správně definovat svůj požadavek.

Na generování dokumentace ze zdrojových kódů jsem se již ptal u TADSu, zde jsi mi potvrdil, že právě Library je takto připravena. HTML dokumentace, o které píšeš, je v takovém případě samoúčelná a zase naplňuje nějaké ty tabulky výkonnosti týmu, ale buďme upřímní – nebyli bychom v práci stejní? Když si vzpomenu na svoje zaměstnanecká léta IT špecialisty, každý den jsem se setkával se záplavou požadavků, co zase nefunguje na stanicích, proč nejede tiskárna, chudákovi manažerovi se jeho nejnovější mobilák nedokáže synchronizovat s Autlukáčem, jaktože najednou nefunguje pdf výstup ze SAPu… Kolega se věčně musel vrtat na linuxovém serveru, protoře požadavky jen pršely a např. po čerstvé instalaci nové verze Oracle musel vychytávat jejich chyby… no a vývojáři eshopu postavené právě nad touto databází si museli užívat to samé, nebyli poté rádi, že si dokumentaci odbyli právě tak zjedodušeně jak píšeš a měli pocit hotové práce? Nevím… já jsem v té době vždy záviděl „starým“ správcům, kteří v devadesátých letech měli na starost jenom kontrolu terminálů připojených k síti starým kulatým ethernetem a hlavní činnost byla denní záloha dosového účetnictví na disketu…

A paradoxně teď, když dělám ouplně jinou práci a na sebe, mám mnohem více času na Linux a konečně už i na to programování, které mě dříve vůbec nechytalo, ale cítil jsem, že už mě jen správa nebaví a rád bych něco vytvořil. Proto díky za TADS a Tvůj čas, baví mě to čím dál tím více a Tvé rady mi připadají jako rady učitele, který nemá v popisu práce jen nějaký teoretický výzkum, ale učí to čerstvé, s čím denně pracuje. Už teď máš u mě pořádnou projížďku na koni, což je alespoň malý revanš za Tvůj čas.
Ha, píšeš o udržování dokumentace QT Creatoru a dere Tě rychlý vývoj – ano, vždy, když jsem nastoupil do nové práce, první činnost bylo projetí dokumentace a její aktualizace plus někdy úsměvná kontrola serverovny a zjištění, co tu za těch X let, kdy se na to nikdo nedíval, vlastně všechno běží… Čím jsem starší, tím dokumentaci beru jako důležitější věc, proto mě ve světě Linuxu moc zaujal Arch, který i přes čerstvé balíčky má opravdu příkladnou wiki. RHEL a SUSE také, ta v Archu je ale dle mého názoru určena spíše pro praktické použití a krásně vysvětluje konkrétní problémy, na které bych se jako uživatel ptal. Klobouk dolů tohle v takové kvalitě udržovat. Tady např. Debian nebo Slackware nemají návody tak dobře zpracované. Otázka zní, zda to tým Archu bude i v budoucnu zvládat, systémy nám stále bobtnají, s čímž se asi nedá nic dělat. Další zajímavost je OpenBSD, zde je mi velmi sympatická jejich snaha nepřidávat bezhlavně nové funkce, ale spíše zeštíhlovat kód a integrovat pouze aplikace podrobně zdokumentované. Prošel jsem si jejich manuálové stránky, na server paráda, pro desktop mi samozřejmě více sednou ty z Archu, což je dáno směrováním obou systémů. Jenomže v OpenBSD nemám Wine a nabídka aplikací je menší plus jejich naprostá ignorace českého jazyka mi zatím nedovoluje s ním aktivně pracovat. Mnoho jejich myšlenek mi ovšem sedne, takže uvidím – naštěstí je zde na výběr a do budoucnosti nevidím a ani nechci.

2. Akce a referenční příručka plus vhodný styl hledání
Ano, určitě souhlasím, že na každou akci bych se měl podívat do Library, to se snažím dělat. Pro mě je zatím největší problém nalézt jak je daná akce pojmenována, pár jich už v paměti držím a další budou přibývat s postupem času, to asi jinak nelze.
Ano, akci PutBehind krásně popisuješ, objekt, který chci za něco umístit, musím držet a protože verify je prázdné, lze tak učinit. Ale každý objekt má implicitně verify nastaven na illogical, které v takovém případě musím potlačit, přesně tak jak jsi psal minule u příkladu se senem. U oblékání musím přetížit verify, které mělo původně implicitně nastavenou hodnotu illogical a ještě musím kontrolovat, zda konkrétní věc na sobě nemám. Teprve poté se může provést akce s oblékáním. A je zde precondition, která je stejná, jako u prvního příkladu PutBehind.

Tak a díky tomuto příkladu už vidím svojí chybu, kterou provádám při hledání v příručce. Dejme tomu, že se potřebuji podívat na definici právě PutBehind:

V Library si klidnu v levém sloupci na P a naleznu řádek PutBehindAction - class in actions.t[1939]. Rozkliknu si PutBehindAction a následně příklad pod číslem 1939. Vidím však jen následující definici:

DefineTIAction(PutBehind)
;

která mi toho opravdu mnoho neřekne, takže začnu laborovat, co s tím. A teď babo raď, jak se mám doklikat k Tebou popisovanému kódu "PutBehind" action? Je mi jasné, že vše naleznu v popisu třídy Thing, to ale vím až teď od Tebe a samotného by mě nenapadlo spávné hledání. OK, zatím si tedy grepnu řetězec "PutBehind" action a nechám se překvapit, co získám. Konečně mě příkaz:

grep -Ri ""PutBehind action"" ./

odkazuje na

www.tads.org/t3doc/doc/libref/source/thing.t.html

Když si nyní v Library rozkliknu vlevo thing.t a následně vpravo source file, Tebou popsaný PutBehind je zde. A jak jsem předpokládal, můj skromný jednořádkový příkaz naleznu také, pokud si vlevo nahoře rozklidnu actions.t .
Takže suma sumárum si také musím zapamatovat, že na akce, které se vážou k předmětu, je nutno juknout se taky do popisu Thing. To je cenná zkušenost, bezva.

3. Kaluž
Právě Immovable mě napadlo jako ideální řešení pro věc, kterou nemohu sebrat. Žádný podobný příklad v referenčních hrách nebo na fóru jsem nenalezl. Bezva nápad s přidáním specialDesc, popis místnosti je hnedle živější, budu jej používat mnohem častěji v další hře. Tak a už se dívám na popis class Immovable: NonPortable a klik na 1998 mě správně odkáže na object.t. A tady v popisu mimo jiné vidím „ The messages to use for the failure messages.“ a hnedle pod tím CustomImmovable přesně tak jak píšeš. Bezva příklad jsem našel i v Základně, soubor regionShip.t – objekt ship: MultiLoc, Fixture. Vše jsem doplnil také ke střepům a senu.
Dokumentace k TADSu je tedy parádní, budu s ní ještě podrobněji pracovat, teď už si v ní připadám skoro jako doma na wiki Archu.

4. Rozbití koule
Ano, tohle také musím prozkoumat v Library. Už se dívám na dobjFor(AttackWith), ano, vidím zde verify() { }, takže akci mohu provést a mažu jej ze své definice. V action zprávu mám, to by mělo být OK. Zde jsem zkoušel různé konstrukce, zatím se mi však nepodařilo zprovoznit jak příkaz „rozbij kouli sekerou“, tak „zaútoč na kouli sekerou“.
Pokusil jsem se dle Tvého doporučení využít:

    dobjFor(AttackWith)
    {
        check()
        {
            if (gIobj != sekera)
                failCheck('Kouli holýma rukama nerozbiješ. ');
        }
        action()
        {
            "Rozbil jsi skleněnou kouli sekerou, kapalina vytekla na zem a všude kolem jsou rozházené střepy. ";
            sklenena_koule.moveInto(nil);
            kaluz.discover();
            strepy.discover();
         }
    }

      dobjFor(Break) asDobjFor(Attack)

Zde ovšem mohu využít pouze příkaz „rozbij kouli sekerou“, jiný nelze.

Nejlépe mým potřebám zatím vyhovuje definice:

    dobjFor(Break)
    {
        verify() {}
        check()
        {
            if (!sekera.isIn(me))
                failCheck('Kouli holýma rukama nerozbiješ. ');
        }
        action()
        {
            "Rozbil jsi skleněnou kouli sekerou, kapalina vytekla na zem a všude kolem jsou rozházené střepy. ";
            sklenena_koule.moveInto(nil);
            kaluz.discover();
            strepy.discover();
         }
    }
      dobjFor(Attack) asDobjFor(Break)

Kde mohu použít „rozbij kouli“ nebo „zaútoč na kouli sekerou“, nefunguje pouze „rozbij kouli sekerou“.
Píšeš ovšem, že definice dobjFor(AttackWith) asDobjFor(Break) není správná, protože melze přesměrovávat akce se dvěma objekty na akci s jedním objektem. Pokud řádek zakomentuji, mohu využít „rozbij kouli“, ovšem „zaútoč na kouli sekerou“ už samozřejmě nefunguje.
Pokud využiji u své konstrukce dobjFor(Break) řádek dobjFor(Attack) asDobjFor(Break), nyní mohu použít „rozbij kouli“ a také „zaútoč na kouli“, jen nesmím vypisovat čím.
Pokud využiji Tvojí konstrukci dobjFor(AttackWith) a řádek dobjFor(Attack) asDobjFor(Break), mohu pouze „zautoc na kouli sekerou“.

Zkoušel jsem definovat nové Verbrule a vyzkoušel u své i Tvé konstrukce:

VerbRule(rozbij_cim)
    ('rozbij' | 'rozbít') singleDobj singleIobj
    | ('rozbij' | 'rozbít') singleIobj singleDobj
    : AttackWithAction
    verbPhrase = 'rozbít/rozbíj{íš}/rozbil{a} (co) (čím)'
    isPrepositionalPhrasing = nil
    omitIobjInDobjQuery = true
    askDobjResponseProd = singleNoun
    askIobjResponseProd = singleNoun
;

Výsledek je trochu jiný, ale stále neuspokojí:

rozbij kouli sekerou
Skleněnou koulí nemůžeš zaútočit.

Zatím tedy ponechám mojí konstrukci dobjFor(Break), která umožňuje rozbít nebo zaútočit na kouli v případě, že má hráč v inventáři sekeru, jen není možné napsat „rozbij kouli sekerou“ nebo „zautoc na kouli sekerou“. Sakra, tohle není sranda, budeš-li mít možnost, prosím jukni na mojí definici.

5. Templates
Výborně, soubor TemplatesQref.PDF se bude hodit, mám uloženo.

6. Seno
Metodu dobjFor(Burn) jsem změnil na dobjFor(BurnWith) a musel jsem trochu upravit definici pochodně. Ano, používat název třídy určitě není vhodné, pojmenoval jsem jí jako pochodeň a přidal PreferredIobj podobně jako u křesadla. Metodu iobjFor(BurnWith) jsem prozkoumal v Library, v tomto případě je na rozdíl od křesadla vhodné použít preCond = [objHeld, objBurning], zkoušel jsem do hranatých závorek „isLit“, to ale není možné a manuál vše krásně popisuje. Díky za upozornění, měl jsem chybu v definici dobjFor(BurnWith) s sena – chybné pochoden.isLit jsem změnil  na !pochoden.isLit a nyní je zapálení sena konečně v suchu.

7. Namočení jehly a VerbRule
V mém případě namáčím co - jehlu, což je dobj kam - do kaluže, což je iobj, jasné. Ano, vím že akce PutIn předmět položí a hráč jej musí zdvihnout, což mi zde nevadí, píšeš, aby mě to u jiných situací nepřekvapilo, myslíš tedy např. tehdy, když budu potřebovat, aby hráč předmět z inventáře nepoložil a po např. po namočení v jedu mu tam zůstal?
Definoval jsem 3 nové VerbRule, nyní mohu využít příkaz „namoč jehlu“, „namoč jehlu v kaluži“ a „namoč jehlu do kaluže “ - jasné, zapomněl jsem definovat prázdnou předložku, kterou si TADS doplní, v a do, upravil jsem i předchozí  VerbRule, které jsem dříve definoval se správnými koncovkami.

Je toho jak vidím ještě stále dosti k dodělání, to ale nevadí, na téhle hře se mnohé naučím a tak to má být.

Krásný víkend přeje Orel
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: Kroužící orel 5. Prosinec 2017 - 12:08

Nyní pokračuji v tvorbě, hru už lze po sebrání všech čtyř drahokamů a projitím branou dokončit, závěr hry jsem připravil pomocí kombinace TravelMessage a finishGameMsg. Kromě malé bolístky u rozbití koule, kterou jsem popisoval v minulém příspěvku se nyní setkávám s pro mě zatím zvláštním chováním u draka i psa:


1. pokud je drak zabitý pomocí otrávené jehly, vše je OK:

>přeřízni draka
Čím ho chceš uříznout?

>sekerou
Odsekl jsi dračí hlavy od těla.

>vezmi hlavy
Hotovo.


2. pokud drak žije a snažím se použít příkaz přeřízni, zde je zvláštní chyba:

>přeřízni draka
Řezat spícího draka určitě není dobrý nápad. Řezat spícího draka určitě není dobrý nápad. Řezat spícího draka určitě není dobrý nápad. Řezat spícího draka určitě není dobrý nápad. Čím ho chceš uříznout?


>přeřízni draka sekerou
Řezat spícího draka určitě není dobrý nápad. Řezat spícího draka určitě není dobrý nápad. Řezat spícího draka určitě není dobrý nápad. Řezat spícího draka určitě není dobrý nápad. Odsekl jsi dračí hlavy od těla.

// a hráč získá hlavy, což by neměl


3. pokud je drak správně zabit otrávenou jehlou, odříznu mu hlavy a nabízím je psovi, vše je OK - viz příklad č. 1:

>dej psovi hlavy
Pes se lačně vrhl na otrávené dračí hlavy. Na jeho předsmrtnou agánii nebyl pěkný pohled.

>v
Opatrně procházíš kolem mrtvého psa dál na východ.


4. pokud drak není správně zabit a tak jako tak seberu dračí hlavy, zde je zvláštní chyba - viz příklad č. 2:

>dej hlavy psovi
Tím se psovi určitě nezavděčíš. Tím se psovi určitě nezavděčíš. Tím se psovi určitě nezavděčíš.
Pes se lačně vrhl na otrávené dračí hlavy. Na jeho předsmrtnou agánii nebyl pěkný pohled.

>v
Opatrně procházíš kolem mrtvého psa dál na východ.

5. pokud psovi v každém případě dám něco jiného a je jedno, zda v inventáři mám nebo nemám dračí hlavy, je zde také zvláštní chyba:

>dej psovi křesadlo
Tím se psovi určitě nezavděčíš. Pes se lačně vrhl na otrávené dračí hlavy. Na jeho předsmrtnou agánii nebyl pěkný pohled.


Tady pravděpodobně nesprávně definuji ty 2 ify v metodě dobjFor(CutWith) u draka a iobjFor(GiveTo) u psa, vše jsem kontroloval v Library a lze bez chyb přeložil. V příloze zasílám aktuální zdroják včetně transkriptu, který končí severně od místnosti s drakem, můžeš se prosím juknout na mé definice? Nevím, zda ty dva ify jsou správné řešení a také psa nechci zabít, ale odstranit jej pomocí podání otrávených dračích hlav, napadla mě metoda dobjFor(CutWith).
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: gaspoda 5. Prosinec 2017 - 13:01
1. pokud je drak zabitý pomocí otrávené jehly, vše je OK:
2. pokud drak žije a snažím se použít příkaz přeřízni, zde je zvláštní chyba:
3. pokud je drak správně zabit otrávenou jehlou, odříznu mu hlavy a nabízím je psovi, vše je OK - viz příklad č. 1:
4. pokud drak není správně zabit a tak jako tak seberu dračí hlavy, zde je zvláštní chyba - viz příklad č. 2:

To bysis tedy měl zopakovat, co jsem psal v kapitole o verify v článku http://www.textovky.cz/clanky/programovani-textovych-her-v-tads-3-cast-5-akce/ (http://www.textovky.cz/clanky/programovani-textovych-her-v-tads-3-cast-5-akce/). Tohle bys už měl umět!

5. pokud psovi v každém případě dám něco jiného a je jedno, zda v inventáři mám nebo nemám dračí hlavy, je zde také zvláštní chyba:

Tohle bude pro tebe asi trochu nové. S postavami se zachází jinak, témata konverzace (a předání předmětu stejně, jako zeptání se nebo mluvení o něčem je také konverzací) se přidávají do postav ve formě Topic objektů. Celý mechanismus interakce s postavami je už naprogramovaný, takže není důvod snažit se akci GiveTo apod. přeprogramovat po svém. Začti se do http://www.textovky.cz/clanky/programovani-textovych-her-v-tads-3-cast-6-npc-postavy/ (http://www.textovky.cz/clanky/programovani-textovych-her-v-tads-3-cast-6-npc-postavy/) a tam uvidíš příklady, jak s postavou komunikovat. Chceš-li postavě dát nějaký předmět, tak naprogramuješ objekt třídy GiveTopic, tedy téma konverace, které odehrává předání předmětu. Tento objekt pomocí plus umístíš do postavy, která má objekt dostat.
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: gaspoda 5. Prosinec 2017 - 22:43
1. Ještě jednou k metodikám a rychlým aktualizacím

...nebyli poté rádi, že si dokumentaci odbyli právě tak zjedodušeně jak píšeš a měli pocit hotové práce?

Možná byli rádi a já bych to i dovedl pochopit - v komerční sféře bývá frmol a musí se prioritizovat, je přeci potřeba vydělat na platy managorů a tak dokumentace musí ustoupit do pozadí. Ale takový je svět, já to chápu, jen mě zaráží, když narazím na nějakého free cool a in týpka, který do světa hlášá, že je to tak správně a že ta jeho dokumentace je příkladná :-)

V Library si klidnu v levém sloupci na P a naleznu řádek PutBehindAction - class in actions.t[1939]. Rozkliknu si PutBehindAction a následně příklad pod číslem 1939. Vidím však jen následující definici:

DefineTIAction(PutBehind)
;

Když půjdeš na akce tudy, tak se moc nedozvíš. To, co tam vidíš, je interní struktura parseru, ale ta není pro programátora hry vůbec zajímavá a k ničemu užitečnému se v ní nedoklikáš. Je to zkrátka ta část programu, která říká, jak poznat ten příkaz, když ho hráč napíše, ale už se tam neřeší, jak příkaz vykonat.

Je mi jasné, že vše naleznu v popisu třídy Thing, to ale vím až teď od Tebe a samotného by mě nenapadlo spávné hledání. OK, zatím si tedy grepnu řetězec "PutBehind" action a nechám se překvapit, co získám. Konečně mě příkaz:

grep -Ri ""PutBehind action"" ./

Fulltextové hledání se někdy také hodí. Ale u těch akcí tě zajímá hlavně implemetace dobjFor resp iobjFor a to můžeš v referenční příručce také najít. Chce to si najít třídu objektu, který tě zajímá. Třeba když máš obyčejný Thing objekt, tak si v manuálu najdeš třídu Thing a budeš hledat na stránce dobjFor(PutBehind). Nebo když je to nějaký konkrétní potomek, třeba kaluž je Hidden, Immovable, RestrictedContainer, tak postupně projdeš uvedené třídy od leva a hledáš, kde najdeš patřičný dobj nebo iobjFor akce, která tě zajímá. Ono ti to ukáže, jestli je to zpracování akce udělané na té třídě nebo zděděné z některého rodiče a můžeš se rovnou prokliknout na definici.

Třeba v tomto konkrétním případě bys viděl, že Hidden sice dědí dobjFor(PutBehind) z Thing, to je ta základní implementace, která povoluje, že každý objekt může být něčím, co vložíš za něco, ale Immovable přímo definuje dobjFor(PutBehind) (tudíž to dostane přednost před zděděným chováním) a to říká, že nepřemístitelný objekt nemůžeš dát za něco, protože je nepřemístitelný.

zatím se mi však nepodařilo zprovoznit jak příkaz „rozbij kouli sekerou“, tak „zaútoč na kouli sekerou“.
Pokusil jsem se dle Tvého doporučení využít:

    dobjFor(AttackWith)
    {
        check()
        {
            if (gIobj != sekera)
                failCheck('Kouli holýma rukama nerozbiješ. ');
        }
        action()
        {
            "Rozbil jsi skleněnou kouli sekerou, kapalina vytekla na zem a všude kolem jsou rozházené střepy. ";
            sklenena_koule.moveInto(nil);
            kaluz.discover();
            strepy.discover();
         }
    }

      dobjFor(Break) asDobjFor(Attack)

Zde ovšem mohu využít pouze příkaz „rozbij kouli sekerou“, jiný nelze.

Když se dostaneš do situace, že hra řekne:

>rozbij kouli sekerou
Skleněnou koulí nemůžeš zaútočit.

tak je to jenom o tom problému, o kterém jsme se tu už bavili. Hra u příkazů, kde role bobj a iobj není přesně určena předložkou, tak potřebuje označkovat, který objekt je přímým a který nepřímým objektem akce. Takže to, co je výše ukázáno je v pořádku, jen si ještě sekeru označ jako nepřímý objekt tím, že ji přidáš třídu PreferredIobj. Potom bude hra správně reagovat na "rozbij kouli sekerou" i "rozbij sekerou kouli".

Nejlépe mým potřebám zatím vyhovuje definice:

    dobjFor(Break)
    {
        verify() {}
        check()
        {
            if (!sekera.isIn(me))
                failCheck('Kouli holýma rukama nerozbiješ. ');
        }
        action()
        {
            "Rozbil jsi skleněnou kouli sekerou, kapalina vytekla na zem a všude kolem jsou rozházené střepy. ";
            sklenena_koule.moveInto(nil);
            kaluz.discover();
            strepy.discover();
         }
    }
      dobjFor(Attack) asDobjFor(Break)

Kde mohu použít „rozbij kouli“ nebo „zaútoč na kouli sekerou“, nefunguje pouze „rozbij kouli sekerou“.

Použij oboje dohromady, tedy dobjFor(AttackWith) i dobjFor(Break) a  dobjFor(Attack) asDobjFor(Break).

Píšeš ovšem, že definice dobjFor(AttackWith) asDobjFor(Break) není správná, protože melze přesměrovávat akce se dvěma objekty na akci s jedním objektem.

TADS má pak i jiné způsoby přesměrování, kterými to lze udělat.

Zkoušel jsem definovat nové Verbrule a vyzkoušel u své i Tvé konstrukce:

VerbRule(rozbij_cim)
    ('rozbij' | 'rozbít') singleDobj singleIobj
    | ('rozbij' | 'rozbít') singleIobj singleDobj
    : AttackWithAction
    verbPhrase = 'rozbít/rozbíj{íš}/rozbil{a} (co) (čím)'
    isPrepositionalPhrasing = nil
    omitIobjInDobjQuery = true
    askDobjResponseProd = singleNoun
    askIobjResponseProd = singleNoun
;

Jasně, to je dobře, ale viz výše. Akorát z toho vyhoď | ('rozbij' | 'rozbít') singleIobj singleDobj, stačí to tam jen jedním způsobem.

7. Namočení jehly a VerbRule
V mém případě namáčím co - jehlu, což je dobj kam - do kaluže, což je iobj, jasné. Ano, vím že akce PutIn předmět položí a hráč jej musí zdvihnout, což mi zde nevadí, píšeš, aby mě to u jiných situací nepřekvapilo, myslíš tedy např. tehdy, když budu potřebovat, aby hráč předmět z inventáře nepoložil a po např. po namočení v jedu mu tam zůstal?

Resp. ono by k tomu v tomto případě došlo - hráč by nepoložil jehlu, tedy nezůstala by v kaluži a to z toho důvodu, že jsi nezavolal inherited() ze své action(). Právě v action() metodě iobjFor(PutIn) kontejneru je naprogramováno to přemístění objektu a ty to překrýváš svojí verzí action(), která dělá něco jiného. Tím standardní chování potlačuješ. Za normálních okolností bys měl inherited volat skoro vždy s výjímkou těch situací, kdy ho chceš potlačit úmyslně.
[/quote]
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: Kroužící orel 7. Prosinec 2017 - 12:11
1. Dračí hlavy a verify
Jé, tak tady jsem se teda opravdu vyznamenal jako nepozornej študák, já vím, popel na mojí hlavu. Omlouvám se za nepozornost, naštěstí oba pracujeme s dětmi, takže snad jsme zvyklí opakovat několikrát jasné věci, sakra, zrovna před mým dotazem jsem si celou kapitolu Akce ve Tvém návodu prošel. Se začátkem tvorby jsem vůbec netušil, o čem je řeč, teď už konečně vnímám např. rozdíl mezi dobjFor a iobjFor a tato kapitola je jasnější, jenže ouha, stále mi vše kolem akcí nedochází. Pro mě je to tedy ta nejobtížnější část tvorby, verify každopádně popisuješ parádně a příklad jsem upravil dle Tvých doporučení, v mém případě je ideální kombinace prázdného verify, které nepřetěžuji, hlavní podmínku, aby byl drak po smrti, kontroluje check a řezat mohu pouze objekty, které to mají povolené pomocí metody iobjFor(CutWith). Zavolal jsem inherited pro volání zdědeného chování a po projití všech těchto kontrol může action() vykonat to, co má.

Tak a hóóóu, já pořádně zpomalím, už se sice těším, až Exotera dokončím, to ale nemá smysl, protože pokud celou metodiku, kterou je naprogramován nepochopím, u další hry se budu jen zbytečně zasekávat. Také jsem zjistil, že u TADSu bude téměř nemožné zcela opisovat styl tvorby textovky, kde univerzální příkaz použij vše řeší – použiju jehlu na draka, on umře, pak použiju sekeru a useknu mu hlavy, jak krásně jednoduché…

Tady ale přeci nemohu nechat draka jen tak, když mu useknu hlavy, musí se objevit jeho bezhlavá mrtvola, která samozřejmě bude mít atribut Immovable se všemi náležitostmi, na které jsi mě upozornil minule, už je to zařízeno. Další věc mě tu pálí, příkaz uřízni/rozřízni draka sekerou opravdu není něco, co by hráče napadlo, i když si u popisu psa může přečíst že k smrti miluje dračí hlavy. Takže budu potřebovat něco jako „uřízni hlavy sekerou“, díval jsem se na zajímavou konstrukci do souboru roomTunnel.t v Základně, kde dvě vozítka rozlišuješ direktivou
disambigName
ta však rozlišuje dvě stejná vozítka, což není můj případ. Takže jsem to vyřešil jednoduše, manipulace drakem = manipulace dračíma hlavama, drak po uříznutí hlav stejně zmizí, takže vše funguje jak má:

      gcName = 'spící drak, spícímu drakovi, spící drak, spícímu drakovi, spícím drakem, dračí hlava, dračím hlavám, dračí hlava, dračím hlavám, dračíma hlavama'
      gcVocab = 'spícímu spícím spícího dračím dračíma dračí drakovi/drakem/draka/hlavám/hlavama/hlavy'

Tímle malým trikem jsem vše vyřešil, jen příkaz:
>uřízni dračí hlavy

Spícím drakem nic nepřeřízneš.
// to chápu, zde parser myslí, že chci něco přeříznout drakem

>uřízni dračí hlavy sekerou
Odsekl jsi dračí hlavy od těla.
// zde je vše OK

Zde mě tedy jako řešení napadá definovat draka jako kontejner podobně jako u strážce, zde ale pravděpodobně také narazím, protože dračí hlavy nemohou jen tak vypadnout z draka po jeho smrti. Druhá možnost je ta, že draka definuji jako dva samostatné objekty např. „dračí hlavy“ a „drak“, pamatuji si, že něco podobného jsem viděl v Erikově manuálu u příkladu s třídou Attachable – jednalo se o kostičky různých barev, které se na sebe skládají jako lego, juknu na ně a zkusím vymyslet vhodnější řešení.

A poslední věc je zabití draka jehlou, zde bych rád také příkaz píchni draka jehlou. Ten ve slovníku zaveden není, přidáním:
VerbRule(pichni_koho)
    ('píchni' | 'píchnout') singleDobj singleIobj
     : AttackWithAction
    verbPhrase = 'píchnout/pích{áš}/píchnul{a} (koho) (čím)'
    askDobjResponseProd = onSingleNoun
    askIobjResponseProd = singleNoun
;

mohu využít „píchni draka jehlou“.

Ha, mohlo by zde třeba být i zrcadlo, do kterého se drak dívá, když si zkouší ty svoje zářící šperky nebo čarovné zbraně a hra by mohla simulovat jak v něm vypadá, když chrní nebo když už je bez hlav plus třída Vaporous bude krásně popisovat ty spráné odlesky od šupin, to si ale opravdu už nechám na příští hru, která se těmito věcmi bude jen hemžit.

2. Pes – příkazy Give to a topic
Aha, nečekal jsem, že příkaz Giveto je spojen s konverzačními tématy, jak vidno, mám dost potíží pochopit akce, upřímně řečeno hovor s postavami jsem chtěl řešit až ve své další hře. To ale nevadí, naštujuji vše už teď.
Ano, už první příklad „Vem Borisův kafovak“ jasně dává najevo, že zde nejde jen o témata rozhovoru, ale o mnohem více. Také s CurState jsem se u postav samozřejmě setkal, netušil jsem, že HermitActorState bude probírán právě v této kapitole, já jsem se k němu dostal přes Erikův manuál… Tak mám dočteno, bezva příklad s tím senilním čarodějem, systém je parádně propracovaný, to jsem ostatně obdivoval už v Základně. Textovkám se přeci jen už v dobách ZX Spektra říkalo konverzační hry, takže toho budu využívat o sto šest. 

Tady musím vše okolo postav pořádně pochopit, v další hře bude klisna, se kterou si chci vysloveně vyhrát, hráč jí bude muset správně vyhřebelcovat, nasedlat, nauzdit a nakonec si s ní i pokecat – možná se z řechtandy vyklube pořádná fešanda, ještě tedy nevím, zda to bude princezna, vědma, stará babička nebo třeba zakletá dračice, určitě ale bude stát za to.

Systém rozhovorů bude nebude tedy o mnoho jednodušší, než akce, ufff, možnosti krásné, ale za jakou cenu. Nyní v T3TourGuide čtu na straně 219 přesně to, o čem píšeš, příkaz iobjFor(GiveTo) není vhodný při interakaci s NPC postavami.
V Learning T3 je poměrně jednoduchý příklad na straně 220, jen u mě bude jeho použití náročnější, protože postřebuji psa, který si vezme otrávené dračí hlavy, zabít. Nejvhodnější mi přijde definice:

+ GiveTopic
     matchObj = draci_hlavy
    topicResponse()
    {
      "Pes se lačně vrhl na otrávené dračí hlavy. Na jeho předsmrtnou agánii nebyl pěkný pohled. ";
      draci_hlavy.moveInto(nil);
      setCurState(pesDeadState);
    }
;

která ovšem vylučuje použití canObjReachSelf(obj), canObjReachContents(obj) a cannotReachFromOutsideMsg(dest), debugger v takovém případě píše, že „The symbol "canObjReachSelf" is already defined“ a u ostatních rovněž. Pokud tyto tři direktivy vymažu, kompilace proběhne, ale pes o dračí hlavy nejeví zájem „Obrovský pes vypadáš nezaujatě.“.

Příklad včetně transkriptu zasílám v příloze, ještě se juknu na definici GiveTopic do Library, snad zjistím, proč se toto děje, hledal jsem např. situaci, kdy hráč někomu podá jed a NPC jej sní a umře, něco podobného je např. ve hře Trollbridge, její definice mi však nepomohla.

3. Hledání v Library
Ano, nyní vždy budu hledat třídu objektu, o který mám zájem, v levém sloupci jsem si zobrazil Classes a např. Hidden, po kliknutí na odkaz 906 si mohu prohlížet dojb akce. Vidím, že Hidden dědí pouze z Thing a Immovable z NonPortable a ta zase z Thing. Rozkliknul jsem si např. UntakeableActor, který mě zajímá, dědí z Actor a ten z Thing.
U Hidden a Immovable jsem si vyhledal všechny metody dobjFor(PutBehind), vše mě odkazuje do object.t, jasně, Immovable dostane přednost před jakýmkoliv zděděným chováním.

4. Rozbití koule sekerou
Ano, o PreferredIobj jsme se bavili, využil jsem jej u pochodně i křesadla. Nyní jsem předefinoval sekeru a příkaz rozbij sekerou kouli i naopak už parádně funguje. Všechnu naši konverzaci mám uloženou, jak vidno, je nejvyšší čas vypíchnout z ní zajímavé dotazy a odpovědi a vše si vytisknout stejně jako Tvůj manuál a Learning T3, udělám to hned.

5. Jehla
Ano, moje action překrývá standardních chování, já chci, aby stará jehla zmizela a objevila se nová otrávená, kterou hráč musí sebrat. Pokud bych chtěl jehlu nechat v inventáři, vymažu řádky jehla.moveInto(nil), otravena_jehla.discover(); a zavolám inherited pro zdědění standardního chování, jasné.

Nebudu tedy spěchat, ještě si pohraju s drakem a pořádně nastuduji konverzaci s NPC. Dál bych si rád zprovoznil lokální webový server, konečně jsem i v Archu zprovoznil QTADS, stabilní verze s novějším kompilátorem mi nechodí, ale ta z gitu ano, přidám si jeho volání do Creatoru tak jak popisuješ. Díval jsem se na sebové hraní, manuál popisuje umístění binárního t3 souboru nejprve na IFArchive, nalezl jsem odkaz:

https://www.ifarchive.org/cgi-bin/upload.py

a následně prolinkování v mém profilu na IFDB, který jsem si vytvořil. To bude paráda, čeká mě doladění draka a psa, slovníky, překlepy, intro, možná malá nápověda apod., ale také bych rád doplnil komentáře tak jako to máš u Základny. Nakonec si vše rozběhám na lokálním webu a poté vložím do IFArchivu, při tom mohu tvořit nejprve kostru nové hry, ostatně jak píšeš v Tipech pro tvorbu vlastní hry, musím si připravit osnovu a strukturu příběhu a na to si některý ten pátek nechat, to nelze uspěchat. 
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: gaspoda 8. Prosinec 2017 - 21:00
1. Dračí hlavy a verify
...v mém případě je ideální kombinace prázdného verify, které nepřetěžuji, hlavní podmínku, aby byl drak po smrti, kontroluje check a řezat mohu pouze objekty, které to mají povolené pomocí metody iobjFor(CutWith). Zavolal jsem inherited pro volání zdědeného chování a po projití všech těchto kontrol může action() vykonat to, co má.

Jen ještě poznámka k tomu minulému, narážel jsem na to, že ve verify se nikdy nesmí zobrazovat žádný text napřímo, veškerá odmítnutí se provádjí jen přes volání některého illogical makra.

Tady ale přeci nemohu nechat draka jen tak, když mu useknu hlavy, musí se objevit jeho bezhlavá mrtvola, která samozřejmě bude mít atribut Immovable se všemi náležitostmi, na které jsi mě upozornil minule, už je to zařízeno.

Také se dá použít např. jednoduše Heavy, pokud bys nechtěl se psát s těmi cannotTakeMsg.

Takže jsem to vyřešil jednoduše, manipulace drakem = manipulace dračíma hlavama, drak po uříznutí hlav stejně zmizí, takže vše funguje jak má:

      gcName = 'spící drak, spícímu drakovi, spící drak, spícímu drakovi, spícím drakem, dračí hlava, dračím hlavám, dračí hlava, dračím hlavám, dračíma hlavama'
      gcVocab = 'spícímu spícím spícího dračím dračíma dračí drakovi/drakem/draka/hlavám/hlavama/hlavy'

V gcName bys neměl kombinovat dva objekty, je třeba zadat právě šest pádů oddělených čárkou, na nic dalšího nebude brán zřetel. Lepší bude hlavy udělat jako samostatný objekt třídy Component a pomocí kontejnerové hierarchie je dát do draka, čili použít u hlav o jedno plus více, než u draka.

Tímle malým trikem jsem vše vyřešil, jen příkaz:
>uřízni dračí hlavy

Spícím drakem nic nepřeřízneš.
// to chápu, zde parser myslí, že chci něco přeříznout drakem

Protože to je uřízni co čím, tak se slovo dračí pochopí jako co budeš řezat a slovo hlavy jako čím budeš řezat. Asi. Protože v TADSu je jen akce CutWith, co chce dva objekty a ne Cut s jedním objektem. Hm, musel bych to víc prozkoumat. Někdy to definování akcí může být trochu neprakticky složité a pro jednorázové výjimky pak mlže být praktičtější využít String PreParser, jak jsem naznačoval myslím v posledním článku.

Zde mě tedy jako řešení napadá definovat draka jako kontejner podobně jako u strážce, zde ale pravděpodobně také narazím, protože dračí hlavy nemohou jen tak vypadnout z draka po jeho smrti. Druhá možnost je ta, že draka definuji jako dva samostatné objekty např. „dračí hlavy“ a „drak“, pamatuji si, že něco podobného jsem viděl v Erikově manuálu u příkladu s třídou Attachable – jednalo se o kostičky různých barev, které se na sebe skládají jako lego, juknu na ně a zkusím vymyslet vhodnější řešení.

Já bych asi useknuté hlavy definoval jako samostatný objekt, který se v místnosti objeví po té, co draka zabiješ. Attachable bych se asi vyhnul, to je v tomto případě kanón na vrabce.

Systém rozhovorů bude nebude tedy o mnoho jednodušší, než akce, ufff, možnosti krásné, ale za jakou cenu.

Za cenu, že bude tvůj mozek trochu zavařenější a z uší budou stoupat obláčky páry - já jsem ochotný to risknout :-) Možnosti rozhovorů jsou dost rozsáhlé, takže bude chvíli trvat, než všechny části pochopíš, ale zase na druhou stranu si z velké části vystačíš s deklarativním přístupem, nebudeš muset psát skoro žádné příkazy, jen definuješ hodnoty vlastností.

V Learning T3 je poměrně jednoduchý příklad na straně 220, jen u mě bude jeho použití náročnější, protože postřebuji psa, který si vezme otrávené dračí hlavy, zabít. Nejvhodnější mi přijde definice:

+ GiveTopic
     matchObj = draci_hlavy
    topicResponse()
    {
      "Pes se lačně vrhl na otrávené dračí hlavy. Na jeho předsmrtnou agánii nebyl pěkný pohled. ";
      draci_hlavy.moveInto(nil);
      setCurState(pesDeadState);
    }
;

která ovšem vylučuje použití canObjReachSelf(obj), canObjReachContents(obj) a cannotReachFromOutsideMsg(dest), debugger v takovém případě píše, že „The symbol "canObjReachSelf" is already defined“ a u ostatních rovněž.

Na to b téma konverzace stejně nereagovalo, aktivita témat se řeší jinak, viz níže. Ale uvedenou chybu to hlásí asi proto, že jsi udělal nějakou jinou chybu, kterou teď přímo nevidím, možná jsi měl objekt ukončený středníkem a ty canObj... za ním.

Pokud tyto tři direktivy vymažu, kompilace proběhne, ale pes o dračí hlavy nejeví zájem „Obrovský pes vypadáš nezaujatě.“.

Musíš dodržet správnou kontejnerovou hierarchii. Máš místnost a v ní je pes. Tedy před psem máš jedno znaménko plus, což psa umisťuje do místnosti, před kterou znaménko plus není. A podle stejné logiky musíš pokračovat dál - téma konverzace potřebuješ umístit do postavy. Tedy musíš mu dát dvě znaménka plus, ale ty tam máš jen jedno. Když dáš jedno, je téma umístěno v místnosti vedle psa, ale tam nijak nereaguje. (A co hůř, rozbil sis tím navíc i stavy psa, protože ty jsou teď umístěné nikoliv ve psovi, ale v GiveTopicu.)

Kód: [Vybrat]
podzemi: Room 'Podzemí' 'do podzemí';
+ pes : UntakeableActor 'obrovský pes' 'obrovský pes' *1;
++ GiveTopic;

Potom by se to mělo ještě trochu vylepšit, to téma totiž bude fungovat i po smrti psa, což není správné. Ty bys chtěl, aby fungovalo, jen dokud je pes živý. Mohl bys do tématu přidat vlastnost isActive = pes.curState == pesGuardState, ale ještě lepší a elegantnější řešení bude GiveTopic dát rovnou do toho stavu, ve kterém má být aktivní a tím pádem pak ve stavu mrtvoly vůbec aktivní nebude:

Kód: [Vybrat]
podzemi: Room 'Podzemí' 'do podzemí';
+ pes : UntakeableActor 'obrovský pes' 'obrovský pes' *1;
++ pesGuardState: HermitActorState;
+++ GiveTopic;
++ pesDeadState: HermitActorState;

No a nakonec to bude chtít vyřešit ještě jeden problém a sice že HermitActorState má za úkol, aby postava na žádné konverzace nereagovala. Bude potřeba to změnit na normální ActorState a asi pak přidat DefaultAnyTopic, který bude reagovat na všechny jiné konverzační příazy, než ten GiveTopic.
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: Kroužící orel 11. Prosinec 2017 - 12:53
Dračí hlavy a CutWith:

Ano, já jsem se opravdu snažil do verify přímo vkládat text, což není dovolené, v Library vždy vidím definici makra illogical, kterou se budu řídit. Zkusil jsem definovat mrtvolu draka jako Heavy, paráda, vše funguje tak jak má, mohu tedy využít Immovable s cannotXXXMsg zprávami nebo Heavy, to je přesně ten typ komentáře, který chci vložit do zdrojového kódu, poznačit si, že jsou zde 2 způsoby. Podobně budu postupovat i u dalších objektů a metod, moc se mi líbí komentáře u Základny a rád bych nejen pro sebe něco podobného vytvořil i u Exotera.

Hm, definovat v gcName dva objekty je nesmysl, já jsem si to také myslel, jen jsem zatím neviděl jiné řešení.
Zkoušel jsem v historii naší komunikace dohledat zmínku o String PreParser, nebyl jsem úspěšný, používáš jej v Základně u componentPreparser.t a roomAlien.t pro to, aby parser poznal znaky obsahující číslici zadanou od hráče společně s textovým řetězcem s nebo bez mezer, jinde jsem se s ním opravdu nesetkal.

Ale je mi jasné, že definice akce CutWith počítá se dvěma objekty, proto získávám odpověď „Spícím drakem nic nepřeřízneš.“. Attachable určitě využívat nebudu, jen jsem si vzpoměl na tam uvedený příklad s kostičky lega, který bych rád využit v kombinaci drak – mrtvý drak – dračí hlavy.

Stále si mi však nedaří akci s CutWith zdárně doknočit. Spící drak má jediné +, rozumím, že hlavy by měly být definované jako komponenta uvnitř draka, takže definuji:

++ draci_hlavy : Hidden, Component
++ drak_bez_hlavy : Hidden, Immovable

Akci CutWith jsem zkoušel definovat jak u spícího draka, tak u sebe:
    dobjFor(CutWith)
    {
        preCond = []
              verify() {}

            check()
            {
                        if (gIobj != sekera)
                        failCheck('To bude chtít něco jiného. ');
            }

                action()   

                {
                        "Odsekl jsi dračí hlavy od těla. ";
                        spici_drak.moveInto(nil);
              drak_bez_hlavy.discover();
                        draci_hlavy.moveInto(me);
                }
    }

Plus testuji příkaz draci_hlavy.moveInto(me); stejně jako využíváš objekt Syringe u základny, aby se vrátil do hráčová inventáře, po vykonání ovšem získávám:

>prozkoumej hlavy
Dokud byly živé, vypadaly hrozivě.

>vezmi hlavy
Nemůžeš ji vzít, protože je součástí tebe.

>polož hlavy
Hlavy je součástí tebe.

Dračí hlavy definované jako Component hlásí po sebrání hlášky typu „nemůžeš je sebrat, protože jsou součástí místnoti/draka“ a draci_hlavy.moveInto(me).

Tady opravdu metodu dobjFor(CutWith) nechápu, asi potřebuji reálný příklad, hledal jsem ve zdrojácích TADS her, které zde mám fulltextem, Základna, Heidi, Tell, Cloak_of_Darkness, Return to Ditch Day, The Elysium Enigma, The Plant, nikdo řezání něčeho něčím nevyužívá a ani s iobjFor(CutWith) to není jiné, opravdu zvláštní.
Našel jsem jen:

http://tads3.gerynarsabode.org/index.php?title=Fuses_Example_Game&action=edit

zde je příklad s drátem, jehož definice není zrovna to, co potřebuji

a

http://users.ox.ac.uk/~manc0049/TADSGuide/trollbridge2.htm

využívající adv3lite, což nemohu použít.

Koukám na čas, tímhle se trápím už přes 4 hodiny, ufff, musím na vzduch si vydechnout, nabrat síly a zařídit dětské akce. Jestli budeš mít čas a chuť na to juknout, můžeš využít minulý transkript a aktuální zdroják zasílám v příloze. Večer nebo zítra juknu na ty konverzace u psa a dám vědět jak dopadly.
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: Kroužící orel 15. Prosinec 2017 - 10:11
Rozhovory a GiveTopic

Ještě jsem si trochu hrál s řezáním hlav a zatím se dál nemohu dostat, nevadí, nyní to nechám být a hlavy dočasně upravím tak, aby je bylo možné bez potíží sebrat a než mě napadnou další možnosti, dám si „rozhovor“ se psem.

Vrhnul jsem se na velké téma rozhovory, jen ať mi ze škeble kouří jako z toho milíře u Heidi, určitě za to budou stát. Díky těm navrhnutým tématům a možnostem zeptat se na něco jiného hra vypadá mnohem realističtěji, všiml jsem si, že pár her, které zde mám i se zdrojáky, jsou právě rozhovorem zakončeny. Tady bude obrovská možnost hru notně oživit, u Základny i Heidi jsou parádní příklady, které využiji při další tvorbě.

Zkoušel jsem si ještě před změnami u rozhovoru pohrát s chybou u třech "can", která vypisovala „The symbol "canObjReachSelf" is already defined“, skutečně se jednalo jen o středník navíc, který jsem měl umístěný po řádku

+ GiveTopic @draci_hlavy

Chybu už vidím, středník zde opravdu nesmí být, ani např. po tom pro mě zatím oříšku dobjFor(CutWith) u draka není, sakra, na ty středníky musím dát bacha, parser poté celou definici chápe ouplně jinak.

Ano, také u rozhovorů musím dodržet hierarchii kontejnerů, jdu to upravit. Mám zde místnost a objekt psa s jedním znaménkem, OK. Aha, pokud v tomto případě dám jediné plus do téma konverzace, je toto umístěno v místnosti a já tedy komunikuji s místností… jasně, tam tedy musí být znaménka dvě. Hmm, teď po vymazání středníku u GiveTopis vidím, že stavy psa by v případě jediného plus byly na něj navázány, to samozřejmě nechci. Hmm, teď už mi rozhovory konečně začínají zacvakávat a chápu, že není tak špatný nápad je u GiveTo používat, jsou krásně zapasované do objektu NPC a ty zase díky kontejnerové hierarchii do místností, což obstarává objektový model, tady asi zatím nejlépe vidím jeho výhodu – jo, právě čtu ve Tvém manuálu, že někteří autoři textovek uváděli zbytečnost kontejnerové hierarchie a zde konečně v praxi vidím opak, super, přesně to jsem potřeboval.

Vyzkoušel jsem první způsob s isActive:

++ GiveTopic
     isActive = pes.curState == pesGuardState
     matchObj = draci_hlavy
    topicResponse()
    {
      "Pes se lačně vrhl na otrávené dračí hlavy. Na jeho předsmrtnou agánii nebyl pěkný pohled. ";
      draci_hlavy.moveInto(nil);
      setCurState(pesDeadState);
    }


canObjReachSelf(obj) { return curState != pesDeadState; }
canObjReachContents(obj) { return curState != pesDeadState; }
cannotReachFromOutsideMsg(dest) { return 'Nepřipadá Ti vhodné dotýkat se psí mrtvoly!'; }
;

++ pesGuardState: HermitActorState
    noResponse = "Vrčí na Tebe a viditelně Tě nechce pustit dál. "
    stateDesc = "Vrčí na Tebe a viditelně Tě nechce pustit dál. "
    isInitState = true
;

++ pesDeadState: HermitActorState
noResponse = "Je mrtvý a už se nehýbe. "
specialDesc = "Pes leží mrtvý na podlaze. "
stateDesc = "Pes je mrtvý. "
;


nebo druhý, kde je pouze pozměněn ++ GiveTopic @draci_hlavy


a zatím získávám stále hlášku:

>dej hlavy psovi
Vrčí na Tebe a viditelně Tě nechce pustit dál.

>dej psovi hlavy
Vrčí na Tebe a viditelně Tě nechce pustit dál.


Nyní zkouším odstranit HermitActorState z PesGuardState, potřebuji, aby pes reagoval na konverzaci. Kód vypadá takto:


+ pes : UntakeableActor 'obrovský pes' 'obrovský pes' *1
      "Vidíš mu na očích, že kromě lidského masa k smrti miluje dračí hlavy. "
     
      gcName = 'obrovský pes, obrovskému psovi, obrovský pes, obrovském psovi, obrovským psem'
      gcVocab = 'obrovskému obrovským obrovského psovi/psem/psa'

      allowAttack = nil

canObjReachSelf(obj) { return curState != pesDeadState; }
canObjReachContents(obj) { return curState != pesDeadState; }
cannotReachFromOutsideMsg(dest) { return 'Nepřipadá Ti vhodné dotýkat se psí mrtvoly!'; }
;

++ pesGuardState: ActorState
    noResponse = "Vrčí na Tebe a viditelně Tě nechce pustit dál. "
    stateDesc = "Vrčí na Tebe a viditelně Tě nechce pustit dál. "
    isInitState = true
;

+++ GiveTopic
     matchObj = draci_hlavy
//     isActive = pes.curState == pesGuardState
    topicResponse()
    {
      "Pes se lačně vrhl na otrávené dračí hlavy. Na jeho předsmrtnou agánii nebyl pěkný pohled. ";
      draci_hlavy.moveInto(nil);
      setCurState(pesDeadState);
    }
;

++ pesDeadState: HermitActorState
noResponse = "Je mrtvý a už se nehýbe. "
specialDesc = "Pes leží mrtvý na podlaze. "
stateDesc = "Pes je mrtvý. "
;

Po nabídnutí dračích hlav se objeví správné hlášení „Pes se lačně vrhl na otrávené dračí hlavy. Na jeho předsmrtnou agánii nebyl pěkný pohled.“, ale stále žije i přes direktivu setCurState(pesDeadState) nebo pes.curState == pesDeadState uvnitř topicResponse(). Překladač ovšem chybu nevyhodí, vypadá to, že jí v topic nebudu moci využít. Zkusil jsem si přidat:

+++ DefaultAnyTopic
    "<.p>Pes nereaguje. "

    deferToEntry(entry) { return !entry.ofKind(DefaultTopic); }
;

který správně funguje, pokud chci psovi dát něco jiného, než dračí hlavy.

Napadlo mě ještě jedno řešení, přidal jsem objekt mrtvolu psa do GiveTopic direktivy pes.moveInto(nil) a mrtvola_psa.discover(). Nyní je vše OK, jen mě pes stále zabíjí vzhledem k definované TravelMessage v místnosti. Tu samozřejmě mohu změnit, není zde nějaký elegantnější způsob, jak mrtvolu psa ponechat v místnosti a moci odejít na východ?

Uff, podle zdrojáků mi vše přijde OK, tady se asi snažím o něco, co GiveTopic nedovoluje. Ještě počkám na Tvůj názor, pokud to jinak nepůjde, upravím  TravelMessage a nechám psa být, vše zasílám v příloze včetně transkriptu. Nečekal jsem, že se tak seknu u draka i psa, když se dívám na Tvá kouzla v Základně, které parádně komentuješ, ale samozřejmě mi často nejsou jasné, kdo ví, kdy e k jejich pochopení dostanu, to ale určitě časem.

Až budeš mít chvilku, prosím koukni na zdroják a pokud to půjde také na to useknutí dračí hlavy. Je tu ještě spousta věcí k doladění, to ale k programování patří, tuším, že ten TADS nebude o moc jednodušší, než klasické C++…

Krásný víkend přeje
Orel
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: gaspoda 15. Prosinec 2017 - 19:35
++ GiveTopic
     isActive = pes.curState == pesGuardState
     matchObj = draci_hlavy
    topicResponse()
    {
      "Pes se lačně vrhl na otrávené dračí hlavy. Na jeho předsmrtnou agánii nebyl pěkný pohled. ";
      draci_hlavy.moveInto(nil);
      setCurState(pesDeadState);
    }

canObjReachSelf(obj) { return curState != pesDeadState; }
canObjReachContents(obj) { return curState != pesDeadState; }
cannotReachFromOutsideMsg(dest) { return 'Nepřipadá Ti vhodné dotýkat se psí mrtvoly!'; }
;

No zde by to opět chtělo pes.setCurState(pesDeadState); jak jsme o tom už mluvili, to všechny další problémy vyřeší. Je to pes, jehož stav chceš změnit. Měnit stav můžeš u objektu nějaké postavy. Topic, i když je připojený k postavě, tak nemá takovou metodu.

Jo a canNěco metody na Topicu nemají žádnou funkci, ty mají roli jen u objektů dědících z OutOfReach.

Nyní zkouším odstranit HermitActorState z PesGuardState, potřebuji, aby pes reagoval na konverzaci. Kód vypadá takto:

+ pes : UntakeableActor 'obrovský pes' 'obrovský pes' *1
      "Vidíš mu na očích, že kromě lidského masa k smrti miluje dračí hlavy. "
     
      gcName = 'obrovský pes, obrovskému psovi, obrovský pes, obrovském psovi, obrovským psem'
      gcVocab = 'obrovskému obrovským obrovského psovi/psem/psa'

      allowAttack = nil

canObjReachSelf(obj) { return curState != pesDeadState; }
canObjReachContents(obj) { return curState != pesDeadState; }
cannotReachFromOutsideMsg(dest) { return 'Nepřipadá Ti vhodné dotýkat se psí mrtvoly!'; }
;

++ pesGuardState: ActorState
    noResponse = "Vrčí na Tebe a viditelně Tě nechce pustit dál. "
    stateDesc = "Vrčí na Tebe a viditelně Tě nechce pustit dál. "
    isInitState = true
;

Pokud už to není HermitActorState, tak noResponse je zbytečné, už nemá žádnou funkci. Navíc opět canNěco metody nemají funkci, protože jsi nepřidal OutOfReach do seznamu tříd, ze kterých objekt dědí. Zde to možné je na rozdíl od Topicu výše, který není fyzicky viditelným objektem v rámci světa.

Napadlo mě ještě jedno řešení, přidal jsem objekt mrtvolu psa do GiveTopic direktivy pes.moveInto(nil) a mrtvola_psa.discover(). Nyní je vše OK, jen mě pes stále zabíjí vzhledem k definované TravelMessage v místnosti. Tu samozřejmě mohu změnit, není zde nějaký elegantnější způsob, jak mrtvolu psa ponechat v místnosti a moci odejít na východ?

Jasně, můžeš psa vyměnit za mrtvolu. To může být někdy i výhodné, protože třeba právě mrtvola má ve slovníku slovo "mrtvolu", takže reaguje na prozkoumej mrtvolu. Pokud to uděláš, tak pak podmínka v canTravellerPass může být formulována třeba jako { return !pes.location; } tedy jinými slovy pokud pes byl přemístěn do nil, tak může projít. Pak jsou i jiné možnosti, můžeš si sám pomocí gReveal('pes-mrtvy'); označit, že pes je už kaput a pak se na to ptát { return gRevealed('pes-mrtvy'); } v canTravellerPass.
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: gaspoda 15. Prosinec 2017 - 20:12
Zkoušel jsem v historii naší komunikace dohledat zmínku o String PreParser, nebyl jsem úspěšný, používáš jej v Základně u componentPreparser.t a roomAlien.t pro to, aby parser poznal znaky obsahující číslici zadanou od hráče společně s textovým řetězcem s nebo bez mezer, jinde jsem se s ním opravdu nesetkal.

StringPreParser je zmíněn v kapitole o akcích mého seriálu http://www.textovky.cz/clanky/programovani-textovych-her-v-tads-3-cast-5-akce/ (http://www.textovky.cz/clanky/programovani-textovych-her-v-tads-3-cast-5-akce/) jako možné řešení pro obejití některých složitých situací, které parser chápe špatně.

Plus testuji příkaz draci_hlavy.moveInto(me); stejně jako využíváš objekt Syringe u základny, aby se vrátil do hráčová inventáře, po vykonání ovšem získávám:

>vezmi hlavy
Nemůžeš ji vzít, protože je součástí tebe.

Jako Component by měly být hlavy jen u živého draka. Jakmile je vyměníš za mrtvolu draka, tak odseknuté hlavy musejí být samostatným objekt, prostě Thing, který se dá sebrat. To je právě smysl třídy Component, aby objekt nešel samostatně sebrat a byl považován za součást toho, v čem je pomocí kontejnerové hierarchie umístěn. Tak např. když mám v základně běžecký pás, jehož součástí je ovládací pultík a součástí pultíku je ovládací knoflík, tak je to nějak takhle:

Kód: [Vybrat]
+ treadmill: Platform, Heavy, OnOffControl 'posuvný běžecký pás' 'běžecký pás' *2;
++ Component 'přítlačné popruhy' 'přítlačné popruhy' *2;
++ treadmillPanel: Component 'ovládací pultík (s) pultík/ovládání/ovládáním' 'pultík s ovládáním' *2;
+++ Component 'počítadlo uběhnuté vzdálenosti/počítadlo' 'počítadlo' *4;
+++ treadmillDial: NumberedDial, Component, OnOffControl 'otočný regulátor' 'regulátor' *2;

A díky tomu, když řekneš seber počítadlo, tak dostaneš odpověď, že to nemůžeš, protože počítadlo je součástí pultíku. Problém tedy v tomto případě není s akcí CutWith, ale s hlavou samotnou.

Tady opravdu metodu dobjFor(CutWith) nechápu, asi potřebuji reálný příklad, hledal jsem ve zdrojácích TADS her, které zde mám fulltextem, Základna, Heidi, Tell, Cloak_of_Darkness, Return to Ditch Day, The Elysium Enigma, The Plant, nikdo řezání něčeho něčím nevyužívá a ani s iobjFor(CutWith) to není jiné, opravdu zvláštní.

Jen čistě ze zvědavosti, Elysium Enigma pokud vím, tak nemá publikované zdrojáky, nepřeřekl ses? Ještě se dají najít zdrojáky k All Hope Abandon a Mrs. Pepper's Nasty Secret.

Koukám na čas, tímhle se trápím už přes 4 hodiny, ufff, musím na vzduch si vydechnout, nabrat síly a zařídit dětské akce. Jestli budeš mít čas a chuť na to juknout, můžeš využít minulý transkript a aktuální zdroják zasílám v příloze. Večer nebo zítra juknu na ty konverzace u psa a dám vědět jak dopadly.
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: Kroužící orel 19. Prosinec 2017 - 17:28
1. Pes
Tak konečně se zase dostávám k tvorbě, mám za sebou Ubuntí školení a už se těším na TADS. Já jsem fakt škeble dubová, nastavit

pes.setCurState(pesDeadState);

mě neťuklo, hmm, nerozpoznal jsem, že u Topicu není metoda změnit stav, na kterou jsem zvyklý u postav. Metody canObjxxx mám nyní umístěné u objektu psa, píšeš, že mají smysl pouze u objektů, které dědí z mix-in OutOfReach, jasné, už se na ní koukám do Library a zkoumám dědičnost.

Direktivu noResponse jsem vymazal, ano, mám GuardState nastaven jako ActorState, aby bylo možné se psem komunikovat. U psa jsem také doplnil OutOfReach stejně jako u strážce, už se koukám na naší starší konverzaci, kde mi toto doporučuješ u draka i psa – sakra, u draka jsem na tuto definici nezapomněl, už ani nevím, proč jsem jí nevyužil také u psa.

Výborně, řešení s mrtvolou psa mi také přijde ideální podobně jako u strážce, možnost reakce hráče na slovo mrtvola se určitě hodí. Takže zde ponechám objekt mrtvola_psa. Otestoval jsem si

{return !pes.location; }

v canTravelerPass a funguje stejně dobře jako moje stávající definice

{return pes.curState == pesDeadState; }

viz aktuální zdroják. Definici gReveal jak vidno hojně využíváš v Základně, použití v kombinaci s isInInitState v roomTunnel.t je dost výmluvné a u pronásledovatelů v canTravelerPass stejné jak nyní popisuješ, paráda.

Psa jsem si ještě označil jako PreferredIobj, aby správně fungoval příkaz „dej hlavy psovi“ i „dej psovi hlavy“, ještě musím doladit „dej sekeru psovi“, který vyhazuje „Nemůžeš sekeře nic dát.“, „dej psovi sekeru“ je OK – zde se pokusím o jiné řešení.
Nyní je tedy vše se psem celkem v pořádku a já si uvědomuji zase další souvislosti plus mám parádně vysvětlený příklad, který využiji i v budoucnu.

2. StringPreParser
Hm, na toto řešení jsem nějak zapomněl, i když jsem Tvůj manuál přečetl několikrát. Vidím jej u podkapitole Předzpracování příkazů, velmi zajímavé, přesně toto bych v budoucnu potřeboval od testerů, zjistit příkazy, které by mě třeba nenapadly a Ty jsi samozřejmě postupoval stejně, "zapni zápis" a případné komentáře po zadání hvězdičky si moc dobře pamatuji. Zrovna zde vidím příklad, já bych např. u psa vždy zadal „dej hlavy“ a parser si sám doplní komu, nenapadlo by mě využít slovo podej, které další člověk ale třeba využije. A jak perfektně uvádíš, potřebuji přepsat hráčem zadaný příkaz ještě dříve, než se k němu dostane parser, tohle v budoucnu určitě využiji, třeba i u nápovědy pro hráče podobně jako v Základně.

3. Zapeklité dračí hlavy
Ano, zase jsem u kontejnerové hierarchie a tentokrát přidáváme Component. Udělal jsem jak radíš a výsledek se konečně dostavil, po zabití draka se nestane nic, protože hlavy už jsou s ním v místnosti a hráč to z popisu draka může zjistit, po zabití draka je možné tyto uříznout a následně mrtvola draka a původní dračí hlavy zmizí a objeví se useknuté dračí hlavy s bezhlavým drakem, podobně jsem situaci řešil u strážce, jen bez Component. Uff, to mi teda dalo práce, ale díky Tvým radám jsem zase dál, hurá.

4. Zdrojáky dalších TADS her
Moc se omlouvám za nepřesnost, ke hře Elysium Enigma opravdu zdrojáky nemám, jen jsem při spuštěném fulltextu hledal i tam a nevšimnul si, že mám pouze t3 soubor. All Hope Abandon a Mrs. Pepper's Nasty Secret jsem si už stáhnul a pořádně prozkoumám, sakra, to už je let ten FbeginnersComp 2008…

5. Algoritmus
Už nějaký čas bych se rád zeptal na algoritmus v programování v podání zkušeného programátora. Vím, že je to vlastně kuchařka, kterou si v hlavě nebo v podobě nějakých postupů či diagramů připravím a dle nich poté zapisuji kód pomocí programovacího jazyka. Existují i knihy věnující se pouze algoritmizaci, jak bychom mohli nejlépe definovat algoritmus v TADSu – v tomto případě se jedná o definici místností, kontejnerové hierarchie a akcí, kterou poté pomocí jazyka implementuji do hry? Nevím, zda se nejedná o hloupou otázku, když už se programováním konečně prokousávám, rád bych se ujistil i v tomto.

6. Závěr hry
Je to neuvěřitelné, ale hra je nyní nahrubo hotová a dohratelná. Ještě, než si zprovozním lokální webový server, kde hru otestuji a vložím do IFDB je ale nutné, abych doladil především gramatické chyby, na které reaguje parser a věci, které zbytečně hru kazí, pro zajímavost zasílám v příloze s aktuálním zdrojákem a transkriptem. Na tyto se zaměřím nyní, věřím, že pomocí dosavadních zkušeností, Tvého překladu a Základny je vyřeším. Poté upravím zdrojový kód tak, aby vše bylo čitelné a sjednotím styl syntaxe plus doplním dokumentaci, která bude lépe vysvětlovat jednotlivé kroky.

Některé akce bych měl barevně nebo jiným písmem zvýraznit, např. informaci o pádu do kupky sena by si nepozorný hráč nemusel všimnout:

Vidis tu truhlu.
>d
Spadl jsi primo doprostred kupky sena, ktera idealne ztlumila tvuj pad.

Severovychodni cast nadvori
Stojis v tmavem koute nadvori. Na severu se do vysky nekolika metru tyci
kamenna vez.

Zkusím něco vymyslet, ideálně vhodného pro řádkového klienta i qtads dohromady plus časem pro webovou hru, to uvádíš i ve svém manuálu.

Jsem strašně rád, že jsem vytrval, hlavně, žes mě furt držel, protože jako neprogramátor musím být hrozný žák… Většinu naučených konstrukcí určitě využiji při další tvorbě a Library mi stále více leze pod kůži, což je paráda. S C++ ještě moment počkám, nejprve vše dokončím a pomocí QT Creatoru vytvořím hru novou, tím si znalosti upevním a učit se dalšímu jazku bude mnohem snažší.
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: gaspoda 20. Prosinec 2017 - 11:51
1. Pes
hmm, nerozpoznal jsem, že u Topicu není metoda změnit stav, na kterou jsem zvyklý u postav.

Jeden fyzický objekt ve hře, jako třeba postava, se může skládat z několika programových objektů, jako třeba samotný actor, jeho jednotlivé stavy, téma konverzace. Když chceš měnit stav, tak to musíš dělat se správným objektem, tedy s postavou a ne s tématem. Je to podobné, jako když se Lego autíčko skládá z několika dílků zacvaknutých do sebe. Když chceš něčím otáčet, tak můžeš otáčet kolečkama, ale ne blatníkem. Každá kostička má svůj jasně daný účel a možnosti manipulace.

Metody canObjxxx mám nyní umístěné u objektu psa, píšeš, že mají smysl pouze u objektů, které dědí z mix-in OutOfReach, jasné, už se na ní koukám do Library a zkoumám dědičnost.

OutOfReach žádnou knihovní dědičnost nemá, jde o to, jaký svůj objekt od ní podědíš ty. Když bych se podržel příkladů s kostičkama stavebnice, tak ty si tvoříš svojí kostičku tím, že dědíš od různých tříd a to pak dává kostičce různé vlastnosti, jako třeba barva, velikost atp. Třeba budu hledat červenou kostičku velikosti 2x1. Najdu ji a teď si vzpomenu fajn, ale já ještě chci, aby měla díru. To, že přidáš nějakou třídu je jako když přidáš nějakou vlastnost. Najdu tedy kostičku s dírou a můžu protáhnout hřídelku. Mít objekt bez třídy OutOfReach je jako mít kostičku bez díry, tedy nemá cenu snažit se protáhnout hřídelku / nemá cenu psát vlastnosti canNěco, nemají žádnou funkci.

Psa jsem si ještě označil jako PreferredIobj, aby správně fungoval příkaz „dej hlavy psovi“ i „dej psovi hlavy“, ještě musím doladit „dej sekeru psovi“, který vyhazuje „Nemůžeš sekeře nic dát.“, „dej psovi sekeru“ je OK – zde se pokusím o jiné řešení.

První by mělo fungovat samo, protože u všech konverzačních akcí je automaticky každá postava označena jako preferovaný iobj už v knihovně. (Podobně je u akce prostrč objekt jiným objektem označeno, že NonPortable objekt je ten, skrz který se protlačuje.) Třída PreferredIobj je určená k využití jen u těch akcí, u kterých to nejde takhle předvídat dopředu.

Ve druhé situaci se jedná o konflikt, protože sekera je už z důvodu využití v jiné akci označená jako PreferredIobj a to je pak nevhodné v konverzačních akcích, kde postava má být iobj, tudíž se to pere mezi sebou - máme dva objekty a oba mají nastveno, že jsou iobj. Jedna možnost, jak to řešit je nenastavit sekeru jako PreferredIobj a místo toho nastavit ten druhý objekt v té druhé akci se sekerou jako PreferredDobj. Nevím, co to je za akci, sekání hlav? Pak sekaným hlaván nastavit PreferredDobj.

Úplně obecné řešení jsem rozebíral s Tekketem na pomezí mezi druhou a třetí stránkou této diskuse.

5. Algoritmus
Už nějaký čas bych se rád zeptal na algoritmus v programování v podání zkušeného programátora. Vím, že je to vlastně kuchařka, kterou si v hlavě nebo v podobě nějakých postupů či diagramů připravím a dle nich poté zapisuji kód pomocí programovacího jazyka. Existují i knihy věnující se pouze algoritmizaci, jak bychom mohli nejlépe definovat algoritmus v TADSu – v tomto případě se jedná o definici místností, kontejnerové hierarchie a akcí, kterou poté pomocí jazyka implementuji do hry? Nevím, zda se nejedná o hloupou otázku, když už se programováním konečně prokousávám, rád bych se ujistil i v tomto.

Algoritmus je obecně postup vyřešení nějaké úlohy a vlastně není závislý na konkrétním programovacím jazyce. Když si představíš recept na jídlo v kuchařce, tak algoritmus je ten postup výroby - nejprve oddělíme žloutek od bílku, tohle přidáme do tohohle, mícháme dokud není taková konsistence, pečeme do růžova,... Pouhý výčet surovin v receptu ale algoritmem není, že potřebujeme dvě vajíčka a půl kilo mouky, to je deklarace, ne algoritmus. Algoritmus je postup řešení, to kde říkáš věci jako nejprve tohle, potom tohle. Dokud něco, tak dělej tohle apod.

Takže definice místností, hierarchie objektů, to jsou pouhé deklarace (a tyto deklarace jsou pak nějakým algoritmem v knihovně následně zpracovávány). Algoritmus je až to, kdy píšeš nějaké příkazy, které jsou vykonávány, tedy když píšeš příkazy v nějaké action() apod. A ačkoliv tedy deklarace dat není algoritmem, může být vymyšlení vhdného uspořádání dat kolikrát i důležitější, než vymyšlení algoritmu, který s nimi pracuje.

O algoritmech a algoritmizaci se má cenu bavit tehdy, když jde o nějaký netriviální postup, který lze dělat třeba různými způsoby, např. učebnicový problém je řazení podle velikosti. Mám řadu různě dlouhých tyček a chci je srovnat podle velikosti. Tak jdu z leva do prava a porovnám každé dvě sousední a pokud jsou v nesprávném pořadí, tak je prohodím. Tento celý postup zopakuji tolikrát, kolik je tyček a pak budou srovnané všechny. To je sice docela snadno pochopitelné, ale je to také jeden z nejpomalejších způsobů (Bubble Sort). Jsou i jiné způsoby, ale jejich pochopení je náročnější. Navíc neexistuje jediný správný a nejlepší způsob, trochu se to liší podle vstupních dat - jsou data úplně náhodná? Jsou už trochu srovnaná? Jsou mezi nimy stejné hodnoty, nebo je každá řazená hodnota jiná, než ostatní? https://www.youtube.com/watch?v=ZZuD6iUe3Pc

Algoritmizace je tedy o schopnosti vymýšlet postupy řešení úloh, schopnosti rozpoznat, že pro některý problém se hodí některý ze známých algoritmů a umět jim porozumět a správně vybrat, který je vhodnější v určité situaci, když je více možností.

6. Závěr hry
Některé akce bych měl barevně nebo jiným písmem zvýraznit, např. informaci o pádu do kupky sena by si nepozorný hráč nemusel všimnout:

Vidis tu truhlu.
>d
Spadl jsi primo doprostred kupky sena, ktera idealne ztlumila tvuj pad.

Severovychodni cast nadvori
Stojis v tmavem koute nadvori. Na severu se do vysky nekolika metru tyci
kamenna vez.

Zkusím něco vymyslet, ideálně vhodného pro řádkového klienta i qtads dohromady plus časem pro webovou hru, to uvádíš i ve svém manuálu.

Lze lecos, třeba i po zobrazení hlášky hru zapauzovat a pokračovat ve výpisu až po stisknutí klávesy, ale osobně to považjí spíše za kontraproduktivní, protože to narušuje plynulost čtení.
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: Kroužící orel 22. Prosinec 2017 - 11:18
1. Objekt v TADS
Hmm, velmi zajímavé a srozumitelné to srovnání s legem. To znamená, že vytvořím objekt ve hře, např. koně, který dědí z jedné nebo více tříd a zároveň obsahuje jak píšeš programové objekty, se kterými dále pracuji – tedy např. stav žije/nežije, mluvím s ním na téma/nekonverzuje. Ano, tady musím přesně určit, se kterým objektem chci pracovat, hmm, tohle hlavně u konverzace budu potřebovat. Teď mě napadá, že jsem se u Základny s takovým objektem a programovatelnými objekty setkal nejen u postav, ale také s trezorem, jeho číselníkem a jednotlivými stavy.

2. OutOfReach
Ještě jednou se dívám na její popis v knihovně, píší, že se jedná o mix-in třídu, kterou lze využít u vytvoření objektu a její obsah lze umístit do jeho vlastností – jo, to sedí s Tvým popisem kostiček lega, teď už mi konečně dává smysl, že v TADSu přidání třídy = přidání vlastnosti. Ale nakonec tak tomu bude i v ostatních OOP jazycích, vytvořený objekt má vícenásobnou dědičnost – i když v dokumentaci píšeš, že v TADSu je mnohem menší rozdíl mezi třídou a objektem, než např. v C++ nebo v Javě.
Jasné, proč bych deklaroval canObjReachSelf např. u draka, který by nedědil z OutOfReach, to by nedávalo smysl.

Jen tak mimochodem, na příkladu s kostičkami je mi tento a minulý příklad konečně jasný, kdyby to podobně psali autoři programátorských učebnic, vývojařina by pro mě a věřím, že nejen pro mě byla záživnější, výčet tříd a tvorba objektů na většinou školních příkladech s čísly, rovnicemi a obecně nějakými počty mi k pochopení zrovna nepřidává, Tebou popsané příklady mají hlavu a patu a jsou krásně srozumitelné, neuvažuješ o tvorbě nějaké učebnice? Myslím to vážně, ideálně určené starším dětěm nebo študentíkům např. ve stylu knihy Python for Kids.

3. PreferredIobj
Pro mě opravdu náročnějí definice na pochopení, ale o to důležitější, vzhledem k četnosti využítí jí musím dokonale pobrat. Máš recht, u psa PreferredIobj není třeba, teď jsem jej vymazal a pes je pouze OutOfReach a UntakeableActor, příkaz „dej hlavy psovi“ i „dej psovi hlavy“ funguje, sakra, teď tedy nevím, co jsem minule zkoušel. Ale je to dobře, alespoň budu vědět, že každá postava je automaticky označena jako PreferredIobj. Podíval jsem se do knihovny, kde se s PreferredIobj vůbec nesetkám a celý svůj TADS adresář jsem si tímto výrazem grepnul, používáš jej ve svém překladu, u Základny a já u Exoteru, ano, už si vzpomínám, že jsme se o něm a úpravou Dobj bavili v souvislosti s novou verzí češtiny.

Ano, také mě napadl konflikt, protože sekera se používá více, u zabití strážce, rozbití skleněné koule a sekání dračích hlav.
Diskuzi si právě procházím, sakra, doufám, že někdy vyjde ta hra s japonským nožem a liánou, kdyby byla v TADSu, nezlobil bych se… Vidím, že je to docela oříšek i pro Tebe, když si tyto situace řešil na fóru, překlad celkově určitě nebyl žádný med. Možnost ladění parseru vypadá také zajímavě, to ale minimálně u mě až někdy později. Tekket nůž s třídou PreferredIobj potřeboval použít jako dobj, to je i můj problém. Využij jsem Tebou doporučené řešení a odstranil PreferredIobj z objektu sekery, naopak přidal jsem PreferredDobj ke strážci, skleněné kouli i dračím hlavám. Nyní je v pořádku „zabij strážce sekerou“ i „zabij sekerou strážce“, „rozbij kouli sekerou“ i  „rozbij sekerou kouli“ a „uřízni dračí hlavy sekerou“ i „uřízni sekerou dračí hlavy“ bez problémů fungují a také „dej psovi sekeru“ a „dej sekeru psovi“.

Teď je mi také jasné, že u křesadla a pochodně budou stejné potíže, hned jsem to vyzkoušel a hnedle u zapálení samotné pochodně křesadlem a využití těchto předmětů u psa je to horší:

>zapal pochoden
Čím ji chceš zapálit?
>kresadlem
To není něco, co by mohlo hořet.

>zapal kresadlem pochoden
To není něco, co by mohlo hořet.

>zapal pochoden kresadlem
Zapaluješ pochodeň.

>dej pochoden psovi
Nemůžeš pochodeň nic dát.

>dej kresadlo psovi
Nemůžeš křesadlu nic dát.

Vše jsem vyřešil stejným způsobem, vše funguje krom:
>zapal pochodni seno
{Tím iobj} nemůžeš nic zapálit

Zkoušel jsem ke kupce sena dát dle diskuze s Tekketem direktivu:
preferredIobj = pochoden

ale zatím bez úspěchu, budu na tom ještě pracovat, PreferredDobj u pochodně potřebuji. Jak vidno, tyto předměty budu muset doladit – kombinace křesadlo, pochodeň, zapálení sena a správné hlášky, pokud tyto předměty chci umožnit ve hře cizí postavě dát, není zrovna triviální.

To nám to ale letí, diskuze s Tekketem z roku 2015 a za čtvrt roku to bude už rok, co jsem opravdu začal s TADSem, času ale rozhodně nelituji, teď zpětně vidím, že to byl dobrý tah a programování mě baví čím dál více. Vida jak se vyplatilo umět přehodnotit svůj postoj k tvorbě a nezabývat se jen příběhem. Tak nějak cítím, že dnes už jsou sice textovky na ústupu, tvořit je ale mohu vždy a i kdyby si je zahrál jen jediný člověk, má to smysl, stejně jako má stále smysl vydávat knihy i v dnešní době. A až doladím webový server, viz níže nebo hry jednoduše umístím na IF, není důvod bát se, že si jich nikdo nevšimne.

4. Algoritmus
Super srovnání s tou kuchařkou, deklaruji tedy objekty stejně jako suroviny a postup vaření je algoritmus – v mém případě akce, které s objekty provádím. Mám zde knížku Programování pro úplné začátečníky od Radka Hylmara, právě o BubleSort píše u porovnávání fotbalových hráčů. Mimochodem jeho styl mi také sedí, preferuje stále pro výuku Pascalu před Pythonem, neboť ten prý nemá datové typy, je to asi věc názoru, musím se ale přiznat, že dnešní objektový Pascal využívaný v na prvním pohled velmi zajímavém prostředí Lazarus se asi od toho původního pro prvotní výuku programování dost liší a také pro větší projekty se bude hodit. Díval jsem se na Lazarus, ten se velmi aktivně vyvíjí a vypadá zajímavě, jen pro něj zatím nemám využití - až zmáknu TADS, vrhnu se na C a C++, případný další Python nebo objektový Pascal už nebude takový problém a pokud k tomu přidám i využívané algoritmy, není co řešit.

Jasně, proto existují knihy o algoritmech, chápu to tak, že jich existuje větší množství už vymyšlených, programátor by je měl znát a v dané situaci se rozhodne jaký využít. I Radek Hylmar jich ve své knize pár doporučuje, až skáknu do Prahy, v Luxoru se na některé juknu, tohle budu v budoucnu určitě potřebovat.

Díky za video, Bubble Sort, Shell Sort, Quick Sort a ostatní prozkoumám a je zde krásně vidět jejich porovnání.

5. Zvýraznění
Hm, máš recht, že zdržovat plynulost čtení asi není dobrý nápad. Každopádně hlavní hlášky nebo třeba dobře provedené akce zkusím barevně odlišit, moc se mi líbí např. Kainovy hry ze Středozemě, když se hráči něco podařilo, text byl psán jinou barvou plus získal body, něco takového bude ideálním řešením.

6. TADS Web server
Neodolal jsem a podle návodu Setting up a custom TADS Web server jsem si nainstaloval lokální server s frobem. Po trošce laborování jsem byl úspěšný, v Ubuntu 16.04 je možné pro Apache povolit a2enmod a mohu v prohlížeči spustit t3launch, v Archu už a2enmod není, v souboru .htaccess v podadresáři t3launch stačí zakomentovat všechny 3 řádky a vše je OK. Test, který popisují, proběhne v pořádku, pokud v prohlížeči zadám
http://localhost/t3launch/

dostávám hlášení a dále viz můj dotaz níže:

Missing Parameters
The link you used to reach this page is missing some required information.

Základnu jsem zkompiloval s využitím Makefile.web.t3m a pomocí příkazu:
frob -i plain -p -N 44 asteroid-web.t3
jí mohu spustit bez Apache pouze s využitím vestavěného frobtads serveru nebo:

frob -i plain -k utf8 -p -N 00 -w localhost -W t3launch asteroid-web.t3 -storagesid=t3launch
využívám lokální Apache a vše je OK, Exoter funguje také, je to paráda.

Spustil jsem si Tvojí Základnu na webu Technoplanety a měl bych malý dotaz ohledně funkce na ostrém webu. V konfiguráku config.php jsem nastavil cestu k lokální databázi, využívám mariadb a vytvořeného uživatele t3launch s databází  t3launch a heslem password. Ten se např. pomocí phpmyadmina do databáze dostane, při příkazu uložit se mi ovšem pozice nabídne ke stažení na lokální počítač a v databázi není nic. Obnovení z lokálního SAVE je v pořádku, pouze databáze nějak hapruje, asi jsem něco zapomněl nastavit v jiném konfiguráku uvnitř t3launch.

Také bych rád Exoter nebo Základnu umístil do adresáře s webovými stránkami, u mě srv/http/, kde mám podadresář t3launch a odkazoval se na hru přímo z prohlížeče. Zde ale netuším, zda je to možné, je mi jasné, že vždy budu potřebovat spustit frob a výše popsané volby, v dokumentaci TADSu ani v rozbaleném zdrojáku a textových souborech frob jsem k tomuto více nenašel – přitom právě takto spuštěný frob si představuji podobně jako Webmin, minimální server s definovaným portem, i když jak vidím, každá spuštěná instance frobu volí jiný. Ty máš na ostrém serveru rozhraní, které zadá jméno a heslo nového uživatele do databáze, se kterou pracuje instance spuštěného frobu s adresou např. 127.0.0.1:4417, která je přesměrována na venkovní adresu. Zatím netuším, kam mám např. soubor asteroid-web.t3 umístit unitř srv/http/, v tuto chvíli obě popsané volby využívám s tím, že hra je v mém domovském adresáři.

Reálně mám v adresáři srv/http/t3launch podadresář inc s upraveným config.php a soubory .htaccess, index.html, t3launch.php plus jsem zkusil přidat svůj exoter-web.t3, jen netuším jak se na něj odkázat, aby jej prohlížeč zobrazil přímo, pokud to je takto vůbec možné.
Mimochodem je zde spousta javaskriptu, takže mé oblíbené framebufferové prohlížeče Links2 a Netsurf mají smůlu, tady se alespoň zatím bez Firefoxu neobjedu.

Není to ale nic, bez čeho bych nemohl žít, jen bych si rád zkusil např. na svém Raspberry zprovoznit plnohodnotný TADS server s funkčním ukládáním do databáze, kromě Apache bych zkusil něco trochu méně náročného v kombinaci třeba s SQLite, kterou popisují v dokumentaci. V příloze zasílám svůj upravený t3launch, Makefile a vygenerovaný Exoter.
Ostrou hru po doladění umístím od IFArchive, vidím, že stačí nahrát můj vygenerovaný exoter-web.t3 do https://www.ifarchive.org/cgi-bin/upload.py a pak se na něj odkázat ze svého profilu, který jsem si vytvořil na IFDB, s tímhle snad problém nebude.

7. Dokončování hry
Mám zde seznam věcí, které ve hře musím dokončit stejně jako výše uvedené PreferredIobj, tím se budu zabývat teď. Je zde jeden problém s množným číslem, pak se mi nelíbí, že některé objekty nemají ve hře žádný popis a když zase nevímpokolikáté už čtu Tvůj manuál, krásně vidím direktivu is plural plus píšeš o StairwayUp, což jsem využil u žebříku. Výklenek v místnosti se sekerou jsem prvně chtěl definovat jako Decoration, chybí mi však vhodná zpráva u sebrání, takže si dekoraci nechám jinam a využiji CustomImmovable.

Zajímavá je hláška u dveří, když se např. nacházím v místnosti s prvním drahokamem, získám:
>prozkoumej dveře
Masivní železné dveře. Jsou otevřené.

Jdu-li na sever a dveře zase prozkoumám, dostávám:
>prozkoumej dveře
Je otevřené.

Tady si pořádně nastuduji vše o množném číslu, podobná potíž se vyskytuje také u drahokamů, pokud jich držím více:
>prozkoumej drahokamy
Slovo "drahokamy" v tomto pribehu neni dulezite.

Další zajímavost je mixování mužského a ženského rodu:
>prozkoumej provaz
Je pevný.
>prozkoumej lano
Je pevný.

Namočit jehlu mohu jen příkazem „namoč jehlu v kaluž“, pro využití „v kaluži“ bude určitě vhodné něco jako {komučemu xxx}, to už jsem viděl v Heidi i v Základně.

Vytisknul jsem si kapitolu o překladu, tohle musím pečlivě prozkoumat.

Ve starém Exoteru sice dekorace a možnost prozkoumat to, co zmiňuje popis místnosti nebyly, každopádně pro mě to bude zkouška nových věcí, které TADS nabízí a pro hráče malé zpříjemnění. Vždy když se znovu začtu do Tvého manuálu nebo od Erica, objevím nebo spíše znovuobjevím něco nového, stačí si představit možnosti, které ve hře mohu využít a práce je o to radostnější.

Užij si Vánoční čas, zkoušel jsem posílat své koňské přání na Tvůj kapsový email uvedený v překladu TADSu, ale bez úspěchu, tak to napravuji zde společně s aktuálním zdrojákem a plánovaným webem.
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: gaspoda 8. Leden 2018 - 20:19
Tebou popsané příklady mají hlavu a patu a jsou krásně srozumitelné, neuvažuješ o tvorbě nějaké učebnice?
Myslím to vážně, ideálně určené starším dětěm nebo študentíkům např. ve stylu knihy Python for Kids.

Haha, dobrý vtip.

3. PreferredIobj
Podíval jsem se do knihovny, kde se s PreferredIobj vůbec nesetkám a celý svůj TADS adresář jsem si tímto výrazem grepnul, používáš jej ve svém překladu,
u Základny a já u Exoteru, ano, už si vzpomínám, že jsme se o něm a úpravou Dobj bavili v souvislosti s novou verzí češtiny.

PreferredIobj s velkým P na začátku je mix-in třída, která slouží jen jako označení, je to jen deklarované a pak v jednom ifu.

Teď je mi také jasné, že u křesadla a pochodně budou stejné potíže, hned jsem to vyzkoušel a hnedle u zapálení samotné pochodně křesadlem a využití těchto předmětů u psa je to horší:

>zapal pochoden
Čím ji chceš zapálit?
>kresadlem
To není něco, co by mohlo hořet.

>zapal kresadlem pochoden
To není něco, co by mohlo hořet.

>zapal pochoden kresadlem
Zapaluješ pochodeň.

Tady se vytvořila řetězová závislost, kdy křesadlem zapaluješ pochodeň a pochodní zapaluješ seno. Tedy pochodeň je jednou přímým objektem a podruhé je nepřímým. Proto pochodeň nemůžeš označit ani jako PreferredDobj, ani PreferredIobj. Protože je to řetězec jen na tři, tak pochodeň, která je uprostřed, nech bez zakéhokoliv označení (tedy uber PreferredDobj u pochodně), křesadlo označ jako PreferredIobj, protože křesadlo je vždy to, co zapaluje něco jiného a kupku sena označ jako PreferredDobj (to už máš), protože to se vždy nechává zapálit něčím jiným.

>dej pochoden psovi
Nemůžeš pochodeň nic dát.

>dej kresadlo psovi
Nemůžeš křesadlu nic dát.

Vše jsem vyřešil stejným způsobem, vše funguje krom:
>zapal pochodni seno
{Tím iobj} nemůžeš nic zapálit

Zkoušel jsem ke kupce sena dát dle diskuze s Tekketem direktivu:
preferredIobj = pochoden

ale zatím bez úspěchu, budu na tom ještě pracovat, PreferredDobj u pochodně potřebuji. Jak vidno, tyto předměty budu muset doladit – kombinace
křesadlo, pochodeň, zapálení sena a správné hlášky, pokud tyto předměty chci umožnit ve hře cizí postavě dát, není zrovna triviální.

Tohle opět koliduje s výše uvedeným řešením, ale upavil jsem knihovnu, aby dávala přednost tomu, že pro konverzační akce je Actor před těmi ad hoc vlajkami. Mimochodem ten nedosazený parametr {Tím iobj} jsem v nové verzi překladu také opravil.

6. TADS Web server
Neodolal jsem a podle návodu Setting up a custom TADS Web server jsem si nainstaloval lokální server s frobem. Po trošce laborování jsem byl úspěšný, v Ubuntu 16.04 je možné pro Apache povolit a2enmod a mohu v prohlížeči spustit t3launch, v Archu už a2enmod není, v souboru .htaccess v podadresáři t3launch stačí zakomentovat všechny 3 řádky a vše je OK. Test, který popisují, proběhne v pořádku, pokud v prohlížeči zadám
http://localhost/t3launch/

dostávám hlášení a dále viz můj dotaz níže:

Missing Parameters
The link you used to reach this page is missing some required information.

Jasně. Ty skripty, které sis nainstaloval slouží ke spuštění webového hraní a fungují jako univerzální gameserver pro TADSové webové hry. Ta chybová hláška znamená, že jsi neřekl, jakou hru chceš spustit. Jako minimum musíš předat parametr storyfile s odkazem na hru. Měl bysis tedy vyrobit třeba nějakou startovací stránku a hru spustit odkazem ve tvaru:

<a href="http://localhost/t3launch/?storyfile=http%3A%2F%2Flocalhost%2Fasteroid-web.t3">spustit základnu</a>

Gameserver je dělaný univerzálně, aby si hru stáhnul z internetu, proto se tam dává HTTP odkaz a ten může věst kamkoliv na internet, kde je soubor se hrou vystavený. Pokud si to chceš hostovat sám, tak si dej soubor se hrou např. do kořenového adresáře webu, tj. zkontroluj si, že když zadáš http://localhost/asteroid-web.t3, tak že ti to nabídne soubor ke stažení a pak bude ten odkaz na t3launch výše fungovat.

V konfiguráku config.php jsem nastavil cestu k lokální databázi, využívám mariadb a vytvořeného uživatele t3launch s databází t3launch a heslem password. Ten se např. pomocí phpmyadmina do databáze dostane, při příkazu uložit se mi ovšem pozice nabídne ke stažení na lokální počítač a v databázi není nic.

Ne, takhle je to v pořádku, skripty t3launch nedělají nic jiného, než spuštění hry a do databáze si zaznamenávají jen jedinou tabulku s informacema o stažených hrách, aby věděly, jestli při příštím stažení mohou použít nakešovanou kopii nebo musí stahovat hru znovu.

Ty máš na ostrém serveru rozhraní, které zadá jméno a heslo nového uživatele do databáze, se kterou pracuje instance spuštěného frobu s adresou např. 127.0.0.1:4417, která je přesměrována na venkovní adresu.

To je funkcionalita storage serveru, která je k dispozici na stránkách ifdb.tads.org. Když máš zaregistrovaný účet na IFDB, tak si můžeš spouštět TADSové hry a při ukládání místo aby se nabídl save file ke stažení, tak se pozice uloží online. Tahle funkcionalita je k dispozici pro každého, i ty si můžeš nahrát svou webovou hru na IFDB a vůbec nemusíš řešit vlastní server, protože dobrovolníci provozují několik veřejných TADS gameserverů.

Já jsem si podobnou funkcionalitu vytvořil sám pro sebe, tj. provozuji vastní gameserver i storageserver, takže i když IFDB nevyužívám, mám také možnost ukládání pozic online pod jménem a heslem. Potřeboval jsem to totiž propojit s uživatelskými účty na Technoplanetě a IFDB mi neposkytne tu bezešvou integraci. Navíc jsem měl naprogramováno odesílání událostí ze hry (změna skóre atp.) do online žebříčku a to by na IFDB také nešlo.

Naprogramování a nastavení storage serveru není nikde zdokumentované a zveřejněné a je to už pokročilá záležitost. Možná to někdy zveřejním, ale nebude to brzy, protože bych to musel pořádně dotáhnout a vyseparovat z jiného kódu.

7. Dokončování hry
Výklenek v místnosti se sekerou jsem prvně chtěl definovat jako Decoration, chybí mi však vhodná zpráva u sebrání, takže si dekoraci nechám jinam a využiji CustomImmovable.

Může být. Přesnější by bylo CustomFixture než CustomImmovable, liší se to v malém detailu, že Fixture je něco, co je pro hráče zcela evidentně součástí lokace a tudíž nepřenosné, kdežto Immovable se z pohledu hráče nemusí jevit nepřenosně, byť nepřenosné je. Samozřejmě se to dá dál rozvíjet, třeba v Return to ditch day je výklenek součástí jednoho puzzlu. Tam je deklarovaný jako Fixture, Platform, aby se dalo stoupnout do výklenku. Ale to už je vyšší dívčí :-)

Jdu-li na sever a dveře zase prozkoumám, dostávám:
>prozkoumej dveře
Je otevřené.

No musíš si dveře označit isPlural = true, vždyť to víš, jen nesmíš zapomenout.

Tady si pořádně nastuduji vše o množném číslu, podobná potíž se vyskytuje také u drahokamů, pokud jich držím více:
>prozkoumej drahokamy
Slovo "drahokamy" v tomto pribehu neni dulezite.

Stačí přidat množné číslo do slovníku, plurál se odděluje hvězdičkou 'první drahokam*drahokamy', koukni v Základně.

Další zajímavost je mixování mužského a ženského rodu:
>prozkoumej provaz
Je pevný.
>prozkoumej lano
Je pevný.

No jasně, o tom jsme v tomhle vláknu už také myslím mluvili. Když jsou synonyma, která jsou v jiném rodu, tak se dají ty další rody zadat pomocí vlastnosti changeGender, např. changeGender = 'lan:4'.

Namočit jehlu mohu jen příkazem „namoč jehlu v kaluž“, pro využití „v kaluži“ bude určitě vhodné něco jako {komučemu xxx}, to už jsem viděl v Heidi i v Základně.

Příkaz "namoč jehlu v kaluži" řekne, že Slovo „kaluži“ v tomto příběhu není důležité, protože jsi slova v gcVocab objektu kaluz oddělil čárkami, což není správné. Změn to na lomítka gcVocab = 'kaluže/kaluži/kaluží'

Užij si Vánoční čas, zkoušel jsem posílat své koňské přání na Tvůj kapsový email uvedený v překladu TADSu, ale bez úspěchu, tak to napravuji zde společně s aktuálním zdrojákem a plánovaným webem.

Díky, kapsácký mail by měl fungovat normálně, nevím, jestli jsi neposlal moc velkou fotku. Jo a je na něm greylisting, takže poprvé mail od serveru odmítne a pokud to poštovní server za chvíli zkusí znovu, tak mail od něj už přijme. To je obrana proti masovému spamu, ale běžný poštovní server by si s tím měl poradit.
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: Kroužící orel 11. Leden 2018 - 11:54
Krásné ráno přeji po Novém roce,
nic se neděje, nastavení kapsy naprosto chápu, se spamem bojujeme všichni, až budu příště něco posílat, tedy raději dvakrát. Hlavně, že jsi přání dostal, to je důležité, řechtavá banda už zase řádí u balíku.
S tou učebnicí mě to fakt mrzí, těšil jsem se, že něco parádního sesmolíš, ale neva, až – jestli – kdovíkdyazdavůbec ze mě bude programátor, vrhnu se na to s radostí sám.

1. Pochodeň, křesadlo, seno a pes
Ano, je to řetězová závislost, se kterou jsem se zatím nesetkal. Vše jsem nastavil jak píšeš a zapálení pochodně je už v pořádku. Kupka sena je také v pohodě, zapálit jí pochodní i křesadlem není  problém. U psa je také vše OK, zkusil jsem křesadlo a pochodeň dát i drakovi, dostávám:

>dej drakovi kresadlo
Pokud ho probudíš, se zlou se potážeš.
>dej kresadlo drakovi
Nemůžeš křesadlu nic dát.

U draka mám direktivu PreferredDobj. Pokud jí vymažu, příklady výše jsou OK, ale:

>pichni draka jehlou
Píchl jsi draka jehlou. Drak překvapeně otevřel oči, pak sebou však několikrát škubnul a bylo po něm.
>pichni jehlou draka
Spícím drakem nemůžeš zaútočit.

Jasně, otrávenou jehlu musím označit jako PreferredIobj a draka ani PreferredIobj, ani PreferredDobj, poté vše krásně funguje.

A dobře, že se to stalo, nyní vidím stejný problém i u strážce. Ten je také označen jako PreferredDobj:

>dej strazci sekeru
Chystá se zabít tě.
>dej sekeru strazci
Nemůžeš sekeře nic dát.

Vymazání PreferredDobj vše řeší, jsem rád, že jsem si s tím tak dlouho hrál, protože zde je opravdu rozdíl mezi kvalitním parserem, který tak obdivuji u Základny a předem nalajnovaným. Dal jsem si tu práci a draka i jehlu postupně označoval jako Iobj, Dobj i nic z toho, abych si vyzkoušel všechny možnosti a na nich si vše vyzkoušel, hurá.

Nová verze české knihovny tedy funguje parádně, je super, že mohu alespoň malinko přispět k jejímu zlepšování.

Setkal jsi se a potrápil s tímto typem řetězení i u Základny?

2. Výklenek
Ten výkenek je opravdu zajímavý, moc díky za upřesnění, CustomFixture bude vhodnějí. A samozřejmě neodolal jsem, juknul na Return of the Ditch Day a v souborech bridge.t a intro.t našel dva zajímavé příklady, o kterých píšeš. To mě také donutilo vyzkoušet si příkaz stoupni a stoupni na, který jsem předtím netestoval, to určitě využiji v další hře. Nyní mám:
+
 maly_vyklenek : CustomFixture, Platform
 
a mohu:

>stoupni na
(na malý výklenek)
Fajn, teď stojíš na malému výklenku.
>stoupni si do výklenku
Už stojíš na malému výklenku.
Popis místnosti: Ve výklenku (stojíš na malému výklenku)

Autor dle zdrojáku využívá i něco jako schovej se ve výklenku, tohle jako milovník příběhů o zlodějích prostě nemohu nevyužít. Vidím, že hra zatím příkaz schovej se nezná, zatím si to nechám jako věc, kterou budu řešit hnedle při další tvorbě.

Úžasné, jak člověk stále něco nového objevuje, ten TADS je prostě systém s velikým eS, dokážu jsi představit jak jsi musel být příjemně překvapený možnostmi, když jsi tvořil Základnu, píšeš to i v jejích komentářích, např. střepy v zadku při rvačce v kosmickém baru…

3. Dveře
Ano, zde mě zmátlo fungující „Jsou otevřené.“ z jedné strany a „Je otevřené.“ ze strany druhé. Sákryš, samozřejmě, že isPlural = true znám, vždyť jej mám u dveří na konci chodby, doplnil jsem je ještě ke dveřím druhým a tady k dračím hlavám.
 
Potíž ovšem stále přetrvává, je zajímavé, že z jedné strany vše funguje jak má a ze druhé nikoliv – nejde jen o množné číslo, ale právě z jedné strany je lze otevřít i zavřít, po zavření pokud chci projít parser automaticky doplní otevření dveří. Ze strany druhé ovšem nikoliv – množné číslo je i přes direktivu isPlural špatné a mohu projít i při zavřených dveřích, aniž by se parser o cokoliv pokusil.

V Základně jsem se se zamčenými dveři nesetkal, právě se dívám na zdroják k české Heidi a zdá se mi, že mám dveře i průchody nastaveny správně. V příloze zasílám zdroják i transkript, kde jsou všechny dveřní operace zaznamenány, mohu poprosit o kontrolu, kde dělám chybu?

4. Množné číslo, mixování mužského a ženského rodu a kaluž
V Základně vidím pěkný příklad množného čísla v souboru roomAlien a příklad s přihrádkami. Zkusil jsem přidat „*drahokamy“ ke všem čtyřem kouskům, příkaz „prozkoumej drahokamy“ už funguje tak jak má.

Synonyma v jiném rodu jsem v naší komunikaci nenašel, ale vůbec nevadí, zase vidím parádní příklad v Základně, soubor regionShip obsahuje changeGender = 'plavi:4, trup:2' a vyzkoušel jsem jej u svého lana.

U kaluže jsem měl skutečně v gcVocab čárky místo lomítka a to samé u střepů, již jsem opravil a vše krásně fungue, uff, pamatuji se, že jsem se tam také dlouho zasekl a pak dělám takovéhle špeky.

5. Webový server
Super, je paráda, že t3launch mám nastavený správně, jen potřebný parametr ?storyfile jsem nikde nedohledal. Dokument Setting up a custom TADS Web server holt už není nejnovější, viz mé menší potíže s Archem a právě jeden dotaz na storyfile jsem našel v diskuzním fóru, kde nabízíš svojí emailovou pomoc. Gameserver nyní funguje parádně, databázi tedy momentálně ani nepotřebuji, jak píšeš, slouží jen ke kešování. Mě to zajímá hlavně z technického hlediska, samozřejmě jsem si mnohem jistější administrací linuxu, než programováním a po dokončení hry jí určitě umístím na IFDB a využiji jejich storage server.

Každopádně Tvé technoplaneťácké řešení je perfektní v tom, že si můžeš hostovat hry nezávisle, to se mi strašně líbí a vidím v tom přínos, protože TADS se teď zrovna moc nevyvíjí. Je mi jasné, že jsi si s tím dal kopu práce a nebude sranda vše dát dohromady pro obecné využití, každopádně minimálně za mě se ke zveřejnění, až budeš mít čas a chuť, moc moc přimlouvám a s radostí pomohu třeba s dokumentací, hnedle si game i storage server nainstaluji na více distribucích a vše zdokumentuji, v TADSu je vše otevřené a pokud bych tímto způsobem mohl pomoci, budu strašně rád. Malé Raspberry bude k hostování TADSu jako stvořené.
Pokud mají mít textovky budoucnost, tak to vypadá, že na webu a čím více serverů bude k dispozici, tím lépe.

6. Co ještě zbývá na Exoterovi
Nyní tedy snad již poslední bolest představují ty dveře. Dívám se na svůj soubor věcí k dodělání, mám zde ještě kromě slova uřízni k doplnění usekni a u kaluže slova kapalina, louže - to nebude problém. Plus lze prozkoumat mrtvolu psa pomocí „prozkoumej mrtvolu“, protože jsem jej definoval jako samostatný objekt jak jsi mi doporučil, u draka ani strážce toto možné není, zde bych pravděpodobně musel postupovat stejně.
Ještě dodělám skóre, ať je hráč více motivován a teď se vrhnu na sjednocení zdrojového kódu, juknu na Základnu a Heidi a určím si svůj styl odsazení, kterého se budu držet. Znovu si projedu naši komunikaci a do zdrojáku doplním věci, které mi nebyly jasné stejně jako v Základně.
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: Kroužící orel 19. Leden 2018 - 13:47
Krásné ráno přeji,
zase se dostávám k tvorbě a dokončuji dokumentaci a úpravu systaxe zdrojáku. Ještě bych se vrátil k webovému hraní, nevím, zda mám nastavené něco špatně, zkoušel jsem rozchodit gameserver pod Archem i Debianem a nyní těsně před spuštěním dostávám chyby.

Pod Archem využívám jako úložiště sqlite a pod Debianem mariadb. V prvním případě dostávám při spuštění např. pomocí:

http://localhost/t3launch/t3launch.php?storyfile=http%3A%2F%2Flocalhost%2Fasteroid-web.t3
- inspiroval jsem se Tvojí minulou odpovědí a např. url Heidi:
http://gs1.tads.cz/t3launch.php?storyfile=http%3A%2F%2Ftads.cz%2Fheidi.t3&key=8e6dec6f9554e0b1e4eaaf02c86ebcc9

chybové hlášení:

PHP Fatal error:  Uncaught Error: Call to a member function bindValue() on boolean in /srv/http/t3launch/t3launch.php:293\nStack trace:\n#0 /srv/http/t3launch/t3launch.php(54): fetchGame('http://localhos...')\n#1 {main}\n  thrown in /srv/http/t3launch/t3launch.php on line 293

U Debianu s mariadb:

Error
An error occurred starting the game.
Try again
Error details: The game displayed the following message(s) before it exited:

Warning: -webhost mode specified, but couldn't read web config file "/usr/games/tadsweb.config"
frob: http://localhost/asteroid-web.t3: file not found.

Note that the game must be designed for Web play to run properly with this service. Standard TADS games won't work on this system. IFDB home page

To samé u Archu s mariadb, zkusil jsem oba systémy, abych vyloučil novější verze serverových démonů. Warning je OK, stačí vytvořit tadsweb.config.

Horší je to s druhou hláškou, pokud zadám http://localhost/asteroid-web.t3, soubor mohu bez problémů stáhnout.

Také příkaz
frob -i plain -p -N 44 asteroid-web.t3

umožňuje po zadání do prohlížeče:

http://localhost:54055/?TADS_session=2524812e-ad34-2a9b-866e7cdd40c7-e8cc

hru hrát.

Problémy s právy v adresářích, kam vidí Apache, určitě nejsou, vyzkoušel jsem i jiné webové aplikace. Všechna nastavení včetně apačích access a error logů zasílám v příloze. Prozkoumal jsem i diskuzi na IFDB, ovšem ani Error copying resource file when compiling for Web play, Is there a Javascript Interpreter for TADS that I can run on my website nebo TADS 3 - IFComp entry online play nepomohly.

Dokument Setting up a custom TADS Web server určitě není aktuální, rád bych ale vše zprovoznil na dnešních linuxech a připravil dokumentaci pro ostatní, která skutečně funguje. Samozřejmě to není nutné, pro svůj Exoter využiji IFDB, TADS se ale stal mým oblíbencem a rád bych, aby vše fungovalo jak má, tak parádní systém si to určitě zaslouží a vidina serveru běžícího nad RPi je stále lákavá.

Pokud najdeš chvilku, prosím o kontrolu, není to ale nic zásadního.

Krásný víkend přeje
Orel
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: Kroužící orel 22. Leden 2018 - 10:59
Zdravím do nového týdne,

tak konečně jsem problém s dveřmi vyřešil, trošku mě zmátla definice u Heidi, kde se používají mezi místností venku a místností uvnitř chaty, nyní se již dveře chovají správně, mohu je prvotně odemknout a následně zamyklat a otevírat dle libosti, množné číslo se také ukazuje správně.

Doplnil jsem komentáře k různým akcím, které jsme společně řešili a myslím, že čas uzrál pro konečné testování. Pokud budeš mít čas a chuť, prosím o projití hry, ještě poprosím svého kamaráda a Thoorina s využitím Zapni zápis plus pokud se na fóru najde další zájemce, je vítán. Také si jsem vložil hru na IFarchiv:

https://www.ifarchive.org/cgi-bin/upload.py

a zatím čekám na schválení do adresáře unprocessed, případných dalších úprav snad již nebude mnoho.

A nyní je čas na hru novou, opravdovou, začínám na ní pracovat a pokusím se využít všechny zkušenosti, které jsem od Tebe získal, moc moc se těším. Budu využívat QT Creator, ať si zvyknu na větší IDE, až při tvorbě zjistím, zda mi více vyhovuje nebo bude vhodnější investovat čas do VIMu či EMACSu, ideální bude pár dní vyzkoušet všehny tři možnosti.
Název: Re: Seriál o programování textových her v TADS 3
Přispěvatel: gaspoda 23. Leden 2018 - 19:59
1. Pochodeň, křesadlo, seno a pes
Jasně, otrávenou jehlu musím označit jako PreferredIobj a draka ani PreferredIobj, ani PreferredDobj, poté vše krásně funguje.

Setkal jsi se a potrápil s tímto typem řetězení i u Základny?

Při té poslední úpravě jsem to právě udělal tak, aby Actor mel v konverzačních příkazech přednost. Ne, na základně to bylo docela jednoduché. Ale docela zajímavý problém byl, když jsem se snažil modelovat konverzaci se dvěma postavami zároveň, aby nevypadala jako rozhovor jen s jednou postavou.

2. Výklenek
>stoupni na
(na malý výklenek)
Fajn, teď stojíš na malému výklenku.
>stoupni si do výklenku
Už stojíš na malému výklenku.
Popis místnosti: Ve výklenku (stojíš na malému výklenku)

Tady by asi bylo vhodnější, aby hra mluvila o to, že stojíš ve výklenku a ne na výklenku. To samozřejmě není problém, podívej se, jak v Základně je nadefinovaný objekt spacáku. Vlastnosti objInPrep, objIntoPrep, objIntoCase a objOutOfPrep definují, jaké předložky a pád použít.

3. Dveře
Ano, zde mě zmátlo fungující „Jsou otevřené.“ z jedné strany a „Je otevřené.“ ze strany druhé. Sákryš, samozřejmě, že isPlural = true znám, vždyť jej mám u dveří na konci chodby, doplnil jsem je ještě ke dveřím druhým a tady k dračím hlavám.
 
Potíž ovšem stále přetrvává, je zajímavé, že z jedné strany vše funguje jak má a ze druhé nikoliv – nejde jen o množné číslo, ale právě z jedné strany je lze otevřít i zavřít, po zavření pokud chci projít parser automaticky doplní otevření dveří. Ze strany druhé ovšem nikoliv – množné číslo je i přes direktivu isPlural špatné a mohu projít i při zavřených dveřích, aniž by se parser o cokoliv pokusil.

Hele já nevím, které dveře máš na mysli, ale asi to bude u všech stejné a nemyslím, že bys to měl opravené. Níže máš jednu půlku dveří dobře a tu druhou máš úplně bez definice. Ta by měla být stejná, nejen isPlural, ale i keyList a slovník a jakékoliv další vlastnosti. To, že jsou obě půlky mezi seou prolinkované, aby se dalo procházet ještě neznamená, že bys nemusel uvést všechno ostatní.

Kód: [Vybrat]
chodba_se_zeleznymi_dvermi: Room 'Chodba' 'do chodby'
    "Stojíš v chodbě. Na jihu jsou masivní železné dveře. \bMůžeš jít na sever. "
    north = chodba_se_zebrikem
    south = dvere_chodba_se_zeleznymi_dvermi
;

+ dvere_chodba_se_zeleznymi_dvermi : LockableWithKey, Door 'dveře' 'dveře' *3
  "Masivní železné dveře. "

     isPlural = true
     keyList = [svazek_klicu]

     gcName = 'dveří, dveřím, dveře, dveřích, dveřmi'
     gcVocab = 'dveří/dveřím/dveřích/dveřmi'
;

//po použití svazku klíčů od strážce: "Podařilo se ti odemknout železné dveře. "

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

zatuchla_komurka: Room 'Zatuchlá komůrka' 'do zatuchlé komůrky'
    "Nacházíš se v malé zatuchlé komůrce. Na severu jsou vidět masivní železné dveře.
    \bMůžeš jít na sever. "
    north = chodba_se_zeleznymi_dvermi
;

+ dvere_zatuchla_komurka : LockableWithKey, Door -> dvere_chodba_se_zeleznymi_dvermi 'dveře' 'dveře' *3
    // Tady chybí uvést to samé, co u prvních dveří
;