Inform e Glulx/RUINS, l'avventura comincia/Il ritorno della mummia (non è un film, è tutto vero)

Wikibooks, manuali e libri di testo liberi.
Indice del libro

Osservate, spaventati a morte, il sacerdote mummificato: il suo corpo è disidratato, ed è tenuto insieme solo grazie alla sua forza di volontà. Provate a dirigervi verso sudovest ma la crepa, verso cui si dirigono i cornicioni, è ostruita dai ghiaccioli; il ghiaccio non riesce comunque a nascondere completamente il simbolo di una mezzaluna e vi chiedete quale possa essere il suo significato. Vi scervellate come non mai, pensando a uno scarabocchio di qualche bambino Maya o all’opera di due innamorati in vena di romanticismo, ma è ancora una volta il vostro immenso “acume archeologico” che vi toglie le castagne dal fuoco: avete con voi un dizionario Maya, perché non consultarlo? Ed ecco svelato il mistero: quel simbolo si pronuncia “xibalba”, anche se il suo significato è sconosciuto. Bella scoperta, e adesso? Nonostante la paura, provate a chiedere aiuto al sacerdote ed egli, con grande stupore da parte vostra, indica con le dita ossute i ghiaccioli, che si sciolgono come neve al sole quando parla: “Xibalbá, l'Oltretomba." è quello che riesce a dirvi, prima di tossire e di cadere quasi a pezzi.


Il ritorno della mummia (non è un film, è tutto vero)[modifica]

Quando si gioca a un’avventura testuale, è logico aspettarsi di dovere prima o poi interagire con qualche personaggio. Nel nostro caso, il personaggio è il sacerdote mummificato:

Object  priest "sacerdote mummificato"
  with  name 'mummificato' 'sacerdote',
        initial
            "Dietro la lastra, un sacerdote mummificato attende in 
             piedi.",
        description
            "Il suo corpo @`e disidratato, ed @`e tenuto insieme solo 
             grazie alla sua forza di volont@`a. Sebbene la sua lingua 
             sia il Maya locale, hai la curiosa impressione che
             comprender@`a le tue parole.",
        life [;
            Answer:
                "Il sacerdote tossisce e cade quasi a pezzi.";
            Ask: switch (second) {
                'dizionario', 'libro':
                    if (dictionary.correct == false)
                        "~Il simbolo dell'uccello... molto divertente.~";
                    "~Un dizionario? Davvero?~";
                'simbolo', 'simboli', 'maya', 'dialetto':
                    "~Nella nostra cultura, i sacerdoti sanno sempre 
                     leggere e scrivere.~";
                'sovrano', 'tomba', 'tempio':
                    "~Questa @`e una faccenda privata.~";
                'pitture':
                    "Il sacerdote si acciglia: ~10 baktun, 4 katun,
                     che sono 1,468,800 giorni dall'inizio del tempo:
                     nel tuo calendario il 19 gennaio 909.~";
                'rovine':
                    "~Le rovine sono sempre state difese dai ladri. 
                     Nell'Oltretomba, i saccheggiatori sono stati 
                     torturati per l'eternit@`a.~ Una pausa. ~Cos@`i come
                     gli archeologi.~";
                'ragnatele', 'Tana', 'tana', 'Verme':
                    "~Nessun uomo pu@`o oltrepassare la Tana Del 
                     Verme.~";
                'xibalba':
                    if (Shrine.sw_to == Junction)
                        "Il sacerdote scuote le dita ossute.";
                    Shrine.sw_to = Junction;
                    "Il sacerdote indica con le dita ossute i ghiaccioli, 
                     che si sciolgono come neve al sole quando parla. 
                     ~Xibalb@'a, l'Oltretomba.~";
                    }
                "~Devi trovare la risposta da solo.~";
            Tell:
                "Il sacerdote non @`e interessato alla tua squallida 
                 vita.";
            Attack, Kiss:
                remove self;
                "Il sacerdote si disidrata riducendosi in polvere 
                 finch@'e non rimane pi@`u nulla.";
            ThrowAt:
                move noun to location; <<Attack self>>;
            Show, Give:
                if (noun == dictionary && dictionary.correct == false) {
                    dictionary.correct = true;
                    "Il sacerdote legge un pezzo del libro, sogghignando 
                     sinistramente. Incapace di nascondere il suo 
                     divertimento, scarabocchia qualche correzione prima            
                     di restituirtelo.";
                    }
                if (noun == newspaper)
                    "Guarda la data. ~12 baktun 16 katun 4 tun 1 uinal
                     12 kin~, dichiara, prima di dare un'occhiata alla 
                     prima pagina. ~Ah, vedo che continua.~";
                "Il sacerdote non @`e interessato alle cose terrene.";
            ],
        orders [;
            Go:
                "~Non devo lasciare il Tempio.~";
            NotUnderstood:
                "~Parli per enigmi.~";
            default:
                "~Non sono ai tuoi ordini~";
            ],
  has   animate

