M.A.C. : Mystery Adventure Creator
v. 2.4
Autore: Paolo Lucchesi |
Dedicato a mia moglie Benedetta |
Sommario
1: Breve descrizione delle avventure testuali e un po' di glossario
4: Il linguaggio di programmazione (o quasi)
4.1: [System], Dati generici per l'avventura
4.2: [Sysmsg], Messaggi di sistema
4.3: [Directions], Il movimento
4.4: [Locations], Le locazioni di gioco
4.5: [Verbs] e [Nouns], Il vocabolario di gioco
0: Introduzione
M.A.C. è un semplice linguaggio per realizzare avventure testuali (quelle che oggi vengono chiamate "Interactive Fiction") ricreando l'atmosfera di quelle che giravano sui vecchi personal computer a 8 bit, come il Sinclair ZX Spectrum o il Commodore 64. Le mie principali fonti di ispirazione sono la serie delle Mysterious Adventures di Brian Howarth e un programma per la progettazione di avventure chiamato "The Quill". Anzi, a grandi linee M.A.C. potrebbe essere considerato un remake di "The Quill".
Paragonato ad altri prodotti simili, come T.A.D.S. o Inform, M.A.C. è sicuramente più primitivo. Il linguaggio di programmazione è estremamente semplice e assolutamente lontano dagli attuali linguaggi orientati agli oggetti, e di conseguenza il gioco stesso non potrà avere mai la flessibilità di prodotti consimili; i comandi riconosciuti saranno nella forma basilare soggetto-complemento, non sarà possibile gestire più personaggi, e via dicendo. In compenso M.A.C. permette la gestione di immagini grafiche legate alle varie "locazioni" in cui si svolge il gioco.
I motivi che mi hanno spinto a realizzare M.A.C. sono vari: ad esempio ritengo che un linguaggio così "primitivo" sia il più adatto per cogliere lo spirito di quegli anni, e inoltre nessun altro prodotto simile era realmente adatto, per me, al rifacimento delle vecchie avventure. Infine mi sono divertito a farlo, e questo è il motivo più importante.
1: Breve descrizione delle avventure testuali e un po' di glossario
Probabilmente se siete interessati a M.A.C. sapete già cosa è un'avventura testuale, ma farò una breve descrizione anche per creare una sorta di "vocabolario comune".
Un'avventura testuale è un gioco in cui il giocatore muove un personaggio virtuale all'interno di un mondo virtuale; il computer fornisce la descrizione della situazione attuale e degli eventi che accadono e il giocatore decide le azioni del personaggio mediante dei comandi dati in linguaggio naturale, come ad esempio "raccogli la mela" o "entra nell'edificio". La complessità dei comandi che possono essere accettati varia molto da gioco a gioco; in alcuni casi sono permesse frasi anche molto lunghe e articolate, in altri (come nel caso di M.A.C.) ci si deve limitare a frasi semplici, composte in genere da un verbo seguito da uno o più complementi. M.A.C. puo' riconoscere tre diverse parole dopo il verbo, ma generalmente la maggior parte dei comandi è nella forma verbo-complemento oggetto.
Il gioco si svolge generalmente in una serie di locazioni, ovvero ambienti virtuali, e in genere il personaggio si può muovere fra queste indicando la direzione dei vari punti cardinali (nord, sud, est, ovest e, meno frequentemente, nordest, nordovest, sudest e sudovest) o indicando se vuole andare su o giù.
Il personaggio può interagire con una serie di oggetti, presenti nelle varie locazioni; alcuni di questi possono essere raccolti e trasportati, alcuni possono essere indossati, alcuni possono essere usati in vari modi, da soli o in combinazione con altri oggetti. L'insieme degli oggetti trasportati dal personaggio si chiama inventario.
Il gioco può finire in tre modi. Il giocatore può decidere in qualsiasi momento di uscire dal programma (magari salvando la situazione per riprendere in seguito da dove aveva interrotto), oppure il personaggio può realizzare lo scopo finale dell'avventura (trovare un certo numero di tesori o un oggetto particolare, uscire da un luogo pericoloso, o un'infinità di altre possibilità) oppure ancora il personaggio può trovarsi nell'impossibilità definitiva di raggiungere tale scopo (prevalentemente perché ha fatto una brutta fine).
2: Uso del programma
M.A.C. è stato per ora realizzato per girare sotto un ambiente DOS a 32 bit, come ad esempio il prompt di DOS di Windows 9x, oppure sotto Windows 9x/NT/2000/ME/XP in finestra. Inoltre è stato realizzato in quattro versioni:
MACSTD.EXE è la versione più semplice, funziona in modo solo testuale. E' stato concepito per essere facilmente portato verso altri sistemi operativi.
MACTXT.EXE è una versione testuale che utilizza in modo avanzato la console del DOS. E' particolarmente indicato per il debug delle avventure.
MAC.EXE è la versione grafica del programma, che ovviamente permette la visualizzazione delle schermate grafiche. Tutte le versioni condividono le stesse opzioni di lancio, quindi da ora in poi faremo riferimento solo a questa. Funziona a schermo pieno ed è un'applicazione dos a 32 bit. Non è garantito il suo funzionamento sotto Windows NT/2000/XP.
WINMAC.EXE è la versione grafica per Windows del programma. Questa versione è da intendersi come beta release (non definitiva) soprattutto per problemi legati alla libreria grafica. Funziona, se possibile, in una finestra di Windows, e richiede per lo meno una risoluzione di 800x600. Per ogni altro aspetto, è identica alla versione grafica per dos a 32bit.
M.A.C. funziona anche sotto Linux; in questo caso esistono solo due versioni: mac (la versione grafica, che gira sotto X11) e macstd (la versione testuale standard, che funziona in console).
Il file che contiene la descrizione dell'avventura può essere in due formati: il primo ha sempre l'estensione .adv ed è un formato testuale; può essere realizzato con un qualsiasi editor di testi (edit o notepad, ad esempio) seguendo quanto specificato nel capitolo 4. Il secondo ha sempre estensione .mac ed è un formato binario (compresso) ottenuto da un file .adv lanciando M.A.C. con l'opzione -c.
Il programma viene lanciato con il comando mac <nomefile>, dove nomefile.mac o nomefile.adv è il nome del file che contiene l'avventura. Se non viene specificato alcun nome, il programma cerca un file che si chiama come se stesso (ovviamente con l'estensione cambiata); quindi in genere mac.exe cercherà il file mac.mac o mac.adv, ma è possibile rinominarlo. Ad esempio se rinomino mac.exe in myadv.exe, quando lo lancerò cercherà il file myadv.mac o il file myadv.adv.
Una volta lanciato il programma legge il file specificato e, se non trova errori, fa partire il gioco. Tutti gli errori vengono visualizzati, ma errori minori (warnings) permettono di far partire ugualmente il gioco.
Bisogna sempre fare attenzione ai nomi dei file; infatti sotto linux le lettere maiuscole e minuscole sono discriminanti (readme.txt e ReadMe.txt sono due file differenti). Quindi per garantire la massima portabilità e un miglior funzionamento è: consigliabile usare nomi di file composti solo da caratteri minuscoli e numeri (evitando maiuscole e spazi).
2.1: Opzioni del programma
Come detto sopra, M.A.C. permette di convertire un file testuale .adv in un file binario .mac. Questo comporta una serie di vantaggi: anzitutto il file .mac è compresso e quindi occupa meno spazio, e inoltre non è possibile in modo semplice controllare il contenuto del file (cosa che è ovviamente possibilissima nel caso di file testuali). Per effettuare la conversione è sufficiente usare l'opzione --compile (o -c); ad esempio il comando mac -c nomefile converte il file nomefile.adv (testuale) nel file nomefile.mac (binario). Se viene usata l'opzione -c M.A.C. si limita ad effettuare la conversione, e non fa partire il gioco.
Normalmente M.A.C. cerca sempre prima un file di testo con estensione .adv, e dopo un file binario con estensione .mac (attenzione: fino alla versione 2.3 faceva esattamente l'opposto, ma questo poteva creare problemi agli sviluppatori di avventure). L'opzione --text (o -t) fa in modo che M.A.C. cerchi soltanto un file (di tipo testo) con estensione .adv, mentre l'opzione --binary (o -b) fa in modo che M.A.C. cerchi soltanto un file binario con estensione .mac.
L'opzione --debug (o -d) fa sì che il programma entri in modo debug, permettendo durante il gioco delle operazioni che permettono di valutare la correttezza dell'avventura. Questo funziona soltanto se viene letto un file di tipo testo (quindi si consiglia di usare anche l'opzione -t). Se è attivata l'opzione di debug è possibile, durante il gioco, immettere al posto del comando il carattere % seguito da un numero n per avere la posizione del n-esimo oggetto e il valore del n-esimo flag, o inserire il solo carattere % per avere la locazione corrente e il numero di oggetti trasportati.
Infine l'opzione --help (o -h) fa sì che il programma mostri un breve messaggio di aiuto e esca, mentre l'opzione --version (o -v) fa sì che il programma mostri il numero di versione e esca.
3: Giocare con M.A.C.
Esistono una serie di comandi standard che sono necessari per giocare un'avventura testuale. Di seguito descriviamo brevemente tali comandi così come sono definiti nel file ital.adh.
I comandi NORD, SUD, EST, OVEST, SU e GIU (abbreviati anche in N, S, E, O, U e G) permettono di muoversi tra le varie locazioni. Il comando INVENTARIO (o I) mostra gli oggetti in possesso del personaggio. Il comando DESCRIZIONE (abbreviato in D) ripete la descrizione della locazione in cui si trova il personaggio (serve solo se si usa la versione testuale standard macstd.exe, le altre versioni mostrano sempre la descrizione).
Il comando ESAMINA (o GUARDA, o CERCA) seguito da un oggetto permette, se possibile, di avere una descrizione dettagliata dell'oggetto in questione. I comandi PRENDI (o RACCOGLI), POSA (o LASCIA), INDOSSA (o METTITI) e TOGLITI, seguiti da un oggetto, permettono ovviamente, se possibile, di interagire con l'oggetto in questione. Il comando ASPETTA serve a lasciar scorrere un certo lasso di tempo in attesa di un qualche evento.
I comandi SALVA (o SAVE) e CARICA (o LOAD) permettono di salvare e ripristinare la situazione corrente in un file. Ad entrambi seguirà la richiesta di un numero da 1 a 9 che identifica il file in cui viene salvata o da cui viene ripristinata la situazione. Il file di salvataggio si chiama come il file dell'avventura, con un'estensione che varia da .sv1 a .sv9. Infine il comando FINE (o QUIT) permette di uscire dal gioco (viene chiesta conferma, poi viene chiesto se si vuole salvare la situazione corrente, ed infine viene chiesto se si vuole riiniziare da capo).
La versione grafica e la versione console permettono di richiamare una lista degli ultimi comandi inseriti usando le frecce verso l'alto e verso il basso.
4: Il linguaggio di programmazione (o quasi)
Effettivamente parlare di "linguaggio di programmazione" è pretenzioso. In realtà il file che costituisce l'avventura vera e propria non è altro che un insieme di definizioni. Non esiste il concetto di procedure, oggetti e nemmeno di flusso. Vediamo comunque i concetti generali.
Il file che contiene l'avventura altro non è che un file di testo in formato ASCII standard, e può essere realizzato con un qualunque editor di testi (Edit o Notepad vanno bene, ma c'è di meglio). Esso è costituito da diverse sezioni, ognuna delle quali inizia con il suo nome indicato tra parentesi quadre. Le sezioni non devono essere poste in alcun ordine particolare e possono essere anche interrotte e poi riprese.
Ogni elemento delle varie sezioni inizia con il carattere # seguito da un numero univoco, seguito da vari campi che determinano i dettagli dell'elemento, separati da virgole. Alla prima riga possono seguire altre righe che non sono divise in campi. Ovviamente nella prima riga di ogni elemento non si può usare il carattere virgola liberamente, ma solo per separare i vari campi; nelle righe successive, altrettanto ovviamente, questa limitazione non sussiste più.
Le parole chiave riconosciute da mac possono essere indicate indifferentemente in lettere maiuscole o minuscole o qualsiasi combinazione di lettere maiuscole o minuscole; ad esempio le parole chiave "LOCATIONS", "locations", "Locations" e "loCAtiONs" sono in tutto equivalenti.
Il carattere | indica la fine della singola riga, ovvero tutto quello che viene dopo il carattere | viene trascurato. Non si deve utilizzare tale carattere alla fine di ogni riga, ma solo se si vuole aggiungere un commento. Ovviamente quindi una riga che inizi con tale carattere è considerata riga di commento.
Il carattere | ha anche un'altra funzione: se per qualche motivo si vuole aggiungere degli spazi alla fine di una riga, questi dovranno essere seguiti da |, o altrimenti verranno trascurati.
Il carattere \, invece, viene usato nelle descrizioni lunghe di oggetti e locazioni, e nei messaggi, e indica un ritorno a capo.
Se si vuole usare il carattere % in un messaggio o una descrizione, lo si deve scrivere due volte (%%). Il motivo di ciò verrà spiegato quando verranno trattate le variabili.
E' possibile includere un altro file all'interno del primo. Per far ciò si inserisce una riga che inizia con il carattere @ seguito immediatamente dal nome del file che si vuole includere. Ad esempio se voglio includere il file mydef.adh all'interno di myadv.adv, in quest'ultimo si inserirà la riga "@mydef.adh".
E' possibile includere ricorsivamente più file uno dentro l'altro ma ciò ha un'utilità limitata e generalmente è sconsigliato.
In genere questo viene usato per inserire in un'avventura una serie di definizioni standard comuni a più o a tutte le avventure, come i messaggi di sistema. Insieme a M.A.C. vengono distribuiti quattro file da usare per questo scopo. ital.adh contiene le definizioni standard in italiano, eng.adh contiene le definizioni standard in inglese, myst.adh contiene le definizioni standard in inglese in stile "Mysterious Adventures", e myst_it.adh contiene la traduzione in italiano di queste ultime.
Conviene ricordare che, per garantire la portabilità, è bene usare sempre nomi di file che non contengano spazi o lettere maiuscole.
4.1: [System], Dati generici per l'avventura
La sezione [System] contiene una serie di costanti di utilizzo generale nel corso dell'avventura. Ogni riga ha la forma <NomeElemento>=<valore>. Essi sono:
StartLocation è il numero della locazione dove inizia l'avventura (esempio StartLocation=5). Se non viene specificato è uguale a 1.
Boolean sono due caratteri che vengono usati per rispondere alle richieste che prevedono una risposta affermativa o negativa, come ad esempio "Vuoi veramente uscire dal gioco (s/n)?". I due caratteri devono seguire il segno =, mettendo prima la risposta positiva; ad esempio Boolean=sn. Di default i due caratteri sono y e n.
MaxItems è il numero di oggetti trasportabile dal personaggio (esempio MaxItems=7). Di default è uguale a 5.
Prompt è la stringa che precede la riga di comando durante il gioco. Di default è il solo carattere >. Ad esempio Prompt=What Now?.
ImagePath è la sottodirectory dove sono tenuti i file che contengono le immagini (ad esempio ImagePath=advimg). Può essere lunga al massimo 32 caratteri. Se non viene specificata, M.A.C. cercherà le immagini nella sua stessa directory.
ShowExits può essere seguito dai caratteri y o n (esempio ShowExits=n) e indica se la descrizione delle varie locazioni deve includere anche la lista delle uscite visibili. Di default vale y (le uscite vengono mostrate).
BgColor e FgColor sono rispettivamente i colori di sfondo e di testo usati nella versione grafica. Possono assumere valori compresi tra 0 e 15 (ad esempio BgColor=7), corrispondendi alla palette VGA standard:
0 = nero | 4 = rosso scuro | 8 = grigio scuro | 12 = rosso |
1 = blu scuro | 5 = viola | 9 = blu | 13 = magenta |
2 = verde scuro | 6 = marrone | 10 = verde | 14 = giallo |
3 = verde acqua | 7 = grigio | 11 = ciano | 15 = bianco |
Title indica il titolo della finestra nella versione Windows.
StatusLine può essere seguito da un messaggio (lungo al massimo 64 caratteri). Questo messaggio viene mostrato continuamente dal programma, e, come vedremo in seguito, può contenere delle variabili. Classicamente viene usato per mostrare il numero di turni trascorsi e il punteggio ottenuto. Questa caratteristica non è presente nella versione testuale semplificata MACSTD.EXE.
CharSet è un indicatore che specifica se il file contenente l'avventura utilizza caratteri diversi dalla tabella ascii dos standard e se deve essere effettuata una conversione (esempio CharSet=w). Al momento puo' assumere solo il valore w, che indica un set di caratteri ascii standard di windows, e la conversione applicata riguarda solo le lettere accentate e altri caratteri presenti sulla tastiera italiana.
4.2: [Sysmsg], Messaggi di sistema.
La sezione [Sysmsg] contiene i messaggi di sistema generici. Essendo tali messaggi non relativi al singolo gioco la loro sistemazione sarebbe in un file di definizioni standard.
Ogni messaggio è definito in una singola riga composta dal numero di messaggio (preceduto dal carattere #) e dal messaggio stesso. Ad esempio #4,Stai trasportando troppi oggetti. I messaggi di sistema sono i seguenti:
1: Errore di sintassi nell'interpretazione del comando (es. "Non capisco quello che intendi")
2: Oggetto non presente per una certa azione (es. "Non vedi niente di simile")
3: Impossibilità generica di compiere una certa azione (es. "Non puoi!")
4: Impossibile aggiungere oggetti all'inventario (es. "Stai già portando troppi oggetti")
5: Movimento in direzione errata (es. "Non puoi andare da quella parte")
6: Oggetto non presente in inventario (es. "Non lo possiedi")
7: Descrizione generica di un oggetto (es. "Non vedo niente di speciale")
8: Impossibilità temporanea di compiere una certa azione (es. "Non posso farlo ora")
9: Messaggio di attesa (es. "Il tempo passa")
10: Conferma di azione avvenuta correttamente (es. "OK!")
11: Prefisso alla descrizione degli oggetti presenti nella locazione (es. "Puoi vedere:")
12: Prefisso alla descrizione degli oggetti dell'inventario (es. "Stai portando:")
13: Suffisso che indica gli oggetti indossati (es. "(indossato)")
14: Messaggio che sostituisce una lista di oggetti se vuota (es. "assolutamente niente")
19: Prefisso alla lista delle direzioni possibili dalla locazione corrente (es. "uscite:")
21: Richiesta del numero che identifica il salvataggio della situazione corrente (es. "Salvare in posizione (1-9)?")
22: Richiesta del numero che identifica il caricamento di una situazione salvata (es. "Caricare dalla posizione (1-9)?")
23: Richiesta di caricare una situazione salvata a inizio gioco (es. "Ripristinare una partita (s/n)?")
24: Richiesta di conferma dell'uscita dal gioco (es. "Vuoi veramente interrompere (s/n)?")
25: Richiesta di salvataggio all'uscita (es. "Salvare la partita (s/n)?")
26: Richiesta di riiniziare la partita (es. "Ricominciare da capo (s/n)?")
29: Messaggio di errore in salvataggio o caricamento (es. "Errore su file!")
Tutti questi messaggi sono già opportunamente definiti nei tre file di definizioni standard forniti, ital.adh, eng.adh e myst.adh.
4.3: [Directions] Il movimento
La sezione [Directions] contiene il nome delle varie direzioni in cui può muoversi il personaggio. Fate attenzione, questi sono soltanto i nomi delle direzioni così come vengono visualizzati di seguito alla descrizione della locazione, e non sono i comandi che invece deve dare il giocatore per muovere il personaggio. Questi ultimi sono definiti nella sezione [Verbs].
Ogni riga è composta da un numero identificante la descrizione (da 1 a 10, preceduto da #) e dal nome della direzione. Ad esempio #2,Sud.
Ovviamente i nomi delle direzioni generalmente non sono dipendenti dal singolo gioco e quindi sarebbe naturale introdurli in un file di definizioni standard. I file ital.adh, eng.adh e myst.adh comprendono la definizione delle direzioni Nord, Sud, Est, Ovest, Su e Giù (numerate da 1 a 6).
4.4: [Locations] Le locazioni di gioco
La sezione [Locations] contiene la descrizione delle varie locazioni in cui si svolge il gioco; se si usa la versione grafica di M.A.C. ad ognuna di esse può essere associata un'immagine grafica.
Ogni locazione è costituita da una prima riga composta dal numero di locazione (da 1 a 32767, preceduto da #), una descrizione breve della locazione (attualmente non usato) il nome del file contenente l'immagine grafica (v. cap. 5), un indicatore di tipo e, di seguito, le locazioni che vengono raggiunte muovendosi nelle varie direzioni (con 0 che indica una direzione verso cui non ci si può muovere). Le righe seguenti contengono la descrizione "lunga" della locazione. L'indicatore di tipo vale 0 se la locazione è normale, mentre vale 1 se la locazione è "buia" e in essa è impossibile vedere a meno che non si abbia una fonte di luce.
Vediamo un esempio:
#1,L'ingresso,ingresso.png,0,3,0,2,0,4,0
Sei nell'ingresso dell'antico maniero Rudolph. Alle pareti vedi
appesi dei lussuosi trofei e delle panoplie di armi. Una scala
in legno porta su di un soppalco.
In questo caso la locazione descritta non è "buia", ad essa è legata l'immagine contenuta nel file ingresso.png e da essa si possono raggiungere la locazione 3 andando a nord, la locazione 2 andando ad est e la locazione 4 andando in su (se le direzioni sono quelle standard).
La locazione 0 è particolare. Essa contiene la descrizione e l'immagine che vengono mostrate al posto di quelle delle locazioni "buie" (al solito a meno che non si abbiano fonti di luce). Ovviamente il tipo e le direzioni di movimento della stanza 0 sono inutili. Un esempio di locazione 0 è il seguente:
#0,Buio,buio.png
E' buio. Non puoi vedere niente.
Quando arriveremo alle le sezioni [Events] e [Actions] vedremo che le direzioni di movimento specificate all'interno delle locazioni e l'illuminazione possono essere modificate nel corso del gioco.
4.5: [Verbs] e [Nouns] Il vocabolario di gioco
La sezione [Verbs] contiene i verbi che potranno essere usati per guidare le azioni del personaggio. Ogni riga contiene il numero di verbo (da 1 a 32767, preceduto da #) e una serie di parole che verranno considerate sinonimi. Ad esempio:
#31,SPINGI,PREMI
#32,TIRA
#33,ACCENDI
#34,SPENGI,SPEGNI
Diversi verbi sono "riservati". Anzitutto i verbi da 1 a 10 corrispondono alle possibili direzioni corrispondenti a quelle definite nella sezione [Directions] e quelle specificate all'interno delle varie locazioni. Gli altri verbi riservati sono:
11: per mostrare l'inventario (INVENTARIO, HO, H)
12: per rivisualizzare la descrizione della locazione (DESCRIZIONE, D)
13: per esaminare un oggetto (GUARDA, ESAMINA, CERCA)
14: per raccogliere un oggetto (PRENDI, RACCOGLI)
15: per posare un oggetto (POSA, LASCIA)
16: per indossare un oggetto (INDOSSA, METTITI)
17: per togliersi un oggetto (TOGLITI)
18: per aspettare (ASPETTA)
21: per salvare la situazione (SALVA, SAVE)
22: per ripristinare una situazione salvata (CARICA, LOAD)
23: per interrompere la partita (FINE, QUIT)
Questi verbi sono già opportunamente definiti nei tre file di definizioni standard forniti, ital.adh, eng.adh e myst.adh
La sezione [Nouns] contiene i nomi (o complementi oggetti) che possono essere usati assieme ai verbi per formare i comandi con cui andrà guidato il personaggio. Anche in questo caso ogni riga contiene il numero di nome (da 1 a 512, preceduto da #) e una serie di parole che verranno considerate sinonimi. Ad esempio:
#1,PISTOLA,MAGNUM
#2,TAVOLO
#3,TORCIA
#5,MANTELLO
#301,CENERE
Normalmente se un nome è associato ad un oggetto, gli viene assegnato lo stesso numero (vedi la sezione [Objects]). Per questo è opportuno separare (ad esempio assegnando un numero sufficientemente alto) i nomi che non sono riferiti a nessun oggetto. Altresì lo stesso nome può riferirsi a più oggetti e anche questo è definito nella sezione [Objects].
4.6: [Objects] Gli oggetti
La sezione [Objects] contiene la descrizione dei vari oggetti con cui si può interagire (o che possono anche essere solamente decorativi, nessuno lo vieta) e che si possono incontrare all'interno del gioco.
Ogni oggetto è costituito da una prima riga composta dal numero di oggetto (da 1 a 32767, preceduto da #), la descrizione "breve" dell'oggetto (quella che viene mostrata normalmente), la locazione dove si trova detto oggetto all'inizio del gioco, un numero che codifica il tipo di oggetto e, opzionalmente, il nome (v. sezione [nouns]) associato a tale oggetto. Le righe successive contengono la descrizione "lunga", quella che viene mostrata quando si "esamina" o "guarda" l'oggetto.
La locazione di partenza può assumere tre valori speciali: 0 indica che l'oggetto non esiste all'inizio dell'avventura (ad esempio una torcia accesa, che verrà creata solo in conseguenza all'azione di accendere una torcia spenta), -1 indica che l'oggetto si trova nell'inventario del personaggio, e 2 indica che l'oggetto è indossato dal personaggio.
Il tipo di un certo oggetto si determina sommando una serie di valori: 1 indica che l'oggetto è trasportabile, 2 indica che l'oggetto è indossabile, 4 indica che l'oggetto è una fonte di luce. Quindi un oggetto di tipo 0 non è né trasportabile né indossabile, e non illumina niente (come ad esempio un grosso macigno), un oggetto di tipo 3 è trasportabile e indossabile (una giacca), un oggetto di tipo 5 è una fonte di luce trasportabile (una torcia); non ha alcun senso, ovviamente, definire un oggetto indossabile ma non trasportabile (di tipo 2).
Il nome associato all'oggetto, se non è definito, ha lo stesso numero dell'oggetto. Viene definito nel caso che più oggetti abbiano lo stesso nome (una torcia spenta e una torcia accesa, ad esempio, hanno sempre il nome TORCIA). Il nome associato all'oggetto può essere sempre indicato con il suo numero o, se il nome è già stato definito (nella sezione [Nouns], anche esplicitamente.
Se non viene indicata la descrizione lunga, quando l'oggetto viene esaminato, al suo posto viene mostrato il messaggio di sistema 7 ("Non vedo niente di speciale", o qualcosa di simile).
Vediamo qualche esempio:
#1,Una pistola,-1,1
La tua fida 44 Magnum.
#2,Un tavolo di mogano,2,0
#3,Una torcia spenta,2,1
#4,Una torcia accesa,0,5,TORCIA
#5,Un mantello,2,3
Un vecchio mantello liso dal tempo
Sono stati definiti 5 oggetti. Per solo due di essi (la pistola e il mantello) è stata fornita una descrizione più accurata. La pistola all'inizio del gioco è già in possesso del personaggio, la torcia accesa (che è ovviamente fonte di luce) non esiste (per ora), gli altri si trovano nella locazione 2. Tutti gli oggetti tranne il tavolo sono trasportabili, e il mantello è anche indossabile. La torcia accesa ha lo stesso nome della torcia spenta.
4.7: [Messages] I messaggi
Durante il gioco normalmente vengono mostrati dei messaggi che descrivono il risultato delle azioni del personaggio o il manifestarsi di qualche evento. Tali messaggi vengono definiti nella sezione [Messages].
Ogni messaggio è costituito dal numero (da 1 a 511, preceduto da #) seguito dal messaggio in questione. Il messaggio può continuare sulle righe successive. Ad esempio:
#1,Sposti faticosamente i barili e questi ultimi
rivelano un passaggio segreto.
#2,Senti il rumore di una sinistra risata.
#3,Come provi a spostare la libreria, quest'ultima
crolla fragorosamente su di te, uccidendoti.
4.8: [Shows] Messaggi con grafica
La sezione [Shows] contiene una serie di messaggi, similmente alla sezione [Messages]; la differenza è che se si usa la versione grafica di M.A.C. ad ognuno di questi messaggi può essere associata un'immagine grafica. Questi messaggi possono essere usati in varie occasioni: ad esempio all'inizio dell'avventura (v. sezione [Events], condizione begin) o alla sua conclusione, o quando succede qualcosa di significativo. E' possibile definire fino a 31 messaggi di tipo shows, ma si consiglia di farne un uso limitato (ad esempio usare più di due o tre messaggi di introduzione può essere pesante e noioso per il giocatore). Inoltre, dopo ognuno di questi messaggi è opportuno far aspettare a M.A.C. la pressione di un tasto o qualche secondo (v. sezione [Events], operazione pause), altrimenti l'immagine potrebbe venir subito risostituita dall'immagine della locazione.
Ogni messaggio è costituito da una prima riga composta dal numero del messaggio (da 1 a 32767, preceduto dal carattere #) e, eventualmente, il nome del file contenente l'immagine grafica (v. cap. 5). Le righe successive contengono il messaggio vero e proprio. Ad esempio:
#1,intro.png
Varcando la porta dell'antico maniero della famiglia Rudolph inizia
il tuo viaggio verso l'ignoto, nella tetraggine che nasconde mille insidie
e mille pericoli. Sarai in grado di ritrovare il rubino di luna e uscire sano
e salvo da questa dimora infernale?
4.9: [Vars] Variabili e flag
Nella sezione [Vars] vengono definite delle variabili (o flag) che, come vedremo, possono venire usate liberamente nelle sezioni [Events] e [Actions]. Il loro uso è fondamentale nella realizzazione di avventure. E' possibile definire 32767 diverse variabili, ognuna delle quali pu assumere valori interi da 0 a 32767. All'inizio del gioco tutte le variabili valgono 0.
Ogni riga della sezione [Vars] contiene i nomi di una o più variabili, separati da virgole. Ad esempio:
In questo modo ho definito quattro variabili (upstair,drinked,counter e mar) che potrò usare nelle sezioni [Actions] e [Events].
Nota bene: le variabili devono avere ovviamente sempre nomi distinti: inoltre le variabili sono identificate solo dai primi 8 caratteri, che quindi devono essere sempre distinti. I nomi precipitato e precipitazione, ad esempio, sono considerati lo stesso nome di variabile. Infine la sezione [Vars] deve precedere obbligatoriamente le sezioni [Actions] e [Events], in quanto non posso usare una variabile che non ho definito precedentemente.
Si possono usare le variabili anche in un messaggio o in una descrizione. Per far ciò si deve introdurre nel messaggio/descrizione il nome variabile tra due caratteri % (questo è il motivo per cui il carattere % deve essere scritto due volte se viene usato da solo). Per esempio:
Se la variabile turns vale 123 e la variabile score vale 42, quando il messaggio sarà visualizzato, si vedrà:
Ovviamente si possono inserire delle veriabili anche nel messaggio di StatusLine. Notare comunque che a differenza di quanto accade per azioni e eventi, in messaggi e descrizioni ` possibile usare variabili non ancora definite.
4.10: [Events] e [Actions] Il motore di gioco
Come abbiamo già visto, M.A.C. gestisce automaticamente le azioni più comuni che il personaggio può fare, come muoversi nelle direzioni fondamentali, raccogliere o posare oggetti, richiamare l'inventario. Ma ovviamente le possibilità del personaggio non sono ristrette a questo; il personaggio dovrebbe essere in grado di eseguire altre operazioni, come, ad esempio, tirare una leva, aprire una porta o un baule, spostare una libreria. Inoltre è possibile che in base a certe situazioni, non correlate direttamente ad una precisa azione del personaggio, debba succedere qualcosa, un qualche evento, come, ad esempio, il crollo di una scala o il sorgere del sole o altro ancora.
Tutto questo viene gestito nelle sezioni [Events] e [Actions], due sezioni talmente simili nella forma che verranno descritte assieme. C'è comunque una netta differenza tra Eventi e Azioni: Gli eventi vengono elaborati prima dell'immissione di ogni comando da parte del giocatore (e quindi non possono dipendere dal comando immesso) e vengono normalmente elaborati sempre tutti. Le azioni vengono elaborate dopo l'immissione di ogni comando (e quindi dovrebbero dipendere dal comando immesso) e normalmente una sola di esse viene realmente eseguita; non solo, ma le azioni "standard" (raccogliere oggetti, muoversi, etc.) sono gestite automaticamente da M.A.C. solo se nessuna azione viene realmente eseguita (c'è un esempio più avanti). Comunque, come vedremo, esiste più di un modo di aggirare la regola "tutti gli eventi e una sola azione".
Le sezioni [Events] e [Actions] sono composte da righe formate da una serie di condizioni e righe formate da una serie di operazioni. Le righe di condizioni iniziano con le parole if, and o or. Le righe di operazioni, invece, iniziano con la parola then (opzionale, ma consigliata) o con la parola do.
Una riga di condizioni che inizia con if è considerata valida se e solo se risultano vere tutte le condizioni che la compongono. Invece una riga di condizioni che inizia con and è valida se, oltre ad essere vere tutte le condizioni che la compongono, sono valide anche le righe di condizioni immediatamente precedenti. Infine una riga di condizioni che inizia con or è valida se sono vere tutte le condizioni che la compongono, oppure se sono valide le righe di condizioni immediatamente precedenti.
Una riga di operazioni viene eseguita se le righe di condizioni precedenti risultano valide, oppure se non è preceduta da una riga di condizioni (ovvero è la prima riga della sezione, oppure è preceduta da un'altra riga di operazioni). Infatti le condizioni influenzano solo la riga di operazioni (o il blocco, come vedremo più avanti) immediatamente successivo.
Attenzione: in versioni precedenti di M.A.C. gli operatori if e or erano considerati sinonimi (e mancava l'operatore and); di conseguenza era possibile (anche se scorretto) scrivere una serie di righe di condizioni inizianti con if, e l'operazione successiva veniva eseguita se solo una di queste era vera (come se si trattasse di un if seguito da una serie di or). Questo non è più valido; le operazioni che seguono una serie di if vengono eseguite solo se l'ultima riga di condizioni è valida. Adesso per ottenere il risultato desiderato bisogna correttamente usare una sola riga di condizioni iniziante con if e (eventualmente) una o più righe inizianti con or.
È possibile anche usare una riga di condizioni iniziante con la parola while (eventualmente seguita da righe di condizioni di tipo and o or). In questo caso la riga di operazioni (o il blocco, come vedremo) seguente verrà ripetuta fino a che le condizioni seguenti il while continuano ad essere vere; dopo un while si consiglia di far iniziare la riga di operazioni con la parola do invece che con then. Si consiglia di fare molta attenzione all'uso del comando while in quanto il suo comportamento non è facilmente prevedibile e può portare facilmente all'esecuzione di cicli infiniti che bloccheranno inesorabilmente il programma. In breve il comando while deve essere usato solo se strettamente necessario/P>
Le condizioni e le operazioni possono essere seguite da uno o due parametri (numeri interi, verbi, nomi o nomi di variabili); i parametri non indicati si intendono uguali a zero. In ogni riga ci possono essere al massimo 8 condizioni o operazioni. Sia la sezione [Events] che la sezione [Actions] possono essere composte, al massimo, da 32767 righe (condizioni o operazioni) ciascuna.
Le condizioni sono le seguenti (indichiamo in quali casi risultano vere):
begin | La condizione è vera solo all'inizio del gioco. Questa condizione non deve essere usata nella sezione [Actions], ed è particolarmente utile per inizializzare variabili o mostrare messaggi introduttivi. |
verb x | Il verbo x (x può essere il numero del verbo o il verbo vero e proprio) fa parte dell'ultimo comando immesso; ovviamente questa condizione non deve mai essere usata nella sezione [Events]; inoltre tutte le azioni dovrebbero comprendere una condizione di tipo verb e, normalmente, una condizione di tipo noun. |
noun x | Il nome x (x può essere il numero del nome o il nome vero e proprio) è il (primo) nome riconosciuto nella scansione del comando immesso; anche questa condizione non deve mai essere usata nella sezione [Events]. |
noun2 x | Il nome x (x può essere il numero del nome o il nome vero e proprio) è il secondo nome riconosciuto nella scansione del comando immesso. Non si consiglia l'uso eccessivo di questa condizione; anche questa condizione non deve mai essere usata nella sezione [Events]. |
noun3 x | Il nome x (x può essere il numero del nome o il nome vero e proprio) è il terzo nome riconosciuto nella scansione del comando immesso. L'uso di questa condizione dovrebbe essere rarissimo; anche questa condizione non deve mai essere usata nella sezione [Events]. |
anynoun x | Il nome x (x può essere il numero del nome o il nome vero e proprio) è uno dei primi tre nomi riconosciuti nella scansione del comando immesso. Questa condizione deve essere usato con molta attenzione; anche questa condizione non deve mai essere usata nella sezione [Events]. |
move x | Il comando inserito è un comando di movimento in una delle direzioni fondamentali. Se x vale 1, la condizione è vera solo se il movimento è realmente possibile. Se x vale 2, la condizione è vera solo se il movimenti è impossibile. Se x vale 0 (o qualsiasi altro valore) la condizione �vera per movimento possibile o impossibile. Anche questa condizione, dipendendo dal comando, non deve mai essere usata nella sezione [Events]. |
at x | Il personaggio si trova nella locazione x. |
exist x | L'oggetto x è esistente (è in qualche locazione, o è trasportato o indossato dal personaggio). |
isin x y | L'oggetto x si trova nella locazione y. |
carried x | L'oggetto x è nell'inventario del personaggio, non indossato. |
worn x | L'oggetto x è indossato dal personaggio. |
owned x | L'oggetto x è trasportato o indossato dal personaggio. |
here x | L'oggetto x è nella locazione corrente (non nell'inventario). |
present x | L'oggetto x è nella locazione corrente, o è nell'inventario del personaggio, o è indossato. |
dark x | La locazione x (se x = 0 si considera la locazione corrente) è buia (e non vi sono fonti di luce). |
eq x y | La variabile x (x è ovviamente un nome di variabile) ha un valore pari a y. |
gt x y | La variabile x (x è un nome di variabile) ha un valore maggiore di y. |
lt x y | La variabile x (x è un nome di variabile) ha un valore minore di y. |
free | Il numero di oggetti attualmente presenti nell'inventario è inferiore al numero massimo di oggetti trasportabili (ovvero, è possibile raccogliere almeno un altro oggetto). |
random x y | Questa condizione è vera causalmente, con x possibilità su y. Ovviamente x deve essere minore di y, o la condizione sarà sempre banalmente vera. Altrettanto ovviamente x deve essere maggiore di zero. Se y è zero (o manca), viene preso uguale a 100 (probabilità in percentuale). |
E' possibile premettere la parola not ad ogni singola condizione; in questo modo la condizione risulta vera se e solo se quanto è indicato sopra risulta falso.
Inoltre una condizione può essere costituita solo da un singolo nome di variabile (eventualmente proceduta da not). In questo caso la condizione risulta vera solo se la variabile ha un valore maggiore da 0 (ovviamente se era preceduta da not la condizione era vera solo le variabile aveva valore 0).
Le operazioni possibili, invece, sono le seguenti:
create x | L'oggetto x viene spostato nella locazione corrente. |
destroy x | L'oggetto x viene reso "non esistente", e scompare dal gioco. |
get x | L'oggetto x viene posto nell'inventario (se l'inventario non è completo, vedi condizione free) |
wear x | L'oggetto x viene posto nell'inventario (sempre se l'inventario non è completo) e indossato dal personaggio. |
put x y | L'oggetto x viene spostato nella locazione y. |
moveall x y | Tutti gli oggetti che si trovano nella locazione x vengono spostati nella locazione y. Se x vale zero vengono spostati gli oggetti che si trovano nella locazione corrente. Se y vale 0, gli oggetti nella locazione x vengono distrutti. |
swap x y | Gli oggetti x e y vengono scambiati di posto; ovviamente, se uno dei due è "non esistente", viene creato al posto dell'altro, mentre l'altro viene fatto sparire. |
go x | Il personaggio viene spostato alla locazione x. |
at x | Questa operazione è particolare: essa indica che la prossima operazione (e solo quella) dovrà svolgersi come se il personaggio fosse in realtà alla locazione x. |
exit x y | Se y è diverso da zero, crea nella locazione corrente un'uscita (nella direzione indicata da x) verso la locazione y. Se y è uguale a zero, elimina nella locazione corrente l'uscita nella direzione indicata da x. Il parametro x indica l'uscita nell'ordine stabilito nella sezione [Directions]. |
subst x y | Tutte le uscite che conducono alla locazione x vengono sostitite con uscite verso la locazione y. Se x vale zero, vengono sostituite le uscite che conducono alla locazione corrente. Se y vale zero, tutte le uscite che conducono alla locazione x vengono eliminate. Questo comando puo' essere utile, assieme a moveall, per sostituire una locazione ad un'altra. |
light x y | Se y è diverso da 0, la locazione x viene considerata da quel momento illuminata, anche se nella sezione [Locations] era definita come buia. Se y vale 0, la locazione x viene considerata da quel momento buia. Se x vale 0, ci si riferisce alla locazione corrente. |
message x | Viene mostrato il messaggio (v. sezione [Messages]) numero x. |
sysmsg x | Viene mostrato il messaggio di sistema (v. sezione [Sysmsg]) numero x. |
show x | Viene mostrato il messaggio con grafica (v. sezione [Shows]) numero x. |
mchoiche x y | Viene chiesto al giocatore di effettuare una scelta numerica tra 1 e y (y compreso tra 2 e 9), il risultato viene messo nella variabile x (x è un nome di variabile). Se il giocatore preme il tasto esc, il risultato è 0. Se y è negativo, la scelta è ovviamente tra 1 e -y, e inoltre il tasto esc viene ignorato. |
bchoiche x | Viene chiesto al giocatore di effettuare una scelta di tipo si/no (v. boolean nella sezione [System]). Nella variabile x (x è un nome di variabile) viene posto 1 se il giocatore risponde si, 0 altrimenti. |
pause x | Viene effettuata una pausa di x millisecondi, interrompibile premendo un tasto. Se x è negativo, la pausa dura x millisecondi e non è interrompibile. Se x è zero, la pausa dura fino a che non viene premuto un tasto. Questa operazione può variare in base al sistema operativo e all'implementazione. |
quit | Il gioco viene interrotto, senza ulteriori richieste. In genere viene usata alla morte del personaggio o alla risoluzione dell'avventura. |
set x y | Alla variabile x (x è un nome di variabile) viene assegnato il valore y. Se y manca, alla variabile x viene assegnato il valore 1. |
reset x | Alla variabile x (x è un nome di variabile) viene assegnato il valore 0. |
add x y | Alla variabile x (x è un nome di variabile) viene aggiunto il valore y. |
sub x y | Dalla variabile (x è un nome di variabile) x viene sottratto il valore y. |
redesc | Viene ripetuta la descrizione della locazione corrente. |
cls | L'area dello schermo destinata ai messaggi viene cancellata. |
halt | Interrompe l'elaborazione. In questo modo gli eventi successivi non vengono elaborati. Tale operazione è ritenuta sottintesa (e quindi inutile) dopo ogni azione, a meno che non si trovi all'interno di un blocco. |
continue | Continua l'elaborazione. In questo modo le azioni successive (e eventualmente le azioni standard gestite automaticamente da M.A.C.) vengono elaborate comunque, e viene eseguita anche la prossima azione valida (solo una, a meno che anche questa con comprenda un continue). Tale operazione è ritenuta sottintesa (e quindi inutile) dopo ogni evento. |
break | Interrompe l'elaborazione del blocco corrente (v. di seguito), saltando alla fine di quest'ultimo. In caso di blocchi inseriti in altri blocchi, solo il blocco più interno viene interrotto. |
Un concetto importante è quello di blocco, ovvero una sequenza di linee di condizioni o di operazioni che prende il posto di una singola linea di operazioni. In questo modo è possibile che una riga di condizioni influenzi più righe di operazioni, e soprattutto si può dare una struttura complessa alle sezioni [Events] e [Actions].
Un blocco inizia sempre con una riga contenente solo la parola begin oppure (preferibilmente) solo il carattere { (aperta graffa), e termina sempre con una riga contenente solo la parola end oppure (preferibilmente) solo il carattere } (chiusa graffa); la parola di inizio del blocco poò opzionalmente essere preceduta da then o da do. Tutte le operazioni e le condizioni contenute tra queste linee speciali verranno considerate come una sola riga di operazioni. Inoltre, nella sezione [Actions], il blocco viene sempre elaborato interamente (a meno che non vengano incontrati i comandi halt o quit). Se un'azione è già stata eseguita, il resto del blocco viene comunque valutato e eventualmente eseguito, e l'elaborazione viene sospesa solo alla fine del blocco (a meno che non sia stato eseguito un comando continue o che all'interno del blocco non venga eseguita alcuna operazione).
È possibile inserire un blocco all'interno di un altro blocco, fino ad una profondità di 15 blocchi uno dentro l'altro. Per questo motivo ` possibile inserire all'inizio di ogni riga un qualunque numero di spazi o tabulazioni. Infatti in questo modo è si può introdurre o aumentare una spaziatura ad inizio riga ogni volta che viene aperto un blocco, e ridurla ogni volta che un blocco viene chiuso, in modo da poter a colpo d'occhio comprendere all'interno di quale blocco si trova una certa riga. Questa operazione si chiama "indentazione", ed è una pratica estremamente consigliata, sebbene non obbligatoria.
Esistono altri due tipi particolari di blocco: Se il blocco inizia con la parola fbegin o con i caratteri {/ l'esecuzione delle azioni verrà interrotta alla fine del blocco, anche se all'interno del blocco non è stata eseguita alcuna operazione (ovviamente ciò vale solo se il blocco viene valutato). Se invece il blocco inizia con la parola sbegin o con i caratteri {+ l'esecuzione del blocco (nella sezione [Actions] si interrompe dopo l'esecuzione della prima riga di operazioni (e comunque, se nel blocco non vengono eseguite operazioni, al termine l'esecuzione delle azioni continua). Questi blocchi particolari sono terminati sempre da end o }.
Attenzione: nelle versioni di M.A.C. precedenti alla 2.3 l'esecuzione delle azioni veniva interrotta alla fine di un blocco, anche se al suo interno non veniva eseguita nessuna operazione (in pratica come i blocchi inizianti con 'fbegin' o '{/'). Ciò non è più vero. Se un blocco viene elaborato, ma al suo interno non vengono eseguite operazioni, l'elaborazione delle azioni continua. I file di avventura binari (in formato .mac) realizzati con versioni precedenti continuano a funzionare come previsto.
Vediamo qualche esempio:
Se in qualsiasi momento il personaggio si trova nella locazione 4, e in tale locazione è presente l'oggetto 1, viene mostrato il messaggio 7 e l'oggetto in questione viene eliminato.
[Actions]
if verb apri noun porta present 14
or verb premi noun pulsante present 16 present 14
then swap 14 15 message 5 exit 3 7
if verb chiudi noun porta present 15
then swap 14 15 sysmsg 10 exit 3 0
Sono già definiti i verbi "apri", "chiudi" e "premi". Inoltre l'oggetto 14 è una porta chiusa, l'oggetto 15 una porta aperta, l'oggetto 16 un pulsante. Il nome 14 ("porta") è riferito sia all'oggetto 14 che all'oggetto 15, mentre il nome 16 ("pulsante") è riferito solo all'oggetto 16. La prima azione (le prime tre righe) viene "innescata" se il comando è "apri la porta" e la porta chiusa è presente, o se il comando è "premi il pulsante" e sono presenti sia il pulsante che la porta chiusa; in questo caso la porta aperta viene sostituita alla porta chiusa, viene mostrato il messaggio 5 ("la porta si apre cigolando" o qualcosa del genere) e viene attivata un'uscita verso est che conduce alla locazione 7. La seconda azione (le ultime due righe) viene "innescata" solo dal comando "chiudi la porta" se è presente la porta aperta; in questo caso alla porta aperta viene sostituita la porta chiusa, viene mostrato il messaggio di sistema 10 ("ok") e l'uscita verso est viene disattivata.
[Events]
if begin
then show 1 pause show 2 pause set foo 2 set bar 4 halt
Questo evento avviene solo all'inizio dell'avventura. Vengono mostrati i messaggi con grafica 1 e 2 (e dopo ognuno si aspetta la pressione di un tasto), la variable foo viene inizializzata a 2, e la variabile bar viene inizializzata a 4. Infine si interrompe l'elaborazione degli eventi.
[Actions]
if move dark
then message 7 continue
if move dark random 1 8
then message 6 quit
La prima azione viene "innescata" se viene dato un comando di movimento (N,S,E,O...) in una locazione buia (senza fonti di luce, ovviamente). In questo caso viene mostrato il messaggio 7 ("è pericoloso muoversi al buio...") e si continua con l'elaborazione delle azioni. Quindi si passa a valutare la seconda azione, che viene "innescata" anch'essa se viene dato un comando di movimento in una locazione buia, ma solo con una possibilità di 1/8 (12.5%); se ciò accade il gioco si interrompe mostrando il messaggio 8 ("cadi e ti rompi l'osso del collo..."). Se questa seconda azione non viene innescata, si procede con la normale risoluzione del movimento, che M.A.C. effettua automaticamente.
[Events]
if not at 5
then set salcnt 0
if at 5
then add salcnt 1
if at 5 eq salcnt 2
then message 5
if at 5 eq salcnt 3
then message 6 quit
Anzitutto la variabile salcnt (definita nella sezione [Vars] ) viene rimessa a 0 ogni qual volta il personaggio non è nella locazione 5. Se il personaggio, invece, è nella locazione 5, la variabile salcnt viene incrementata ad ogni turno, e quando raggiunge il valore 2 viene mostrato il messaggio 5 (probabilmente un messaggio di avvertimento), mentre quando raggiunge il valore 3 (ovvero il turno successivo) viene mostrato il messaggio 6 (che dice che il personaggio ha fatto una fine orribile) e il gioco finisce.
[Actions]
if verb aspetta noun 0
then {
set count 5
while gt count 0
do sysmsg 9 pause 500 sub count 1
}
Se il comando è 'aspetta' o simili viene mostrato cinque volte a intervalli regolari il messaggio di attesa standard. Questo viene ottenuto assegnando il valore 5 alla variabile count e ripetendo (while) la sequenza 'mostra il messaggio - pausa - decrementa la variabile di 1' fino a che la variabile non arriva a 0.
[Actions]
if verb parla noun agente present 8
{
if eq rsp 1
then message 12
if eq rsp 2
{
if eq rsp 1
then message 14
if eq rsp 2
then message 15 create 9
reset rsp
if eq rsp 3
then message 16
reset rsp
if verb parla noun agente
then message 17
Se il comando è "parla all'agente" (o qualcosa di simile) e il personaggio è in presenza di un agente di polizia (oggetto n. 8), viene iniziata l'esecuzione di un blocco. Anzitutto viene mostrato il messaggio 11 (che propone tre diverse opzioni di dialogo) e viene richiesto al giocatore di scegliere tra queste tre opzioni (comando mchoiche, il giocatore può evitare di scegliere premendo esc); la variabile rsp prende il numero della scelta fatta. Se il giocatore sceglie la prima o la terza opzione (quindi se rsp vale 1 o 3), viene mostrato rispettivamente il messaggio 12 o il messaggio 16, senza altri effetti. Se invece il giocatore sceglie la seconda opzione (se rsp vale 2), viene iniziata l'esecuzione di un secondo blocco all'interno del primo. In questo secondo blocco, similmente, viene mostrato il messaggio 13, che propone due opzioni di dialogo, e viene chiesto al giocatore di scegliere tra queste due opzioni (questa volta però il tasto esc non funziona); rsp viene ora usata per prendere il risultato di questa scelta. Se il giocatore sceglie la prima opzione, viene mostrato il messaggio 14, e se il giocatore sceglie la seconda opzione, viene mostrato il messaggio 15 e viene creato l'oggetto n. 9 (un modulo per una denuncia di smarrimento, ad esempio). Alla fine di ogni blocco la variabile rsp viene messa a 0 per non interferire con altri comandi. Alla fine del blocco più esterno, e solo a questo momento, l'elaborazione della sezione [Actions] viene sospesa (al solito, come per ogni azione eseguita); alla fine del blocco più interno l'elaborazione non viene sospesa, perchè deve essere terminato il blocco più esterno. Le ultime due righe trattano il caso in cui il comando "parla all'agente" viene dato quando l'agente stesso non è presente.
Con questo è conclusa la descrizione del "linguaggio" che viene usato per scrivere le avventure. Per esempi più completi, è possibile guardare le avventure distribuite con M.A.C.
5. La grafica
Abbiamo già visto come ai messaggi della sezione [Shows] e alle locazioni possono essere associate delle immagini grafiche. La versione grafica di M.A.C., infatti, ha una "finestra" dedicata a questo scopo.
Ogni immagine deve essere contenuta in un file distinto (sebbene la stessa immagine possa essere usata in più occorrenze); abbiamo già visto come vengono specificati questi file nelle sezioni [Shows] e [Locations]. I file che contengono le immagini devono trovarsi nella directory di M.A.C. o, meglio, nella sottodirectory specificata alla voce ImagePath della sezione [System].
Le immagini gestite da M.A.C. devono seguire delle regole abbastanza restrittive: infatti sono ammesse solo immagini di dimensioni 384x256, in RGB (24 bit per pixel) o con palette fino a 256 colori (8 bit per pixel); inoltre di questi 256 colori gli ultimi 2 (254 e 255) sono colori di sistema e quindi non dovrebbero essere usati.
M.A.C. legge solo immagini in formato png (portable network graphics) con alcune semplificazioni: Sono ammesse solo immagini con tabella dei colori (fino a 256), immagini a livelli di grigio (sempre fino a 256) e immagini in RGB (true color, 16 milioni di colori), sempre senza canale di trasparenza. Non sono ammesse immagini interlacciate. Inoltre tutte le informazioni opzionali (ovvero gli ancillary chunks) sono completamente trascurate.
È possibile anche, se si vuole, codificare le immagini in modo che non siano leggibili da un normale programma di grafica, e distribuire queste immagini codificate con i propri giochi. Per far ciò basta usare il programma pngsrmb (scaricabile dal sito ufficiale di M.A.C.). La sintassi da usare è semplicemente: pngsrmb nomeimmagine.png; se applicato ad un'immagine codificata, questo programma la decodifica. M.A.C., ovviamente, è in grado di leggere anche immagini codificate
Per fare un esempio: supponiamo di voler associare un'immagine alla locazione che rappresenta la biblioteca. In questo caso realizzeremo l'immagine con un qualsiasi programma grafico, facendo attenzione che le dimensioni siano quelle richieste (384x256) e assicurandoci di usare una palette a 256 colori (soprattutto prestiamo attenzione a non fare un'immagine a 16 milioni di colori). Salviamo il file nella directory dove è tenuta la nostra avventura, con il nome biblio.png, e specifichiamo questo nome nella sezione [Locations].
Conviene infine ricordare che, per garantire la portabilità, è bene usare, per le immagini, nomi di file che non contengano spazi o lettere maiuscole.
6. Crediti
M.A.C. è stato scritto in C usando il compilatore Gnu GCC
Il compilatore è soggetto ai termini della GNU GENERAL PUBLIC LICENSE, che trovate allegata nel file gpl.txt.
La versione per dos 32bit è stata compilata usando la distribuzione DJGPP, © 1995,1996 DJ Delorie.
Il compilatore, i sorgenti e l'intero toolkit possono essere scaricati dalla Home Page ufficiale: http://www.delorie.com/djgpp.
La versione nativa Windows è stata compilata usando la distribuzione MinGW (Minimal Gnu for Windows).
Il compilatore, i sorgenti e l'intero toolkit possono essere scaricati dalla Home Page ufficiale: http://www.mingw.org.
La versione grafica di M.A.C. è stata implementata usando la libreria grafica GRX, © Csaba Biegl.
La libreria in questione è soggetta ai termini della GNU LIBRARY GENERAL PUBLIC LICENSE, che trovate allegata nel file lgpl.txt.
La libreria GRX v2.4.5 e i suoi sorgenti possono essere scaricati da
Per la gestione dei file è stata usata la libreria di compressione ZLIB, © 1995-1998 Jean-loup Gailly and Mark Adler.
La libreria ZLIB può essere scaricata da http://www.cdrom.com/pub/infozip/zlib.
Ringraziamenti a RikTik per la preziosissima opera di debugging.
7. Licenza e garanzie
M.A.C. è rilasciato sotto i termini della GNU General Public License (vedere il file gpl.txt per i dettagli).
Ogni utente ha il diritto di copiare, usare e distribuire il programma in questione, purchè garantisca gli stessi diritti a tutti coloro a cui viene distribuito il programma.
Ogni utente ha il diritto di modificare come crede il programma, purchè garantisca tale diritto e i diritti di copia, uso e distribuzione a tutti coloro a cui viene distribuito il programma modificato.
Ogni distribuzione di M.A.C. deve comprendere i file README.TXT, COPYING.TXT, CREDITS.TXT, gpl.txt e lgpl.txt, senza alcuna modifica oltre all'eventuale aggiunta di una traduzione in altra lingua.
Questo programma è distribuito SENZA ALCUNA GARANZIA. L'autore non si assume nessuna responsabilità per eventuali danni di qualsiasi genere dovuti all'uso del programma.