18. Prosinec 2018 - 18:50

Autor Téma: akce po určitém počtu tahů  (Přečteno 569 krát)

ajs

  • Nováček
  • *
  • Příspěvků: 7
    • Zobrazit profil
akce po určitém počtu tahů
« kdy: 1. Listopad 2018 - 20:33 »
Ahoj všem.
Po několika letech jsem se pokusil (opět) o vytvoření nějaké té textovky.
Protože nejsem žádný programátor pátral jsem po nějakém jednoduchém enginu a našel hru "Základna na asteroidu" a sní i skvělý návod na programování v TADS 3 od gaspody.
Po několika dnech zkoušek jsem se rozhodl že začnu tvořit nějaký ten jednodušší celek.
Vzpomněl jsem si na svou první textovku Indiana Jones II na ZX spectrum a začal ji předělávat (podobně jako Kroužíci orel Exotera).

Měl bych na vás zkušenější dotaz.
Hráč je na začátku v letadle, které plachtí vzduchem bez pilota.
Hráč musí najít padák a vyskočit z letadla.
Pokud nemá na sobě padák tak umírá a je konec.
To mám OK.
Ale podle původní hry je nutné do určitého počtu tahů opustit letadlo dříve než spadne.

A má otázka zní: Jak udělat aby pokud je hráč ještě v letadle a provede 5 tahů tak hra skončí.
Nyní se hráč může donekonečna rozhlížet po letadle. A to není to pravé.

Josef

Místnost v letadle mám takto.
Kód: [Vybrat]
m_V_letadle: Room 'V letadle'
"Probudil ses v malém dvoumotorovém letadle plachtícím nad egytskou pouští.
\nJe tu nádherný klid, protože motory stojí a na palubě není kromě tebe živá duše.
Jediné co tu je vidět jsou <b>prázdná sedadla</b> a pár nepotřebných věcí.
\n(Celkem zajímavá situace, že ano?). "

// north, south, east, west, up, down | šikmé směry: northeast, northwest, southeast, southwest | dovnitř a ven: in, out
out : TravelMessage
{  -> m_Na_pousti
"Vznášíš se mezi oblaky. Užij si tohoto zajímavého pocitu, a nevzrušuj se zemí, která se rapidně přibližuje. Mimochodem v dálce na jihu je vidět nějaký vojenský tábor.
\nNad hlavou se ti rozevřel padák a po chvíli jsi šťastně přistál… "

// pokud máme oblečený padák jsme přesměrováni na místnost m_Na_pousti
canTravelerPass(traveler) {return p_Padak.isWorn();}

// pokud nemáme oblečený padák KO
explainTravelBarrier(traveler)
{
"Vznášíš se mezi oblaky. Užij si tohoto zajímavého pocitu, a nevzrušujn se zemí, která se rapidně přibližuje. Mimochodem v dálce na jihu je vidět nějaký vojenský tábor.
\nStal jsi se zakladatelem sportovního odvětví které vejde do dějin jako skok hluboký.";

// Hru ukončíte příkazem, který zobrazí hlášku a nabídne menu konce hry.
finishGameMsg(ftDeath, [finishOptionUndo] );
}
}

// přesměruje příkaz dolů na ven
down asExit(out)
;

gaspoda

  • Plný člen
  • ***
  • Příspěvků: 126
    • Zobrazit profil
Re: akce po určitém počtu tahů
« Odpověď #1 kdy: 1. Listopad 2018 - 21:27 »
Protože nejsem žádný programátor pátral jsem po nějakém jednoduchém enginu a našel hru "Základna na asteroidu"
a sní i skvělý návod na programování v TADS 3 od gaspody.

Nó, TADS je obvykle vnímán spíš jako složitější, protože nemaskuje skutečnost, že je nástrojem pro programátory :-)
Ale zase se umí odměnit svými schopnostmi vytvořit opravdu uhlazenou a dobře fungující hru. Takže držím palce!

A má otázka zní: Jak udělat aby pokud je hráč ještě v letadle a provede 5 tahů tak hra skončí.

