Inform e Glulx/Inform e ancora Inform/Su e giù con l'ascensore

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

Su e giù con l'ascensore[modifica]

La gestione di un ascensore è un altro "classico" delle avventure testuali. Ecco allora come funziona l’esempio da me proposto:

Ascensore
Un semplice esempio che gestisce un ascensore a quattro piani
di Vincenzo Scarpa

Versione 1 -- Numero di serie 050704
Inform v6.30 -- Libreria 6/11  --  Infit v2.5    S

Piano terra
Sei al piano terra.

Puoi vedere delle porte scorrevoli qui.

>

All’inizio abbiamo davanti a noi delle porte scorrevoli. Naturalmente, occorre aprirle per entrare poi nella cabina:

>esamina le porte
C'è un pulsante accanto alle porte.

>premi pulsante
Le porte si aprono silenziosamente.

>entra

Cabina dell'ascensore
Sei nella cabina dell'ascensore.

Puoi vedere un pannello di controllo con quattro tasti numerati da zero a tre.

>

Eccoci dunque dentro la cabina del nostro ascensore. Se non soffrite di claustrofobia, potete allora decidere a quale piano andare premendo l’apposito pulsante:

>premi 2
Le porte si chiudono e la cabina si mette in movimento.
Improvvisamente, le porte si aprono di nuovo.

>esci
Non appena esci dall'ascensore, le porte scorrevoli si chiudono silenziosamente alle tue spalle.

Secondo piano
Sei al secondo piano.

Puoi vedere delle porte scorrevoli qui.

>

Una volta arrivati a destinazione, potete uscire dalla cabina quando volete, ricordandovi però di riaprire le porte se dovete usarla di nuovo:

>entra
Le porte sono ancora chiuse: credi forse di essere un fantasma?

>premi il pulsante
Le porte si aprono silenziosamente.

>entra

Cabina dell'ascensore
Sei nella cabina dell'ascensore.

Puoi vedere un pannello di controllo con quattro tasti numerati da zero a tre.

>

A questo punto, il suo utilizzo dovrebbe ormai essere abbastanza chiaro. Occorre però ancora notare che, se il giocatore preme il tasto corrispondente al piano su cui si trova l’ascensore, non accade nulla:

>premi 2
Non accade nulla.

>

come d’altra parte avviene in tutti gli ascensori che si rispettino. Per quanto riguarda invece il codice, occorre fare alcune considerazioni. Iniziamo dalla funzione Muovi_cabina:

[Muovi_cabina x y;
    Ascensore.piano_asc = x; 
    if (parent(Porte_scorrevoli) ~= y) {
        move Porte_scorrevoli to y;
        move Pulsante_chiamata to y;
        print_ret "Le porte si chiudono e la cabina si mette in 
                   movimento. ^Improvvisamente, le porte si aprono di 
                   nuovo.";
        }
    else print_ret "Non accade nulla.";
];

I parametri che devono esserle passate sono rispettivamente il numero del piano che l’ascensore deve raggiungere (x) e il nome dell’oggetto al quale corrisponde il piano stesso (y). È facile allora capire che una chiamata del tipo:

Button -> Pulsante_2 "terzo pulsante"
  with name 'terzo' 'due' '2//',
       before
       [;
          Push:   Muovi_cabina(2, Piano_2);
                  rtrue;
       ];

fa sì che, se il giocatore preme il pulsante due, viene effettuata una chiamata alla funzione Muovi_cabina con, come parametri, 2 per la variabile locale x e Piano_2 per la variabile locale y. A questo punto, viene dapprima assegnata alla variabile locale piano_asc il valore contenuto in x, utile all’oggetto Ascensore per sapere a quale stanza deve indirizzare il giocatore quando questi esce dalla cabina:

Object Ascensore "Cabina dell'ascensore"
  with description "Sei nella cabina dell'ascensore.",
       out_to [; 
          <<Go n_obj>>;
       ],
       n_to [;
          give Porte_scorrevoli ~open;
          print "Non appena esci dall'ascensore, le porte scorrevoli si
                 chiudono silenziosamente alle tue spalle.^";
          if (self.piano_asc == 0) return Piano_terra;
          if (self.piano_asc == 1) return Piano_1;
          if (self.piano_asc == 2) return Piano_2;
          if (self.piano_asc == 3) return Piano_3;
       ],
       piano_asc 0;

Segue poi, una condizione che verifica se il nome dell’oggetto al quale appartiene Porte_scorrevoli è o meno uguale al nome dell’oggetto passato come parametro alla funzione stessa. Se lo è, allora non accade nulla (il giocatore ha cioè premuto il tasto corrispondente al piano stesso in cui si trova la cabina dell’ascensore), altrimenti vengono spostati gli oggetti Porte_scorrevoli e Pulsante_chiamata al relativo piano.

Per capire meglio quanto ho appena detto, occorre rifarsi al concetto di albero; Inform, cioè, raggruppa gli oggetti con uno schema di questo tipo:

dove gli oggetti Y e Z appartengono all’oggetto X (e sono di conseguenza i child di X), mentre quest’ultimo è il parent di Y e Z. L’oggetto J è il sibling di Z (e non appartiene a X) ma anche parent di K e così via.

