Capitolo 10: Capitan Fato: prima! ================================= S was a sailor, and spent all he got; T was a tinker, and mended a pot. Pur semplici come sono, i nostri due giochi hanno coperto la maggior parte delle funzionalità di base di Inform, fornendo un terreno abbastanza solido sotto i piedi da permettervi di cominciare a creare storie semplici. Anche se qualcosa di ciò che avete incontrato può sembrarvi ancora senza senso, dovreste essere capaci di esaminare il codice sorgente di un gioco e farvi un'idea generale di cosa succede. Adesso creeremo un terzo gioco, per mostrarvi alcune caratteristiche addizionali e darvi ancora del codice di esempio da analizzare. in "Heidi" abbiamo provato ad andare avanti un passo per volta, spiegando ogni pezzettino di codice che abbiamo inserito nel gioco mentre creavamo gli oggetti in sequenza. In "Guglielmo Tell" avrete notato che abbiamo fatto qualche necessaria divagazione esplicativa man mano che i concetti divenivano più interessanti e complessi. Qui organizzeremo le informazioni in sezioni didattiche logiche, definendo alcuni degli oggetti inizialmente in modo minimo e poi aggiungendo complessità quando serve. Ancora una volta, questo significa che non potrete compilare per fare le prove dopo l'aggiunta di ogni spezzone di codice, quindi, se state digitando il codice del gioco man mano che leggete, avrete bisogno di controllare i consigli in "Compile-as-you-go" a pagina 227. Abbiamo già visto una grossa parte di ciò che va a finire nel gioco; potete dedurre da questo che l'attività di progettazione di un gioco è abbastanza ripetitiva e che la maggior parte dei giochi sono, quando ci riferiamo al livello della programmazione, solo un altro remake del solito vecchio tema. Be', sì e no: avete una cinepresa a avete visto come si girano alcuni brevi film, ma da qui a Casablanca ce n'è di strada da fare. Per rimanere su quest'analogia, adesso costruiremo la sequenza iniziale di un film indipendente di serie B, un tributo allo stile da super-eroi reso famoso da un'intera infanzia di fumetti: "Impersonando il tranquillo John Covarth, assistente garzone in una insignificante drogheria, ti FERMI di colpo quando il tuo udito finissimo decifra una chiamata radio della POLIZIA. Un FOLLE sta attaccando la popolazione al Parco Granaio! Devi indossare velocemente il tuo costume da Capitan FATO...!" cosa che non sarà così semplice da fare. In questo breve esempio, il giocatore vincerà quando riuscirà a cambiarsi nel suo costume da super-eroe e volare via per incontrare il nemico. Il confronto avverrà -forse- in un altro gioco, nel quale potremo solo sperare che Capitan Fato riuscirà ad annientare le forze del male, grazie ai suoi misteriosi (e qui non specificati) poteri. Dissolvenza su: una non meglio descritta strada cittadina ********************************************************* Il gioco comincia con il mite John Covarth che cammina per la strada. Prepariamo il gioco come al solito: !============================================================================ Constant Story "Dressed To Save"; Constant Headline "^Semplice esempio in Inform ^di Roger Firth and Sonja Kesserich.^"; ! Traduzione di Paolo Lucchesi Release 1; Serial "020428"; ! per tener conto delle release pubbliche Constant MANUAL_PRONOUNS; Constant MAX_SCORE 2; Constant OBJECT_SCORE 1; Constant ROOM_SCORE 1; Replace MakeMatch; ! richiesto da pname.h Replace Identical; Replace NounDomain; Replace TryGivenObject; Include "Parser"; Include "pname"; ! pname.h la trovate nell'Archivio Include "VerbLib"; Include "Replace"; !============================================================================ ! Classi Class Room with description "IN COSTRUZIONE", has light; Class Appliance with before [; Take,Pull,Push,PushDir: "Anche se i tuoi muscoli SCOLPITI e adamantini ne sarebbero. in grado, tu sei contrario ai danni alla altrui proprietà."; ], has scenery; !============================================================================ ! Oggetti Room strada "In strada" with name 'citta' 'edifici' 'grattacieli' 'negozi' 'appartamenti' 'macchine', description "Da una parte, che grazie al tuo SOVRUMANO senso della direzione sai essere il NORD, c'è un bar in cui si può anche pranzare a quest'ora. Verso sud, vedi una cabina del telefono."; !============================================================================ ! The player's possessions !============================================================================ ! Entry point routines [ Initialise; #Ifdef DEBUG; pname_verify(); #Endif; ! suggested by pname.h location = strada; lookmode = 2; "^^Impersonando il tranquillo John Covarth, assistente garzone in una insignificante drogheria, ti FERMI di colpo quando il tuo udito finissimo decifra una chiamata radio della POLIZIA. Un FOLLE stà attaccando la popolazione al Parco Granaio! Devi indossare velocemente il tuo costume da Capitan FATO...!^^"; ] !============================================================================ ! Standard and extended grammar Include "ItalianG"; Quasi tutto è familiare, a parte qualche dettaglio: Constant MANUAL_PRONOUNS; Constant MAX_SCORE 2; Constant OBJECT_SCORE 1; Constant ROOM_SCORE 1; Inform utilizza in modo predefinito un sistema di pronomi automatici: non appena il personaggio giocante entra in una stanza, la libreria assegna pronomi come ESSO o LUI agli oggetti appropriati (se giocate "Heidi" o "Guglielmo Tell" e digitate PRONOUNS, potete vedere come cambiano le impostazioni). C'è un'altra opzione. Se dichiariamo la costante MANUAL_PRONOUNS, forziamo la libreria ad assegnare i pronomi agli oggetti solo quando il giocatore li menziona (cioè, ESSO non viene assegnato fino a che il giocatore digita, per esempio, ESAMINA ALBERO, e a tal punto ESSO diventa l'ALBERO). Il comportamento dell'assegnazione dei pronomi è una questione di gusto personale; nessun sistema è obiettivamente perfetto. A parte la costante MAX_SCORE che abbiamo già visto in "Guglielmo Tell", che definisce il numero massimo di punti che si possono fare, adesso vediamo due nuove costanti: OBJECT_SCORE e ROOM_SCORE. Ci sono vari sistemi di punteggio predefiniti in Inform. In "Guglielmo Tell" abbiamo visto come potevate manualmente aggiungere (o sottrarre) punti cambiando il valore della variabile score. Un altro approccio è quello di dare punti al giocatore alla prima occasione in cui questo (a) entra in una particolare stanza, o (b) raccoglie un particolare oggetto. Per impostare una stanza o un oggetto veramente come "particolari", tutto quello che avete da fare è di dar loro l'attributo scored; la libreria pensa a tutto il resto. I punteggi predefiniti sono di cinque punti per le stanze finalmente raggiunte e quattro punti per la straordinaria acquisizione di oggetti. Con le costanti OBJECT_SCORE e ROOM_SCORE possiamo cambiare questi valori base; Per amor d'esempio, abbiamo deciso di dare modestamente un punto per ognuno. A proposito, l'uso del segno du uguale = è opzionale con Constant; queste due linee hanno identico effetto: Constant ROOM_SCORE 1; Constant ROOM_SCORE = 1; Un'altra differenza ha a che fare con uno speciale metodo scorciatoia che Inform fornisce per far visualizzare stringhe di testo. Finora, vi abbiamo mostrato: print "E ora, per qualcosa di completamente diverso...^"; return true; ... print_ret "E ora, per qualcosa di completamente diverso..."; Entrambe le righe fanno la stessa cosa: visualizzano la stringa tra virgolette, aggiungono un carattere di andata a capo, e restituiscono il valore vero. Come avete visto nei precedenti giochi di esempio, questo succede abbastanza spesso, così c'è un modo ancora più breve per ottenere lo stesso risultato: "E ora, per qualcosa di completamente diverso..."; Cioè, in una routine (dove il compilatore si aspetta di trovare una collezione di istruzioni ognuna terminata da un punto e virgola), una stringa tra doppie virgolette da sola, senza bisogno di alcuna parola chiave esplicita, funziona esattamente come se avesse un print_ret davanti. Ricordate che questo modo di mostrare il testo implica un return true alla fine (che perciò provoca l'uscita immediata dalla routine). Questo dettaglio diviene importante se non vogliamo restituire vero dopo che la stringa è stata mostrata sullo schermo - in questo caso dobbiamo usare l'istruzione print esplicita. Noterete che - cosa inusuale per una stanza - il nostro oggetto strada ha una proprietà name: Room strada "In strada" with name 'citta' 'edifici' 'grattacieli' 'negozi' 'appartamenti' 'macchine', ... Poiché normalmente non ci si riferisce alle stanze per nome, questo può sembrare strano. In realtà, stiamo illustrando una caratteristica di Inform: la capacità di definire parole di dizionario come "conosciute ma non rilevanti" in questa locazione. Se il giocatore qui digita ESAMINA CITTA', l'interprete risponderà "Non è qualcosa di cui tu abbia bisogno per RISOLVERE la situazione", piuttosto che l'ingannevole "Non vedi nulla del genere". Solitamente preferiamo gestire parole scenografiche del genere utilizzando classi come Prop e Furniture, ma qualche volta la proprietà name di una stanza è una soluzione rapida ed efficace. In questo gioco, forniamo una classe chiamata Appliance per prenderci cura del mobilio e degli oggetti non spostabili. Noterete che la stanza di partenza che abbiamo definito non ha collegamenti, per ora. La descrizione menziona una cabina telefonica e un bar, perciò potremmo volerli programmare. Mentre il bar è una stanza normale, può sembrare logico che la cabina telefonica è in realtà una grossa scatola sul marciapiede; perciò definiamo un container sistemato nella strada, e in cui il giocatore può entrare. Appliance cabina "cabina del telefono" strada with name 'vecchia' 'gialla' 'pittoresca' 'cabina' 'del' 'telefono', description "Il vecchio pittoresco modello giallo, con spazio per una sola persona.", before [; Open: "La cabina è già aperta."; Close: "Non c'è modo di chiudere la cabina."; ], after [; Enter: "Con velocità implausibile, ti fiondi all'interno della cabina."; ], has enterable container open female; La parte interessante sono gli attributi alla fine della definizione. Ricorderete dall'oggetto nido di Heidi che un container è un oggetto in cui possano essere messi altri oggetti. Se rendiamo qualcosa enterable, il giocatore conta come uno di questi oggetti, così ci si può schiacciare dentro. Infine, i containers sono, per definizione, intesi come chiusi. Potete renderli openable (apribili) se volete che il giocatore li possa APRIRE e CHIUDERE a piacimento, ma questo comportamento non sembra appropriato per una cabina pubblica - diventerebbe noioso dover digitare APRI CABINA e CHIUDI CABINA quando queste azioni non fanno nulla di speciale - così aggiungiamo invece l'attributo open (come facemmo con il nido), dicendo all'interprete fin dall'inizio che il contenitore è aperto. Il giocatore, ovviamente, non è consapevole del nostro arrangiamento; può certamente provare ad APRIRE o CHIUDERE la cabina, perciò intercettiamo queste azioni in una proprietà before che semplicemente dice al giocatore che queste non sono scelte rilevanti. La proprietà after fornisce un messaggio personalizzato per passare sopra e ignorare le impostazioni di base della libreria per comandi come ENTRA NELLA CABINA o VAI NELLA CABINA. Poiché nella descrizione della strada abbiamo detto al giocatore che la cabina telefonica è a sud, egli potrebbe anche tentare di digitare SUD. Dobbiamo intercettare questo tentativo e ridirigerlo (già che ci siamo, aggiungiamo un collegamento verso l'ancora indefinita stanza del bar e un messaggio di default per i movimenti che non sono permessi): Room strada "In strada" with name 'citta' 'edifici' 'grattacieli' 'negozi' 'appartamenti' 'macchine', description "Da una parte, che grazie al tuo SOVRUMANO senso della direzione sai essere il NORD, c'è un bar in cui si può anche pranzare a quest'ora. Verso sud, vedi una cabina del telefono.", n_to bar, s_to [; <>; ], cant_go "Non c'è tempo per esplorare. Ti muoverai molto più velocemente nel tuo costume da Capitan FATO."; Questo per quanto riguarda l'entrare nella cabina. Ma per uscirne? Il giocatore può digitare ESCI o FUORI mentre è dentro a un contenitore enterable e l'interprete obbedirà ma, di nuovo, potrebbe digitare NORD. Questo è un problema, perché noi siamo in realtà nella strada (pur se dentro la cabina) e a nord abbiamo il bar. Possiamo provvedere a questa condizione nella proprietà before della stanza: before [; Go: if (player in cabina && noun == n_obj) <>; ], Visto che siamo all'aperto e che la cabina fornisce un riparo, non è impossibile che il giocatore possa provare semplicemente DENTRO, che è un ragionamento perfettamente valido. Tuttavia, questo sarebbe un comando ambiguo, perché si può anche riferire al bar, quindi esprimiamo la nostra perplessità e forziamo il giocatore a provare qualcos'altro: n_to bar, s_to [; <>; ], in_to "Va bene, ma da che parte?", Ora sembra essere tutto a posto, eccetto che per un piccolissimo particolare. Abbiamo detto che, mentre è all'interno della cabina, la posizione del personaggio giocante è sempre nell'oggetto strada, senza riguardo del fatto che si trova all'interno di un oggetto container; se il giocatore provasse a scrivere GUARDA, riceverebbe il messaggio: In strada (nella cabina del telefono) "Da una parte, che grazie al tuo SOVRUMANO senso della direzione sai essere il NORD, c'è un bar in cui si può anche pranzare a quest'ora. Verso sud, vedi una cabina del telefono."; Descrizione difficilmente appropriata quando si è dentro la cabina. Esistono più modi di risolvere il problema, a seconda del risultato che si vuole ottenere. La libreria fornisce una proprietà chiamata inside_description che potete utilizzare con i contenitori in cui si può entrare. Funziona più o meno come la proprietà description normale, ma viene stampata a schermo solo quando il giocatore si trova all'interno del container. La libreria fa uso di questa proprietà in una maniera molto ingegnosa, poiché per ogni azione GUARDA controlla se possiamo vedere al di fuori del contenitore: se il contenitore ha l'attributo transparent impostato, o se è open, la libreria mostra prima la normale description della stanza e poi la inside_description del contenitore. Se la libreria decide che non possiamo vedere fuori del contenitore, viene mostrata solo la inside_description. Guardate ad esempio il seguente esempio (semplificato): Room palcoscenico "Sul palcoscenico" with description "Il palcoscenico è pieno degli aggeggi magici di David Copperfield.", ... Object scatola_magica "scatola magica" palcoscenico with description "Una grossa scatola allungata decorata con stelle argentate, dove fanciulle succintamente abbigliate eseguono un numero della scomparsa della donna.", inside_description "I pannelli interni della scatola magica sono coperti di velluto nero. C'è un minuscolo interruttore accanto al tuo piede destro." ... has container openable enterable light female; Adesso, il giocatore potrebbe APRIRE LA SCATOLA ed ENTRARE NELLA SCATOLA. Un giocatore che provasse a GUARDARE riceverebbe il messaggio: Sul palcoscenico (nella scatola magica) Il palcoscenico è pieno degli aggeggi magici di David Copperfield. I pannelli interni della scatola magica sono coperti di velluto nero. C'è un minuscolo interruttore accanto al tuo piede destro. Se ora il giocatore chiude la scatola e GUARDA: Sul palcoscenico (nella scatola magica) I pannelli interni della scatola magica sono coperti di velluto nero. C'è un minuscolo interruttore accanto al tuo piede destro. Nel nostro caso, però, noi vogliamo che la descrizione della strada non sia mostrata per niente (anche se una persona che telefona dovrebbe in teoria poter vedere la strada dall'interno di una cabina telefonica). Il problema è che abbiamo reso la cabina un contenitore open, e in questo modo la descrizione della strada verrebbe mostrata sempre. C'è un'altra soluzione. Possiamo rendere la proprietà description della stanza strada un po' più complessa, e cambiarne il valore: invece di una stringa, scriviamo una embedded routine. Ecco la stanza (quasi) finita: Room strada "In strada" with name 'citta' 'edifici' 'grattacieli' 'negozi' 'appartamenti' 'macchine', description [; if (player in cabina) "Da questo punto STRATEGICO ottieni una visuale completa di tutto il marciapiede e dell'ingresso al bar di Benny."; else "Da una parte, che grazie al tuo SOVRUMANO senso della direzione sai essere il NORD, c'è un bar in cui si può anche pranzare a quest'ora. Verso sud, vedi una cabina del telefono."; ], before [; Go: if (player in cabina && noun == n_obj) <>; ], n_to [; <>; ], s_to [; <>; ], in_to "Va bene, ma da che parte?", cant_go "Non c'è tempo per esplorare. Ti muoverai molto più velocemente nel tuo costume da Capitan FATO."; La descrizione dall'interno della cabina nomina il marciapiede, cosa che potrebbe invitare il giocatore a ESAMINARLO. Nessun problema: Appliance "marciapiede" strada with name 'marciapiede' 'selciato' 'strada', article "il", description "Esegui un veloce controllo del marciapiede e scopri, con tua immensa sorpresa, che è in TUTTO simile ad ogni altro marciapiede della CITTA'!"; Purtroppo, entrambe le descrizioni menzionano anche il bar, che sarà una stanza e perciò non, dall'esterno, un oggetto esaminabile. Il giocatore può entrarci e riceverà qualunque descrizione scriveremo come risultato di un'azione GUARDA (che avrà a che fare con come il bar appare dall'interno); ma mentre siamo in strada abbiamo bisogno di qualcos'altro per descriverlo: Appliance fuori_dal_bar "Il bar di Benny" strada with name 'bar' 'di' 'benny' 'locale' 'entrata', description "Il miglior bar della città per uno spuntino veloce. Il bar di Benny ha un look da nave spaziale anni 50'", before [; Enter: print "Con un impressionante commistione di fretta e nonchalance entri all'interno del bar.^"; PlayerTo(bar); return true; ], has enterable proper; NOTA: Se volessimo chiamare il nostro bar "caffè", sarebbe consigliabile all'interno del gioco semplificarlo in "caffe". Questo per chiarezza, e non perche Inform non supporta le lettere accentate. L'Inform Designer's Manual spiega in dettaglio come mostrare questi caratteri in "§1.11 How text is printed" e fornisce l'intero elenco dei caratteri della Z-Machine nella Tabella 2. Nel nostro caso, avremmo potuto mostrare questo: Il miglior caffè della città per uno spuntino veloce. Il caffè di Benny ha un look da nave spaziale anni 50'. impostando la proprietà description come una qualsiasi di queste: description "Il miglior caff@`e della città per uno spuntino veloce. Il caff@`e di Benny ha un look da nave spaziale anni 50'", description "Il miglior caff@@182 della città per uno spuntino veloce. Il caff@@182 di Benny ha un look da nave spaziale anni 50'", description "Il miglior caff@{E8} della città per uno spuntino veloce. Il caff@{E8} di Benny ha un look da nave spaziale anni 50'", Tuttavia, tutte e tre le forme sono più difficili da leggere del semplice "caffe", perciò è meglio rendersi la vita semplice. A differenza dell'oggetto marciapiede, stavolta offriamo più di una semplice descrizione. Poiché il giocatore potrebbe tentare di ENTRARE NEL BAR come ragionevole via d'accesso - cosa che avrebbe confuso immensamente l'interprete - cogliamo l'opportunità per rendere anche quest'oggetto enterable, e bariamo un po'. L'attributo enterable ha permesso al verbo ENTRA di essere applicato a quest'oggetto, ma questo non è un container; invece vogliamo che il giocatore sia spedito nella vera stanza del bar. Questa cosa è gestita dalla proprietà before, che intercetta l'azione, mostra un messaggio e teletrasporta il giocatore dentro al bar. Facciamo return true per informare l'interprete che ci siamo presi cura da soli dell'azione Enter, e che può fermarsi lì. Come ultimo dettaglio, notate che adesso abbiamo due modi di entrare nel bar: la proprietà n_to della stanza strada e l'azione Enter dell'oggetto fuori_dal_bar. Un perfezionista potrebbe far notare che sarebbe più ordinato gestire il reale movimento del giocatore tutto in un unico posto del nostro codice, perché questo aumenta la chiarezza. Per ottenere ciò, ridirigiamo la proprietà n_to della strada in questo modo: n_to [; <>; ], Potreste pensare che questa sia solo una mania inutile, ma a buon intenditor poche parole: in un gioco grande, vorrete che la gestione di un'azione avvenga quanto più possibile in un solo posto, perché vi aiuterà a tener conto di dove le cose stanno accadendo se qualcosa va plof (come, credeteci, succederà; leggete "Fare il debug del vostro gioco" a pagina 173). Non c'è bisogno di essere pignoli, soltanto attenti. Una cabina telefonica in una situazione del genere è un chiaro invito per il giocatore a entrarci dentro e provare a cambiarsi nel costume di Capitan Fato. Non permetteremo che ciò accada - il giocatore non è Clark Kent, dopo tutto; più avanti spiegheremo come vietare quest'azione - e questo costringerà il giocatore a entrare nel bar, cercando un posto tranquillo per spogliarsi; ma prima, congeliamo John Covarth davanti al bar Benny's e riflettiamo su una verità fondamentale. Un eroe non è una persona normale ********************************* Che sarebbe come dire, le azioni normali non saranno le stesse per lui. Come avrete probabilmente dedotto dai capitoli precedenti, alcune delle azioni predefinite della libreria sono meno importanti di altre nel far avanzare il gioco verso una delle sue conclusioni. La libreria definisce PREGA e CANTA, per esempio, che sono di poca importanza in una normale situazione di gioco; ognuna mostra un messaggio generico, non compromettente a sufficienza, e questo è tutto. Chiaramente, se il vostro gioco include un portale magico che appare solo se il giocatore intona un brano di Wagner, potreste intercettare l'azione Sing in una proprietà before e modificare il suo, abbastanza inutile, comportamento predefinito. Altrimenti, c'è il messaggio "Sei stonatissimo" pronto per voi. Tutte le azioni, utili o no, hanno una serie di messaggi ad esse associati (i messaggi sono immagazzinati nel file italian.h e sono elencati (per la versione inglese) nell'Appendice 4 dell'Inform Designer's Manual). Abbiamo già visto una maniera di alterare la descrizione del personaggio giocante - "Hai sempre lo stesso bell'aspetto" - in "Guglielmo Tell", ma anche gli altri default possono essere ridefiniti a seconda dei vostri gusti e necessità di circostanza. John Covarth, alias Capitan Fato, potrebbe tranquillamente andar bene per la maggior parte di questi messaggi di default, ma riteniamo che valga la pena di dargli qualche risposta personalizzata. Se non altro, questo migliora l'atmosfera generale, una finezza che molti giocatori considerano importante. Per questo obiettivo, faremo uso dell'oggetto LibraryMessages. Include "Parser"; Include "pname"; ! pname.h la trovate nell'Archivio Object LibraryMessages ! devono essere definiti tra Parser e VerbLib with before [; Buy: "Il piccolo commercio ti ha raramente interessato."; Dig: "I tuoi super-sensi non percepiscono NIENTE sotto terra che possa interessarti in questo momento."; Pray: "Non hai bisogno di disturbare DIVINITA' onnipotenti per risolvere la situazione."; Sing: "Ahimè! Questo non è uno dei tuoi superpoteri."; Sleep: "Un eroe è SEMPRE all'erta."; Sorry: "Capitan FATO non ha tempo per le scuse, ma solo per l'AZIONE."; Strong: "Un vocabolario non adatto ad un EROE come te."; Swim: "Rivolgi la tuta ATTENZIONE alla ricerca di un posto adatto per ESERCITARE il tuo superiore stile di nuoto ma, aihmè, non trovi niente di simile."; Miscellany: if (lm_n == 19) if (vestiti has worn) "Negli abiti della tua identità segreta, riesci in maniera estremamente efficace a sembrare un perdente, un perfetto imbranato."; else "Ora che indossi il tuo costume, proietti l'immagine di PURA potenza , di MUSCOLI gonfi e multicolorati, e di uno stile ARDITO e SOBRIO allo stesso tempo."; if (lm_n == 38) "Non hai bisogno di questo verbo per risolvere con SUCCESSO la situazione."; if (lm_n == 39) "Non è qualcosa di cui tu abbia bisogno per RISOLVERE la situazione."; ]; Include "VerbLib"; Include "Replace"; Se lo fornite, l'oggetto LibraryMessages deve essere definito tra l'inclusione di Parser e quella di VerbLib (altrimenti non funzionerebbe e ricevereste un errore dal compilatore). Questo oggetto contiene un'unica proprietà - before - che intercetta i messaggi di default che volete cambiare. Un tentativo di CANTARE, ad esempio, ora, farà mostrare il messaggio "Ahimè! Questo non è uno dei tuoi superpoteri". In aggiunta a queste risposte specifiche per il singolo verbo, la libreria definisce altri messaggi non direttamente associati a un'azione, come la risposta predefinita quando un verbo non viene riconosciuto, o se tentate di riferirvi a un oggetto che non è nei dintorni, e altre cose. Si può accedere alla maggior parte di questi messaggi tramite la voce Miscellany, che ha una lista numerata di risposte. La variabile lm_n contiene il valore corrente del numero del messaggio da stampare, così potete cambiare il default con un controllo come questo: if (lm_n == 39) "Non è qualcosa di cui tu abbia bisogno per RISOLVERE la situazione."; dove 39 è il numero che sta per il messaggio standard "Non è importante ai fini del gioco" - mostrato quando il giocatore menziona una parola che è elencata nella proprietà name di una stanza, come abbiamo fatto per la strada. Non sorprende quindi che il messaggio predefinito per quando ci si auto-esamina: "Hai sempre lo stesso bell'aspetto" compaia all'interno di Miscellany - è il numero 19 - così possiamo modificarlo attraverso l'oggetto LibraryMessages invece di assegnare, come facevamo in precedenza, una nuova stringa alla proprietà player.description. Nel nostro gioco, la descrizione del personaggio giocante ha due stati: con gli abiti normali come John Covarth e con il costume da super-eroe come Capitan Fato; da qui il controllo if (vestiti has worn). Questa discussione sul cambiare le apparenze del nostro eroe mostra che esistono modi diversi di ottenere lo stesso risultato, situazione che è comune quando si progetta un gioco. I problemi possono essere avvicinati da angoli differenti; perché usare una tecnica e non un'altra? Di solito, il contesto fa pendere la bilancia in favore di una soluzione, anche se può capitare che optiate per la soluzione non-così-buona a causa di qualche altro fattore più importante. Non vi scoraggiate; scelte come queste diventano sempre più frequenti (e facili) man mano che la vostra esperienza aumenta. NOTA: tornando al nostro esempio, un approccio alternativo sarebbe di impostare la variabile player.description nella routine Initialise (come abbiamo fatto con "Guglielmo Tell") sulla stringa "vestiti normali", e cambiarlo più tardi, quando serve. Dopo tutto è una variabile, e potete alterare il suo valore con un'altra istruzione come player.description = look che vi pare in qualunque punto del codice. Questa soluzione alternativa potrebbe essere migliore se intendessimo cambiare la descrizione del giocatore molte volte nell'arco del gioco. Poiché pensiamo di avere soltanto due stati, l'approccio LibraryMessages andrà benissimo. Un'avvertimento finale: come abbiamo spiegato quando estendevamo la grammatica dei verbi standard, voi potreste modificare l'appropriato file della libreria e cambiare tutti i messaggi di default, ma questa non sarebbe una pratica vantaggiosa, perché il vostro file di libreria probabilmente non andrebbe più bene per il prossimo gioco. Consigliamo camdamente l'uso dell'oggetto LibraryMessages. Se state digitando il codice del gioco, probabilmente vorrete leggere la breve sezione sul "Compile-as-you-go" a pagina 227 prima di eseguire una compilazione di prova. Una volta che tutto è a posto, è ora che il nostro eroe entri dentro quell'invitante bar.