Diskuze o textových hrách

Kroužící orel 2

Kroužící orel

  • Plný člen
  • ***
    • Příspěvků: 205
    • Zobrazit profil
    • Šťastný statek
Po delší době zdravím všechny textovkáře,

moc se omlouvám za odmlku, v poslední době jsem se věnoval klasickému programování nakonec v Javě, kde mě oslovily knihy pana Pecinovského a rozhodně nelituji, je opravdu fuk, čím člověk začne, ale styl výkladu holt hraje prim. Doslova před pár dny jsem si přečetl Holynovu recenzi na Orla I. a slíbil jsem, že před Otěžemi zimní noci, textovek z ruské občanské války a jiných zajímavých témat nejprve dokončím indiánskou trilogii.

Orla dvojku již tvořím sám kompletně v TADSu, hra má cca 40 místností (ve dne i v noci, viz níže), spoustu postav a věcí k prozkoumání, hádanky samozřejmě budou, nejvíce jsem se však zaměřil na příběh a rozhovory, což mě u textovek vždy bavilo. S Exoterem jsem se dosloval plácal, protože OOP rozhodně není sranda, teď už jsem doufám jinde a hru dokončím s nabitými zkušenostmi. Už nebude jeden ne zrovna přehledný zdrojový soubor, inšpiroval jsem se svým programováním v Javě a samozřejmě Základnou, čímž jsem kód mnohem více zpřehlednil, více souborů a využití Makefile je pro už přeci jen mírně větší projekt to pravé. Právě nyní dokončuji Akce a hraji si s PreCondition, poté se vrhnu na konverzační témata (ta v Exoteru vůbec nebyla, model TADSu je ale parádní) a nakonec neodolám, indiánská vesnice ve dne je nádherná, v noci ale o nic méně zajímavá. K naprogramování denní a noční lokace jsem nenašel žádnou dokumentaci, takže krom klasických třídy Room vytvořím ještě nové objekty DarkRoom včetně všech změn, to ale nevadí.

Pány jistě potěší ženské postavy, se kterými lze konzervovat a možná i něco navíc (spíš určitě), ctěný zájemce ať si sám vybere, hrajeme konverzační hry a právě na rozhovory jsem se zaměřil asi nejvíc.

TADS je opravdu famózní, už asi po dvacáté čtu skvělý Gaspodův manuál (který mi vždy připadal nekonečný a v poslední době příliš stručný, ach jo) a ještě více se hrabu ve zdrojácích Základny, teď s vědomostmi z Javy konečně vidím tu šílenou práci, kterou si s ním autor dal, takže jí prostě nemohu nevyužít. Hra bezvadně funguje od Win XP po Win 10 a na všech hlavních linuxech, připravím aktuální info o dnešních interpreterech (např. poslední verze Gargoyle už TADS zvládne také). Bezva nápady na textovku v Javě jsem našel zde:

https://java.vse.cz/4it101/ZadaniAdventury

a ano, přesně toto a mnohem, mnohem více TADS řeší. Škoda, že není k dispozici moderní IDE, když se např. rozhodnu, že název mistostTipiOrla potřebuji všude přejmenovat na mistostTypiOrla, nejde to tak jednoduše jako např. v Netbeansech nebo v Idee, ale alespoň o to více si budu vážit kvalitních prostředí, která opravdu pomáhají. A pokud bych v budoucnu TADS z jakéhokoliv důvodu nemohl využít (přeci jen se už nevyvíjí, naštěstí fórum stále funguje), vypadá to, že mohu klidně textovkařit v Javě a drobet upravit ty skvělé předpřipravené třídy (to ale alespoň zatím nehrozí, starý dobrý Workbenech jede všude a frobtads také, Fabularium na Androidu také odvádí skvělou práci no a nakonec možnost webového hraní, kde jsem se na fóru dozvěděl o využití moderního javascriptu např. u automapingu). Mimochodem, pro mapování využívám právě JS aplikaci Trizbort:

https://github.com/henck/trizbort

která pro TADS i jiné systémy umí z mapy vygenerovat názvy místností a propojení mezi nimi (ne vždy přesně, ale rozhodně pomůže).


Kdy hra vyjde? Do konce roku nemám šanci, i když teď na ní makám téměř denně. Vidím to na leden, maximálně únor, není totiž od věci, když si všechno, co jeden den připravím, druhý den přečtu ještě jednou. Jakmile vydám hru, počkám cca měsíc na uveřejnění zdrojáků. Postupně budu informovat o pokračování ve vývoji, netušil jsem, že seznamování se s vývojařinou bude trvat takhle dlouho, ach jo, už chápu, proč vznikla Adv3lite (tam ale chybí skvělý Gaspodův český překlad, takže jedu klasiku).


gaspoda

  • Plný člen
  • ***
    • Příspěvků: 141
    • Zobrazit profil
Ahoj, přeji pohodové vánoce a gratuluji, že ses na programování nevykašlal, ale jdeš si za svým cílem! Popravdě jsem si nebyl jistý, protože mi přišlo, že o tom nedokážeš nemluvit a dlouho o tobě nebylo vidu ani slechu ;-) Přeji mnoho úspěchů a těším se :-)


Kroužící orel

  • Plný člen
  • ***
    • Příspěvků: 205
    • Zobrazit profil
    • Šťastný statek
Zdravím Toma,

děkuji za parádní povzbuzení, na programování jsem se opravdu nevyklašlal, jen jsem musel zkusit pár přístupů a zjistit, který mi nejvíce vyhovuje. Stejně jako s Linuxem, kde pro mě z vícero důvodů zvítězil Arch jsem zkoušel i C, Python a nakonec se zaměřuji na Javu a TADS, nejde ani tak o jazyk, ale naučit se opravdu programovat a chápat souvislosti, zde mi sednul Pecinovský a skvěle jsem se odpíchnul od věčného začátečníka.