Sulla base di quanto è stato detto finora, è facile dedurre che gli oggetti di questo tipo hanno l’attributo animate e che la loro "vita" (il loro grado cioè di interazione con il giocatore) è descritto all’interno della proprietà life:

>parla con il sacerdote
Il sacerdote non è interessato alla tua squallida vita.

>mostra al sacerdote il giornale
Guarda la data. "12 baktun 16 katun 4 tun 1 uinal 12 kin", dichiara, prima di dare un'occhiata alla prima pagina. "Ah, vedo che continua."

>mostra al sacerdote la macchina
Il sacerdote non è interessato alle cose terrene.

>mostra al sacerdote il dizionario
Il sacerdote legge un pezzo del libro, sogghignando sinistramente. Incapace di nascondere il suo divertimento, scarabocchia qualche correzione prima di restituirtelo.

>chiedi al sacerdote delle pitture
Il sacerdote si acciglia: "10 baktun, 4 katun, che sono 1,468,800 giorni dall'inizio del tempo: nel tuo calendario il 19 gennaio 909."

>chiedi al sacerdote di xibalba
Il sacerdote indica con le dita ossute i ghiaccioli, che si sciolgono come neve al sole quando parla. "Xibalbá, l'Oltretomba."

>sacerdote, vai a nord
"Non devo lasciare il Tempio."

Questi sono solo alcuni esempi delle possibili risposte che il sacerdote può dare[1]. Dobbiamo però fare attenzione a due azioni particolari: la prima (la correzione del dizionario) la vedremo meglio nel prossimo paragrafo, mentre la seconda (lo scioglimento dei ghiaccioli) è fondamentale per il proseguimento del gioco.

Quando il giocatore entra per la prima volta nella sala del Tempio, ecco cosa accade se cerca di dirigersi verso sudovest:

>so
I cornicioni si vanno restringendo in una crepa che proseguirebbe se non fosse ostruita dai ghiaccioli. Il ghiaccio non riesce a nascondere completamente il simbolo di una mezzaluna.

Il passaggio è quindi bloccato dai ghiaccioli; tuttavia, è possibile scorgere il simbolo di una mezzaluna. Se il giocatore cerca di rifarsi ancora una volta all’aiuto dello strano sacerdote:

>chiedi al sacerdote della mezzaluna
"Devi trovare la risposta da solo."

deve arrangiarsi da solo. A questo punto, ecco che entra in "azione" il dizionario Maya:

>cerca mezzaluna nel dizionario
Mezzaluna: credo che si pronunci "xibalba", sebbene il suo significato sia sconosciuto.

e il mistero è risolto: quando si chiede di "xibalba" al sacerdote, se la direzione sudovest del Tempio (Shrine.sw_to) è bloccata, la nuova direzione diventa Junction (Shrine.sw_to = Junction;). Così facendo, è finalmente possibile accedere all’incrocio di Xibalbá:

>chiedi al sacerdote di xibalba
Il sacerdote indica con le dita ossute i ghiaccioli, che si sciolgono come neve al sole quando parla. "Xibalbá, l'Oltretomba."

>so

Xibalbá
Sei a cinquanta metri sotto la foresta pluviale e lo scroscio dell'acqua si sente ovunque: queste profonde ed erose miniere di calcare si estendono come radici. Verso nordest un percorso scivoloso, formato da un'ampia colonna di roccia ricoperta dal ghiaccio, ti riporta al Tempio, mentre un canyon prosegue verso l'alto a nord e verso il basso a sud. Alla luce diffusa della lampada al sodio proveniente da sopra, sembra essere bianco come i denti di uno squalo.

