Inform e Glulx/Inform e ancora Inform/Su e giù con l'ascensore
Wikibooks, manuali e libri di testo liberi.
[modifica] Su e giù con l'ascensore
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 |
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. |
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. |
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? |
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. |
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. |
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. |
Rimane tuttavia un altro problema; se il giocatore prova a premere il pannello di controllo:
| Cabina dell'ascensore Sei nella cabina dell'ascensore. |
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. |
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].
[modifica] Note