Orla v TADSu se pokusím vytvořit sám bez dotazů, když se juknu do historie naší komunikace, už se jen usmívám nad některými dotazy, ale jinak to nešlo. Poradil jsem si se dvěma osobami v jedné místnosti a změnou dne a noci, nerad bych Ti zkazil zážitek z hraní dotazy se zdrojáky. Opravdu pečlivě se snažím vše popsat, ať se hráč do světa může pořádně vcítit, TADS mi dává parádní možnosti plus zkoumám mapovací program Trizbort, který by se možná dal využít jako automapa k webovému hraní, to zjistím časem.

Snažím se pokud možno opouštět Workbench, debugger obsažený ve frobtads mi stačí, zatím vyvíjím v kombinaci editor Pluma + příkazová řádka frobtadsu a zkouším QT Creator včetně testovacích skriptů, o tomto všem jsme si psali minule. Zde získám bezva zkušenosti plus Library reference jsem si připravil pro offline prohlížeč dokumentace Zeal (jen zatím neumím provést indexaci, aby Zeal vyhledával pomocí fulltextu, na to se vrhnu výhledově). Zdrojáky jsou opravdu mohutné, "užvatlanost" Javy vidím i zde, pokouším se však dodržovat maximální přehlednost, takže s vývojem nemám probléma ani při několika tisících řádků kódu.

Krásné prázdninové a sváteční dny přeje

Orel


Kroužící orel

  • Plný člen
  • ***
    • Příspěvků: 205
    • Zobrazit profil
    • Šťastný statek
Krásné ránko přeji,

hlásím, že vývoj jde podle plánu, nejvíce času zaberou detaily typu přesného popisu všeho možného, správné mluvnické
rody a košaté rozhovory. Zatím jsem si poradil se všemi potížemi ohledně postav, práce s oděvy i kontejnery, opravdu
mi velmi pomáhá, když se umím podívat do knihovny funkcí a metod, kterou jsem si upravil pro Zeal. Dnes jsem dokonce
zjistil, že nejsem zdaleka sám, kdo vyvíjí hru z indiánského prostředí, This land is my land vypadá moc pěkně, sice
si jí na svém železe opravdu nespustím, ale i ta videa stojí za to.

Zeptal bych se na jednu drobnost, kterou sice umím vyřešit, ale rád bych věděl, zda je možné elegantní řešení vzhledem
ke struktuře mých zdrojáků. Jedná se o využití třídy Enterable, pokud chci např. jít do týpí, mohu zadat "dovnitř" nebo
"jdi dovnitř", ale po zadání "jdi to týpí" dostanu odpověď "To není něco, do čeho bys mohl vstoupit". Situaci chápu,
ostatně popisuješ jí ve svém návodu a také v Getting Started in TADS3 je na straně 56 přesně vysvětleno, co a proč dělat
plus v Library a souboru travel.t je krásně vidět provázanost jednotlivých tříd.
V příloze zasílám minimální zdrojáky pro postavu a dvě místnosti, je možné při této struktuře docílit funkčnosti příkazu
"jdi to týpí"? Pokud to nebude možné, nezbývá mi vše předělat tak jak popisuje manuál a je vyřešeno např. u chaty v Heidi.

A bych měl ještě něco z druhého soudku, TADS stále prozkoumávám a z Frobtads 1.2.3 jsem již před časem přešel na verzi
1.2.4. Vše je OK, jen pokud se pokouším zkompilovat Základnu, dostávám následující chybové hlášení, které jsem v předchozím
sestavení nezaznamenal:

symbol_export itemTablet.t -> obj/itemTablet.t3s
Neoprávněný přístup do paměti (SIGSEGV) (core dumped [obraz paměti uložen])

Program v Cčku bych např. projel pomocí GDB a Valgrindu, zde v TADSu debugger nemám. Mohu poprosit o simulaci, docela by
mě zajímalo, kde může být problém, protože se s ním při své budoucí tvorbě mohu setkat taky.

Jdu makat dále, tvorba mě čím dál více baví a to parádní způsob pro další vývoj.


gaspoda

  • Plný člen
  • ***
    • Příspěvků: 141
    • Zobrazit profil
Je možné při této struktuře docílit funkčnosti příkazu "jdi to týpí"? Pokud to nebude možné, nezbývá mi vše předělat tak jak popisuje manuál a je vyřešeno např. u chaty v Heidi.

Myslíš bez použití EntryPortalu? No zkusil jsem níže uvedené a zdálo se mi, že to funguje bez problému, tedy že jsem enterable přesměroval na cílovou lokaci, takže se zdá, že není potřeba směrovat na místní objekt představující dveře, který směruje na protilehlou lokaci, ale jde směrovat rovnou na cíl.

Kód: [Vybrat]
+ typiBystrehoRysa : Enterable, CustomImmovable -> mistnostTypiBystrehoRysa 'týpí' 'týpí' *4


Kroužící orel

  • Plný člen
  • ***
    • Příspěvků: 205
    • Zobrazit profil
    • Šťastný statek
Paráda, přesměrování rovnou do týpí díky Tvému zápisu parádně funguje, upravím u všech vchodů, tenhle trik jsem v manuálu nenašel nebo přehlédnul, určitě se do budoucna bude hodit. Zatím jde tvorba bez problémů, jdu pokračovat, únor budu ještě na tvorbu potřebovat, ale nevadí, rád bych se vyvaroval co největšího počtu chyb a popsal bez příliš častého využívání knihovní hlášky co nejvíce situací, do kterých se hráč může dostat.

Zatím se loučí

Orel


Kroužící orel

  • Plný člen
  • ***
    • Příspěvků: 205
    • Zobrazit profil
    • Šťastný statek
Orlí jámy a využití akce dobjFor(LieOn)

