Capitolo 15: Compilate il vostro gioco ====================================== Raro quasi quanto un alchimista che ottiene l'oro dal metallo, il processo di compilazione è quello che trasforma il vostro codice sorgente in uno story file (sebbene il risultato che si ottiene più spesso è un rimprovero che spiega perché ciò non sia - ancora una volta - accaduto). Una tale magia è prodotta dal compilatore, che è il programma che prende il vostro codice (più o meno comprensibile) e lo traduce in un file binario: un insieme di numeri che segue uno specifico formato capito solo da un interprete Z-code. Ad uno sguardo superficiale la compilazione può sembrare un trucco molto semplice. Voi eseguite solo il compilatore, indicandogli qual è il file sorgente dal quale volete generare un gioco et voilà! La magia è fatta. Tuttavia gli ingredienti dell'incantesimo vanno preparati con cura. Il compilatore "legge" il vostro codice sorgente, ma non nella maniera flessibile con la quale lo leggerebbe un essere umano. E' necessario che la sintassi segua alcune regole molto precise, od il compilatore si lamenterà che non è in grado di portare a termine il suo lavoro in queste condizioni. Il compilatore si cura poco del significato, ma molto dell'ortografia, come il più inflessibile degli insegnanti; non ci sono occhi lucidi alla Bambi che tengano qui. Sebbene l'incantesimo lanciato dal compilatore sia sempre lo stesso, potete indicare, con qualche limitazione, come volete che la magia venga fatta. Ci sono un po' di opzioni che modificano il processo di compilazione; alcuni li definite nel codice sorgente, altri con degli _switch_ (modificatori) e con determinati comandi quando eseguite il programma. Il compilatore assumerà alcune opzioni predefinite, ma potete sempre modificarle se ne avete la necessità. Molte di queste opzioni sono fornite "nel caso in cui" determinate condizioni speciali debbano essere applicate; altre servono a programmatori con una certa esperienza che hanno bisogno di requisiti complessi ed avanzati, ed è meglio lasciarle (per ora) a quelli che sono avanti con le conoscienze. Ingredienti *********** Se il file sorgente non viene scritto in maniera corretta, il compilatore protesta, producendo un messaggio di warning (avvertimento) oppure un messaggio di error (errore). I warning sono lì per dirvi che potrebbe esserci un errore che potrebbe modificare il comportamento del gioco durante l'esecuzione (run-time), ma il compilatore non fermerà il processo e produrrà, comunque, uno story file. Gli error, invece, riguardano errori che rendono impossibile al compilatore la creazione di tale file. Di questi i fatal error (errori fatali) fermano immediatamente la compilazione, mentre i non-fatal error (errori non fatali) consentono al compilatore di continuare a leggere il codice sorgente. (Come vedremo tra poco, questo porta sia vantaggi che svantaggi: sebbene possa essere utile avere un compilatore che riporti quanti più non-fatal error possa, scoprirete presto che la maggior parte degli stessi potrebbe essere causata da un singolo errore). *** Fatal error È difficile, ma non impossibile, causare un fatal error. Se indicate il nome sbagliato come nome di file sorgente, il compilatore non sarà neanche in grado di partire, dicendovi: Couldn't open source file nomefile [Non posso aprire il file sorgente nomefile] Se il compilatore individua un gran numero di non-fatal error, può abbandonare l'intero processo con un: Too many errors: giving up [Troppi errori: mi arrendo] La maggior parte dei fatal error, comunque, capita perché il compilatore termina la memoria o lo spazio su disco; anche se con i computer di oggi è poco comune. Potreste, però, incontrare dei problemi se lo story file, che deve rientrare all'interno dei (ristretti) limiti della Z-Machine, diventa troppo grande. Inform, normalmente, compila il vostro codice sorgente in un file Versione 5 (ecco cosa indica l'estensione .z5 che vedete nel file prodotto), che ha una dimensione massima di 256 Kbyte. Se il vostro gioco è più grande di tale limite, dovete compilare il vostro gioco in un file Versione 8 (.z8), che può crescere fino a 512 Kbyte (e lo potete fare semplicemente impostando lo switch -v8; ne parleremo dopo). Avrete bisogno di un'incredibile quantità di codice per superare questi limiti: non dovreste preoccuparvene per qualche mese, o per sempre. *** Non-fatal error I non-fatal error sono molto più comuni. Imparerete subito a conoscere: Expected qualcosa but found qualcos'altro [Mi aspettavo qualcosa ma ho trovato qualcos'altro] Questo è il modo standard per riportare errori di punteggiatura od errori di sintassi. Se digitate una virgola al posto di un punto e virgola, Inform cercherà invano quello che si aspettava di trovare. La cosa buona è che vi verrà indicata la riga incriminata: Tell.inf(76): Error: Expected directive, '[' or class name but found found_in > found_in Compiled with 1 error (no output) [Tell.inf(76): Errore: Mi aspettavo una direttiva, '[' od un nome di classe ma ho trovato found_in > found_in Compilato con 1 errore (nessun output)] Potete vedere il numero di riga (76) e quello che vi è stato trovato, così tornate al codice sorgente e gli date un'occhiata. In questo caso l'errore è stato causato da un punto e virgola dopo la stringa della descrizione (description), invece di una virgola: Prop "banchi" with name 'banchi', description "Cibo, abiti, attrezzature da montagna; la solita roba."; found_in strada vicino_piazza, has pluralname; Qui c'è un messaggio abbastanza ingannevole che potrebbe suggerire che le cose nel nostro codice sorgente sono nell'ordine sbagliato, o che qualche segno di punteggiatura atteso non è stato messo: Fate.inf(459): Error: Expected name for new object or its textual short name but found door > Object door Compiled with 1 error (no output) [Fate.inf(456): Errore: Mi aspettavo il nome per il nuovo oggetto o la sua descrizione breve ma ho trovato door [porta] > Object door Compilato con 1 errore (nessun output)] In effetti non c'è niente di sbagliato nella punteggiatura o nell'ordine delle cose. Il problema è che abbiamo cercato di definire un oggetto con un ID interno pari a door [porta] - potreste pensare che sia abbastanza ragionevole, visto che l'oggetto _è_ una porta - ma Inform già conosce quella parola (è il nome di un attributo di libreria). Il messaggio d'errore, sfortunatamente, fornisce solo un vago accenno al fatto che dovete scegliere un nome diverso: al suo posto abbiamo usato toilet_door [porta_del_bagno]. Quando il compilatore perde la traccia e non trova quello che si aspettava, è normale che le righe che seguono vengano interpretate erroneamente, anche se sono perfettamente corrette. Immaginate un metronomo che batte a tempo con un disco che state ascoltando. Se il disco è rovinato e la puntina salta, può sembrare che il resto del disco sia fuori sincrono, quando in realtà è solo un po' in ritardo a causa di quel singolo incidente. Questo succede anche con Inform, che a volte tira fuori una lista enorme di Expected but not Found. In questo caso la regola è: correggete il primo errore della lista e ricompilate. Potrebbe essere che il resto della canzone sia perfetto. È inutile che vi forniamo una lista dettagliata di tutti gli errori, primo perché gli errori sono numerosi e, poi, perché di solito il testo prodotto indica quello che manca. Avete degli errori se dimenticate una virgola od un punto e virgola. Avete degli errori se usate lo stesso nome per due cose. Avete degli errori per... un sacco di ragioni. Leggete il messaggio, andate alla riga che indica (e, magari, controllate anche quelle un po' prima ed un po' dopo), ed apportatevi quella che sembra la correzione più giusta. *** Warning I warning non sono immediatamente catastrofici, ma dovete liberarvene per fare una buona partenza nella ricerca degli errori di run-time [esecuzione] (leggete "Fare il debug del vostro gioco" a pagina XXX). Potreste aver dichiarato una variabile per poi non usarla; potreste aver confuso gli operatori di assegnazione ed aritmetico (= al posto di ==); potreste aver dimenticato la virgola che separa le proprietà; ecc. ecc. Per questi warning, e per molti altri, Inform ha trovato qualcosa che è legale ma su cui ha dei dubbi. Uno degli incidenti più comuni è quando si torna indietro nel mezzo di un blocco di istruzioni, prima che il resto delle istruzioni possa essere raggiunto. Questo non sempre è evidente come potrebbe pensare, ad esempio in un caso come questo: if (steel_door has open) { print_ret "La brezza spegne il vostro cerino."; give match ~light; } Nell'esempio sopra l'istruzione print_ret restituisce true [vero] dopo che la stringa è stata stampata e, quindi, la riga give match ~light non verrà mai eseguita. Inform si accorge della cosa e ve lo dice. L'intenzione dello scrittore, forse, era: if (steel_door has open) { give match ~light; print_ret "La brezza spegne il vostro cerino."; } La compilazione à la carte ************************** Uno dei vantaggi di Inform è la sua portabilità attraverso sistemi differenti e macchine differenti. Gli usi specifici del compilatore variano di conseguenza, ma alcune funzionalità dovrebbero essere presenti in tutti gli ambienti operativi. Per avere informazioni precise su di una determinata versione dovete eseguire il compilatore fornendogli lo switch -h1. Il compilatore, di solito, viene eseguito solo con il nome del file sorgente come unico parametro. Questo dice al compilatore "leggi questo file e genera uno story file Versione 5 con lo stesso nome". Se vogliamo compilare un gioco in italiano, dobbiamo ricordarci di inserire anche l'indicazione +language_name=italian, altrimenti il compilatore cercherà di produrre un gioco con le regole inglesi. La maggior parte del codice sorgente è piena di istruzioni che definiscono come si debba comportare il gioco durante l'esecuzione, ma contiene anche istruzioni di compilazione indirizzate proprio al compilatore (sebbene tale comando possa sembrare un'istruzione [statement], il suo comportamento è diverso, ed è conosciuta come direttiva [directive]). Abbiamo già visto la direttiva Include: Include "nomefile"; Quando il compilatore raggiunge una riga come quella, va alla ricerca di nomefile - un altro file che contiene codice Inform - e lo tratta come se le istruzioni e le direttive contenute in nomefile si trovassero al posto della direttiva Include. +-----------------------------------------+ | | | MioGioco.inf RobaMia.h | +----------+ | | | codice A | | +--------------------+ +----------+ | | . | | | codice A | | codice B | | \ | . | | | . | +----------+ | ===\ | . | | | . | | ===/ | . | | | . | | / | codice B | | | . | | | . | | | include "RobaMia"; | | | codice C | | | . | | +----------+ | | codice C | | | +--------------------+ | +-----------------------------------------+ In ogni gioco Inform in inglese, includiamo i file di libreria Parser, VerbLib e Grammar. In quelli in italiano includiamo sempre Parser, VerbLib, Replace e ItalianG. Volendo possiamo includere anche altri file. Questo, ad esempio, è il modo che si usa per incorporare le estensioni della libreria scritte da altre persone, come avete visto quando abbiamo incluso pname.h nel nostro gioco "Capitan Destino". Nota: su alcune macchine, un file di libreria viene chiamato, in realtà - ad esempio - Parser.h, mentre su altre solo Parser. Il compilatore si preoccupa di queste differenze; potete sempre digitare semplicemente Include "Parser"; nel vostro codice sorgente. Quando acquisite esperienza con Inform, e i vostri giochi diventano più complessi, potreste trovare che il file sorgente stia diventando ingestibilmente grande. Una tecnica molto utile è quella di dividerlo in sezioni, ognuna memorizzata in un file separato, che includete in un file principale più piccolo. Ad esempio: !================================================================= Constant Story "Guerra e Pace"; Constant Headline "^Un esempio Inform esteso ^by me e Leo Tolstoy.^"; Include "Parser"; Include "VerbLib"; Include "Replace"; Include "1805"; Include "1806-11"; Include "1812A"; Include "1812B"; Include "1813-20"; Include "ItalianG"; Include "Verboski"; !================================================================== Switch (modificatori) ********************* Quando eseguite il compilatore potete impostare alcuni controlli opzionali; questi vengono chiamati switch (modificatori, interruttori) e la maggior parte sono impostati (accesi) o non impostati (spenti), altri accettano un valore numerico 0-9. Gli switch modificano la compilazione in una varietà di modi, spesso cambiando semplicemente i messaggi mostrati dal compilatore quando viene eseguito. Una riga di comando tipica (sebbene possa essere differente su macchine differenti) potrebbe essere: inform file_sorgente story_file switch dove "inform" è il nome del compilatore, il parametro story_file è opzionale (in modo tale che possiate indicare un nome differente da quello di file_sorgente) ed anche gli switch sono opzionali. Un indicatore opzionale (non è propriamente uno switch) ma necessario se vogliamo produrre file in italiano è, come detto prima, +language_name=italian. Gli switch sono preceduti dal segno meno -; se volete impostare, ad esempio, il modo Strict dovete scrivere -S, mentre se volete disattivarlo dovete scrivere -~S. Il simbolo della tilde (~) deve essere interpretato, qui come altrove, come "non" ("not" in inglese). Se volete impostare molti switch potete farlo separandoli con uno spazio ed usando un meno per ogni switch, oppure raggruppandoli tutti insieme dopo un segno di meno senza mettere spazi: inform MioGioco.inf -S -s -x inform MioGioco.inf -Ssx Tutti gli switch, normalmente, sono disattivati per impostazione predefinita, l'unica eccezione è il modo Strict (-S), che è attivo e controlla il codice per degli errori addizionali, rendendo disponibili i verbi di debug durante l'esecuzione del gioco. Questa è l'impostazione ideale mentre si sta scrivendo il codice, ma dovete disattivare il modo Strict (-~S) quando distribuite il vostro gioco. Fortunatamente è molto facile controllare la cosa, visto che il banner del gioco visualizza le lettere "SD" quando è stato compilato in modo Strict: Vestito per Salvare Un semplice esempio Inform by Roger Firth e Sonia Kesserich. Versione 1 / Numero di Serie 020428 / Inform v6.21 Libreria 6/10 SD Gli switch fanno differenza tra maiuscole e minuscole, quindi avrete risultati differenti tra -x e -X. Alcuni degli switch più utili sono: -~S Disattiva il modo Strict del compilatore. Questo evita che vengano fatti alcuni controlli aggiuntivi al vostro codice sorgente ed, inoltre, non aggiunge i verbi di debug al vostro story file (a meno che voi non specifichiate -D). Il modo Strict è attivo per impostazione predefinita. -v5 -v8 Compilano in quella versione di story file. Le Versioni 5 (quella predefinita) ed 8 sono le uniche di cui dovete occuparvi; producono, rispettivamente, story file con estensione .z5 e .z8. La Versione 5 era quella progettata dalla Infocom come Advanced (avanzata), ed è quella che viene prodotta per impostazione predefinita da Inform. Questa è la versione che di solito utilizzerete, e consente di creare file grandi fino a 256 Kbyte. Se il vostro gioco cresce oltre quella dimensione, dovete compilare uno story file Versione 8, che è molto simile alla Versione 5, ma consente di creare file grandi fino a 512 Kbyte. -D -X Includono, rispettivamente, i verbi di debug ed il debbuger Infix nello story file (leggete "Fare il debug del vostro gioco" a pagina XXX) -h1 -h2 Visualizzano le informazioni di aiuto sul compilatore. -h1 fornisce informazioni sulla nomenclatura dei file, mentre -h2 visualizza gli switch disponibili. -n -j -n visualizza il numero di attributi, proprietà ed azioni che avete dichiarato. -j elenca gli oggetti così come verranno letti e costruiti nello story file. -s Mostra le statistiche sul gioco. Fornisce parecchie informazioni sul vostro gioco, compreso il numero di oggetti, verbi, voci del dizionario, uso della memoria, ecc. indicando allo stesso tempo il massimo previsto in ogni categoria. Utile per controllare se state raggiungendo i limiti di Inform. -r Memorizza tutti i testi del gioco in un file temporaneo, utile per controllare le vostre descrizioni ed i vostri messaggi attraverso un correttore ortografico. Se eseguite il compilatore con lo switch -h2 scoprite che ci sono molti altri switch, che, spesso, offrono funzionalità oscure od avanzate che, crediamo, siano di scarso interesse per i principianti. Sentitevi, comunque, liberi di provare qualunque switch catturi la vostra attenzione; niente di quello che fate in questa fase modifica il vostro codice sorgente, che, per quel che riguarda il compilatore, è assolutamente sola lettura.