19. Říjen 2018 - 00:49

Zobrazit příspěvky

Tato sekce Vám umožňuje zobrazit všechny příspěvky tohoto uživatele. Prosím uvědomte si, že můžete vidět příspěvky pouze z oblastí Vám přístupných.


Příspěvky - gaspoda

Stran: [1] 2 3 ... 8
1
TADS / Re: Otěžemi zimní noci v TADS3
« kdy: 19. Únor 2018 - 17:53 »
No vida, to je chyba v překladu, jestli si chceš opravit soubor msg_neu.t, tak od řádku 2842, chybí tam jen to obj ve složené závorce:

Kód: [Vybrat]
    /* generic "no can do" message for intangibles */
    notWithIntangibleMsg(obj)
    {
        gMessageParams(obj);
        return 'To {|[jsi]} {s/se} {kýmčím obj} nem{ůž[eš]|ohl[a]} udělat. ';
    }

    /* generic failure message for varporous objects */
    notWithVaporousMsg(obj)
    {
        gMessageParams(obj);
        return 'To {|[jsi]} {s/se} {kýmčím obj} nem{ůž[eš]|ohl[a]} udělat. ';
    }

Při té příležitosti se dá nadhodit, že pro objekty, jako je třeba Měsíc, který je ten jeden a stejný Měsíc vidět z více lokací, tak na to se používá MultiLoc třída, která se přimíchá před ostatní běžné třídy.

2
TADS / Re: Seriál o programování textových her v TADS 3
« kdy: 31. Leden 2018 - 21:59 »
Hardwarová kalibrace je určitě záležitostí pouze drahých grafických monitorů a použití speciální sondy, tyhle levné, které nejsou určeny na profi práci to neumí. V OSD mého monitoru jde nastavit jas, teplota, gamma, saturace a zisk jednotlivých barevných složek, ale neměl jsem potřebu to měnit.

3
TADS / Re: Seriál o programování textových her v TADS 3
« kdy: 29. Leden 2018 - 20:07 »
To Eizo má ještě mj. i zajímavý stojan (myslím, že je to jeden z těch typů umožňující monitor sklopit do polohy jako knížku drženou v rukou) a tradičně pětiletou záruku na rozdíl od tříleté. Na druhou stranu, i když je uvnitř v podstatě ekvivalentní panel od Samsungu (AH IPS), tak u daného Eiza je jen 16:9 a ne 16:10 (Eizo má i druhou variantu, ale stojí kolem 10 tis.).