Na hře stále pracuji, mám hotovo cca 70 procent, takže jsem byl s rychlejším dokončením přeci jen přílišný optimista.
Je ale jasné, že se někde seknu, zatím jsem na většinu programátorských nástrah přišel. Už několik dní se ale pachtím s
akcí dobjFor(LieOn) a jak vidno, potřebuji si ujasnit věci, které se snažím aplikovat ne tak jak autoři při tvorbě jazyka předpokládali.
V příloze zasílám aktuální situaci s několika potřebnými místnostmi.

Ve hře se nachází orlí jámy určené na lov těchto dravců, potřebuji, aby hra reagovala na příkaz "lehni si do jámy" s tím,
že pokud má hráč nůž a návnadu, akce se provede a po zpracování opeřence získám nové předměty.


Pokud nemám v ruce žádný předmět, vše je OK a vyskočí hláška, kterou potřebuji:


>lehni si do jámy
Orla musím nejen na něco chytit, ale také mít šikovný předmět na zpracování masa a peří, nic nesmí zůstat nevyužito.


Pro úspěšný lov potřebuji mít v ruce nůž a návnadu. I přes můj kód však stačí mít jen jediný předmět, např. nůž a ještě
se text opakuje, místo aby hra zobrazila blok uvedený v else. Předměty typu PresentLater se v pořádku objeví:


>inv
Neseš nůž a na sobě máš bederní roušku, opasek, orlí medicínu a mokasíny.

>lehni si do jámy
Takže Ty se opravdu nebojíš lovu orlů...

>lehni si do jámy
Takže Ty se opravdu nebojíš lovu orlů...

>roz
Jihozápadní hranice prérie (ležíš na jámách)
Na jámách je orlí maso, orlí perutě, orlí pera a orlí letky.



Nejde mi jen o vyřešení problému, ale pochopení toho, co dělám špatně, přeci jen z Pecinovského Javy využívám IDE typu BlueJ, kde krásně graficky vidím provázanost tříd, objektů a volaných metod, zde mi není jasné následující:

V referenční knihovně si vyhledám Akce a rozkliknu LieOnAction, pokud dobře chápu, zjišťuji, že se jedná o třídu dědící od tříd TAction a Action a také od BasicProd a Resolver (které jsou však označeny jako objekty, i když po rozkliknutí jako třídy, zde se asi bude jednat o ten minimální rozdíl mezi třídou a objektem, který uvádíš ve svém manuálu). V sumáři vlastností a metod třídy LieOnAction vidím několik akcí xxx dobj xxx (snad se vyjadřuji přesně), nikoliv však akci s názvem dobjFor(LieOn), kterou potřebuji použít. Dobrá, vyhledám si všechny metody s názvem dobjFor(LieOn) (zde netuším, zda mohu akci typu dobj nebo iobj chápat jako metodu?) a vidím:
 
dobjFor(LieOn) - method of ComplexContainer in extras.t[207]
dobjFor(LieOn) - method of Thing in thing.t[10072]
dobjFor(LieOn) - method of Room in travel.t[4617]
dobjFor(LieOn) - method of NestedRoomFloor in travel.t[5161]
dobjFor(LieOn) - method of Floor in travel.t[5336]
dobjFor(LieOn) - method of BasicChair in travel.t[6440]
dobjFor(LieOn) - method of NominalPlatform in travel.t[6730]

Zde mě zaráží, že jsem nedohledal žádné propojení s třídou LieOnAction, tady něco chápu špatně. Potřebuji pracovat s věcmi v inventáři, takže se juknu blíže na aplikaci této metody ve spojení s třídou Thing a dostávám předpis:

    dobjFor(LieOn)
    {
        preCond = [touchObj]
        verify() { illogical(&cannotLieOnMsg); }
    }

Já se však ve svém kódu snažím využít nikoliv preCond a verify (mohu je chápat jako atributy metody?), ale verify, check a action společně s podmínkou začínající příkazem if a končící else, nakonec se snažím umožnit hráči nejen si s potřebnými předměty lehnout do jámy, ale také při položení obou věcí dosáhnout téhož pomocí dobjFor(PutIn) asDobjFor(LieOn).

Pokud dobře chápu, potřebuji rozšířit funkcionalitu metody dobjFor(LieOn) tak, abych mohl využít atributů verify, check a action. Je nepříjemné, že můj zápis hra nebere jako chybu (syntaktická to pro kompilátor není, sémantická však ano, pokud dobře rozumím, i tak je chování zvláštní, neměl by TADS při překladu zařvat, že se snažím volat neexistující atributy?).

Něco mi holt uniká, nechápu zatím propojení mezi třídou LieOnAction a metodou dobjFor(LieOn), tuším, že zde takové propojení bude např. přes třídu Thing a její metody.

Tohle ale pro další tvorbu musím pochopit, jinak na netriviálních akcích ztroskotám. Je mi jasné, že jsem se u Exoteru ptal na každou prkotinu, protože bez chápání výše uvedeného jsem se dál prostě nemohl dostat a jen zkoušel, zda nějaký zápis projde či nikoliv (a podobně jako zde se mi to např. s hořící pochodní podařilo, hru kompilátor přeložil, ale chovala se jinak, než jsem zamýšlel).


Moc se omlouvám za sakra dlouhou zprávu, snažil jsem se vyjádřit co nejpodrobněji. Mohu poprosit o objasnění - nejde jen o vyřešení problému, ale hlavně o postup a vysvětlení, co dělám špatně? Je mi jasné, že až mi tyto věci docvaknou, bude už šumák, jaký jazyk pro tvorbu použiji (samozřejmě budu-li se pohybovat v rámci OOP, pokud se nemýlím), protože stále více vidím, že princip programování je u všech těchto jazyků podobný. Pecinovského "Architektura nejdříve" a využití návrhových vzorů a UML bude parádní pro vymýšlení jak mám funkcionalitu programu navrhnout, šikovná metodika, např. programování řízené testy a právě pochopení propojení třída - objekt - metody mi umožní program konkrétně zapsat. Tak vývojařinu v současné době chápu, pokud se mýlím, nevadí, člověk se stále učí.

