Capitolo 3: Heidi, il nostro primo gioco in Inform =================================================== E was an esquire, with pride on his brow; F was a farmer, ad followed the plough. Ognuno dei tre giochi presenti in questa guida sara' esaminato passo passo, al fine di facilitare lÂ’apprendimento; per trarre il maggior beneficio dai nostri esempi, consigliamo, soprattutto se si e' agli inizi, di non limitarsi a leggere il libro, ma di esercitarsi scrivendo il codice sul proprio computer. Il primo gioco, descritto in questo capitolo e nei due che seguiranno narra una breve e romantica storia: "Heidi vive in una piccola baita nel profondo della foresta. Un bel giorno, mentre riposa davanti alla sua baita, sente il frenetico cinguettio di un piccolo passerotto, il cui nido e' caduto da un grande albero nella radura! Heidi mette lÂ’implume nel nido, e quindi si arrampica sullÂ’albero e adagia il nido sul suo ramo. Ahhh non e' tenerissima?" Sembrerebbe davvero semplice, ma anche cosi' dovremo sudare parecchio prima di farne un gioco in Inform completo e soddisfacente. Proseguiremo gradualmente, innanzi tutto abbozzeremo la storia e quindi successivamente rifiniremo tutti i dettagli fino a quando non otterremo un risultato che soddisfi le nostre ambizioni, considerato che siamo al nostro primo lavoro in inform (ci sara' tempo piu' tardi per aggiungere cose piu' interessanti). Creare un file sorgente di base ******************************* Il primo obiettivo e' creare un modello di file sorgente di Inform. Ogni gioco che progetteremo comincera' con i seguenti passaggi: 1. Crea una cartella Inform\Games\Heidi (magari copiando da Inform\Games\MyGame1). 2. Nella cartella, usa il tuo editor di testo per creare il file Heidi.inf: !=============================================================================== Constant Story "Heidi"; Constant Headline "^Semplice esempio in Inform ^di Roger Firth e Sonja Kesserich.^"; ! Traduzione di Paolo Lucchesi Constant MAX_CARRIED 1; Include "Parser"; Include "VerbLib"; Include "Replace"; !=============================================================================== ! Oggetti di gioco !=============================================================================== ! Entry point routines [ Initialise; ]; !=============================================================================== ! Grammatica Include "ItalianG"; !=============================================================================== Presto spiegheremo quale e' il significato di queste istruzioni. Per adesso limitiamoci a scrivere il codice nel file di testo heidi.inf facendo particolare attenzione agli otto punti e virgola e assicurandoci di chiudere tutte le virgolette "....". Le linee che iniziano con il punto esclamativo sono invece semplici commenti con il compito di rendere piu' semplice la lettura del codice. Controlla che il nome del file sia Heidi.inf, e non Heidi.txt o Heidi.inf.txt. Un buon consiglio per imparare Inform piu' velocemente e' quello di provare il proprio codice e non limitarsi a seguire pedissequamente questa guida. 3. Nella stessa cartella, usa il tuo editor di testo per creare il file di supporto per la compilazione del sorgente Heidi.bat (su un PC le istruzioni prima di "pause" sono un’unica lunga linea): ..\..\Lib\Zcode\Infrmw32 Heidi –S +language_name=italian + include_path=.\,..\..\Lib\Zcode,..\..\Lib\Contrib | more pause "alla fine della compilazione" o Heidi.icl (su un Macintosh): -S +source_path=":::Games:Heidi" +code_path=":::Games:Heidi" +include_path=":::Games:Heidi,,::Contrib" +language_name=italian compile Heidi.inf Digita il codice nel file o copia e incolla dal file MyGame1.bat (o MyGame1.icl). A questo punto, dovresti avere una cartella Heidi contenente due file: Heidi.inf e Heidi.bat o Heidi.icl. 4. Compila il file sorgente Heidi.inf. (Fai riferimento a "Inform su un PC IBM" a pagina 19; o per il Mac, lancia Inform-Z, fai click su Compile, e seleziona Heidi.icl nel box di dialogo.) Se la compilazione funziona, verra' creato il file dellÂ’avventura Heidi.z5 nella cartella. Se la compilazione non funziona, hai probabilmente commesso qualche errore di digitazione nel testo, controlla fino quando non lo trovi. 5. Adesso lanciando il file dell’avventura nel tuo interprete per Inform dovresti vedere esattamente le seguenti righe (ad eccezione del Serial number che sara' differente essendo basato sulla data): Heidi Un semplice esempio in Inform di Roger Firth e Sonja Kesserich. Release 1 / Serial number 020827 / Inform v6.21 Library 6/10 SD Oscurita'. E’ completamente buio, e non riesci a vedere niente. > Quando otterrai queste risultato, il tuo file sorgente sara' corretto. Andiamo ora a spiegarne il contenuto. Comprendere il file sorgente **************************** Sebbene ognuno di noi si possegga un approccio personale e una propria liberta' di espressione, i file sorgenti tendono tutti a conformarsi allo standard, soprattutto per quanto riguarda la struttura: le prime linee di inizio, il pezzo di codice alla fine, e tutta quella roba che cÂ’e' in mezzo. Cio' che intendiamo fare e' una mappa della struttura del file sorgente in modo da avere un quadro chiaro nel quale disporre ogni elemento del gioco. Avere una buona visione di questa mappa fin dallÂ’inizio ci aiutera' a tenere ben organizzato e soprattutto comprensibile il codice man mano che svilupperemo il gioco. Gia' da subito possiamo individuare una mezza dozzina di regole di Inform guardando il nostro piccolo codice sorgente. * Quando il compilatore incontra un punto esclamativo, esso ignora tutto il contenuto che lo segue sulla riga. Se il ! e' all’inizio della linea, l’intera riga sara' ignorata; se il ! e' a meta' della linea il compilatore terra' conto della prima meta' di essa e ignorera' qualsiasi cosa vi sia dopo il punto interrogativo. Per questo il punto esclamativo viene utilizzato per commentare il codice; i commenti sono utili per ricordarci come funziona un certo passaggio o perche' abbiamo affrontato un problema in una certa maniera. La lunga sfilza di = che abbiamo inserito nel codice, percio', non hanno nulla di speciale, sono li unicamente per formare una linea di demarcazione tra pezzi di codice. E’ sempre una buona idea quella di commentare il codice, anche se hai tutto chiaro nella tua testa quando lo scrivi, considera che tra qualche mese probabilmente ti sarai dimenticato tutto. Naturalmente il compilatore non riserva nessun trattamento speciale ai punti interrogativi presenti nel testo quotato: un ! tra virgolette "..." e' trattato come un normale carattere. Su questa linea ad esempio, il primo ! e' parte della sequenza (string) di caratteri che viene visualizzata, mentre il secondo, fuori dal testo quotato, preannuncia un commento: print "Ciao mondo!"; ! <- e' invece per il commento * Il compilatore ignora le righe bianche, e tratta gli spazi ripetuti come un singolo spazio (ad eccezione di quando gli spazi sono parte di una stringa). Le due regole viste ci dicono che potremmo avere un file sorgente che assomiglia a questo: Constant Story "Heidi"; Constant Headline "^Un semplice esempio in Inform^di Roger Firth e Sonja Kesserich.^"; Include "Parser";Include "VerbLib";Include "Replace"; [ Initialise; ]; Include "ItalianG"; Noi abbiamo preferito non digitarlo in questa maniera perche', sebbene piu' corto, e' molto piu' difficile da leggere. Quando si progetta un gioco, si spende un sacco di tempo a studiare il codice che si scrive, cosi' e' sempre meglio organizzarlo al meglio ed in modo che sia il piu' leggibile possibile. * Ogni gioco ha bisogno della definizione di alcune constanti: Story (il nome del gioco) e Headline (normalmente informazioni sul tema dell’avventura, il copyright, i nomi degli autori e cosi' via). Questi due valori string, assieme al numero della versione, alla data e ai dettagli del compilatore, compongono il banner che viene visualizzato allÂ’inizio di ogni partita. * Ogni gioco ha bisogno di quattro linee che iniziano con il comando Include che includono nel file sorgente le librerie standard: Include "Parser"; Include "VerbLib"; Include "Replace"; ... Include "ItalianG"; Devono sempre essere disposte in questo ordine, con Parser e VerbLib vicino all’inizio del file, e ItalianG vicino alla fine. * Ogni gioco ha bisogno di definire una routine Initialise : [ Initialise; ]; La routine che abbiamo definito non fa nulla di utile, ma in ogni caso e' necessario che sia presente. Piu' tardi, torneremo su Initialise e spiegheremo che tipo di routine e', e perche' ne abbiamo bisogno. * Avrai notato che alla fine di ogni istruzione menzionata nelle precedenti tre regole vi e' un punto e virgola. Inform e' veramente pignolo nella sua punteggiatura e non sara' affatto contento se ti dimentichi un punto e virgola alla fine di una istruzione. Infatti, il compilatore continua a leggere il codice fino a quando non ne incontra uno; questo e' anche il motivo per il quale abbiamo potuto usare tre linee per definire la costante Headline Constant Headline "^Un semplice esempio in Inform ^di Roger Firth and Sonja Kesserich.^"; Giusto per ripeterci: ogni gioco che progetti comincera' da un codice sorgente come questo e non sarebbe male tenere una copia di questo modello in un posto sicuro, come punto di partenza per le tue future avventure). Adesso che abbiamo fatto un piccolo tour di Inform, possiamo iniziare a pensare a cio' che richiede in particolare il nostro primo gioco. Definire le locazioni del gioco ******************************* Un buon punto di partenza in ogni gioco e' pensare alle locazioni che sono necessarie, percio' andiamo a fare una mappa che mostra le quattro stanze di cui abbiamo bisogno: +----------+ +----------+ |Una radura| |In cima | | nella |O--@| | | foresta | |all'albero| +----------+ +----------+ / / +----------+ +----------+ |Di fronte | |Nel folto | | a una |----| del | | baita | | bosco | +----------+ +----------+ Nell’ IF, spesso si parla delle locazioni con il termine room (stanza), anche quando non ci si trova esattamente fra quattro mura. Andiamo a vedere come Inform definisce queste stanze. Ecco un primo tentativo: Object "Di fronte a una baita" with description "Ti trovi davanti a una baita. Verso est si stende la foresta.", has light; Object "Nel folto del bosco" with description "Attraverso la folta vegetazione, ti pare di scorgere un edificio verso ovest. Un sentiero porta verso nord-est.", has light; Object "Una radura nella foresta" with description "Un alto sicomoro si erge al centro di questa radura. Il sentiero si inoltra tra gli alberi, serso sud-ovest.", has light; Object "In cima all'albero" with description "Ti tieni precariamente appesa al tronco.", has light; Ancora una volta possiamo ricavare una serie di principi da questo esempio: * La definizione di una locazione comincia con la parola Object e finisce, quattro linee circa piu' in basso con un punto e virgola. Ogni componente che appare nel tuo gioco – non solo le locazioni, ma anche le persone, le cose che puoi vedere e toccare, i suoni, gli odori, un vento forte - sono definiti in questa maniera; pensa ad un "oggetto" semplicemente come a un termine generico per la miriade di cose che assieme compongono il modello del mondo che la tua avventura riproduce. * La frase tra virgolette che segue la parola Object e' il nome che l’interprete usa per fornire al giocatore la lista degli oggetti che circondano il personaggio protagonista dellÂ’avventura: dove e', cosa puo' vedere, cosa sta trasportando e cosi' via. * Segue la parola chiave with, che semplicemente dice al compilatore cosa si deve aspettare dopo. * La parola description, introduce unÂ’altro pezzo di testo che fornisce piu' dettagli a proposito dellÂ’oggetto: nel caso di una locazione, da la descrizione di cio' che circonda il giocatore quando entra in quella stanza. La descrizione testuale e' racchiusa da virgolette ed e' seguita da una virgola. * Vicino alla fine, appare la parola chiave has, che ancora dice al compilatore di aspettarsi un certo tipo di informazioni. * La parola light dice che lÂ’oggetto e' una sorgente di illuminazione, e che quindi il personaggio protagonista puo' vedere cosa accade nella locazione. Ci dovrebbe essere almeno una sorgente di luce in ogni stanza (a meno che non si voglia che gettare il giocatore nell’oscurita'); nella maggior parte dei casi viene impostata come sorgente di luce la stessa locazione. Accenniamo a cosa sono queste parole chiave (ne parleremo piu' diffusamente nel prossimo capitolo). Un oggetto puo' avere sia delle proprieta' (introdotte dalla parola chiave with) sia degli attributi (che seguono la parola chiave has). Una proprieta' e' caratterizzata da un nome (tipo description) e da un valore (come la stringa "Ti trovi davanti a una baita. Verso est si stende la foresta."); un attributo invece possiede solamente il nome. Quando giocherai questa piccola avventura ti accorgerai che comincera' in questo modo: Davanti alla baita Ti trovi davanti a una baita. Verso est si stende la foresta. In queste righe puoi vedere come vengono usati il nome della locazione (Davanti la baita) e la descrizione (description) (Ti trovi davanti a una baita. Verso est si stende la foresta.). Spostarsi tra le locazioni ************************** Abbiamo detto che questo era il primo tentativo di definire le locazioni; e' un inizio abbastanza buono ma mancano ancora diverse informazioni. Se guardi la bozza della mappa, puoi vedere come sono disposte le locazioni e come vengono collegate tra di loro; dal "nel folto del bosco", per esempio, il giocatore dovrebbe potersi muovere a ovest verso la baita o a nordest verso la radura. Anche se le descrizioni che abbiamo scritto gia' menzionano le possibili direzioni, abbiamo bisogno di esplicitare tali movimenti tra le definizioni della locazione in una forma che abbia senso per l’interprete. Andiamo a vedere: Object davanti_baita "Di fronte a una baita" with description "Ti trovi davanti a una baita. Verso est si stende la foresta.", e_to foresta, has light; Object foresta "Nel folto del bosco" with description "Attraverso la folta vegetazione, ti pare di scorgere un edificio verso ovest. Un sentiero porta verso nord-est.", w_to davanti_baita, ne_to radura, has light; Object radura "Una radura nella foresta" with description "Un alto sicomoro si erge al centro di questa radura. Il sentiero si inoltra tra gli alberi, serso sud-ovest.", sw_to foresta, u_to sull_albero, has light; Object sull_albero "In cima all'albero" with description "Ti tieni precariamente appesa al tronco.", d_to radura, has light; Abbiamo inserito due cambiamenti all’oggetto locazione. * Come primo punto, tra la parola Object e il nome dellÂ’oggetto tra virgolette abbiamo inserito un diverso tipo di nome: un nome identificativo interno che non verra' mai visto dal giocatore, ma che noi potremo usare nel sorgente per relazionare tra loro gli oggetti. NellÂ’esempio, la prima locazione e' identificata come davanti_baita, e la seconda come foresta. Diversamente dal nome esterno contenuto tra le virgolette, il nome identificativo interno deve essere unÂ’unica parola - ossia senza spazi. Per maggiore facilita' di lettura, useremo spesso il carattere underscore come pseudo spazio: davanti_baita e' piu' chiaro di davantibaita. * Come secondo punto, abbiamo aggiunto dopo la descrizione della locazione delle istruzioni che usano i nomi interni identificativi delle locazioni per mostrare come esse sono connesse tra di loro; una istruzione per ogni connessione. L’oggetto davanti_baita ha quindi questa linea aggiuntiva: e_to foresta, Essa consente al giocatore che e' davanti alla baita di digitare VAI A EST (o EST, o solo E), e il gioco lo trasportera' alla locazione verso lÂ’identificativo interno specificato, ossia in questo caso verso la foresta. Se il giocatore prova a dirigersi verso qualsiasi altra direzione ricevera' la risposta "Non puoi andare in quella direzione". Cio' che abbiamo definito e' quindi un unico tipo di spostamento verso est: davanti_baita -----> foresta. L’oggetto foresta ha altre due istruzioni: w_to davanti_baita, ne_to radura, La prima linea definisce la direzione verso ovest foresta -----> davanti_baita (cio' permette al giocatore di tornare verso la baita), e la seconda definisce la connessione foresta -----> radura che va verso nordovest. Inform prevede 8 direzioni "orizzontali" (n_to, ne_to, e_to, se_to, s_to, sw_to, w_to, nw_to) due "verticali" (u_to, d_to) e due speciali, in_to e out_to. Vedremo l’uso di alcune di queste nei rimanenti collegamenti tra locazioni. E’ rimasto un ultimo dettaglio prima di poter testare la nostra avventura. Ricorderai che la nostra storia comincia con Heidi che sta davanti alla baita. Dobbiamo dire allÂ’interprete quindi che lÂ’oggetto davanti_baita e' la locazione da dove il gioco deve iniziare, per farlo useremo la routine Initialise : [ Initialise; location = davanti_baita; ]; location e' una variabile, parte della libreria, che dice all’interprete in quale locazione risiede il giocatore al momento. Qui stiamo quindi dicendo allÂ’interprete che allÂ’inizio del gioco, il personaggio giocatore e' nella stanza davanti_baita . Ora possiamo aggiungere cio' che abbiamo scritto al sorgente del file modello Heidi.inf. A questo punto, dovresti studiare le quattro definizioni delle locazioni, comparandole con la bozza di mappa fatta, fin quando ti sarai convinto di aver capito come si creano le connessioni tra le locazioni. !=============================================================================== Constant Story "Heidi"; Constant Headline "^Semplice esempio in Inform ^di Roger Firth e Sonja Kesserich.^"; ! Traduzione di Paolo Lucchesi Include "Parser"; Include "VerbLib"; Include "Replace"; !=============================================================================== ! Oggetti di gioco Object davanti_baita "Di fronte a una baita" with description "Ti trovi davanti a una baita. Verso est si stende la foresta.", e_to foresta, has light; Object foresta "Nel folto del bosco" with description "Attraverso la folta vegetazione, ti pare di scorgere un edificio verso ovest. Un sentiero porta verso nord-est.", w_to davanti_baita, ne_to radura, has light; Object radura "Una radura nella foresta" with description "Un alto sicomoro si erge al centro di questa radura. Il sentiero si inoltra tra gli alberi, serso sud-ovest.", sw_to foresta, u_to sull_albero, has light; Object sull_albero "In cima all'albero" with description "Ti tieni precariamente appesa al tronco.", d_to radura, has light; !=============================================================================== ! Entry point routines [ Initialise; location = davanti_baita; ]; !=============================================================================== ! Grammatica Include "ItalianG"; !=============================================================================== Digita il codice facendo sempre attenzione alla punteggiatura, specialmente alle virgole e ai punti e virgola. Compila il sorgente e correggi gli eventuali errori che riporta il compilatore. Ora puoi giocare lÂ’avventura, naturalmente non puoi fare molto, ma dovresti essere in grado di muoverti liberamente tra le quattro locazioni che hai definito. NOTA: per minimizzare lo spazio ed il tempo dedicato a scrivere gli esempi, qui sono state usate descrizioni molto brevi, naturalmente tu poi invece renderle piu' lunghe ed interessanti. Aggiungiamo l’uccello ed il nido ******************************** Dati i precedenti, non dovresti essere molto sorpreso nellÂ’apprendere che sia lÂ’uccello che il nido in inform sono degli oggetti. Cominceremo la loro definizione in questo modo: Object uccello "uccellino" with description "Troppo giovane per saper volare, il passerotto pigola inerme.", has ; Object nido "nido di uccelli" with description "Il nido e' fatto di rametti e sterpi intrecciati.", has ; Puoi notare come queste definizioni ricalcano lo stesso schema delle locazioni che abbiamo definito precedentemente: una parola unica come identificatore interno (uccello, nido), e una parola o una frase come nome esterno a beneficio del giocatore (uccellino, nido di uccelli). Entrambi hanno una descrizione piu' dettagliata, ma mentre per le stanze questa viene visualizzata quando il giocatore vi entra per la prima volta, o quando digita GUARDA, per gli altri oggetti essa viene visualizzata quando il giocatore ESAMINA quellÂ’oggetto. Cio' che gli altri oggetti non hanno sono naturalmente le connessioni dei movimenti (e_to, w_to, etc. che si applicano solo alle locazioni) o la luce light (che non e' necessaria visto che le locazioni assicurano che vi sia luce sempre disponibile). Quando il gioco e' in esecuzione, il giocatore vorra' poter interagire con questi due nuovi oggetti, dicendo ad esempio ESAMINA L’UCCELLINO o PRENDI il NIDO. Per fare in modo che queste azioni funzionino correttamente dobbiamo specificare la parola (o le parole) con cui il giocatore potrebbe riferirsi ai due oggetti. Il nostro obiettivo e' la flessibilita', ossia prevedere il vocabolario del giocatore, in modo di avere buone possibilita' che i comandi da lui digitati vengano compresi dal parser. Aggiungiamo una riga per ogni definizione: Object uccello "uccellino" with description "Troppo giovane per saper volare, il passerotto pigola inerme.", name 'uccello' 'uccellino' 'passero' 'passerotto' 'volatile', has ; Object nido "nido di uccelli" with description "Il nido e' fatto di rametti e sterpi intrecciati.", name 'nido' 'rametti' 'sterpi', has ; La parola chiave name introduce una linea di virgolette singole '...'. Ognuno dei vocaboli quotati rappresenta una parola del dizionario, nota che stiamo parlando di una "parola", non di una "frase" ('uccello' 'uccellino' oppure 'passerotto'); non si possono usare spazi, virgole o periodi nelle parole del dizionario, sebbene vi sia uno spazio tra ognuna di esse, e lÂ’intera lista finisca con una virgola. LÂ’idea e' che lÂ’interprete decide a quale oggetto il giocatore si riferisce controllando lÂ’intero dizionario di parole. Se il giocatore cita UCCELLO, o UCCELLINO o PASSEROTTO, e' lÂ’ uccello cio' a cui vuole riferirsi; se invece menziona NIDO, STERPI o RAMETTI si sta chiaramente riferendo al nido. E se invece digita PASSEROTTO NIDO o STERPI UCCELLO, lÂ’interprete rispondera' educatamente che non capisce un tubo di cosa gli dice il giocatore. Potresti chiederti il motivo per cui abbiamo bisogno di una lista di parole name per lÂ’uccello e il suo nido, dal momento che li abbiamo gia' messi nelle locazioni. EÂ’ perche' il giocatore non puo' interagire con una locazione allo stesso modo con cui interagisce con gli altri oggetti; per esempio, non ha bisogno di scrivere ESAMINA LA FORESTA - gli basta scrivere GUARDA. La definizione dellÂ’uccello e' completa, ma ci sono ancora alcune particolari da inserire per il nido: abbiamo infatti bisogno di poter mettere lÂ’uccello al suo interno. Possiamo fare cio' definendo il nido come un container - ossia un oggetto capace di contenere altri oggetti al suo interno - cosi' il giocatore puo' digitare METTI (o INSERISCI) LÂ’UCCELLO NEL NIDO. Inoltre definiamo il nido come open - aperto - in modo da evitare che lÂ’interprete ci chieda di aprirlo quando gli ordiniamo di mettere lÂ’uccello nel nido. Object nido "nido di uccelli" with description "Il nido e' fatto di rametti e sterpi intrecciati.", name 'nido' 'rametti' 'sterpi', has container open; Ora che abbiamo definito per bene i due oggetto possiamo incorporarli nel gioco. Per farlo dobbiamo scegliere la locazione dove il giocatore puo' trovarli. Decidiamo di mettere l’uccello nella foresta, mentre il nido e' nella radura. Ecco come facciamo cio': Object uccello "uccellino" foresta with description "Troppo giovane per saper volare, il passerotto pigola inerme.", name 'uccello' 'uccellino' 'passero' 'passerotto' 'volatile', has ; Object nido "nido di uccelli" radura with description "Il nido e' fatto di rametti e sterpi intrecciati.", name 'nido' 'rametti' 'sterpi', has container open; Leggi la prima riga come: "Questa e' la definizione di un oggetto che viene identificato in questo file come uccello, ed e' conosciuto dal giocatore con il nome di uccellino, esso e' inizialmente collocato allÂ’interno dellÂ’oggetto identificato in questo file come foresta." Dove mettere questo nuovo oggetto nel nostro file sorgente? Piu' o meno dove volete, ma troverete convenienteinserirlo di seguito alla locazione nel quale si trova. Cio' significa aggiungere lÂ’uccello subito dopo la foresta, e il nido appena dopo la radura. Ecco la parte intermedia del nostro sorgente: !=============================================================================== ! Oggetti di gioco Object davanti_baita "Di fronte a una baita" with description "Ti trovi davanti a una baita. Verso est si stende la foresta.", e_to foresta, has light; Object foresta "Nel folto del bosco" with description "Attraverso la folta vegetazione, ti pare di scorgere un edificio verso ovest. Un sentiero porta verso nord-est.", w_to davanti_baita, ne_to radura, has light; Object uccello "uccellino" foresta with description "Troppo giovane per saper volare, il passerotto pigola inerme.", name 'uccello' 'uccellino' 'passero' 'passerotto' 'volatile', has ; Object radura "Una radura nella foresta" with description "Un alto sicomoro si erge al centro di questa radura. Il sentiero si inoltra tra gli alberi, serso sud-ovest.", sw_to foresta, u_to sull_albero, has light; Object nido "nido di uccelli" radura with description "Il nido e' fatto di rametti e sterpi intrecciati.", name 'nido' 'rametti' 'sterpi', has container open; Object albero "albero di sicomoro" radura with description "Fieramente alto nel mezzo della radura, l'albero sembra molto facile da scalare.", name 'albero' 'sicomoro' 'tronco', has scenery; Object sull_albero "In cima all'albero" with description "Ti tieni precariamente appesa al tronco.", d_to radura, has light; !=============================================================================== Fai i cambiamenti, ricompila il gioco e prova lÂ’avventura, ecco cio' che dovresti vedere: Nel folto del bosco Attraverso la folta vegetazione, ti pare di scorgere un edificio verso ovest. Un sentiero porta verso nord-est. Puoi vedere un uccelino qui. > Aggiungiamo l’albero e il ramo ****************************** La descrizione della radura menziona un albero fieramente alto, sul quale si suppone il giocatore potra'arrampicarsi. Andiamo a definire questo nuovo oggetto. Object albero "albero di sicomoro" radura with description "Fieramente alto nel mezzo della radura, l'albero sembra molto facile da scalare.", name 'albero' 'sicomoro' 'tronco', has scenery; Ogni istruzione a questo punto dovrebbe risultare familiare, con lÂ’eccezione dellÂ’attributo scenery verso la fine. Abbiamo gia' citato lÂ’albero nella descrizione della radura, cosi' non vogliamo che lÂ’interprete aggiunga una nuova riga "Puoi vedere un albero di sicomoro qui" dopo di essa, come invece avviene per lÂ’uccello ed il nido. Definendo lÂ’albero come scenery noi sopprimiamo tale ripetizione, inoltre impediamo al giocatore la possibilita' di raccogliere l’oggetto albero. Ci rimane da definire un ultimo oggetto: il ramo in cima allÂ’albero. Non ci dovrebbero essere sorprese nella sua definizione: Object ramo "ramo largo e robusto" sull_albero with description "E' abbastanza largo da sostenere un'oggetto.", name 'ramo' 'largo' 'robusto', has static supporter; Le uniche nuove istruzioni sono i due attributi. static e' simile a scenery: previene che il ramo possa essere raccolto dal giocatore, ma non sopprime la frase che menziona lÂ’oggetto quando viene data la descrizione della locazione. Invece supporter e' piu' simile allÂ’istruzione container che abbiamo usato per il nido, con lÂ’eccezione che questa volta il personaggio giocatore puo' mettere gli oggetti sopra il ramo. (Approfittiamo dellÂ’occasione per far sottolineare che un oggetto non puo' normalmente essere allo stesso tempo un container e un supporter.) Ecco qui i nostri oggetti: !=============================================================================== ! Oggetti di gioco Object davanti_baita "Di fronte a una baita" with description "Ti trovi davanti a una baita. Verso est si stende la foresta.", e_to foresta, has light; Object foresta "Nel folto del bosco" with description "Attraverso la folta vegetazione, ti pare di scorgere un edificio verso ovest. Un sentiero porta verso nord-est.", w_to davanti_baita, ne_to radura, has light; Object uccello "uccellino" foresta with description "Troppo giovane per saper volare, il passerotto pigola inerme.", name 'uccello' 'uccellino' 'passero' 'passerotto' 'volatile', has ; Object radura "Una radura nella foresta" with description "Un alto sicomoro si erge al centro di questa radura. Il sentiero si inoltra tra gli alberi, serso sud-ovest.", sw_to foresta, u_to sull_albero, has light; Object nido "nido di uccelli" radura with description "Il nido e' fatto di rametti e sterpi intrecciati.", name 'nido' 'rametti' 'sterpi', has container open; Object albero "albero di sicomoro" radura with description "Fieramente alto nel mezzo della radura, l'albero sembra molto facile da scalare.", name 'albero' 'sicomoro' 'tronco', has scenery; Object sull_albero "In cima all'albero" with description "Ti tieni precariamente appesa al tronco.", d_to radura, has light; Object ramo "ramo largo e robusto" sull_albero with description "E' abbastanza largo da sostenere un'oggetto.", name 'ramo' 'largo' 'robusto', has static supporter; !=============================================================================== Ancora una volta, fai i cambiamenti, e magari qualche esperimento su cosa puo' fare il tuo modello di mondo. Ritocchi finali *************** Il nostro primo passo verso la creazione di una avventura e' quasi fatto; aggiungiamo solo due ulteriori modifiche. La prima e' semplice: Heidi non puo' arrampicarsi sullÂ’albero tenendo in mano lÂ’uccello ed il nido separatamente: vogliamo che il giocatore metta prima il passerotto nel suo nido. Un semplice modo di raggiungere questo obiettivo e' aggiungere un comando vicino l'’inizio del file: !============================================================================ Constant Story "Heidi"; Constant Headline "^Semplice esempio in Inform ^di Roger Firth e Sonja Kesserich.^"; ! Traduzione di Paolo Lucchesi Constant MAX_CARRIED 1; Il valore di MAX_CARRIED limita il numero di oggetti che il personaggio puo' portare con se contemporaneamente; impostando il suo valore a 1 stiamo dicendo che il giocatore puo' scegliere di portare o lÂ’uccello o il nido, ma non entrambi. Naturalmente, il limite ignora il contenuto di un oggetto container o supporter , quindi il nido con lÂ’uccello dentro e' considerato come un oggetto singolo. La seconda modifica e' leggermente piu' complessa ed importante: al momento non esiste un modo di vincere il gioco! LÂ’obiettivo per il giocatore e' mettere lÂ’uccello nel nido, portare il nido sullÂ’albero e piazzarlo sul ramo; quando ha compiuto tutte queste azioni il gioco dovrebbe terminare. Ecco come possiamo fare: Object ramo "ramo largo e robusto" sull_albero with description "E' abbastanza largo da sostenere un'oggetto.", name 'ramo' 'largo' 'robusto', each_turn [; if (nido in ramo) deadflag = 2; ], has static supporter; NOTA: diamo una piccolo spiegazione di cio' che avviene. Se trovi difficolta' a comprendere questo passaggio non ti preoccupare. EÂ’ il piu' difficile, e introduce diversi nuovi concetti tutti in una volta. Piu' avanti nella guida, spiegheremo questi concetti piu' chiaramente, cosi' se vuoi puoi saltare questo passaggio ora, per riprenderlo piu'in tardi puoi farlo tranquillamente. La variabile deadflag, parte della libreria, e' normalmente pari a 0. Se si imposta il suo valore a 2, l’interprete notera' il cambiamento e terminera' il gioco con il messaggio "HAI VINTO!". L’istruzione: if (nido in ramo) deadflag = 2; dovrebbe essere letta come: "Controlla se il nido e' al momento nel ramo (se il ramo e' un container) o su di esso (se il ramo e' un supporter); se la condizione e' vera allora imposta la variabile deadflag a 2; Altrimenti non fare nulla." La parte che contiene l’istruzione: each_turn [; ... ], dovrebbe essere letta come: "Alla fine di ogni turno (quando il giocatore e' nella stessa locazione del ramo) fai qualsiasi cosa sia scritta allÂ’interno delle parentesi quadre". Quindi mettendo il tutto assieme: * Alla fine di ogni turno (dopo che il giocatore digita qualcosa e preme il pulsante INVIO, e lÂ’interprete ha fatto cio' che gli e' stato richiesto) lÂ’interprete controlla se il giocatore e il ramo sono nella stessa locazione. Se la condizione non si verifica non accade nulla. Se invece sono insieme, controlla dove e' il nido. Inizialmente e' nella radura, quindi non accade nulla. * Alla fine di ogni turno lÂ’interprete controlla anche il valore della variabile deadflag. Normalmente e' pari a 0, cosi' non accade niente. * Finalmente il giocatore mette il nido sul ramo. "Aha!" dice lÂ’interprete (a se stesso naturalmente), e imposta il valore della deadflag a 2. * Immediatamente dopo, (unÂ’altra parte de) lÂ’interprete la controlla e trova che il valore deadflag e' cambiato a 2, che significa che il gioco e' stato completato con successo; allora, dice al giocatore "HAI VINTO!" Il che era cio' che volevamo ottenere per adesso da questo esempio. Fai questi ultimi cambiamenti ricompia e prova l’avventura. Probabilmente troverai che alcune cose potevano essere fatte meglio - anche un semplice gioco come questo puo' essere considerato una possibilita' per migliorare - percio' nel prossimo capitolo rivisiteremo un pochino Heidi e la sua foresta. Ma prima ricapitoleremo cio' che abbiamo imparato.