A pokud se teď vrátíme k topicu, tak na logy jsem se krátce díval a nic mě zatím nenapadlo, bylo to takové matoucí. Já na to myslím, jen teď mám dost málo času :-(

4
TADS / Re: Seriál o programování textových her v TADS 3
« kdy: 26. Leden 2018 - 23:34 »
Teď se ještě dívám na Alzu a popis dvou levnějších EIZ:
https://www.alza.cz/24-eizo-ev2450-bk-d2268875.htm?o=1
https://www.alza.cz/24-eizo-flexscan-ev2451-bk-d4725652.htm?o=2

Paper Mode se zdá zajímavý a např. recenze na typ EIZO FlexScan EV2450-BK vypadají velmi, velmi dobře. Tenhle kousek se mi tedy začíná líbit čím dál tím víc.

V dané cenové kategorii to není špatné, i ty Delly jsou docela fajn. V Kapse máme starší Dell 2412 za cenu těsně přes 6000,- a má eIPS panel. Ty levnější IPS panely jsou myslím jen 6 bitové, ale dobré je, že to na nich kupodivu není znát. Samozřejmě IPS panely trpí na jemné glow v černé obrazovce, mají však velmi slušné pozorovací úhly a barvy neurazí. Osobně je považuji za docela doporučení hodné, pokud nechceš dát více.

Nejlepší je projít si nějaký skutečný test, doporučuji mrknout na:

http://www.tftcentral.co.uk/reviews/eizo_ev2450.htm
http://www.tftcentral.co.uk/reviews/dell_u2715h.htm
http://www.tftcentral.co.uk/reviews/benq_bl3200pt.htm

a porovnat si je. A pokud máš možnost je vidět naživo, tak také, jen je dobré se trochu vyzbrojit zkušenostmi a vědět, co je na těch monitorech potřeba vidět (glow, kontrast, úroveň černé, rovnoměrnost podsvětlení, pohled ze spodu, blikající pwm podsvícení při nižším jasu, jak moc jde jas snížit pro práci po tmě, ghosting při rolování textu nebo obrazu s jemným šedým vzorkem, jemný šedý gradient apod.) To Eizo za osmičku je o trochu lepší. Samozřejmě pak j vyšší cenová kategorie, kde jsou lepší a dražší panely, tuším, že Dell dělal něco lehce přes 12 tis.

5
TADS / Re: Seriál o programování textových her v TADS 3
« kdy: 25. Leden 2018 - 20:02 »
Dveře jsem upravil dle Tvého doporučení, funkcionalita zůstala stejná. Já se inšpiroval právě u Heidi, kde jsou plně definovány také jen na jednom místě, viz cottageDoor na řádku 425 a cottageDoorInside na řádku 706. Budu ale používat syntaxi, kterou uvádíš, určitě je přehlednější.

Aha, to bude opomenutí, dveře by měly být skutečně definovány plnohodnotně z obou stran, aby se daly prozkoumat atp.

Když už jsme u těch dveří, podíval jsem se na mříž, která je definována stejně a pokud hráč prolézá nahoru a je otevřená, přidal jsem TravelMessage s popisem, což vypadá zase o chlup reálněji. Jen mě napadá, že po jejím přepilování nemají smysl příkazy otevři/zavři mříž, které sice hráč zapsat může a parser mu odpoví, efekt zde však není žádný a hlášení nevypadá dobře.

Dobrá, ale pak asi nemá cenu modelovat mříž jako dveře, pokud to není taková mříž, která se jako dveře otevírá. Konektorů, které spojují místnosti existuje více. Co kdybys vyzkoušel ThroughPassage, ze které konec konců dveře dědí? Je to podobné, dveře navíc dědí ještě od Openable. Tj. ThoughPassage je něco, skr co se dá projít do jiné místnosti, jako např. díra ve zdi, tunel apod., skrátka cokoliv, u čeho by hráč chtěl zadat příkaz projdi/prolez něčím. Podobně existuje PathPassage, která funguje podobně, ale popisuje pohyb po objekty, tedy např. jdi po cestě apod. Na rozdíl od dveří se tyto objekty nedají zavírat a otevírat, ale stejně jako jiné konektory u nich funguje canTravellerPass/explainTravelBarrier, takže by neměl být problém je použít.
V Základně jsem našel parádní příklad, regionBase.t definuje IndirectDoor s využitím IndirectLockable a následné direktivy, které jsem si upravil na:

Dnes budu mít jen jeden technický dotaz ohledně monitoru vhodného pro programování. Vývojařina samozřejmě unavuje oči, displej na mém armádním notebooku není zrovna dvakrát šetrný. Napadlo mě situaci řešit e-ink displejem, jediný dostupný monitor nabízí Dasung E-Ink PaperLike Pro s šílenou cenou a ne zrovna jednoduchým objednáním z ciziny.

No to teda nevím, na čtečku knih, kde jednou za minutu obrátíš stránku asi ok, ale byl bych hodně skeptický, že by se něco takového dalo použít jako normální monitor...

možná by byl vhodný ten BenQ EW2775ZH s přeci jenom rozumnější cenou. Jaké máš zkušenosti jako vývojář Ty, můžeš mi vhodné zobrazovadlo doporučit?

BenQ patří k lowendu. Panely vždy vyrábí někdo jiný, ale elektronika asi nebude nejkvalitnější. Ale doporučení, to je těžké. No u toho BenQu píší, že to je AMVA+ panel, takže to asi není tak strašlivé, jako TNka, ale zkušenost s tím žádnou nemám. Pokud by byla pravda, že panl je osmibitový a má pozorovací úhlu 178 stupňů a nativní kontrast 3000:1‎, jako píší na http://www.relaxedtech.com/reviews/benq/ew2775zh/1, tak by to nemuselo být až tak zlé, ale na druhou stranu cena je podezřelá - předpokládám, že to má nějaký háček, jak už to tak bývá. Snad jen jedinou poznámku, že když už širokoúhlý, tak programátor ocení spíš 16:10, aby nebyl panel tak ošizený na výšku. Jenže tím se výběr prudce sníží.

Já osobně mám doma ještě dnes už stařičké Eizo S1910, které ve své době stálo asi 19 tisíc. Z dnešního pohledu je to už trochu malé, ale má to SPVA panel, který je docela dobrý kompromis, má dobré úhly, kontrast 1000:1 není největší, ale stačí a sice ne kalibrované, ale docela hezké barvy. Neprojevují se u něj žádné zásadní vady, jako u TN a byl výrazně levnější, než profi IPSka. V práci mám na stole nějaké levné Eizo s TN panelem, které mě děsně štve, protože má šestibitové barvy a ditheruje...

6
TADS / Re: Seriál o programování textových her v TADS 3
« kdy: 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ří
;

7
TADS / Re: Seriál o programování textových her v TADS 3
« kdy: 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.

8
TADS / Re: Seriál o programování textových her v TADS 3
« 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í.

9
TADS / Re: Seriál o programování textových her v TADS 3
« 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.

10
TADS / Re: Seriál o programování textových her v TADS 3
« 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.

11
TADS / Re: Seriál o programování textových her v TADS 3
« 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.

12
TADS / Re: Seriál o programování textových her v TADS 3
« 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]

13
TADS / Re: Seriál o programování textových her v TADS 3
« 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.

14
TADS / Re: Seriál o programování textových her v TADS 3
« kdy: 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, 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íš. ');

15
TADS / Re: Seriál o programování textových her v TADS 3
« kdy: 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
http://geekandpoke.typepad.com/.a/6a00d8341d3df553ef017ee8123faf970d-pi
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
http://geekandpoke.typepad.com/.a/6a00d8341d3df553ef0153925eca87970b-pi
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 :-)

Stran: [1] 2 3 ... 8