Zatím se loučí

Orel


gaspoda

  • Plný člen
  • ***
    • Příspěvků: 141
    • Zobrazit profil
Pro úspěšný lov potřebuji mít v ruce nůž a návnadu. I přes můj kód však stačí mít jen jediný předmět, např. nůž

Ty tam máš podmínku:

Kód: [Vybrat]
  if(!navnada.isIn(me) && !nuz.isIn(me))
ale to není správně utvořená negace. Ty říkáš, že potřebuješ nůž A ZÁROVEŇ návnadu. Co je tedy opakem, kdy akci nedovolíš? Když nemáš nůž NEBO nemáš návnadu. Zapoměl jsi prohodit tu logickou spojku. Je to stejné, jako když řeknu, že půjdu ven, když budu mít čas A ZÁROVEŇ bude hezky. Čili nepůjdu ven, pokud buď nebudu mít čas, NEBO bude ošklivě. Říká se tomu DeMorganovy zákony a dají se zapsat jako !(A * B) = !A + !B či !(A + B) = !A * !B (hvězdička značí logický součin, tedy "a zároveň", plusko logický součet, tedy "nebo" a vykřičník je negace). Měl bys tedy napsat:

Kód: [Vybrat]
  if(!navnada.isIn(me) || !nuz.isIn(me))
a ještě se text opakuje, místo aby hra zobrazila blok uvedený v else. Předměty typu PresentLater se v pořádku objeví:

Ty tam říkáš:

Kód: [Vybrat]
  if(!moved)
Ale dej si pozor, koho se ptáš. Protože píšeš přímo vlastnost moved bez určení objektu, tak se ptáš objektu, ve kterém je napsaný if() a to jsou jámy, které se nikdy nepohnou. Možná bys měl testovat např. orliMaso.moved, potom to bude zabírat, dokud se maso nepohne, čili než ho sebereš. (Teď jsi nejsem jistý, jestli makePresent způsobí pohnutí masa, ale myslím, že ano - záleží, jestli chceš změnit text po objevení nebo až po sebrání a podle toho přizpůsobit podmínku. Můžeš také zkoušet testovat if(orliMaso.location != nil))

V referenční knihovně si vyhledám Akce a rozkliknu LieOnAction, pokud dobře chápu, zjišťuji, že se jedná o třídu dědící od tříd TAction a Action a také od BasicProd a Resolver

Ano, od TAction a BasicProd přímo a ty zase od Action a Resolver.