Sembrerebbe tutto a posto, ma c’è un’ultima considerazione da fare. Definendo il primo pulsante come segue:

Button -> Pulsante_1 "secondo pulsante"
  with name 'secondo' 'uno' '1//',
       before
       [;
          Push:   Muovi_cabina(1, Piano_1);
                  rtrue;
       ];

tutto sembra essere a posto. Tuttavia, quando il giocatore preme il pulsante 1:

Cabina dell'ascensore
Sei nella cabina dell'ascensore.

Puoi vedere un pannello di controllo con tre tasti numerati come zero, uno e due.

>premi 1
(il pannello di controllo)
È fisso al suo posto.

>

Inform assegna il nome 1 al pannello di controllo anziché all’oggetto Pulsante_1. Questo bug, che non so se imputare a Inform stesso o a Infit, è possibile evitarlo con un po’ d’astuzia. Iniziamo a esaminare l’oggetto Pannello_controllo:

Object -> Pannello_controllo "pannello di controllo" 
  with name 'pannello' 'controllo',
       description "Lo osservi attentamente, ma non noti nulla di 
                    speciale.",
       initial "Puoi vedere un pannello di controllo con quattro tasti 
                numerati da zero a tre.",
   has static;

La prima modifica che occorre fare è l’inserimento dell’azione Push (che in questo caso deve essere analoga a quella dell’oggetto Pulsante_1):

Object -> Pannello_controllo "pannello di controllo" 
  with name 'pannello' 'controllo',
       description "Lo osservi attentamente, ma non noti nulla di 
                    speciale.",
       initial "Puoi vedere un pannello di controllo con quattro tasti 
                numerati da zero a tre.",
       before 
       [; 
          Push:    Muovi_cabina(1, Piano_1);
                   rtrue;
       ],
   has static;

Agendo in questo modo, l’ascensore si può spostare al primo piano:

Cabina dell'ascensore
Sei nella cabina dell'ascensore.

Puoi vedere un pannello di controllo con quattro tasti numerati da zero a tre.

>premi 1
(il pannello di controllo)
Le porte si chiudono e la cabina si mette in movimento. 
Improvvisamente, le porte si aprono di nuovo.

>

Come potete però vedere, prima che l’ascensore si sposti viene anche stampato il nome dell’oggetto, che non è ovviamente il pannello di controllo. Occorre allora fare una seconda modifica:

Object -> Pannello_controllo "secondo pulsante" 
  with name 'pannello' 'controllo',
       description "Lo osservi attentamente, ma non noti nulla di 
                    speciale.",
       initial "Puoi vedere un pannello di controllo con quattro tasti 
                numerati da zero a tre.",
       before 
       [; 
          Push:    Muovi_cabina(1, Piano_1);
                   rtrue;
       ],
   has static;

Cambiando il nome dell’oggetto come secondo pulsante, abbiamo risolto anche il secondo problema:

Cabina dell'ascensore
Sei nella cabina dell'ascensore.

Puoi vedere un pannello di controllo con quattro tasti numerati da zero a tre.

>premi 1
(il secondo pulsante)
Le porte si chiudono e la cabina si mette in movimento. 
Improvvisamente, le porte si aprono di nuovo.

>

Rimane tuttavia un altro problema; se il giocatore prova a premere il pannello di controllo:

Cabina dell'ascensore
Sei nella cabina dell'ascensore.

Puoi vedere un pannello di controllo con quattro tasti numerati da zero a tre.

>premi pannello
Le porte si chiudono e la cabina si mette in movimento.
Improvvisamente, le porte si aprono di nuovo.

>

Inform continua a eseguire il codice relativo all’azione Push associata (la stessa, cioè, dell’oggetto Pulsante_1). Per risolvere questo terzo problema, bisogna ricorrere a una soluzione drastica:

Object -> Pannello_controllo "secondo pulsante" 
  with name 'pannello' 'controllo',
       initial "Puoi vedere un pannello di controllo con quattro tasti 
                numerati da zero a tre.",
       parse_name [;
           if (NextWord() == 'pannello' or 'controllo') return 0;
       ],
       before 
       [; 
          Push:    Muovi_cabina(1, Piano_1);
                   rtrue;
       ],
   has static;

Utilizzando la proprietà parse_name in questo modo, "obbligo" Inform a ignorare totalmente i nomi "pannello" e "controllo":

Cabina dell'ascensore
Sei nella cabina dell'ascensore.

Puoi vedere un pannello di controllo con quattro tasti numerati da zero a tre.

>premi il pannello
Non vedi nulla del genere.

>premi 1
(il secondo pulsante)
Le porte si chiudono e la cabina si mette in movimento. 
Improvvisamente, le porte si aprono di nuovo.

>esci
Non appena esci dall'ascensore, le porte scorrevoli si chiudono silenziosamente alle tue spalle.

Primo piano
Sei al primo piano.

Puoi vedere delle porte scorrevoli qui.

>

Certo, la risposta di sistema non è delle migliori (il pannello di controllo infatti esiste, nonostante Inform affermi il contrario), ma d’altra parte non si può sempre avere tutto[1].

Note[modifica]

  1. Cliccate qui per scaricare il listato di questo esercizio (il file 5.07.inf).