Torna alla pagina Introduttiva del commento al codice

Classe Ambiente

 

Classe Ambiente

protected:
    map<string,luogo*> luoghi;
    luogo* utente;
    luogo* fine;
    static oggcont zaino;
    string titolo;
    string finegioco;
    list<string> dati;
public:
    ambiente(luogo& ll);
    ~ambiente();
    bool carica();
    void setutente(luogo* & l);
    string prntitolo();
    ambiente& operator+=(luogo& l);
    void analizza(string s);
    void start();
    void end();
    int salva();
 

La struttura dati della classe ambiente incentrata su una mappa di oggetti Luogo.

Oltre alla mappa di luoghi, nella parte protetta di questa classe allocato un puntatore a luogo (luogo* utente) che punta in ogni fase del gioco al luogo in cui si trova il giocatore.
Il puntatore a luogo fine (luogo* fine) memorizza lindirizzo del luogo in cui si concluder lavventura.
Un altro componente del campo protetto una stringa (string titolo) che serve per poter personalizzare  il titolo dellavventura. La stringa finegioco (string finegioco),invece, inizializza il messaggio che verr stampato quando lobiettivo del gioco sar raggiunto, quindi alla conclusione del gioco.
Infine viene allocata una lista di stringhe (list<string> dati) da inizializzare con i nomi degli oggetti da recuperare per raggiungere lobiettivo.
E presente anche un oggetto di tipo contenitore (Oggcont, vedi la classe oggetto), dichiarato static, che abbiamo utilizzato per rappresentare lo zaino. Lo zaino un oggetto che non inserito in alcun luogo e al quale lutente pu accedere attraverso le funzioni lascia e prendi. E un oggetto di default infatti sar sempre presente in qualsiasi storia creata con il nostro Gota.


METODI

Nel campo pubblico, oltre al costruttore che assegna lindirizzo del luogo passato come argomento al puntatore utente e al distruttore che cancella dalla mappa i luoghi puntati, abbiamo inserito due semplici funzioni: void prntitolo () e void setutente (luogo*& l).
La prima ritorna la stringa titolo del campo protetto; la seconda assegna al puntatore utente il puntatore  parametro formale e individua cos la posizione del giocatore nella mappa dei luoghi.
La ridefinizione delloperatore += (ambiente& operator +=(luogo& l))permette di inserire un luogo nella mappa della classe ambiente attraverso operazioni del tipo  ambiente+=luogo.
La funzione void start() stampa la descrizione di un luogo quando vi si effettua il primo accesso attraverso una chiamata alla funzione guarda del Luogo. In seguito la funzione cambiastato() definita nella classe Luogo setta a true il booleano stato nella parte protetta della classe Luogo e impedisce successive stampe della descrizione lunga in caso di futuro accesso al luogo.
La funzione che gestisce la fine del gioco invece void end(), che scorre la lista dati presente nel campo protetto e per ogni stringa della lista, richiamando la funzione ricerca sui luoghi, controlla se nel luogo presente il nome delloggetto chiave. Se nel luogo sono presenti tutti gli oggetti della lista dati, allora viene stampato il messaggio di fine gioco.


ANALIZZATORE SINTATTICO

Lanalizzatore sintattico il tramite tra i comandi inseriti da tastiera dallutente e il funzionamento del gioco. La funzione che svolge il lavoro di analizzatore sintattico void analizza(string s), che da una stringa passata come argomento (il comando inserito dallutente) riesce a risalire alle opportune funzioni che consentono di giocare lavventura.
Il principio di funzionamento dellanalizzatore sintattico quello di separare le singole parole che costituiscono la stringa  immessa dallutente e di sistemarle allinterno di un array statico di stringhe. Attraverso il primo ciclo for, allinterno del quale un iteratore scorre le lettere della stringa, viene ricavata la dimensione dellarray da allocare sfruttando gli spazi presenti tra una parola e laltra evitando opportunamente di conteggiare gli spazi ripetuti. In un secondo ciclo for, invece, viene fatta scorrere nuovamente la stringa e le singole parole, memorizzate carattere per carattere in una stringa temporanea, vengono inserite nelle posizioni dellarray.
In questo modo, facendo dei controlli sulle stringhe presenti in ogni posizione dellarray , possibile gestire le corrette combinazioni verbo-oggetto, richiamare le opportune funzioni sulle classi Luogo e Oggetto e segnalare opportunamente eventuali comandi mancanti o errori.
I comandi gestiti dallanalizzatore sono:

prendi oggetto;
usa oggetto con oggetto;
lascia oggetto;
vai direzione;
apri oggetto;
apri oggetto con oggetto;
oggetto;
accendi oggetto;
accendi oggetto con oggetto;
guarda oggetto, luogo;
esci;
salva;
aiuto.


SALVA