(které jsou však označeny jako objekty, i když po rozkliknutí jako třídy

Třídy poznáš, že zpravidla začínají velkým písmenkem a objekty malým. Nicméně klíčové slovo "object", které v manuálu vidíš napsané poblíž BasicProd a Resolver neznamená, že BasicProd je objekt, je to třída, ale dědí od speciální třídy nazvané "object", což je označení, že třída nemá žádné předky v knihovně, od kterých by dědila vlastnosti.


Citace
   An object must always have at least one superclass, but you can use the special class name "object" if you want a generic object that is not based on another object that your program defines.

V sumáři vlastností a metod třídy LieOnAction vidím několik akcí xxx dobj xxx (snad se vyjadřuji přesně), nikoliv však akci s názvem dobjFor
(LieOn), kterou potřebuji použít.

V prvé řadě dobjFor(LieOn) bys měl hledat na herním objektu (potomku Thing), kde se definuje chování akce. Třída LieOnAction se přímo o konkrétní chování nestará, všechny akční třídy jsou součastí parseru, starají se o rozpoznání akce v příkazu hráče a pro samotné vykonání pak zavolají preCond, verify, check a nakonec action na herním objektu.

Zde mě zaráží, že jsem nedohledal žádné propojení s třídou LieOnAction, tady něco chápu špatně.

Potřebuji pracovat s věcmi v inventáři, takže se juknu blíže na aplikaci této metody ve spojení s třídou Thing a dostávám předpis:

Kód: [Vybrat]
    dobjFor(LieOn)
    {
        preCond = [touchObj]
        verify() { illogical(&cannotLieOnMsg); }
    }

Já se však ve svém kódu snažím využít nikoliv preCond a verify (mohu je chápat jako atributy metody?),

Zápis s dobjFor() samo o sobě ještě není ani metoda, ani vlastnost, ale taková zkratka v zápisu, aby vypadal více hierarchicky a méně se opakovalo psaní. Říká se tomu propertyset a je to specialita TADSu. To, co takhle napíšeš, tak se změní na metodu (verify, action,...) či vlastnost (preCond) tak, že se název zkombinuje z obou částí:

Kód: [Vybrat]
    preCondDobjLieOn = [touchObj]
    verifyDobjLieOn() { illogical(&cannotLieOnMsg); }

Ale jinak ano, teď už hledáš na správném místě. V těchto místech se skrývá chování, které chceš ovlivnit.

ale verify, check a action společně s podmínkou začínající příkazem if a končící else, nakonec se snažím
umožnit hráči nejen si s potřebnými předměty lehnout do jámy, ale také při položení obou věcí dosáhnout
téhož pomocí dobjFor(PutIn) asDobjFor(LieOn).

Tak to ale pozor, o jakou akci se jedná. Když se snažíš jednu akci přesměrovat na jinou, nesmíš míchat různé druhy akcí dohromady. Jednak bys nemohl přesměrovávat akci, co žádné objekty nebere na akci, co bere jen přímý objekt a podobně akci, co bere přímý objekt na akci, která používá přímý i nepřímý objekt. To není kompatibilní. Ve tvém příadě LieOn je akce, kde hráč ulehá na objekt a to není kompatibilní s akcí, kdy objekt se položí na jiný objekt. I když nemůžeš použít asDobjFor, tak můžeš obě možnosti naprogramovat velmi podobně, ale zvlášť.

Pokud dobře chápu, potřebuji rozšířit funkcionalitu metody dobjFor(LieOn) tak, abych mohl využít atributů
verify, check a action. Je nepříjemné, že můj zápis hra nebere jako chybu (syntaktická to pro kompilátor
není, sémantická však ano, pokud dobře rozumím, i tak je chování zvláštní, neměl by TADS při překladu zařvat,
že se snažím volat neexistující atributy?).

Neměl by řvát, je to obráceně. Ty je nevoláš, ty je vytváříš (a máš možnost vytvořit jakoukoliv metodu či proměnnou chceš), volá je akce v knihovně. A nebo pokud se spleteš a nepojmenuješ metodu správně nebo z jiného důvodu ji nikdo nechce, tak ji holt nikdo nezavolá.

Zde se ale už dostáváme dost do teorie a možná většina tvých problémů zmizí, když vyřešíš ty drobné chybky v logice ifů zmíněné na začástku
mé odpovědi.

Něco mi holt uniká, nechápu zatím propojení mezi třídou LieOnAction a metodou dobjFor(LieOn), tuším, že zde
takové propojení bude např. přes třídu Thing a její metody.

Ze strany akční třídy se spouští vykonání akce, např. kdyby sis našel ve třídě TAction metodu verifyAction(), tak tam uvidíš, jak zde akce volá tu verifyDobjLieOn tvé jámy. Ale pointa je, že kód LieOnAction bys ani neměl číst, to jsou ty nízkoúrovňové věci, které sice tvoří jádro zpracování, ale jako autor hry tu nic užitečného nenajdeš.


Kroužící orel

  • Plný člen
  • ***
    • Příspěvků: 205
    • Zobrazit profil
    • Šťastný statek
No tak to je paráda, s negací jsi vše krásně vysvětlil, jak vidno, přečíst si o ní něco v knížce je pěkné, ale opravdové využití je něco jiného, zvláště když neznám zákony Herr De Morgana, díky za ně. Pokud potřebuji prověřit, zda hráč nemá nůž nebo návnadu, musím využít OR, vše jasné. Jsem moc rád, že se právě tato chyba stala, protože se mi vryje do paměti víc, než kapitola o těchto zákonitostech pojednávající v různých příručkách.

Hmm, pomocí if(!moved) nic nevyřeším, musím se ptát, zda se pohnul předmět Orlí maso. Konstrukce if(!orliMaso.moved) je zcela funkční a situace funguje tak jak má, metoda makePresent pohnutí orlího masa způsobí a potíž je vyřešena. Na druhou stranu if(orliMaso.location != nil) využít nemohu, zde se vždy provede blok za else a dostávám hned hlášení "Orlí jáma už mi pomohla dostatečně, vzhůru za dalším dobrodružstvím. " stejně jak by již akce byla provedena.

Referenční manuál mě tady trochu mátl, když si rozkliknu LieOnAction , vidím hnedle v záhlaví informaci:
class LieOnAction :   TAction      // after macro expansion
a poté prohlížím Superclass Tree - LieOnAction tedy dědí od TAction a Resolver a právě zde jsem byl zmaten tím, že pod BasicProd a Resolver vidím uvedeno object, hmm, teď je mi po Tvé informaci jasné, že se jedná o speciální třídu, kterou manuál uvádí, ale tuhle informaci jsem přehlédl. Tady je to trochu jinak, než v Javě, kde pokud dobře chápu jasně vidím rozdíl mezi třídami a objekty, ve Tvém manuálu jsem se ale dočet, že rozdíl mezi nimi je v TADSu mnohem menší, na to si budu muset zvyknout. Nevadí, mám alespoň možnost porovnat obé, tyto jazyky tvořili zkušení programátoři a určitě sakra dobře věděli proč zvolili právě tento styl.

V tomto konkrétním případě mě tedy zajímá metoda dobjFor(LieOn) - method of Thing in thing.t[10072], kde vidím Tebou popsané preCond a verify, ještě jednou jsem si projel Tvůj manuál, vše je vysvětleno v sekci Akce s objekty na akci "sněz jahody", paráda. Já jsem chybně chápal dobjFor() jako metodu, jasně, jedná se o zkratku nebo jak píše Erik v Getting Started na straně 71 makro, tady jsem si o propertysets přečetl více. Míchání dvou druhů akcí dohromady tedy není možné, chápu to snad správně jako pokus využít metodu třídy z jiné třídy, která jí nemá definovanou (ovšem to je případ z Javy, zde se jedná o makro).

Hmm, parser tedy nebude řvát, pokud metodu pojmenuji chybně, jasné, tady se jedná nikoliv o chybu v zápisu, ale v logice programu. Změna zápisu ifu vše vyřešila, jsem ale vděčný i za tuto informaci, teorii a nízkoúrovňovou logiku TADSu bych časem také rád pochopil, zdá se mi totiž, že OO jazyky jsou v této teorii o tom samém a jejich tvůrci se jen snaží přiohnout si je po svém, diskuze o tom "nej" jazyku jsou poté zcela zbytečné. Po Tvých informacích ještě více, než kdykoliv předtím vidím, že je opravdu jedno, jaký jazyk člověk zpočátku zvolí, TADS a Java se mi po praktickém využití každého z nich krásně spojí, musím jen co nejvíce programovat. A časem pochopím třeba i to, proč je Java tak ukecaná, ale díky tomu jednoduchá a čitelná pro čtení, proč se vývojáři jazyka C a následně C++ rozhodli pro své konstrukce nebo proč je Ada tak tvrdě striktní, ale např. pro mě ještě o chlup čitelnější, než zápis Javy. OOP bude možná přehlednější a pro budoucí rozšíření programu vhodnější, než strukturovaný zápis, to ale musím zjistit vlastní praxí, kdo ví a vše má svůj dobrý důvod.

Teď je drobet náročnější, že děti nejsou ve škole, takže na ranní vývojařinu mnoho času nezbývá, budu ale pokračovat jak budu moci, abych hru dokončil co nejdříve.


Kroužící orel

  • Plný člen
  • ***
    • Příspěvků: 205
    • Zobrazit profil
    • Šťastný statek
Na hře stále pracuji, děti máme doma a také tvořím nové stránky pro MŠ, postupuji však dále a to je hlavní. Setkal jsem se s pár záludnostmi u rozhovorů, všechny se mi podařilo dát dohromady, mnohdy stačí dát si oddych a další den řešení přijde, to asi zná každý z nás. Každopádně už se cítím mnohem jistější a mohu zúročit zkušenosti z Exotera, Tvého návodu a dalších her, takže se mi možná podaří hru dokončit bez dalších dotazů, uvidíme. Pomáhá i základní znalost Javy, konečně vidím tu výhodu OOP, programuje se mi díky němu přeci jen pohodlněji a orientace v kódu a v dokumentaci je mnohem snažší.

Mimochodem vyšla nová verze QTADS, jsou tam drobná vylepšení, hlavní však je, že se stále vyvíjí, k hraní na počítadle je to můj nejoblíbenější interpretr.


Kroužící orel

  • Plný člen
  • ***
    • Příspěvků: 205
    • Zobrazit profil
    • Šťastný statek
Pokračuji dále v tvorbě, již několik dní se snažím vyřešit správnou definici metody PresentLater, zde mě však zastavila nečekaná věc. Ve hře se vyskytuje místnost Napajedlo pro koně, kde se nacházejí otisky koňských kopyt. Pomocí dobjFor(LookIn) a příkazu "koukni se do otisků" (koukni se na otisky nelze využít, protože parser příkaz pochopí jako prozkoumej otisky) naleznu zvláštní stopu. Tu definuji stejně jako otisky s tím, že po příkazu koukni se do stopy by se mělo objevit houští. I přes definici stejné metody dobjFor(LookIn) , která funguje v předchozím případě se tak ale nestane a získávám stejnou odpověď, jako bych se již do stop díval, ale houští nevidím.

Toto chování je mi zatím nepochopitelné, když jediný rozdíl mezi objekty otiskyKonskychKopyt a zvlastniStopa je ten, že zvlastniStopa představuje PresentLater a stejně tak houští. Využívám zde kontejnerovou hierarchii a hra se v pořádku zkompiluje, výsledek je však následující:

// začátek transskriptu hry
Napajedlo pro koně
Mělká zátočina slouží koním jako napajedlo, což je vidět ze všudypřítomných otisků kopyt, které lovce opravdu zaujmou, ani neví jak. Momentálně tu žádný řechták není, koním dost dobře stačí i čerstvá orosená ranní tráva. Paprsky slunce se na hladině krásně lesknou.
Můžeš jít na severovýchod, východ a na jihozápad.

>prozkoumej otisky
Stopovat zde by bylo nemožné, vidíš nejrůznější mozaiku těch nejmenších poníkových i mohutných těžkých stop. Ale moment, jedna je taková zvláštní.

>koukni se na otisky
Stopovat zde by bylo nemožné, vidíš nejrůznější mozaiku těch nejmenších poníkových i mohutných těžkých stop. Ale moment, jedna je taková zvláštní.

>koukni se do otisků
Tady je jedna opravdu zvláštní stopa, která koním určitě nepatří.

>r
Napajedlo pro koně

Mělká zátočina slouží koním jako napajedlo, což je vidět ze všudypřítomných otisků kopyt, které lovce opravdu zaujmou, ani neví jak. Momentálně tu žádný řechták není, koním dost dobře stačí i čerstvá orosená ranní tráva. Paprsky slunce se na hladině krásně lesknou.
Můžeš jít na severovýchod, východ a na jihozápad.

>prozkoumej stopu
Jedna stopa se od ostatních dost liší, je mnohem menší a vypadá trochu jako psí. Téměř se ztrácí, ale když ji sleduješ, vypadá to, že někam vede.

>koukni se na stopu
Jedna stopa se od ostatních dost liší, je mnohem menší a vypadá trochu jako psí. Téměř se ztrácí, ale když ji sleduješ, vypadá to, že někam vede.

>koukni se do stopy
Stopa už Ti pomohla k nalezení toho, cos potřeboval vidět.

>prozkoumej houští
Nic takového jako „houští“ tu nevidíš.
// konec transskriptu hry

Mohu poprosit o kontrolu tohoto chování? Také jsem si všimnul, že pokud objekt definuji jako Immovable, CustomImmovable nebo Fixture, v textu nebo po příkazu "rozhlédni se" se nezobrazí, ale bez tohoto označení ano. Byl bych rád, aby byl vždy objekt, který hráč nalezl, viditelný, ale nebylo jej možné sebrat, zde se ještě zkusím juknout do knihovny, proč se tak děje.

V příloze jsem stejně jako minule připravil hru jen s několika místnostmi včetně Napajedla pro koně.


gaspoda

  • Plný člen
  • ***
    • Příspěvků: 141
    • Zobrazit profil
příkazu "koukni se do otisků" (koukni se na otisky nelze využít, protože parser příkaz pochopí jako prozkoumej otisky) naleznu zvláštní stopu.

A nemáš to už trochu překombinované? Určitě by to chtělo takový příkaz hráče předem naučit a asi s nějakým synonymem, osobně bych doporučil třeba spíš vyjít z Readable a tedy příkaz "přečti stopy" a doplnit ho o synonyma a různá přeměrování, ale asi by mě nenapadlo to dávat do sebe jako kontejnery, to mi připadá zbytečné. (Asi jsi to udělal, abys měl povolený "podívej se do", ale to můžeš udělat i bez kontejneru.)

Tu definuji stejně jako otisky s tím, že po příkazu koukni se do stopy by se mělo objevit houští. I přes definici stejné metody dobjFor(LookIn) , která funguje v předchozím případě se tak ale nestane a získávám stejnou odpověď, jako bych se již do stop díval, ale houští nevidím.

Toto chování je mi zatím nepochopitelné, když jediný rozdíl mezi objekty otiskyKonskychKopyt a zvlastniStopa je ten, že zvlastniStopa představuje PresentLater a stejně tak houští. Využívám zde kontejnerovou hierarchii a hra se v pořádku zkompiluje, výsledek je však následující:

V TADSu jsou dvě třídy pro realizaci skrytých objektů. Hidden a PresentLater. Každá funguje trochu jinak a PresentLater funguje tím způsobem, že hra objekt přesune při kompilaci pryč (zvlastniStopa.location bude nil) a v okamžiku přesunutí zvlastniStopa.makePresent(); se vráti zpět. Jenže v ten okamžik se nemůžeš ptát if(zvlastniStopa.moved), protože jsi ji právě přesunul. Nechtěl ses ptát na housti.moved?

Také jsem si všimnul, že pokud objekt definuji jako Immovable, CustomImmovable nebo Fixture, v textu nebo po příkazu "rozhlédni se" se nezobrazí, ale bez tohoto označení ano. Byl bych rád, aby byl vždy objekt, který hráč nalezl, viditelný, ale nebylo jej možné sebrat, zde se ještě zkusím juknout do knihovny, proč se tak děje.

Ano, to tak je, protože se to předpokládá jako obvykle žádoucí, samozřejmě jde změnit nastavením nekteré z uvedených vlastností na true:

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

Pokud to uděláš, vylistuje se podobně, jako bežné položené předměty (vidíš tu...) Ale jak se praví v popisku, většinou spíš budeš chtít buď zapracovat popis stop přímo do popisu místnosti, nebo pokud se o nich chceš zmínit ve výpisu místnosti prominentně, tak nastav u stop specialDesc a z toho se pak udělá samostatný odstavec.


Kroužící orel

  • Plný člen
  • ***
    • Příspěvků: 205
    • Zobrazit profil
    • Šťastný statek
Moc děkuji za velmi rychlou odpověď, upřímně řečeno nešlo mi o povolení příkazu "podívej se do", ale kontejnerová hierarchie mě napadla hnedle poté, co jsem potřeboval postupně odhalovat nové objekty. Krásně mě totiž inšpirovala hra Heidi, kde je podobná situace využita u prstenu v hnízdě na stromě a já si po tom věčném študiu jejích zdrojáků a samozřejmě i Základny pár pasáží už pamatuju. Osobně mi právě kontejnery zde připadají přehledné, ale třeba se mýlím a je zde elegantnější řešení, zkusím se na něj ještě juknout (to bude asi ta refaktorizace = optimalizace kódu, kdy vymažu nadbytečný kód a nahradím jej štíhlejším, mám v el. podobně zajímavou knížku na toto téma s názvem Čistý kód - určena primárně pro Javu, ale našel jsem i ekvivalenty pro Python a C++, na vše se časem juknu).

Ajaj, u PresentLater jsem dopadl podobně jako předem u potíží s Orlí jámou, tam jsem nepochopil negaci a zde se ptám na již neexistující objekt Zvláštní stopa. Ano, housti.moved vše řeší a následná úprava dobjFor(LookIn) právě u houští s využitím if(bizoniKost.moved && chrestidlo.moved) také pomohla. Ještě jsem stopy označil jako Readable s tím, že příkaz "podívej se do" = "přečti", využití dobjFor(Read) asDobjFor(LookIn) zařídí vše potřebné, zde mám v Základě bezpočet příkladů. Ještě jednou jsem si přečetl sekci Hidden a PresentLater ve Tvém návodu, mix-in třída PresentLater v tomto případě řeší přesně to, co potřebuji.

Ano, já opravdu využívám u většiny objektů vlastnost CustomImmovable z třídy NonPortable, zkusil jsem si různé možnosti, ale nejvíce mi vyhovuje využití specialDesc u stopy a houští. Rád bych, ale se v reakci na rozvíjející se příběh tyto objekty ukazovaly a toto řešení je pro mé potřeby ideální (i když mohu pomocí ifů změnit i popis přímo v místnosti jak je to na více místech v Základně).

Já teď ve volných chvílích zkouším kromě TADSu i Javu a Python, rád se probírám definicemi OOP z různých pohledů, je to někdy docela terminologický guláš. Zatímco v Javě je mi rozdíl mezi třídou, objektem a metodou jasný, v Pythonu se, i když vše je objekt, setkávám mimo metody i s funkcemi a to ani nemluvím o OOP v Objektovém Pascalu nebo v Adě. Naštěstí je to stále o posílání zpráv objektům a využívání jejich metod, jen to musí jednomu docvaknout, viz můj dnešní a minulý dotaz. Každopádně i když mi to zpočátku přišlo trochu nereálné, dnes už vidím, že TADS3 se opravdu dá využít jako první jazyk pro výuku programování a principů OOP, to je paráda, jen to sakra trvá, už chápu, proč je programátorů stále nedostatek. Postupně jdu vyvíjet dále, baví mě to čím dál víc a to je hlavní.


gaspoda

  • Plný člen
  • ***
    • Příspěvků: 141
    • Zobrazit profil
Moc děkuji za velmi rychlou odpověď, upřímně řečeno nešlo mi o povolení příkazu "podívej se do", ale kontejnerová hierarchie mě napadla hnedle poté, co jsem potřeboval postupně odhalovat nové objekty.

Asi to můžeš řešit i pomocí kontejnerové hierarchie, jen mi v tomto případě přišlo trochu nadbytečné. Určitě by kontejnery byly na místě, pokud bys měl třeba písek a stopy v písku nebo stopy na něčem, pak TADS umí chápat, že něco je v něčem (viz i příklad s prstenem v hnízdě) a třeba se ptát ">prozkoumej stopy / A které stopy máš na mysli, stopy v písku nebo stopy na mostě?" apod. Ve tvém příkladu ale jsou spíš tak jako vedle sebe, jen prozkoumáním jedněch si všimneš druhých.

PresentLater by fungoval, i kdyby objekty nebyly v sobě, jde jen o to na jaký příkaz pak pověsíš zviditelnění. Jediné co, že kontejner má povolený (verify) příkaz na podívej se do, takže to nemusíš dělat a napíšeš jen action(), tak ušetříš jeden řádek.

Ještě bych si také dával trochu pozor na slovník. Máš tam vidět objekt otisky, ale v popisu říkáš "i mohutných těžkých stop.". Zde prozrazuješ slovo "stopa" dřív, než hráč objeví zvláštní stopu a to může trochu zmást, protože se hráč může pokusit prozkoumat stopu dřív, než ji zviditelníš. Je dobré si trochu hlídat, jaká podstatná a přídavná jména v popisech píšeš.

Zatímco v Javě je mi rozdíl mezi třídou, objektem a metodou jasný, v Pythonu se...

V Pythonu je spousta WTF momentů... Ale jsem rád, že tě to baví.


Kroužící orel

  • Plný člen
  • ***
    • Příspěvků: 205
    • Zobrazit profil
    • Šťastný statek
Ano, souhlasím, já využívám kontejnery jakoby bez předmětů v nich, uvedl jsi pěkný příklad s tím pískem a stopami. Zde je nepotřebuji, stačí malá úprava, otisky a zvláštní stopu definuji pouze jako CustomImmovable, u stopy ještě Readable a objekt typu kontejner využiju jen u houští, které obsahuje další dva předměty, tam to dává smysl. Metodu PresentLater mám definovanou správně i bez kontejnerů, alespoň to tak vypadá, aktuální zdrojový soubor mistnostNapajedloProKone.t funguje nyní bez potíží.

Strašně moc Ti děkuji za parádní postřeh s těmi stopami, jasně, jako hráč bych je určitě zkusil prozkoumat ještě před kouknutím se do otisků. Tohle si musím hlídat, ještě projedu všechny zdrojáky, kde by se tento problém mohl vyskytnout - je více, než možné, že to nebude jediný případ. Nechtěl jsem zatím zveřejňovat žádné zdrojáky, ale co se dá dělat, takhle to je lepší a věřím, že si hru užiješ, je toho tam naštěstí mnohem více, než jen orlí jámy a pár řechtákových stop.

He, he, to jsi mě pobavil, na WTF momenty jako začátečník narážím ve všech jazycích, vím ale, že jsme se v minulosti o tomto bavili a doporučoval jsi začít nějakým neskriptovacím. Já tak nějak tuším, že Python není ouplně to nej pro začátečníka, už jen když se juknu na zdroják v Javě, je pro mě koukatelnější, než třeba Pythoňácký, na to si ale zvyknu - každopádně kdo ví, Python se k výuce využívá dnes asi docela často a důvod zde určitě bude (minimálně ta interaktivní konzole stojí za to, i když např. v Javě mám JSHELL). Každopádně Java se mi zdá fajn tak nějak na všechno (plus výborné příručky a bezva IDE), ale Python ať už je jakýkoliv, má obrovskou komunitu včetně české (Pyladies, Czechitas, kurzy KSP). Bez Tebe bych se v TADSu moc daleko nedostal, se dvěma výše uvedenými jazyky se také pomoci dočkám, takže proč do toho nejít (a můžu prozkoumávat i opravdu veliké projekty typu IS, v Pythonu Odoo a v Javě třeba A(I)dempiere). Stejně jde hlavně o princip, zaměřil jsem se na OOP, který mě svým stylem zaujal a pak už ho jen naroubuju na konkrétní jazyk (a je mi fuk, zda to bude C++, Ada nebo Objektový Pascal, všechny mají něco do sebe a třeba Pascal s Adou u mě díky svému užvatlanému stylu begin - end nebo neustálému with - use bodují v čitelnosti i na Javou).

Jo, vývojařina mě baví, linux už jsem si vybral, i když to trvalo pár let zkoušení - Arch mi sedne opravdu na všechno a zvládnu v něm vše, co potřebuji, ohledně jazyka uvidím později. Žádný systém nebo jazyk není lepší nebo horší stejně jako vše ostatní v životě, takhle to beru a je mi hej. Vývojařinu není problém spojit s rodinou, koňmi i dalšími zájmy, když opravdu chci, čas si vždy najdu.

Měl bych dotaz na Klub Kapsa, je na něj odkaz z tads.cz a už dříve jsem jeho stránky prozkoumal. Fungujete stále (teď třeba vzdáleně) s využitím C++ a grafických knihoven s IDE QT Creator? Teď jsem zjistil, že je k mání i kroužek Pythonu pro mladší účastníky. Mě by zajímaly reakce dětí, jak se na tyto jazyky dívají a zda se pro výuku osvědčily? Dříve jsem na táborech dětem také v učebně ukazoval něco v linuxu a počítačovém mapování, teď už sotva stíháme program venku a u koní, takže jsem počítadla zcela vyškrtnul, proto by mě zajímaly Tvé zkušenosti.