Diskuze o textových hrách

Seriál o programování textových her v TADS 3

gaspoda

  • Plný člen
  • ***
    • Příspěvků: 141
    • Zobrazit profil
poslední verze Workbenche 3.1.3 je alespoň na mých počítadlech dosti nestabilní a ani WINE v Linuxu na tom není jinak, s trochou trpělivosti se však použít dá.

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

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

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

Každopádně pokud nebudeš jen sršit přehnaným optimismem a skutečně se i pokusíš něco udělat, tak rád ve fóru zodpovím otázky, na které nevyhnutelně narazíš. Každopádně se snaž udržet na uzdě a nejprve zkoušej jednoduché věci, tedy deklarace místností a objektů, různé typy objektů a jak se chovají a až to budeš mít bezpečněji v ruce, tak teprve zkoušej různé akce a složitější interakci. Moje série článků je opravdu jen stručný přehled, ale ke skutečné práci to chce přečíst Learning TADS 3, alespoň kap. 1-9.


Kroužící orel

  • Plný člen
  • ***
    • Příspěvků: 205
    • Zobrazit profil
    • Šťastný statek
Ano, s Workbenchem jsme na tom stejně. Já mám na notebooku staré Windows XP a Q4OS, do XP chodím spouštět pouze aplikace, které v Linuxu nedokážu stabilně emulovat a je odpojen od internetu, právě sem jsem instaloval poslední verzi TADS a krom toho, že jej nelze klasickým způsobem odinstalovat, padá tehdy, když zde založím nový projekt a vytvářím zdrojáky. Vyřešil jsem to jednoduše, zdrojový t soubor píši v linuxovém VIMu a debugguji ve Workbenchi spuštěným přes WINE, tam už mám vždy otevřený projekt a jen aktualizuji t soubor, zde alespoň zatím nemám problémy. Zvýraznění syntaxe funguje parádně, jediné, co chybí, je právě ten debugger, viz příspěvek jednoho uživatele také používacího QT Creator:

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

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


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

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

Jdu tvořit a určitě se budu ptát, už se těším...


Kroužící orel

  • Plný člen
  • ***
    • Příspěvků: 205
    • Zobrazit profil
    • Šťastný statek
Tak jsem se pomalu pustil do práce, hlídám nemocnou dcérenku, ale ve volných chvílích studuji manuál od Eveho a několikrát ten Tvůj, připravuji zatím Exoteří lokace a jejich propojení. Ještě bych se rád zeptal na jednu drobnost, abych se vyznal v místnostech a jejich pojmenování, potřebuji si připravit mapu. V dokumentaci TADSu jsem nenašel, zda přímo Workbench něco podobného podporuje a zatím využívám Dungeon Crafter. Ve WINE spustím starší verzi 1.41 i zatím nejnovější 3 Silver, v první vidím paletu nástrojů, ale pod emulátorem mi nefunguje export výsledné mapy, naopak u 3 export funguje bez problémů, ale nevidím paletu nástrojů, ufff, tohle opravdu zamrzí. Zatím to řeším tak, že v jedničce udělám snímek obrazovky a ten oříznu GIMPem.

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

Jak si u Základny řešil mapu pod Linuxem? Neznáš elegantnější řešení?


gaspoda

  • Plný člen
  • ***
    • Příspěvků: 141
    • Zobrazit profil