Il metodo salva presente nella classe ambiente di fondamentale importanza per il corretto funzionamento del gioco, in quanto attraverso questa funzione possibile interrompere una partita in un punto qualsiasi e riprenderla in seguito caricando la versione precedentemente salvata.
Il funzionamento del metodo salva si basa sulla scrittura dei dati su file.
Attraverso lutilizzo della classe fstream presente nellomonima libreria, in un file prescelto (world.ini) vengono scritte tutte quelle informazioni inerenti lavventura necessarie per ricostruire la stessa al momento del caricamento. Per far s che ci avvenga correttamente la funzione salva della classe ambiente effettua delle chiamate ad alcune funzioni (come la salva) presenti nelle altre classi (Luogo, Oggetto, etc). Importante nella scrittura del file world.ini lutilizzo di separatori di inizio e di fine che permettono una corretta lettura da parte della carica. 


CARICA

Il metodo carica funziona in simbiosi con il metodo salva, in quanto la lettura, oltre che da un file di default (mondo.ini), pu essere effettuata dal file generato dalla salva (world.ini).
Limplementazione di questa funzione prevede, dopo la scelta del file da caricare e la gestione di eventuali errori, la lettura del file avviene per singole righe mediante la funzione getline e, cosa molto importante, avviene limitatamente ad ogni intervallo individuato dai separatori di inizio e di fine. La prima stringa ad essere inizializzata quella del titolo. In questo caso la getline legge tra i separatori [Titolo] e [EndTitolo] e inizializza la stringa titolo nel campo protetto di Ambiente con il contenuto di tutte le righe comprese (considerando anche i ritorni a capo).
Dopo il titolo, vengono caricati gli oggetti contenuti nello zaino; con un meccanismo identico al caricamento del titolo e a quello di tutti gli altri elementi, la getline scorre e legge tutte le righe comprese tra i  separatori.
La lettura si arresta appena viene trovato il separatore di inizio di un oggetto o di un oggetto-derivato; quando questo avviene, utilizzando loperatore >> ridefinito nella classe Oggetto, si costruisce loggetto in funzione di fstream  (vedi operatore >>), se ne assegna lindirizzo a un puntatore e tramite loperatore += ridefinito si inserisce loggetto nello zaino.
Per la costruzione dei luoghi, come per la costruzione degli oggetti abbiamo appositamente ridefinito loperatore >> (fstream& operator >>) in modo da ottimizzare al meglio il codice. Una volta ottenuto il puntatore al luogo costruito, viene inizializzata la stringa di descrizione e attraverso la funzione insert (insert una funzione della STD per le mappe), viene inserito il luogo nellambiente.
Caricati i luoghi, bisogna caricare gli oggetti in esso contenuti
Ovviamente con un primo ciclo while si scorre la mappa dei luoghi affinch in ogni luogo siano inseriti i relativi oggetti. Per ogni luogo, attraverso un secondo ciclo while  si scorrono tutte le linee tramite la solita getline e su ogni singola linea viene chiamata la funzione research (vedi research). Questa ritorna true o false se riuscita o meno a dividere la linea di ingresso. In caso affermativo si assegna alla stringa temporanea nomeluogo la stringa right restituita dalla research. A questo punto, dopo aver controllato che il luogo esiste nellAmbiente, si costruiscono, come per lo zaino, gli oggetti con tutte le loro propriet (attraverso loperatore >>) e si inseriscono nel luogo (operatore +=).
Il caricamento dei puntatori a luogo necessario per collegare in maniera corretta i luoghi appena creati. Questa volta se il risultato della funzione research true e se il luogo esiste, vengono fatti una serie di controlli sulla stringa left restituita. Se left NOMELUOGO, la stringa nomeluogo viene inizializzata con il valore right; se left una direzione (NORD, SUD, EST, OVEST, ALTO, BASSO), tramite le funzioni pdirezione (pnord, psud, pest, povest, palto, pbasso)per ogni luogo vengono inizializzati i puntatori in base alla stringa right; se left unostruzione (OStrUZIONENORD, OStrUZIONESUD, OStrUZIONEEST, OStrUZIONEOVEST, OStrUZIONEALTO, OStrUZIONEBASSO) tramite le funzioni Odirezione (Onord, Osud, Oest, Oovest, Oalto, Obasso) per ogni luogo si inizializzano i puntatori delle ostruzioni con il campo right della research.
Quando si arriva al separatore di inizio [FineGioco] comincia linserimento degli oggetti chiave nella lista dati di Ambiente. Sempre grazie al lavoro della research, infatti, viene fatto un controllo sulla stringa left; se si tratta di OBJ viene fatto linserimento mentre se si tratta di FINELUOGO si inizializza il puntatore fine dellAmbiente con lindirizzo del luogo in cui si conclude avventura.
La linea successiva che viene esaminata [MsgFineGioco], attraverso cui viene inizializzata la stringa finegioco di Ambiente con un messaggio che indichi la conclusione dellavventura.
Lultima linea letta dalla carica [Utente]; se la research torna come stringa left INIZIO, allora il puntatore utente di Ambiente viene inizializzato con lindirizzo del luogo corrispondente alla stringa right. Se il luogo viene trovato il caricamento finito e si pu iniziare a giocare altrimenti il programma visualizza un messaggio di errore.