>

Leggendo la descrizione di questa nuova locazione, viene quasi istintivo chiedersi come far sì che la lampada non possa in qualche modo "seguire" il nostro archeologo verso sudovest. È presto detto: basta aggiungere le seguenti righe di codice all’azione PushDir dell’oggetto sodium_lamp:

Object  sodium_lamp "lampada al sodio" 
.
.
.
before [;
       .
       .
       .
    PushDir:
        if (location == Shrine && second == sw_obj)
            "La cosa migliore che puoi fare @`e spingere la lampada 
             proprio verso il margine del Tempio, dove il pavimento della 
             caverna si ritira.";
        AllowPushDir();
        rtrue;
    ],
    .
    .
    .
  has   female switchable;

Se il giocatore si trova nella sala del Tempio e dà il comando "spingi la lampada a so", Inform stampa a video il relativo messaggio, altrimenti viene eseguito il comando e la lampada si sposta insieme al giocatore.

Passiamo ora a esaminare il dizionario Maya (l’oggetto dictionary):

Object  dictionary "dizionario maya di Waldeck"
  with  name 'dizionario' 'locale' 'guida' 'libro' 'maya' 'waldeck',
        description
            "Compilata dall'inaffidabile litografia del leggendario 
             narratore ed esploratore ~Conte~ Jean Frederic Maximilien 
             Waldeck (1766??-1875), questa guida contiene quel poco che 
             si conosce sui simboli usati nell'antico dialetto locale.",
        before [ w1 w2 glyph;
            Consult:
                wn = consult_from;
                w1 = NextWord(); 
                w2 = NextWord(); 
                if (consult_words ==1 && w1~='simbolo' or 'simboli') 
                    glyph = w1;
                else if (consult_words ==2 && w1=='simbolo') glyph = w2;
                else if (consult_words ==2 && w2~='simbolo') glyph = w2;
                else "Prova ~cerca <nome del simbolo> sul dizionario~.";
                switch (glyph) {
                    'q1':        "(Questo @`e uno dei simboli che hai 
                                  annotato!)^^
                                  Q1: ~luogo sacro~.";
                    'mezzaluna': "Mezzaluna: credo che si pronunci 
                                  ~xibalba~, sebbene il suo significato 
                                  sia sconosciuto.";
                    'freccia':    "Freccia: ~viaggio; divenire~.";
                    'teschio':    "Teschio: ~morte, destino funesto; fato 
                                   (non nec. brutto)~.";
                    'cerchio':   "Cerchio: ~il Sole; anche la vita, 
                                  l'arco della vita~.";
                    'giaguaro':  "Giaguaro: ~sovrano~.";
                    'scimmia':   "Scimmia: ~sacerdote?~.";
                    'uccello':   if (self.correct) "Uccello: ~morto
                                 stecchito~.";
                                 "Uccello: ~ricco, benestante?~.";
                    default:     "@`E un simbolo che non @`e ancora stato 
                                  annotato.";
                }
            ],
        correct false;

