Inform e Glulx/RUINS, l'avventura comincia/Il primo tesoro (speriamo che non sia un anello): differenze tra le versioni

Contenuto cancellato Contenuto aggiunto
Nessun oggetto della modifica
Gian BOT (discussione | contributi)
m Bot: sostituzione tag obsoleti
Riga 9:
Verb 'fotografa' * noun -> Photograph;
 
che può essere così interpretata: <ttcode>il verbo (Verb) FOTOGRAFA ('fotografa') [OGGETTO] (* noun) equivale all’azione PHOTOGRAPH (-> Photograph;)</ttcode>. Ricordatevi però, che '''ogni nuova azione ha bisogno di un'apposita subroutine definita come [nome_azione + sub]''' (nel nostro specifico caso <ttcode>PhotographSub</ttcode>):
 
[ PhotographSub;
Riga 28:
];
 
Se il giocatore non possiede la macchina fotografica (<ttcode>camera notin player</ttcode>) Inform stampa a video il messaggio corrispondente ("<ttcode>Non puoi farlo senza la tua macchina fotografica.</ttcode>"); se prova invece a fotografare se stesso ("<ttcode>fotografa me stesso</ttcode>") viene stampato a video il messaggio "<ttcode>Meglio di no. Non ti sei fatto la barba da quando hai lasciato il Messico.</ttcode>", un pizzico di umorismo che mette però in risalto un’altra importante caratteristica di Inform: il <ttcode>player</ttcode>.<br>
Esso infatti, viene considerato come un oggetto vero e proprio, che di default ha la seguente descrizione:
 
{| style="width:100%;" class="wikitable"
|<ttcode>>esamina me stesso<br>
Hai sempre lo stesso bell'aspetto.</ttcode>
|}
 
Se poi il giocatore possiede più di un oggetto (<ttcode>children(player) > 1</ttcode>), ecco che diventa impossibile fare delle fotografie. I <ttcode>children</ttcode> (in inglese "bambini" o "figli") del <ttcode>player</ttcode> sono proprio tutti gli oggetti che lui possiede. E se avete capito la descrizione della lampada al sodio, dovreste già sapere che gli oggetti del <ttcode>player</ttcode> hanno come <ttcode>parent</ttcode> il player stesso. Chiaro, no?
 
Dal momento però, che questo povero archeologo non si è fatto la barba da quando ha lasciato il Messico, non credo che questo messaggio corrisponda proprio alla verità. Come vedete, è molto importante personalizzare "l’ambiente", se non altro per rendere più veritiera l’avventura in sé. Ecco quindi come possiamo modificare anche questo messaggio:
Riga 57:
 
{| style="width:100%;" class="wikitable"
|<ttcode>>esamina me stesso<br>
Assomigli proprio a Matusalemme.</ttcode>
|}
 
Riga 88:
];
 
In questo esempio abbiamo definito il naso. Di per sé, l’oggetto nose non ha nulla di particolare, mentre la riga <ttcode>selfobj.add_to_scope = nose;</ttcode> contenuta nella funzione <ttcode>Initialise</ttcode> è quella che dice a Inform di assegnare l’oggetto in questione al <ttcode>player</ttcode> (<ttcode>selfobj</ttcode>). Il risultato che si ottiene è il seguente:
 
{| style="width:100%;" class="wikitable"
|<ttcode>>esamina il mio naso<br>
A punta e pieno di lentiggini.</ttcode>
|}
 
Riga 129:
];
 
Quella che viene adesso associata al <ttcode>player</ttcode> è l’intera funzione <ttcode>IncludeBodyParts</ttcode> al cui interno vengono resi visibili, tramite l’istruzione <ttcode>PlaceInScope</ttcode>, il naso e i capelli. Ecco allora il risultato:
 
{| style="width:100%;" class="wikitable"
|<ttcode>>esamina i miei capelli<br>
Li hai persi tutti quando eri piccolo.<br><br>
>esamina il mio naso<br>
A punta e pieno di lentiggini.</ttcode>
|}
 
Provare per credere.
 
