Diskuze o textových hrách

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

pedromagician

  • Globální Moderátor
  • Starší člen
  • *****
    • Příspěvků: 309
    • Zobrazit profil
    • Pedro - blog
zaujímavé poučné, už sa neviem dočkať ďalšej časti :-)
pedro.pohroma.de
txt.pohroma.de


gaspoda

  • Plný člen
  • ***
    • Příspěvků: 141
    • Zobrazit profil
Jasně, zase ve čtvrtek ráno, konkrétně v 6.00 (to je takové to klasické Technoplanetí ráno ;-)) Tentokrát zaplníme místnosti spoustou nejrůznějších objektů, ať už přenosných předmětů či nepřenosných dekorací. Vysvětlíme si pojmenování objektu a zadání jeho slovníku i spoustu dalších užitečných vlastností. A nakonec v poslední pokročilé kapitolce dojde i na objekt "chrápání".


gaspoda

  • Plný člen
  • ***
    • Příspěvků: 141
    • Zobrazit profil
Tak dnes vyšel další díl o kontejnerech a jejich hierarchii. Na příště mám nachystaný díl o akcích, čímž se uzavře kolečo znalostí, které je potřeba znát pro každou hru. Poctivě však už chystám díl o NPC postavách, mám popsaný skoro celý mechanismus rozhovorů, akorát jsem narazil na malý zádrhel, že už teď je tak dlouhý, jako ostatní články, a potřebuji do něj ještě dostat samotné postavy, jejich stavy a agendu. Tak doufám, že to alespoň ti nejodvážnější z vás přečtou. Jo a najde se dobrovolník, který napíše Syrečky? :-)


tekket

  • Mladší člen
  • **
    • Příspěvků: 68
    • Zobrazit profil
Narazil jsem v knihovně na takovou skrytou podivnost u standardních odpovědi na CutWithAction ve VerbRule(CutWithWhat) - když napíšu uřízni strom - napíše mi zprávu(špatně) Co jím chceš uříznout, zatímco přeřízni strom napíše(správně) Čím ho chceš uříznout

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

Také mě zaujalo, že existuje CutAction, ale nepoužívá jí žádné VerbRule a místo toho je zřejmě ono CutWithWhat, které prakticky pouze upozorňuje na absenci iobj


gaspoda

  • Plný člen
  • ***
    • Příspěvků: 141
    • Zobrazit profil
Ano, vidím chybu, že synonymum přezízni na rozdíl od uřízni bylo jen u akce CutWithWhat a ne u CutWith. Tím pádem došlo k tomu, že přeřízni nožem liánu bylo vyhodnoceno jako:

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

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

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

Pomohla tato odpověď, nebo ještě zbyl nějaký problém?


tekket

  • Mladší člen
  • **
    • Příspěvků: 68
    • Zobrazit profil
ještě jsem to nezkoušel, ale myslím, že přidání synonym by to zmatení parseru mohlo vyřešit.

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

Zatím si také nejsem jistý do jakého objektu dát akci, když se jedná o akci zahrnující přímý a nepřímý objekt.


gaspoda

  • Plný člen
  • ***
    • Příspěvků: 141
    • Zobrazit profil
Zatím si také nejsem jistý do jakého objektu dát akci, když se jedná o akci zahrnující přímý a nepřímý objekt.
V podstatě si můžeš vybrat. Obvykle je potřeba se buď řídit tím, jak je akce naprogramována v knihovně, pokud se snažíš upravit či změnit výchozí chování knihovny, nebo si vybereš ten objekt, kde je výsledek akce specifičtější. Tím myslím, že když máš pět provazů a přeříznout jdou jedním jediným objektem, tak akci naprogramuješ u něj. Když máš jeden provaz a přeříznout jde pěti různými objekty, naprogramuješ akci u provazu apod.


tekket

  • Mladší člen
  • **
    • Příspěvků: 68
    • Zobrazit profil
