[semafori] robots

Si deve gestire la sincronizzazione di una versione multithreaded del classico robots UNIX.

Ci sono N_ROBOTS thread robots che cercano di catturare il giocatore. Il giocatore si muove su una board condivisa usando i tasti e,r,t,d,f,g,c,v,b per muoversi nelle varie direzioni. Il tasto ‘f’ è il ‘teletrasporto’. Quando il giocatore si muove tutti i robot si muovono verso di lui. I robot si distruggono quando urtano uno con l’altro (lasciando garbage ‘#’ sulla board). Lo scopo è di sopravvivere e distruggere tutti i robot facendoli urtare tra loro o contro garbage esistente.

I robot seguono il seguente schema di esecuzione:

while(1) {

  robot_attendi_mossa(id);

  /***************** computa la mossa ********************/

  inizia_mossa();

  /**** esegue la mossa modificando la board condivisa ***/

  fine_mossa();

  /* se la mossa fallisce il robot si 'inibisce' comportandosi come segue */
    	while(1) {
    		robot_mossa_effettuata(id);
    		robot_attendi_mossa(id);
    	}

  /************** altrimenti il robot prosegue ***********/

  robot_mossa_effettuata(id);
}

Il giocatore segue il seguente schema:

while(1) {
    player_attendi_mossa();

    /***** stampa il board e legge il comando ************/

    inizia_mossa();

    /**** esegue la mossa modificando la board condivisa ***/

    fine_mossa();

    /****** se la mossa fallisce il giocatore termina *******/

    player_mossa_effettuata();

}

Si devono implementare le seguenti funzioni di sincronizzazione:

/* inizializza semafori e variabili */
inizializza() {}

/* viene invocata prima di ogni mossa */
inizia_mossa() {}

/* viene invocata dopo ogni mossa */
fine_mossa() {}

/* il robot id attende che il giocatore si muova */
robot_attendi_mossa(int id) {}

/* il robot id si è mosso, il giocatore può fare la mossa successiva */
robot_mossa_effettuata(int id) {}

/* il giocatore attende che i robot si muovano tutti */
player_attendi_mossa() {}

/* il giocatore si è mosso, possono muoversi i robots */
player_mossa_effettuata() {}

/* elimina i semafori */
chiudi() {}

Fare attenzione che

  1. Le mosse dei robot e del giocatore modificano la board condivisa (una matrice condivisa tra tutti i thread)
  2. Ogni mossa del giocatore causa una mossa di tutti i robot. Il giocatore non può muoversi finché tutti i robots non hanno completato la loro mossa.

Utilizzare il seguente programma di prova.

Per chi finisce presto c’è una variante che viene abilitata compilando con -D EXTRA in cui i robot effettivamente terminano l’esecuzione invocando una funzione aggiuntiva robot_termina(id). Se volete realizzare questa variante aggiungete codice usando #ifdef EXTRA in modo che il codice in più venga attivato quando si compila con -D extra.