La rimanente parte del codice dovrebbe essere ormai abbastanza chiara, tranne che per quella strana istruzione denominata <ttcode>AfterRoutines</ttcode>. Una cosa molto importante da tenere a mente quando si descrive una nuova azione, è a quale gruppo essa deve appartenere (in genere 2 o 3). Ora, come dice Paolo Lucchesi<ref>Autore di "<ttcode>La pietra della Luna</ttcode>", Paolo Lucchesi è anche il creatore di <ttcode>MAC</ttcode> (<ttcode>Mistery Adventure Creator</ttcode>), uno strumento di creazione per le avventure testuali rivolto ai meno esperti della programmazione. Ulteriori informazioni potete trovarle all’indirizzo [http://www.paololucchesi.it http://www.paololucchesi.it/]).</ref>, se l’azione non fa praticamente nulla (ed è quindi molto semplice), appartiene al gruppo 3 e dipende dalla proprietà <ttcode>before</ttcode>:
 
[ XyzzySub; "Non succede nulla."; ];
Riga 146:
Verb "xyzzy" * -> Xyzzy;
 
Se invece l’azione compie delle operazioni complesse, appartiene allora al gruppo 2 e dipende dalla proprietà <ttcode>after</ttcode>. Quindi, dopo quanto detto, è facile dedurre che l’azione <ttcode>Photograph</ttcode> fa parte del gruppo 2, e l’istruzione <ttcode>AfterRoutines</ttcode> si prende cura di tutto quello che avviene in questa azione quando fa parte della proprietà after di un oggetto qualsiasi: se ritorna <ttcode>true</ttcode>, tutto è andato bene, se invece ritorna <ttcode>false</ttcode>, qualcosa è andato storto:
 
Object -> statuette "statuetta pigmea"
Riga 185:
has female;
 
La variabile locale <ttcode>photographed_in_situ</ttcode> vale inizialmente <ttcode>false</ttcode>. Quando il giocatore riesce in qualche modo a fotografare la statuetta, il valore della variabile diventa <ttcode>true</ttcode>. Ora, se omettiamo la riga di codice relativa alla <ttcode>AfterRoutines()</ttcode> in <ttcode>PhotographSub</ttcode>, ecco cosa accade:
 
{| style="width:100%;" class="wikitable"
|<ttcode>Corridoio in pendenza<br>
Un corridoio basso e squadrato va da nord verso sud, inclinandosi verso la fine.<br><br>
Il passaggio è bloccato da una massiccia porta di pietra gialla.<br><br>
Riga 203:
Prepari l'elefantiaca macchina fotografica a lastre, sistemi la lampada al sodio e metti pazientemente in posa la statuetta pigmea.<br><br>
>prendi la statuetta<br>
Questi sono gli anni '30 e non i tempi andati. Prendere un manufatto senza prima registrarlo equivale a un saccheggio.</ttcode>
|}
 
Nonostante la statuetta sia stata fotografata, non si può ancora prendere. Ecco quindi spiegato il motivo della presenza della <ttcode>AfterRoutines</ttcode>: senza, viene ignorata l’azione <ttcode>Photograph</ttcode> della proprietà <ttcode>after</ttcode> dell’oggetto <ttcode>statuette</ttcode>, la variabile locale <ttcode>photographed_in_situ</ttcode> continua a valere <ttcode>false</ttcode> e di conseguenza la statuetta continua a non poter essere fotografata (e a non poter essere presa dal giocatore)<ref>Cliccate [http://www.vincenzoscarpa.it/inform/manuale/Capitolo4_esercizi.zip qui] per scaricare il listato di questo esercizio (il file '''4.07.inf''').</ref>.
 
[[Immagine:Inform e Glulx-sp.gif|centre|435 px|]]
Riga 248:
];
 
La costante <ttcode>MAX_SCORE</ttcode> determina il punteggio massimo, mentre la variabile locale <ttcode>cultural_value</ttcode> determina il punteggio della statuetta. Nella proprietà <ttcode>after</ttcode>, l’azione <ttcode>Insert</ttcode> ("<ttcode>posa la statuetta nella cassa</ttcode>) incrementa il valore della variabile di libreria <ttcode>score</ttcode> di 5 (il punteggio della statuetta); se <ttcode>score</ttcode> vale 30, allora il nostro archeologo ha raccolto tutti i tesori e ha finito la sua avventura nel migliore dei modi (non è stato cioè ucciso ma ha invece vinto). <ttcode>PrintRank</ttcode> è una funzione di libreria che, a seconda del punteggio, stampa a video il relativo messaggio; questo avviene però, solo se il gioco termina o se si danno i comandi "<ttcode>punteggio</ttcode>" e "<ttcode>punteggio pieno</ttcode>".
 
Esiste poi, una ''modalità completa'' del punteggio, nel senso che è possibile stabilire, per un’azione qualsiasi, quanti punti assegnarle. Se, ad esempio, vogliamo dare 5 punti al giocatore quando mangia il fungo e 10 punti quando posa il bozzolo nel raggio di sole, ecco cosa dobbiamo fare:
* Per prima cosa, bisogna definire un array di nome <ttcode>task_scores</ttcode> nel seguente modo:
 
Constant Story "RUINS";
Riga 264:
Array task_scores -> 5 10;
 
Il numero 5 è il punteggio che viene assegnato alla prima azione (quando il giocatore mangia il fungo) mentre il numero 10 viene assegnato alla seconda azione (quando il giocatore posa il bozzolo nel raggio). A questo array, si associano sempre le costanti <ttcode>NUMBER_TASKS</ttcode> (che contiene, a sua volta, il numero dei punteggi totali - in questo caso 5 e 10 &nbsp;&#x27A8;&nbsp; 2) e <ttcode>TASKS_PROVIDED</ttcode>. Ricordatevi inoltre, che '''l’array deve avere una lunghezza massima di 255 celle (da 0 a 254) e che i punteggi non possono essere negativi o maggiori di 255'''.
* Occorre poi, modificare l’azione <ttcode>Eat</ttcode> dell’oggetto <ttcode>mushroom</ttcode> come segue:
 
Eat:
Riga 276:
sull'altra.";
 
L’istruzione <ttcode>Achieved(0);</ttcode> è proprio quella che assegna 5 punti alla prima azione, e li va a prelevare dalla posizione 0 dell’array <ttcode>task_scores</ttcode>. Una modifica abbastanza simile va fatta per l’azione <ttcode>Insert</ttcode> dell’oggetto <ttcode>Square_Chamber</ttcode>:
 
Insert:
Riga 290:
}
 
L’unica differenza, sta nel fatto che ora l’istruzione <ttcode>Achieved</ttcode> va a prelevare il valore 10 anziché il valore 5.
Per verificare che le azioni di assegnamento dei punteggi abbiano avuto effettivamente luogo, basta testarle con l’istruzione <ttcode>task_done</ttcode>:
 
if (task_done->0 == 0)... ! se i 5 punti non sono stati assegnati...
Riga 301:
 
{| style="width:100%;" class="wikitable"
|<ttcode>>prendi il fungo<br>
Hai raccolto abilmente il fungo, senza staccarlo dal suo gambo sottile.<br><br>
>mangia il fungo<br>
Riga 324:
>punteggio<br>
Finora hai totalizzato 15 punti su 30 possibili, in 8 turni, guadagnando il rango di Rigattiere.<br><br>
></ttcode>
|}
 
Bisogna anche considerare, come dice lo stesso Paolo Lucchesi, la ''modalità a punteggio pieno'', dove è necessario inserire la funzione di libreria <ttcode>PrintTaskName</ttcode>:
 
[ Initialize...
Riga 344:
];
 
In poche parole, se il giocatore ha mangiato il fungo e ha posato il bozzolo nel raggio di sole, ecco cosa stampa a video Inform con il comando "<ttcode>punteggio pieno</ttcode>":
 
{| style="width:100%;" class="wikitable"
|<ttcode>>punteggio pieno<br>
Finora hai totalizzato 15 punti su 30 possibili, in 8 turni, guadagnando il rango di Rigattiere.<br><br>
Il punteggio è così composto:<br><br>
Riga 353:
&nbsp;&nbsp;&nbsp;10 hai trovato la chiave di pietra<br><br>
&nbsp;&nbsp;&nbsp;15 in totale (su 30 possibili)<br><br>
></ttcode>
|}
 
A ogni modo, non siete obbligati a supportare questa funzione nella gestione del punteggio in modalità completa; se il giocatore, durante il gioco, dà questo comando senza che la funzione <ttcode>PrintTaskName</ttcode> sia stata implementata, Inform stampa a video lo stesso messaggio previsto per il comando "<ttcode>punteggio</ttcode>".
 
[[Immagine:Inform e Glulx-sp.gif|centre|435 px|]]
 
Non sempre le azioni effettuate dal giocatore meritano di essere premiate. Ecco allora come procedere per far sì che il punteggio possa anche essere diminuito:
* La prima cosa da fare è quella di definire un array di nome <ttcode>task_scores</ttcode> nel seguente modo:
 
Constant Story "RUINS";
Riga 376:
Array task_scores --> 10 (-5);
 
* Dal momento che è presente l’istruzione <ttcode>replace</ttcode>, occorre poi ridefinire la funzione di libreria <ttcode>TaskScore</ttcode>:
 
.
Riga 388:
 
{| style="width:100%;" class="wikitable"
|<ttcode>>prendi il fungo<br>
Hai raccolto abilmente il fungo, senza staccarlo dal suo gambo sottile.<br><br>
>mangia il fungo<br>
Riga 409:
Lasci cadere il bozzolo nel bagliore solare. Ribolle oscenamente, si dilata e poi scoppia. Centinaia di piccoli insetti corrono in tutte le direzioni nell'oscurità; gli spruzzi di melma e una curiosa chiave di pietra gialla sono tutto ciò che rimane sul pavimento.<br><br>
[Il tuo punteggio è appena diminuito di cinque punti.]<br><br>
></ttcode>
|}
 
Riga 416:
[[Immagine:Inform e Glulx-sp.gif|centre|435 px|]]
 
Definendo, infine, la costante <ttcode>NO_SCORE</ttcode> nel seguente modo:
 
Constant Story "RUINS";
Riga 431:
.
 
è possibile disabilitare il punteggio, che non viene più segnalato sulla status line. Inoltre, perdono la loro efficacia le funzioni di libreria <ttcode>PrintRank;</ttcode> e <ttcode>PrintTaskName;</ttcode>
 
== Note ==