ciao a tutti!Io e la mia collega abbiamo un nuovo problema da risolvere. Dobbiamo fare una versione di Space Invaders utilizzando la SystemV con i semafori. Il problema č che i nemici non si muovono in modo fluido, vanno a scatti e non capiamo dove stiamo sbagliando..potete aiutarci? grazie anticipatamente!
codice:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <curses.h>
#include <signal.h>
#include <semaphore.h>
#include <unistd.h>

#define PASSO 1 //entita' dello spostamento del nemico
#define SINISTRA 68 // freccia sx
#define DESTRA 67 // freccia dx
#define SGANCIA 32 // spazio
#define MAXX 80 // numero di colonne dello schermo
#define MAXY 24 // numero di righe dello schermo
#define M 3 // numero di nemici di 1° livello
#define G 4 // numero di nemici di 2° livello per gruppo


/* chiavi per l'identificazione dei segmenti di memoria da creare */
key_t mem_key; // chiave memoria
key_t sem_key; // chiave set di semafori

/* identificatori per i segmenti di memoria allocati */
int seg_mem; // identificatore segmento di memoria
int semid; // identificatore set di semafori

/* Struttura union semun */
union semun {
	int val; // per SETVAL
	struct semid_ds *buf; // per IPC_STAT e IPC_SET
	unsigned short *array; // per GETALL e SETALL
	struct seminfo * __buf ; /* buffer for IPC_INFO */
	};

/* Struttura per la comunicazione fra figli e padre */
typedef struct pos
     {
        char c; // soggetto che invia il dato: astronave, nemico, bomba o missile
        int x; // coordinata x
        int xi; // coordinata x del primo nemico di secondo livello
        int xf; // coordinata x dell'ultimo nemico di secondo livello
        int y; // coordinata y
        int DIRX; // direzione del nemico di 2° livello
        int p; // posizione del nemico all'interno del vettore v[] che rappresenta il gruppo di nemici di primo livello
        int pid; // pid del processo
        int vita; // 0: il nemico č morto; 1: il nemico č vivo
        int nem_vivi[G]; // vettore che indica lo stato di vita dei nemici di secondo livello all'interno di ciascun gruppo
        int g; // rappresenta il numero del gruppo a cui appartiene il nemico di secondo livello
        int n; // rappresenta il numero assegnato al nemico di 2° livello all'interno del proprio gruppo
      } pos;

/* Puntatori alla memoria condivisa */
pos* pos_mem;

/* Prototipi funzioni */
void astronave ();
void missile (int i, int x1, int y1);
void nemico(int i);
void nemico2(int i,int x, int y);
void bomba(int x1, int y1);
void sem_iniz(int semaforino);
void wait_sem(int semaforino);
void post_sem(int semaforino);
void controllo();
void gestione_mem();
void libera_mem();

main()
{
initscr();      // inizializzazione dello schermo
start_color(); // per l'utilizzazione dei colori
noecho();     // i caretteri corrispondenti ai tasti premuti non saranno visualizzati sullo schermo del terminale
curs_set(0); // nasconde il cursone

int pid_astronave, pid_nemico, i;

/* Chiamate per l'inizializzazione della memoria condivisa e dei semafori */
gestione_mem();
sem_iniz(0);


/* Creazione processi */
switch(pid_astronave=fork()) {
    case -1: perror("Errore nell'esecuzione della fork astronave");
         exit(1);
    case 0:  astronave();
                  }

for(i=0;i<M;i++)
    {
     switch(pid_nemico=fork()) {
        case -1: perror("Errore nell'esecuzione della fork nemico");
                      exit(1);
        case 0: nemico(i);
                   }
    }


controllo();

libera_mem();

/** Siamo usciti dal controllo e si terminano i procssi figli. Ripristina il normale modo operativo dello schermo **/
endwin();

return(0);
}


/**Funzione GESTIONE_MEM - per la gestione della memoria **/
void gestione_mem()
{
int i;
/* creazione delle chiavi per i segmenti di memoria e per il set di semafori */
if((mem_key = ftok(".",0)) == -1) {
    perror ("\nErrore ftok memoria!");

    exit (1);

  } 

if((sem_key = ftok(".",1)) == -1) {
    perror ("\nErrore ftok set di semafori!");

    exit (1);

  }

/* Allocazione dei segmenti di memoria condivisa e del set di semafori */
if((seg_mem = shmget(mem_key,sizeof(pos),IPC_CREAT | 0666)) < 0) {
    perror ("Errore shmget memoria!");

    exit (1);

  }

if((semid = semget(sem_key,1,IPC_CREAT | 0600)) < 0) {
    perror ("Errore semget set di semafori!");

    exit (1);

  }

/* Attachment dei segmenti di memoria */
if((int) (pos_mem = shmat(seg_mem, NULL, SHM_RND)) == -1) {
    perror ("Errore shmat memoria!");

    exit (1);

  }

} // fine funzione GESTIONE_MEM


/** Funzione SEM_INIZ - per l'inizializzazione dei semaforini **/
void sem_iniz(int semaforino)
{
union semun arg;
unsigned short values[2];

values[0] = 1;
values[1] = 0;

arg.array = values;

if(semctl(semid,semaforino,SETALL,arg) == -1) {
    perror ("Errore semctl semaforino!");

    exit (1);

  }
} // fine funzione SEM_INIZ


/** Funzione WAIT_SEM **/
void wait_sem(int semaforino)
{
struct sembuf op[1];

op[0].sem_num = semaforino;
op[0].sem_op = -1;
op[0].sem_flg = SEM_UNDO;

semop(semid,op,1);
} // fine funzione WAIT_SEM