Pro vytváření časovaných událostí jsou k dispozici třídy Fuse a Daemon. Ty chceš tu první, která načasuje událost
jednorázově na zadaný počet tahů dopředu. Daemon spouští událost opakovaně. Příklad je v páté kapitole návodu
k TADSu (http://www.textovky.cz/clanky/programovani-textovych-her-v-tads-3-cast-5-akce/).  Tedy něco na tenhle způsob, ale netestoval jsem to:

Kód: [Vybrat]
m_V_letadle: Room 'V letadle'
"Probudil ses v malém dvoumotorovém letadle...<<nacasuj()>> "

casovac = nil
nacasuj()
{
/* Nacasuj jen jednou, i kdyz se popisek mistnosti zobrazi vicekrat. */
        if(casovac == nil) casovac = new Fuse(self, &havaruj, 5);
        }
havaruj()
{
/* Pokud uz jsem se z letadla dostal, neudelame nic. */
if(me.isIn(m_V_letadle))
{
"Bum! ";
finishGameMsg(ftDeath, [finishOptionUndo] );
}
}
;

ajs

  • Nováček
  • *
  • Příspěvků: 7
    • Zobrazit profil
Re: akce po určitém počtu tahů
« Odpověď #2 kdy: 1. Listopad 2018 - 22:00 »
No tak to je paráda.
Ani jsem nedoufal v tak rychlou odpověď
Tvůj kód funguje přesně tak jak jsem potřeboval.
Netušil jsem že třeba pří zkoumání předmětu se vykonává i kód v části Room i když bez výpisu popisu. Dobré vědět.
Čekal jsem to mnohem složitější.
Myslel jsem že se to bude řešit novou třídou ale to je zatím na mě ještě moc.
Budu pokračovat a uvidíme jak to půjde.
Moc děkuji.




gaspoda

  • Plný člen
  • ***
  • Příspěvků: 126
    • Zobrazit profil
Re: akce po určitém počtu tahů
« Odpověď #3 kdy: 1. Listopad 2018 - 23:57 »
Já si v popisu místnosti kód provádějící načasování volám. Do textového výpisu se dá vložit spousta různých věcí prostřednictvím těch zdvojených špičatých závorek. Třeba podmínit část výpisu <<if něco>>text<<end>> ale i jakýkoliv příkaz, který se vykoná a vloží do textu svůj výstup. V příkladu výše žádný výstup není, ale akce načasování se spustí.

Šlo by to napsat i jinak. Ten popisek místnosti uvedený ve dvojitých uvozovkách na začátku místnosti je taková zkratka - použije se šablona, která vloží daný text do vlastnosti desc, takže bys také mohl napsat desc = "Popis. " Vtip je v tom, že desc je metoda, která se spustí a má úkol vytisknout popis místnosti na obrazovku, nejde tedy o obyčejnou proměnnou, do které se uloží nějaký text. Takže místo výše uvedeného by šlo napsat:

Kód: [Vybrat]
m_V_letadle: Room 'V letadle'
    desc()
    {
        "Popis. ";
        if(casovac == nil) casovac = new Fuse(self, &havaruj, 5);
    }
;

Pokud se ti bude zdát divné, že míchám pojmy proměnné (data) a metody (funkce, příkazy), tak je to tím, že se to v TADSu zase tolik nerozlišuje. TADS je hodně dynamický jazyk a text napsaný v dvojitých uvozovkách není řetězcová konstanta, nejsou to data, je to *příkaz* k provedení tisku.
« Poslední změna: 1. Listopad 2018 - 23:59 od gaspoda »

ajs

  • Nováček
  • *
  • Příspěvků: 7
    • Zobrazit profil
Re: akce po určitém počtu tahů
« Odpověď #4 kdy: 8. Listopad 2018 - 19:32 »
Tak děkuji za další způsob. Použil jsem ten první.
Jinak jsem ještě zápasil s akcí sraž něco něčím.
Žádnou správnou akci jsem na to nenašel (možná jsem špatně hledal).
Po pročtení dlouhého vlákna zde jsem to vyřešil akcí "AttackWith" s nadefinováním vlastních slov.
Akorát kazí dojem že lze na předmět i úspěšně zaútočit. A to asi hráče nenapadne.
Pokud by byl lepší způsob tak se podělte.
Mám to takto:
Předmět "Diamant u stropu"
Kód: [Vybrat]
+ p_Diamant_u_stropu: Thing, Fixture 'diamant u stropu/diamantu u stropu/diamantem u stropu' 'diamant u stropu' *2
"Leží na malém výstupku těsně u stropu místnosti, asi dva metry nad tvou hlavou. "

// pokud nejde shod/sraz diamant u stropu lopatou zobrazí se tato hláška
notAWeaponMsg = 'Holýma rukama to nepůjde. Nedosáhneš na něj. '

// pokud nejde vem diamant u stropu zobrazí se tato hláška
cannotTakeMsg = 'Nemůžeš ho vzít. Nedosáhneš na něj. '
cannotMoveMsg = 'Nemůžeš ho posunout. Nedosáhneš na něj. '

// je tu pro zobrazeni nepřenosných objektů v popisu mistnosti
isListed = true

// tedy napíšeme postupně 2. koho? čeho? 3. komu? čemu? 4. koho? co? 6. (o) kom? (o) čem? 7. kým? čím? pád oddělené čárkou
gcName = 'diamant u stropu, diamantu u stropu, diamant u stropu, diamantu u stropu, diamantem u stropu'
gcVocab = 'diamant u stropu/diamantu u stropu/diamantem u stropu'

// toto funguje na zautoc bicem na diamant u stropu   zautoc na diamant u stropu lopatou  gIobj != p_Bic  !p_Bic.isIn(me)
dobjFor(AttackWith) {
verify() {}
check() {
// pokud to "čím" není zobrazíme hlášku
if (gIobj != p_Bic)
failCheck('{Kýmčím iobj} diamant nesrazíš. Nedosáhneš na něj. ');
}
action() {
"Podařilo se ti srazit diamant dolů. ";
// necháme zmizet předmět "diamant u stropu"
p_Diamant_u_stropu.moveInto(nil);
// přidáme do místnosti předmět "druhý diamant"
p_Diamant2.discover();
}
}
;
A samotnou akci takto:
Kód: [Vybrat]
+ p_Diamant2: Hidden, Thing 'druhý druhému druhým diamant/diamantu/diamantem' 'druhý diamant' *2
"Druhý diamant je těžký, neforemný drahý kámen. "

dobjFor(Take) {
action() {
"Vzal jsi druhý diamant. ";
achievement.awardPointsOnce();
inherited;

}
// zvýší skóre o 1 bod
achievement: Achievement { +1 "nalezení druhého diamantu." }

// tedy napíšeme postupně 2. koho? čeho? 3. komu? čemu? 4. koho? co? 6. (o) kom? (o) čem? 7. kým? čím? pád oddělené čárkou
gcName = 'druhý diamant, druhému diamantu, druhý diamant, druhém diamantu, druhým diamantem'
gcVocab = 'druhý druhému druhým diamant/diamantu/diamantem'
;
// definice nového slova sraž
VerbRule(rozbij_cim)
('sraž' | 'shoď' | 'shodit') singleDobj singleIobj
: AttackWithAction
verbPhrase = 'srazit/sraz{íš}/srazil{a} (co) (čím)'
isPrepositionalPhrasing = nil
omitIobjInDobjQuery = true
askDobjResponseProd = singleNoun
askIobjResponseProd = singleNoun
;

gaspoda

  • Plný člen
  • ***
  • Příspěvků: 126
    • Zobrazit profil
Re: akce po určitém počtu tahů
« Odpověď #5 kdy: 9. Listopad 2018 - 09:37 »
Jinak jsem ještě zápasil s akcí sraž něco něčím.
Žádnou správnou akci jsem na to nenašel (možná jsem špatně hledal).
Po pročtení dlouhého vlákna zde jsem to vyřešil akcí "AttackWith" s nadefinováním vlastních slov.
Akorát kazí dojem že lze na předmět i úspěšně zaútočit. A to asi hráče nenapadne.

Samozřejmě vždy je možnost si zadefinovat úplně novou akci, která nebude navázaná na stávající, ale s každou takovou neobvyklou akcí hrozí, že hráč neuhodne správné sloveso. Proto by obvykle autor měl spíš sledovat opačný cíl, umožnit akci provést více slovesy a více synonymy, přesměrovat i méně pravděpodobné akce na tu správnou, aby průbeh hry byl hladší. Když bude hra reagovat na příkaz "zaútoč na diamant bičem", tak to dojem toho, koho napadne "sraž" nezkazí a toho, koho to nenapadne a místo toho "zaútočí", tak tomu to pomůže se posunout dál, tak jeho dojem to také nezkazí. Určitě bych přesmeroval také akci MoveWith, tedy posuň něco něčím, ta je pro nějaké štouchnutí do něčeho asi přímo určená, ale jak říkám, čím více synonym, tím lépe.

A ještě lépe, pokud hráče na neobvyklou akci někde předem připravíš. Třeba v naší hře jsme hráče předem důkladně procvičili, že může namířit tablet na něco, aby to později mohl použít k řešení problému.

Kód: [Vybrat]
gcVocab = 'diamant u stropu/diamantu u stropu/diamantem u stropu'
A samotnou akci takto:
Kód: [Vybrat]
gcVocab = 'druhý druhému druhým diamant/diamantu/diamantem'

Pozor na formát gcVocab, tedy zápisu slovníku. V tom prvním případě nemáš správně, zapisuj se 'přídavné přídavné podstatné/podstatné', tj. neoddělují se lomítkem skupiny slov, ale jenotlivá podstatná jména. V tom druhém případě to máš správně napsané, takže jsi se asi jen překoukl nebo si to neuvědomil.

ajs

  • Nováček
  • *
  • Příspěvků: 7
    • Zobrazit profil
Re: akce po určitém počtu tahů
« Odpověď #6 kdy: 10. Listopad 2018 - 14:26 »
Ahoj.
Děkuji za odpověď.
Vím že do gcVocab se dávají slova v pořadí 'přídavné přídavné podstatné/podstatné'.
Jak tedy zadat správně "diamant u stropu"?
gcVocab = 'diamant/diamantu/diamantem'
Nebo:
gcVocab = 'diamant/diamantu/diamantem/strop/stropu/stropem'
A kam zapsat "u"? Nebo ho mám vynechat?
Mimochodem kde se používájí slova z gcVocab?
A ještě otázka k akci MoveWith. Jak je zapsat aby bylo možné použít obě jak MoveWith tak i AttackWith?
Mám je napsat pod sebe jako akci AttackWith nebo je lze nějak spojit?

gaspoda

  • Plný člen
  • ***
  • Příspěvků: 126
    • Zobrazit profil
Re: akce po určitém počtu tahů
« Odpověď #7 kdy: 10. Listopad 2018 - 15:06 »
Mimochodem kde se používájí slova z gcVocab?

gcVocab resp. vocabWords, který se obvykle zapisuje pomocí šablony jako ta první sada slovíček, se používá pro naplnění slovníku parseru, tj. té části programu, která se snaží analyzovat, co hráč napsal, a dát tomu nějaký význam a provést jeho příkaz. Použijí se tedy k porovnání s tím, co hráč napsal a z toho se odvodí, jestli s tímto objektem hráč chce manipulovat.

Naproti tomu název objektu, tj. vlastnost gcName a name, která se obvykle píše jako druhý řetězec v apostrofech na začátku objektu, je název, který hra použije při výpisu zpráv na obrazovce, ať už se jedná o hlášení, že jsi něco zvednul, výpisu inventáře atd., zkrátka kdykoliv hra tiskne název objektu na obrazovku.

Kód: [Vybrat]
+ cDoor: Door 'vnitřní tlakové dveře dveře/těsnění*dveře'
    'vnitřní tlakové dveře' *3
    "Jsou to mohutné dveře schopné udržet atmosféru v oddělené části lodi. Po
        obvodu je měkké těsnění, které občas prověřuješ. Z obou stran jsou
        výrazné tlakoměry ukazující tlak na druhé straně dveří. V případě
        potřeby tlakový uzávěr může lehce zaklapnout a udrží i velmi prudkou
        změnu tlaku. "

    /* Dveře jsou pomnožné, tj. mají vždy tvar množného čísla. */
    isPlural = true

    gcName = 'vnitřních tlakových dveří, vnitřním tlakovým dveřím, vnitřní
        tlakové dveře, vnitřních tlakových dveřích, vnitřními tlakovými dveřmi'
    gcVocab = 'vnitřních vnitřním tlakových vnitřními tlakovým tlakové tlakovými
        dveří/dveřím/dveřích/dveřmi'
;

Tyhle dvě role se důsledně rozlišují a ve slovníku pochopitelně člověk uvede i mnoho různých synonym, aby hráč nemusel uhodnout jeden přesný název. A pochopitelně i všechny důležité pády, nemusejí se však opakovat ani být seřazené, což naopak u názvu potřeba je, aby si TADS uměl vybrat. U slovníku parseru stačí jen poznat.

Jak tedy zadat správně "diamant u stropu"? A kam zapsat "u"? Nebo ho mám vynechat?

Kód: [Vybrat]
gcVocab = 'diamant diamantu diamantem (u) (stropu)/diamant/diamantu/diamantem'
Tohle je trochu složitější název objektu a jak jsem řekl přídavné a podstatné jméno, tak zde úplně neodpovídá. Řekl jsem to trochu zjednodušeně a teď je příležitost dovysvětlit. Pro TADS není úplně důležité, co to je v rámci mluvnice českého jazyka, ale jak slovo chápat a kde se může vyskytnout. Tedy základní pravidla zní, že poznáme objekt tehdy, když:

  • Hráč použije jen jedno slovo ze slovníku podstatných jmen.
  • Hráč použije jedno či více slov za sebou ze slovníku přídavných jmen v libovolném pořadí.
  • Hráč použije kombinaci předchozích, ale přídavná jména musí vždy stát před jediným z podstatných jmen, ne naopak.

Tedy když mám velký červený míč, napíšu asi 'velký červený míč/míček' a z toho se vygenerují všechny smysluplné kombinace, např. bude fungovat >vem červený i >vem míček, libovolné pořadí, třeba >vem červený velký i >vem velký červený míč. Nebude ale fungovat >vem míč červený, protože přídavné jméno má vždy stát před podstatným.

Protože diamant i strop je podstatné jméno, tak ten diamant zopakuji i jako přídavné (že může stát před druhým podstatným jménem) a i zvlášť jako skutečné podstatné jméno, když hráč jen řekne >vem diamant. To opakování není úplně nezbytné, fungovalo by to i bez něj, ale TADS vždy bere samotné přídavné jméno jako méně hodnotnou shodu, když posuzuje více možností, o jaký objekt jde.

Ta slova v závorce pak jsou taková, která mohou být v příkazu zadaná, ale pokud jsou samotná, tak je bude TADS ignorovat. Jde o to, že třeba "u" je tak obecné slovíčko, že by ho hráč nenapsal samo o sobě a že je příliš nevýznamné, než aby se měl parser domnívat, že hráč hovoří o daném objektu. Podobně i to "stropu", je mnohem větší šance, že hráč chce prozkoumat strop a ne diamant u stropu, když napíše >prozkoumej strop.

Ještě poznámka - gcVocab je duplicitní a záměnné se slovníkem, který lze zapsat rovnou pomocí šablony v úvodu definice objektu. Ale při všech těch pádech je to takové delší, tak se hodí mít na to samostatný řádek - já třeba v záhlaví objektu uvedu jen první pád a ty ostatní pak dávám do gcVocab, ale mohl bych to nacpat všechno jen nahoru.

A ještě otázka k akci MoveWith. Jak je zapsat aby bylo možné použít obě jak MoveWith tak i AttackWith?
Mám je napsat pod sebe jako akci AttackWith nebo je lze nějak spojit?

Jednu uděláš tak, jak potřebuješ a u druhé přesměruješ, např.:

Kód: [Vybrat]
    dobjFor(LookThrough)
    {
        verify()
        {
            if(location.isOpen())
                illogicalNow('Dveře jsou zasunuty ve stěně komory, takže okénko
                    je teď schované. ');
        }
        action ()
            { "Odsud je jím vidět do kupole. "; }

    }
    dobjFor(LookIn) asDobjFor(LookThrough)

ajs

  • Nováček
  • *
  • Příspěvků: 7
    • Zobrazit profil
Re: akce po určitém počtu tahů
« Odpověď #8 kdy: 10. Listopad 2018 - 16:55 »
Ahoj.
Děkuji za vysvětlení.
Zkusil jsem to předělat a zdá se to být funkční.
Pokud by to někoho zajímalo tak jsem dodělal již celou hru.
Je přiložená v příloze.
Asi v ní budou ještě chybky ale hra je jednoduchá stejně jako její vzor na ZX Spectru.


gaspoda

  • Plný člen
  • ***
  • Příspěvků: 126
    • Zobrazit profil
Re: akce po určitém počtu tahů
« Odpověď #9 kdy: 10. Listopad 2018 - 21:20 »
Jen pár drobností, ani to většinou nejsou chyby, spíš různé tipy, co jde ještě udělat trochu jinak:

Kód: [Vybrat]
setGameTitle () {
"<i>Indiana Jones II.</i>\b";
}

Tohle je torchu podezřelé, odřízl jsi <title> tag, to asi může trochu rozbít některé interpretry, ani nevím. Obvykle se tohle nemění.

Kód: [Vybrat]
havaruj() {
/* Pokud uz jsem se z letadla dostal, neudelame nic. */
if(me.isIn(m_V_letadle)) {

Dá se také napsat me.isIn(self), self totiž je odkaz na současný objekt, prostě taková zkratka.

Kód: [Vybrat]
+ p_Padak: Hidden, Wearable 'bílý americký padák' 'padák' *2
gcVocab = 'bílý americký padák'

Nemusíš opakovat ta slova slovníku, co jsi napsal výše. Spíš bych doplnil ostatní pády pro jistotu, 'bílého bílému bílém bílým amerického americkému americkém ameryckým padáku/padákem'.

Kód: [Vybrat]
+ p_Prazdna_sedadla: Chair, CustomImmovable 'prázdná prázdné sedadla/sedadlo' 'prázdná sedadla' *4
Nemusíš pojmenovávat objekty, pokud na ně nikde jinde neukazuješ. Lecjakou dekoraci můžeš prostě vytvořit anonymně, tedy jen + Chair...

Kód: [Vybrat]
m_V_oaze: OutdoorRoom 'V oáze' 'k oáze'
"Jsi v malé oáze uprostřed pouště. U malého jezírka tu stojí <b>palma</b> s několika kokosovými ořechy. Nic moc.
\nZajímavější je, že kousek odtud směrem na jih je plot z ostnatého drátu s bránou a strážní věží.
<<if p_Lopata.isIn(me) || d_Pisek_podlaha.isOpen>><<d_Pisek_podlaha.isOpen ? '\nV písku je vidět vchod do podzemí. ' : '\nV <b>písku</b> pod palmou to vypadá jakoby se před nějakou dobou trochu propadla zem. '>>"

Možná trochu jednodušeji:

Kód: [Vybrat]
    <<if d_Pisek_podlaha.isOpen>>\nV písku je vidět vchod do podzemí.
    <<else if p_Lopata.isIn(me)>>\nV <b>písku</b> pod palmou to vypadá jakoby se před nějakou dobou trochu propadla zem. "

Kód: [Vybrat]
roomParts = [m_Zem_v_oaze]
Tady jsi odstranil defaultSky, nevím, jestli záměrně.

Kód: [Vybrat]
+ p_Palma: Fixture, CustomFixture 'kokosová palma' 'palma' *3
Jen CustomFixture, ne obě třídy. To je buď jedno nebo druhé, liší se to jen tím, jestli cannotTakeMsg reaguje na všechny druhy hýbání stejně, nebo se píší tři různé hlášky.

Kód: [Vybrat]
+ p_Auto: Container, CustomFixture 'německý automobil/auto/auta' 'německý automobil' *2
"Mercedes Benz, ale bohužel v nepojízdném stavu. "

// je tu pro zobrazeni nepřenosných objektů v popisu mistnosti
isListed = true

Tohle děláš na více místech. isListed zařídí takové obyčejné listování, což možná chceš, protože to pak vypadá, jako ve starých hrách, ale v TADSu se na vypíchnutí objektu v rámci místnosti častěji používá vlastnost specialDesc, která věnuje objektu zvláštní odstaveček po rozhlédnutí v místnosti, používá se to většinou u pár důležitých objektů a většinou se pak napíše trochu víc, než jen že objekt vidíš.

Kód: [Vybrat]
++ p_Baterie: Hidden, Wearable 'baterie' 'baterie' *3
Asi ne Wearable ;-)

Kód: [Vybrat]
action() {
"Otevřel jsi truhlu, a našel v ní zajímavé věci! ";
inherited;
makeOpen(true);

Inherited by myslím měl udělat makeOpen(true) automaticky.

Kód: [Vybrat]
<<if d_Hrobka.isOpen>>\nUprostřed oltáře je otvor vedoucí do podzemí! <<end>>"
End na konci řetězce je nepovinný.

Kód: [Vybrat]
+ d_Hrobka: SecretDoor 'otvor/díra/vchod' 'otvor' *2
"<<isOpen ? 'Uprostřed oltáře je otvor vedoucí do podzemí!' : 'Nic takového tu nevidíš.'>> "

// otevře se směr dolů do uvedené místnosti
destination = m_Hrobka

iobjFor(PutOn) {
action() {
if(gActionIn(PutOn)) {
"Záření oltáře ještě zesílilo! ";
}
inherited;
}
}

afterAction() {
if(p_Diamant1.isHeldBy(p_Oltar) && p_Diamant2.isHeldBy(p_Oltar) && p_Diamant3.isHeldBy(p_Oltar) && p_Diamant4.isHeldBy(p_Oltar) && p_Diamant5.isHeldBy(p_Oltar)) {
"\b<<if !d_Hrobka.isOpen>>Uprostřed oltáře se otevřel otvor vedoucí do podzemí! <<end>>";
if (!d_Hrobka.isOpen) {
makeOpen(!d_Hrobka.isOpen);
}
}
inherited;
}

// tedy napíšeme postupně 2. koho? čeho? 3. komu? čemu? 4. koho? co? 6. (o) kom? (o) čem? 7. kým? čím? pád oddělené čárkou
gcName = 'otvor, otvoru, otvor, otvoru, otvorem'
gcVocab = 'otvor/otvorem/díra/dírou/vchod/vchodem'
;

To iobjPutOn a afterAction je nějaké divné, dole u oltáře beru, ale tady je to nějak navíc asi omylem.
« Poslední změna: 10. Listopad 2018 - 21:23 od gaspoda »

ajs

  • Nováček
  • *
  • Příspěvků: 7
    • Zobrazit profil
Re: akce po určitém počtu tahů
« Odpověď #10 kdy: 13. Listopad 2018 - 19:01 »
Ahoj.
Děkuji za opravy a trpělivost jakou se mnou máš.
Opravil a doplnil jsem podle tvých rad.
Kód přikládám.

"setGameTitle" - máš pravdu, chybí tam <title>. Doplnil jsem.

Odkaz na současný objekt (self) jsem také opravil.

Slova ve slovníku jsem také opravil. (doufám že dostatečně)

If v místnosti "m_V_oaze" jsem zjednodušil tak jak jsi napsal.

DefaultSky jsem neodstranil záměrně. To byla moje chyba. Nevěděl jsem že pokud nadefinuji jedno, musím nadefinovat i ostatní (doufám že si to myslím správně).

Fixture nebo CustomFixture u "p_Palma" jsem opravil.

isListed = true u "p_Auto" a jinde je opravdu záměr. Trefil jsi to přesně. Má to vypadat jako původní stará hra.

Předmět "p_Baterie" nadefinovaný jako "Wearable" je blbost. Opravil jsem. (zůstalo mi to tam při kopírování z jiného předmětu)

Inherited u makeOpen(true) se opravdu udělá automaticky. Opraveno.

End na konci řetězce vím že je nepovinný. Ono je těch nepovinných konců řetězců víc. Ale zatím mi to přijde přehlednější. Časem do toho určitě proniknu.

U dveří "d_Hrobka" je iobjFor(PutOn) opravdu navíc. Ale afterAction() způsobí otevření cesty směrem dolů. Když to dám jinam tak to nejde. Asi by mělo být něco jiného než afterAction(), ale nevím co. Každopádně takto je to funkční. Nebo to způsobuje chybu, kterou jsem nenašel?

gaspoda

  • Plný člen
  • ***
  • Příspěvků: 126
    • Zobrazit profil
Re: akce po určitém počtu tahů
« Odpověď #11 kdy: 13. Listopad 2018 - 20:24 »
DefaultSky jsem neodstranil záměrně. To byla moje chyba. Nevěděl jsem že pokud nadefinuji jedno, musím nadefinovat i ostatní (doufám že si to myslím správně).

Pokud přepíšeš vlastnost roomParts vlastním polem, tak se tím zahodí předchozí hodnota (předchozí pole) zděděné z třídy OutdoorRoom, obsahující výchozí části místnosti. OutdoorRoom má právě jen zem a oblohu na rozdíl od běžné místnosti. Jestliže chceš některou součást místnosti vyměnit za svojí upravenou, pak jsou dva způsoby. Buď napíšeš nové pole a uvedeš všechny části, tj. tvojí zem i původní oblohu a nebo je i jiný zápis, kterým přidáš svojí zem a odebereš tu výchozí, přičemž obloha zůstane zachovaná:

Kód: [Vybrat]
roomParts = [m_Zem_v_oaze, defaultSky]
roomParts = static inherited - defaultGround + m_Zem_v_oaze

Předmět "p_Baterie" nadefinovaný jako "Wearable" je blbost. Opravil jsem. (zůstalo mi to tam při kopírování z jiného předmětu)

To já samozřejmě chápu: http://hackles.org/cgi-bin/archives.pl?request=37  :D

U dveří "d_Hrobka" je iobjFor(PutOn) opravdu navíc. Ale afterAction() způsobí otevření cesty směrem dolů. Když to dám jinam tak to nejde. Asi by mělo být něco jiného než afterAction(), ale nevím co. Každopádně takto je to funkční. Nebo to způsobuje chybu, kterou jsem nenašel?

Jasně, ale asi bych to afterAction čekal spíš v tom objektu oltáře, pocitově mi to tam spíš patří, protože se toho týká. To by také fungovalo, ne? Resp. já bych to celé zjištění, jestli jsou všechny diamanty napsal asi rovnou do action() metody iobjFor(PutOn), ve které mimochodem máš if(gActionIn(PutOn)), který se mi zdá zbytečný - jsi v iobjFor(PutOn), tak to asi jiná akce být nemůže a pomocí validContents máš omezeno, že tam nikdo nedá nic jiného, tak mě nenapadá, za jakých okolností nenapsat hlášku o záři.

Ale to jsou takové drobnosti, většinou je více cest, jak různé věci udělat a komentuju je spíš proto, abys pro zajímavost viděl některé souvislosti, ale jde ti to pěkně od ruky.

ajs

  • Nováček
  • *
  • Příspěvků: 7
    • Zobrazit profil
Re: akce po určitém počtu tahů
« Odpověď #12 kdy: 14. Listopad 2018 - 19:45 »
Moc děkuji za rady. Jsou neocenitelné. Bez nich bych to už asi vzdal a nikdy nedokončil.

Tak s tou zemí "m_Zem_v_oaze" jsem to opravil a zvolil ten první způsob. Přijde mi přehlednější.

afterAction v tom objektu oltáře jsem měl ale musel jsem mít něco špatně protože mi to nefungovalo.
Zkusil jsem to dát do action() metody iobjFor(PutOn) a zjistil jsem že to musí být až po inherited což byla asi před tím ta chyba.

gaspoda

  • Plný člen
  • ***
  • Příspěvků: 126
    • Zobrazit profil
Re: akce po určitém počtu tahů
« Odpověď #13 kdy: 14. Listopad 2018 - 20:06 »
Ano, určitě po inherited, protože ve zděděném chování se provede právě to přemístění na oltář, které následně testuješ. Občas je docela fajn nakouknout do Library Reference Manual (http://www.tads.org/t3doc/doc/libref/index.html), jak jsou naprogramované ty různé akce, tj. d/iobjFor, abys věděl, co vlastně přetěžuješ a kolikrát se tam dočteš zajímavé souvislosti. Např. jestli je něco zakázané checkem nebo verify, jestli je to někam přemapované, jak se to provádí atp.

Jsem rád, že se ti to povedlo a i když jsi se nám snažil namluvit, že nejsi programátor, tak je vidět, že určitě zkušenosti máš. Smím se optat, jestli jsi narazil na nějaké věci, které by potřebovaly lépe vysvětlit, nebo na něco, co tě překvapilo, zaujalo atp.? A pokud tě to ještě úplně neodradilo, tak někdy trošku koukni na pokročilejší možnosti, jako třeba konverzační systém, které dokážou hry posunout přeci jen dál, než bylo zvykem za starých časů.