Questo oggetto, in effetti, è piuttosto complicato, ma proviamo comunque a dargli ugualmente un’occhiata: la variabile di libreria wn contiene, grazie all’istruzione consult_from, la posizione del simbolo all’interno della frase (o, come dice più "tecnicamente" Giancarlo Niccolai[2], il numero delle parole riconosciute come topic). Nella definizione in Infit del verbo cerca, la parola-chiave topic (che in Inform si riferisce a qualsiasi testo digitato dal giocatore) occupa la seconda posizione e, con un comando del tipo "cerca freccia nel dizionario", abbiamo che:

  • la variabile di libreria wn vale 2 (il testo topic freccia occupa la seconda posizione nel comando digitato dal giocatore;
  • Inform mette a disposizione del programmatore le variabili locali w1 e w2.

L’istruzione NextWord, poi, "preleva" dal comando la parola che occupa la posizione wn e l’assegna alla variabile locale w1:

>cerca freccia nel dizionario
Freccia: "viaggio; divenire".

mentre la variabile locale w2, in questo caso, è vuota.

L’istruzione consult_words, si occupa invece del numero delle parole digitate dal giocatore nel topic:

>cerca la freccia nel dizionario
Freccia: "viaggio; divenire".

>cerca simbolo freccia nel dizionario
Freccia: "viaggio; divenire".

Nel primo esempio, abbiamo nel topic le parole la (prelevata dall’istruzione NextWord e memorizzata in w1) e freccia (prelevata dall’istruzione NextWord e memorizzata in w2); consult_words vale allora 2 (nell’esempio precedente valeva invece 1, perché il giocatore aveva digitato solo "freccia"). Se w1 è uguale a "simbolo" (è il caso del secondo esempio), allora il simbolo da cercare sul dizionario è quello contenuto in w2, altrimenti (è il caso del primo esempio) è sempre quello contenuto in w2[3].

Concludiamo questo paragrafo con le definizioni dei verbi. Diamo nuovamente un'occhiata alla definizione del verbo fotografa:

Verb 'fotografa' * noun                                -> Photograph;

dove noun si riferisce a qualsiasi oggetto definito all’interno dell’avventura stessa, che deve però essere visibile dal giocatore (in poche parole, non posso fotografare una statuetta se questa non è presente nella locazione in cui mi trovo). Ma, come è logico che sia, esistono diversi altri modi (alcuni più semplici e altri più complessi) per definire un nuovo verbo (e di conseguenza una nuova azione). Vediamo allora alcuni esempi presi dal file ItalianG.h:

Verb 'salta'     *                                     -> Jump;

Beh, questo è elementare: basta digitare "salta" per far sì che l’azione Jump abbia luogo. Occorre notare che, a differenza dell’azione Photograph, in questo caso non è necessario creare una funzione JumpSub, perché l’azione Jump è una di quelle riconosciute da Inform come standard.

Vediamo invece la definizione del verbo scava:

Verb 'scava'     * noun                                -> Dig
                 * noun 'con'/'col' held               -> Dig; 

Come potete vedere, è possibile definire, per un verbo, una stessa azione in modalità differenti. La prima funziona esattamente come l’azione Photograph, mentre la seconda presenta una novità: held. Questa parola-chiave si riferisce agli oggetti posseduti dal giocatore nel suo inventario: in questo caso, è possibile prevedere un comando del tipo "scala la terra con la pala", a patto però che il giocatore abbia nel suo inventario la pala medesima.

Il verbo bacia (poteva mai mancare un verbo così?) ci riserva altre novità:

Verb 'bacia' 'abbraccia'
                 * creature                            -> Kiss;

Quindi, è possibile definire più verbi per una stessa azione. La parola-chiave creature si riferisce a tutti quegli oggetti che hanno l’attributo animate: in Ruins, infatti, posso baciare il sacerdote, ma questi è talmente timido da ridursi poi in polvere.

Invece, la definizione del verbo apri:

Verb 'apri' 'scopri'
                 * noun                                -> Open
                 * noun 'con'/'col'/'a' held           -> Unlock;

mostra chiaramente che è possibile definire azioni diverse per uno o più verbi.

Un’altra caratteristica interessante può essere poi notata per il verbo chiedi:

Verb 'chiedi' 'domanda'
                 * noun 'a'/'ad'/'all^'/'allo'/'alla'/'al'/'agli'/'ai'/
                   'alle' creature              -> AskFor reverse;

In questo caso, reverse inverte di posto noun e creature, dando al giocatore la possibilità di digitare un comando del tipo "chiedi al sacerdote delle rovine" (e non "chiedi delle rovine al sacerdote", come avverrebbe se si lasciasse solo AskFor).

Ecco poi, come si possono inserire delle abbreviazioni:

Verb 'esamina' 'x//' 'descrivi' 
                * noun                                   -> Examine;

dove digitare "esamina la cassa e "x cassa" equivale alla stessa azione.

Ci sono poi alcuni verbi che, per poter essere utilizzati, richiedono la presenza di almeno due oggetti visibili dal giocatore:

Verb 'lega' 'fissa' 'congiungi' 'unisci' 'allaccia' 'annoda'
                * noun                                   -> Tie
                * noun 'a'/'ad'/'all^'/'allo'/'alla'/'al'/'agli'/'ai'/
                  'alle'  noun                           -> Tie
                * noun 'con'/'col' noun                  -> Tie;

come accade, ad esempio, se si digita un comando del tipo "lega la corda al lampadario", dove abbiamo appunto due oggetti: la corda (il primo noun) e il lampadario (il secondo noun)[4] . Ricordatevi però, che per testare in Inform un’azione di questo tipo occorre rifarsi al seguente codice:

Tie:     if (noun == corda && second == lampadario)...

Un’altra esigenza, potrebbe essere legata al fatto che alcuni verbi possono essere utilizzati con più oggetti alla volta:

Verb 'prendi' 'trasporta' 'afferra' 'raccogli'
                * multi                                  -> Take
                * multiinside 'da'/'dal'/'dallo'/'dalla'/'dall^'/
                  'dagli'/'dalle'/'dai' noun             -> Remove;

Verb 'metti' 
                * held                                   -> Wear
                * 'gi@`u'/'giu' multiheld                -> Drop
                * multiheld 'gi@`u'/'giu'                -> Drop
                * multiexcept 'dentro'/'in'/'nel'/'nello'/'nell^'/'nella'
                  /'negli'/'nelle'/'nei' noun            -> Insert
                * multiexcept 'su'/'sul'/'sullo'/'sull^'/'sulla'/'sui'/
                  'sugli'/'sulle'/'sopra' noun           -> PutOn;

In questi esempi, il giocatore ha la possibilità di digitare dei comandi del tipo "prendi il fungo e la mappa" (multi), oppure "prendi il giornale e la macchina dalla cassa" (multiinside  ➨  agisce su più oggetti solo se si trovano all’interno di un contenitore), o ancora "metti giù la maschera, la mappa e la macchina" (multiheld  ➨  agisce su più oggetti solo se si trovano nell’inventario del giocatore) e "metti la maschera e la mappa sull'altare" (multiexcept  ➨  agisce su più oggetti ad eccezione dell’altare stesso). Ovviamente, si possono anche usare forme del tipo "prendi tutto", "prendi tutte le monete", "lascia tutto", ecc.

Se invece dobbiamo rifarci a una direzione ben precisa, diamo allora un’occhiata alla definizione del verbo vai:

Verb 'vai' 'cammina' 'corri' 'va'
                * 'a'/'ad'/'verso' noun=Adirection       -> Go

dove noun è uguale a una direzione qualsiasi tra quelle permesse da Inform (Adirection). Se invece dobbiamo toglierci un vestito:

Verb 'rimuovi' 'togli'  
                 * worn                                  -> Disrobe

ecco la parola-chiave da usare (worn).

Può anche verificarsi il caso in cui si abbia la necessità di ampliare, in qualche modo, l’utilizzo di un verbo già esistente (o meglio, già dichiarato nel file ItalianG.h). In questo caso si deve ricorrere all’istruzione Extend, che possiamo applicare, ad esempio, al verbo cerca, così definito di default:

Verb 'cerca' 'trova' 'ricerca' 'fruga'
!               * noun                           -> Search
                * 'dentro'/'in'/'nel'/'nello'/'nell^'/'nella'/
                  'negli'/'nelle'/'nei'/'fra'/'tra' noun
                                                 -> Search
                * topic 'dentro'/'in'/'nel'/'nello'/'nell^'/'nella'/
                  'negli'/'nelle'/'nei'/'fra'/'tra' noun
                                                 -> Consult reverse
                * 'dentro'/'in'/'nel'/'nello'/'nell^'/'nella'/
                  'negli'/'nelle'/'nei'/'fra'/'tra' noun topic
                                                 -> Consult;

Facendo riferimento al dizionario Maya, con questo verbo è possibile dare il comando "cerca [nome_simbolo]nel dizionario", ma non "cerca [nome_simbolo] sul dizionario". Ecco allora come ampliare la definizione di questo verbo:

Extend 'cerca' * topic 'su'/'sul'/'sui'/'sulle'/'sullo'/'sull^'/
                       'sulla'/'sugli' noun               -> Consult;

La parola-chiave topic, come abbiamo già detto, si riferisce a un qualsiasi testo digitato dall’utente. Volendo essere estremamente pignoli, possiamo anche usare l’istruzione Extend only, utile nel caso in cui si voglia estendere il significato di un solo verbo, appartenente però a un’azione che ne prevede più di uno:

Extend only 'cerca' * topic 'su'/'sul'/'sui'/'sulle'/'sullo'/'sull^'/
                       'sulla'/'sugli' noun               -> Consult;

Così facendo, la seguente regola grammaticale vale solo per il verbo cerca e non per i verbi trova, ricerca e fruga. Nonostante però la definizione estesa del verbo sia giusta, il comando sembra non voler ancora funzionare. Ecco infatti quello che succede:

Il Grande Altopiano
I tuoi appunti menzionano qualcosa circa questa bassa scarpata di calcare, ma la foresta pluviale ne ha rivendicato il possesso. Cupi ulivi crescono ovunque, e una pioggia appena smessa riempie l'aria con una calda nebbia bagnata.
La "Struttura 10" è un cumulo di materiali da costruzione, che una volta avrebbero potuto costituire una piramide sepolcrale, ma della quale ora nulla rimane, eccetto alcuni gradini scolpiti nella nuda roccia che portano giù, nell'oscurità.

Un fungo macchiato cresce dalla terra fradicia, su un gambo lungo.

La tua cassa d'imballaggio giace qui, pronta per contenere eventuali scoperte di alto valore culturale da riportare alla civiltà.

>cerca freccia sul dizionario
Dentro cosa vuoi cercare?

Questo accade perché, per come è definito questo verbo di default, dobbiamo ricorrere alla parola-chiave first[5]:

Extend 'cerca' first * topic 'su'/'sul'/'sui'/'sulle'/'sullo'/'sull^'/
                       'sulla'/'sugli' noun               -> Consult;

che si usa quando abbiamo la necessità di stabilire quale riga della grammatica di un verbo debba essere eseguita per prima. Se invece deve essere eseguita per ultima, si può ricorrere all’utilizzo della parola-chiave last:

Extend	 "spingi"	last
                * noun 'verso'/'vicino'/'sotto' noun	       -> PushDir;

Se poi si vuole sostituire un verbo già esistente, si può usare la parola-chiave replace:

Extend  "leggi"		replace		
			 	*					        -> Leggi
                                * noun					        -> Leggi;

con la quale si sostituisce, in questo esempio, il verbo leggi.

La parola-chiave meta è riservata invece solo ai comandi per il gioco (come ad esempio "carica", "salva", "fine", ecc.) e non viene usata quasi mai.

Infine è possibile, come dice Francesco Cordella, aggiungere un sinonimo a un verbo già esistente tramite l’operatore di assegnamento =, come accade nel seguente esempio:

Verb 'perquisisci' = 'cerca';

dove perquisisci è il sinonimo in questione.

Note[modifica]

  1. La libreria wtalk_it.h, scritta da Paolo Lucchesi, permette un sistema di conversazione con dialoghi a menu (in status line o finestra). Ulteriori informazioni sul suo utilizzo potete trovarle nel prossimo capitolo.
  2. Giancarlo Niccolai è l’autore della stratosferica "Warmage", e mi piace definirlo come "un marziano travestito da terrestre". È in grado di fare, con Inform, praticamente tutto (o quasi) quello che vi può passare per la mente. L’indirizzo della pagina web della sua avventura è: http://pitermos.niccolai.cc/diven.php.
  3. Cliccate qui per scaricare il listato di questo esercizio (il file 4.09.inf).
  4. Attenzione: non si fa riferimento alle parole "corda" e "lampadario", ma a due oggetti denominati corda e lampadario (oppure a due oggetti con dei nomi qualsiasi, ma con sinonimi relativi rispettivamente a corda per il primo e lampadario per il secondo, presenti nelle with name... dei rispettivi oggetti di appartenenza).
  5. Questo è ovviamente un caso a sé. Nella maggior parte dei casi, infatti, per estendere il significato di un verbo basta ricorrere alle sole espressioni Extend 'nome_verbo' * ... e Extend only 'nome_verbo' * ...