/** Funzione POST_SEM **/
void post_sem(int semaforino)
{
struct sembuf op[1];

op[0].sem_num = semaforino;
op[0].sem_op = 1;
op[0].sem_flg = SEM_UNDO;

semop(semid,op,1);
} // fine funzione POST_SEM


/** Funzione LIBERA_MEM - per il detachment e la deallocazione dei segmenti di memoria **/
void libera_mem()
{
/* Detachment dei segmenti di memoria*/
if(shmdt(pos_mem) == -1) {
    perror ("Errore shmdt memoria!");

    exit (1);

  }

/* Deallocazione dei segmenti di memoria e del semaforo */
if(shmctl(seg_mem,IPC_RMID,0) == -1) {
    perror ("Errore deallocazione nemico di primo livello!");

    exit (1);

  }

if(semctl(semid,1,IPC_RMID) == -1) {
    perror ("Errore deallocazione semaforo!");

    exit (1);

  }
} // fine funzione LIBERA_MEM


/** Funzione ASTRONAVE **/
void astronave ()
{
pos pos_astronave;
int pid_missile[2]; // l'astronave spara contemporaneamente due missili:uno a destra e uno a sinistra
int i;

pos_astronave.c='#';
pos_astronave.x=MAXX/2;
pos_astronave.y=MAXY-1;
pos_astronave.pid=getpid();

wait_sem(0);
*pos_mem = pos_astronave;
post_sem(1);

while(1)
     {
      char c;
      switch(c=getch()) { //gestione movimento o sgancio dei missili da parte dell'astronave
        case SINISTRA: if(pos_astronave.x>0)
                                      pos_astronave.x-=1;
                                   break;
        case DESTRA: if(pos_astronave.x<MAXX-1)
                                    pos_astronave.x+=1;
                                 break;/*
        case SGANCIA: for(i=0;i<2;i++)
                                        switch(pid_missile[i]=fork()) {
                                                    case -1: perror("Errore nell'esecuzione della fork");
                                                                  exit(1);
                                                    case 0: missile(pipeout,i,pos_astronave.x,pos_astronave.y);
                               
                                                                                        }
                                  break;*/
                                } // fine switch gestione movimento

    	wait_sem(0);
	*pos_mem = pos_astronave;
	post_sem(1);
    }
} // fine Funzione Astronave


/** Funzione NEMICO **/
void nemico(int i)
{
pos pos_nemico;
int dx,dy; // spostamenti in x e y;
int SOGLIAX; // soglia oltre la quale il nemico non puō andare - puō essere 1 o MAXX-1
int DIRX; // direzione in x - se dirx=1 vā a destra, se dirx=-1 va a sinistra
int time_giu=0; // contatore per far scendere il nemico
int SOGLIA_GIU=10*(0+rand()%4)+i*5; // soglia per far scendere il nemico di una riga
int time_bomb=1; // contatore per far sganciare una bomba
int SOGLIA_BOMB=30+i*(0+rand()%5); // soglia per far sganciare la bomba
int pid_bomba;

pos_nemico.c='$';
pos_nemico.p=i;
pos_nemico.pid=getpid();
pos_nemico.y=1; // i nemici partono tutti sulla stessa riga
pos_nemico.x=9+(i*20); // ma distanziati

if(!(i%2)) // se il numero assegnato al nemico č pari
  {
    DIRX=1; // vā a destra
    SOGLIAX=MAXX-1; // e la soglia max in x č MAXX-1
  }
else // altrimenti
   {
     DIRX=-1; // vā a sinistra
     SOGLIAX=1; // e la soglia max in x č 1
   }

wait_sem(0);
*pos_mem = pos_nemico;
post_sem(1);

while(1)
{
 
      if(pos_nemico.x==SOGLIAX) // se il nemico sbatte contro una parete laterale
       {
         DIRX*=-1; // cambio la direzione
         if(SOGLIAX==MAXX-1) // se la nuova direzione č destra
            SOGLIAX=1; // la soglia č MAXX-1
         else // altrimenti
            SOGLIAX=MAXX-1; // la soglia č 1
       }   

     if(DIRX==1) // se la direzione č destra
      dx=PASSO; // il suo spostamento sarā di PASSO
    else // altrimenti
      dx=-PASSO; // il suo spostamento sarā di -PASSO
      
    pos_nemico.x+=dx; // scriviamo la posizione in x del nemico

    if(!(time_giu%SOGLIA_GIU)) // ad intervalli regolari
       {
         dy=PASSO; // il nemico avanza di PASSO verso la soglia massima in Y
         time_giu=1; // riazzero il contatore
       }
    else
       {
         dy=0; // il nemico non avanza verso la soglia massima in Y
         time_giu++; // aggiorno il contatore per la discesa del nemico
       }

    pos_nemico.y+=dy; // scriviamo la posizione in y del nemico

    // aggiorniamo la posizione del nemico e la comunichiamo al controllo
    wait_sem(0);
    *pos_mem = pos_nemico;
    post_sem(1);

/*
    if(!(time_bomb%SOGLIA_BOMB)) // ad intervalli regolari
       switch(pid_bomba=fork()) { // il nemico sgancia la bomba
                    case -1: perror("Errore nella creazione del processo bomba");
                                  exit(1);
                    case 0: bomba(pipeout,pos_nemico.x,pos_nemico.y);
                                }
    time_bomb++; // aggiorno il contatore per la bomba
*/
    usleep(300000);

} // fine while;

} // fine Funzione Nemico
(continua)