Na rozdíl od Inform7, které má i nástroje pro vykreslení mapy (myslím automaticky ze zdrojáku), tak Workbench připomíná spíš běžné programátorské vývojové prostředí a tyto věci jsou mimo jeho oblast zájmu. Existuje program Trizbort (http://trizbort.genstein.net/), který je však windowsový. Měl by ale umět do jisté míry zpracovat log hry a mapu automaticky vytvořit. Ovšem asi jen v angličtině. Pak ještě vím o IFMapperu (http://ggarra13.github.io/ifmapper/en/start.html), ale ani s ním nemám přímou zkušenost.

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

Spíš co jsem řešil, tak že jsem organizoval zdrojáky tak, aby každá místnost měla samostatný soubor, aby se ve všem dalo rychle zorientovat a snadno přecházet mezi různými místnostmi. Totiž když je vše pohromadě v jednom souboru a je tam už hodně objektů, tak je to hodně rolování a blbě se hledá, kde člověk má nějaký objekt. Navíc TADS kompiluje jen nezbytně nutné soubory, ve kterých nastala změna, takže se šetří čas.


Kroužící orel

  • Plný člen
  • ***
    • Příspěvků: 205
    • Zobrazit profil
    • Šťastný statek
Díky moc za info, Trizbort jsem vyzkoušel a ve WINE funguje, jen ten zpropadený export zlobí - v obrázku se zobrazí jen názvy lokací a ohraničení už ne. IFMapper je v tuto chvíli na serveru nedostupný, zkusím v pondělí. Takže zatím budu testovat Dungeon Crafter a Trizbort s využitím snímku obrazovky, je pravda, že u menšího počtu lokací to bude zcela dostačovat.

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

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

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



Kroužící orel

  • Plný člen
  • ***
    • Příspěvků: 205
    • Zobrazit profil
    • Šťastný statek
V příloze zasílám svůj první výtvor. Celý původní Exoter jsem dohrál a veškeré popisy místností, předmětů a hlášek jsem připravil do souboru Exoter.t. Ještě mě čekají hlášky, které se objevují v některých místnostech, na ty se zaměřím až na konec. Zkusil jsem připravit konektory místností a doplnit i pár předmětů. Hnedle na počátku je třeba dostat se z první místnosti mříží, nevím, zda je mé řešení takto OK, trochu kostrbaté, ale funguje. Vše, co chybí, by mělo být v komentářích, nyní se zaměřím právě na jejich obsah. Místnosti jsou nyní již přístupné, čeká mě hlavně doplnění předmětů a omezení u dveří. Původně jsem plánoval udělat pro každou místnost samostatný soubor, jen mi to alespoň zatím přijde nepřehledné, takže zatím zůstanu u zdrojáku jediného.

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

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

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



gaspoda

  • Plný člen
  • ***
    • Příspěvků: 141
    • Zobrazit profil
V příloze zasílám svůj první výtvor.
Proběhnul jsem to a pár postřehů posílám níže:

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

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

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

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

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

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

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

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

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

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

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

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


Kroužící orel

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

A nyní mé dotazy:

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

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

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

Kromě hidden objektů mě čeká nastudovat chování strážce a po jeho zabití manipulace s jeho předměty, podobné to bude i u draka a psa, rozsvícecní pochodně ve studni (o tom píšeš v návodu, takže by neměl být problém), naprogramování akce pádu do kupky sena nebo hráčovy smrti, pokud tam není. Dveře by měly být OK, ještě musím vyřešit omezení přechodu do lokace před jejich odemknutím, to nastiňuješ v manuálu, juknu se ještě na příklady v Heidi a u Eveho. Slovník předmětů jsem definoval, zatím jsem nepoužil pomnožný tvar. Mříž a pilník tedy zatím nechám být a budu se věnovat výše popsanému.


gaspoda

  • Plný člen
  • ***
    • Příspěvků: 141
    • Zobrazit profil
Nejprve jsem otevřené závorky zkusil vymazat, debugger ale nepochopil jak interpretovat mříž, takže jsem je vrátil na úroveň objektu, pokud je to takto správně.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Nicméně vřele bych se doporučil těmto problémům úplně vyhnout např. označením 'první diamant' apod.


Kroužící orel

  • Plný člen
  • ***
    • Příspěvků: 205
    • Zobrazit profil
    • Šťastný statek
Citace: Kroužící orel   2. Květen 2017 - 13:07
deklarace objektu
//Ano, na straně 11 jsem tuto informaci našel přesně tak jak píšeš. Nyní již používám všude zkrácený zápis s ukončovacím středníkem. A právě zde jsem v příkladu s první hrou našel direktivu noun, kterou jsem dříve používal, aniž bych věděl, co znamená.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

---

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

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

Ale v první řadě oceňuji Tvojí pomoc, je paráda, že se mám koho zeptat a jak rychle reaguješ na mé  dotazy. Stejně se snažím reagovat i já, pokud se mě lidi zeptají na něco z oblasti Linuxu a umím jim pomoci. Dal jsi si obrovskou práci s překladem, se Základnou a teď i s vysvětlováním, tady je krásně vidět, že kvalitní systém je hlavně o lidech. Tím spíš se těším na další programování a objevování, textovky nestárnou a možnosti TADSu jsem\prozkoumal zatím jen povrchně. Taky mi pomohl v přehodnocení mého názoru na programování, stojí to za to.


gaspoda

  • Plný člen
  • ***
    • Příspěvků: 141
    • Zobrazit profil
A právě zde jsem v příkladu s první hrou našel direktivu noun, kterou jsem dříve používal, aniž bych věděl, co znamená.

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

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

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

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

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

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

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

  • Proměnná (variable) je pojmenované místo v operační paměti počítače, do kterého lze uložit hodnotu. Je to něco jako paměť v kalkulačce, ale proměnné v počítači dokáží uložit různé typy hodnot, nejen čísla.
  • Třída (class) je návod, jak vytvořit objekt. Něco jako stavební plán domu, podle kterého zedník může postavit dům. Nebo mnoho stejných domů. Konkrétně definuje vlastnosti, tj. proměnné, které budou součástí objektu a k nim přidává metody, tj. funkce, které budou s objektem zacházet.
  • Objekt (object) je konkrétní balíček proměnných (tj. vlastností) v paměti počítače (to konkrétní obsazené místo paměti, které drží informace o něčem).
  • Vlastnost (property) je prostě proměnná, která je součástí nějaké třídy, potažmo objektu.
  • Metoda (method) je prostě funkce, která je součástí nějaké třídy a může manipulovat s objekty dané třídy.
 

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

Ano, přesně tak.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Jo, docela dobrý. Prolítl jsem zdroják a vedeš si dobře, žádné zásadní problémy tam nevidím.


Kroužící orel

  • Plný člen
  • ***
    • Příspěvků: 205
    • Zobrazit profil
    • Šťastný statek
Ohledně noun je vše jasné, budu používat vocabWords/gcVocab a zvyknu si na něj.

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

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

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

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

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

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

Zítra se zase dostanu k úpravě zdrojáku, takže budu makat a o výsledek se rád podělím. Až se dostanu dále, určitě bude zase nějaká ta nová otázka, tuším, že s akcemi, už se těším...


gaspoda

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

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

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

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

Hlavní poselství je, že bysis měl zvyknout vždy při přetěžování knihovních metod volat inherited. Vyhledej si to slovíčko fulltextem ve zdrojácích Základny, abys viděl příklady, kde a jak se to používá, to bude asi nejvíce ilustrativní. Nezavolání inherited musí být vědomé rozhodnutí, ne opomenutí.


Kroužící orel

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

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

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

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

Orel


Kroužící orel

  • Plný člen
  • ***
    • Příspěvků: 205
    • Zobrazit profil
    • Šťastný statek
Tak dnes jsem se konečně dostal k pokračování a alespoň něco se zadařilo.

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

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


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


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

Teď ještě musím vymyslet, aby se předměty objevily až po zneškodnění strážce, změnu textu pomocí if – else – end jsem už doplnil. Pokud vložím jediné plus, předměty lze sebrat, pokud dvě, jsou vidět jen před zabitím strážce – tady by možná byl vhodný kontejner, jen nesmím strážce nechat „zmizet“, na to se teď vrhnu. Pokud se mi vše podaří, podobnou situaci připravím u draka a psa.