23. Leden 2018 - 20:39

Poslední příspěvky

Stran: 1 2 [3] 4 5 ... 10
21
Programování / Re: Seriál o programování textových her v TADS 3
« Poslední příspěvek od gaspoda kdy 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í.
22
Programování / Re: Seriál o programování textových her v TADS 3
« Poslední příspěvek od Kroužící orel kdy 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žší.
23
Programování / Re: Seriál o programování textových her v TADS 3
« Poslední příspěvek od gaspoda kdy 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/ 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.
24
Programování / Re: Seriál o programování textových her v TADS 3
« Poslední příspěvek od gaspoda kdy 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.
25
Programování / Re: Seriál o programování textových her v TADS 3
« Poslední příspěvek od Kroužící orel kdy 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
26
Programování / Re: Seriál o programování textových her v TADS 3
« Poslední příspěvek od Kroužící orel kdy 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.
27
Programování / Re: Seriál o programování textových her v TADS 3
« Poslední příspěvek od gaspoda kdy 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.
28
Programování / Re: Seriál o programování textových her v TADS 3
« Poslední příspěvek od Kroužící orel kdy 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. 
29
Programování / Re: Seriál o programování textových her v TADS 3
« Poslední příspěvek od gaspoda kdy 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]
30
Programování / Re: Seriál o programování textových her v TADS 3
« Poslední příspěvek od gaspoda kdy 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/. 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/ 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.
Stran: 1 2 [3] 4 5 ... 10