Jasně, to dává smysl. Takže v tomto případě by byl nejlepší nůž, i kdyby ve hře reálně fungoval příkaz jen na jeden objekt, protože by mohly existovat další situace, ve kterých by dávalo smysl, že chci něco uříznout, i kdyby to mělo hodit jen odezvu, že to nejde.

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

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


tekket

  • Mladší člen
  • **
    • Příspěvků: 68
    • Zobrazit profil
Ještě pro úplnost k třídě PreferredIobj. Ještě by se mělo do VerbRule(CutWith) přidat: preferredIobj = PreferredIobj

Alespoň bez toho mi to nefungovalo.


gaspoda

  • Plný člen
  • ***
    • Příspěvků: 141
    • Zobrazit profil
Jasně, to dává smysl. Takže v tomto případě by byl nejlepší nůž, i kdyby ve hře reálně fungoval příkaz jen na jeden objekt, protože by mohly existovat další situace, ve kterých by dávalo smysl, že chci něco uříznout, i kdyby to mělo hodit jen odezvu, že to nejde.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Ty akce bez předložek (MoveWith, TurnWith, BurnWith, CutWith, CleanWith, (Un)LockWith, (Un)ScrewWith) nemám zatím moc prozkoušené a doladěné.
« Poslední změna: 6. Listopad 2015 - 19:46 od gaspoda »


tekket

  • Mladší člen
  • **
    • Příspěvků: 68
    • Zobrazit profil
Citace
Sladění synonym u CutWithWhat a CutWith pomohlo. Jen odezva na uřízni lianu odpoví - Co jí chceš uříznout.

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

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

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

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

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

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

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

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

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

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

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

Jinak, nemám založit další diskuzi, abych to tady netapetoval?


gaspoda

  • Plný člen
  • ***
    • Příspěvků: 141
    • Zobrazit profil
Jo víš, co jsem ještě udělal? Já smazal z CutWith tu variantu s opačným pořadím, která nedávala smysl:
Kód: [Vybrat]
VerbRule(CutWith)
    ('uřízni' | 'uříznout' | 'přeřízni' | 'přeříznout') singleDobj singleIobj
    : CutWithAction
    verbPhrase = 'uříznout/řež{eš}/uřízl{a} (co) (čím)'
    askDobjResponseProd = singleNoun
    askIobjResponseProd = singleNoun
;

Co se týče diskuse, to je asi celkem jedno, on se stejně nikdo moc na seriál neptal, tak to ani moc nevadí. Samozřejmě pokud by vznikly dotazy k určitým tématům ve větším množství, tak by bylo užitečnější je mít v samostatných vláknech s titulkem vyjadřující to které téma, aby se v tom ostatním lépe hledalo, pokud by řešili stejnou věc.


tekket

  • Mladší člen
  • **
    • Příspěvků: 68
    • Zobrazit profil
Tak v tomhle byl problém. Je zajímavé, že i když se vymaže ta varianta s opačným pořadím, tak to příkaz s opačným pořadím pochopí.


gaspoda

  • Plný člen
  • ***
    • Příspěvků: 141
    • Zobrazit profil
Parser TADSu je pro mě zdaleka nejsložitější část, jejíž vrstvy loupu jen velice pomalu. Kdysi jsem si myslel, že musím ve VerbRule uvést obě možná pořadí dobj a iobj, aby si parser mohl vybrat tu správnou interpretaci odpovídající pořadí, v němž zadal objekty hráč.

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

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

S příkazy, ve kterých není určena role objektů předložkou, jsem si dlouho lámal hlavu, až jsem problém nadhodil na anglickém fóru a Mikawa mi poradil řešení. Po resolvování slotů na herní objekty, kdy už je možné o objektech zjišťovat informace, jako třeba jejich třídu, se provede případné prohození slotů mezi sebou. Detaily jsou na: http://www.intfiction.org/forum/viewtopic.php?f=10&t=5480


tekket

  • Mladší člen
  • **
    • Příspěvků: 68
    • Zobrazit profil
Teď si říkám, co se stane, když mám nůž s třídou PreferredIobj a chci hi použít v akci, kde ho chci mít jako dobj?