Subversion Repositories shark

Rev

Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed


/*--------------------------------------------------------------*/
/*                        DEFENDER GAME                         */
/*--------------------------------------------------------------*/

#include <kernel/kern.h>
#include <drivers/glib.h>
#include <drivers/keyb.h>
#include <semaphore.h>
#include <stdlib.h>
#include <math.h>

#define YMENU    10             /* menu level                   */
#define XMIN     50
#define XMAX     600
#define YMIN     100
#define YMAX     450
#define VEL      3              /* linear velocity (def. = 3)   */
#define ANG      30             /* angolo massimo sterzata (30) */
#define D        3              /* raggio alieno                */
#define DD       6              /* diametro alieno              */
#define ESC      27             /* ASCII code of ESCAPE key     */
#define MAX_ALIEN    30         /* max number of aliens         */
#define MAX_MISSIL   10         /* numero massimo di missili    */

#define M_GROUP        1
#define ALIEN_GROUP    2
#define MISSILE_GROUP  3

#define STUPID   2
#define NORMAL   14
#define BAD      13
#define BASTARD  4

int tipo[4] = {STUPID,NORMAL,BAD,BASTARD};

#define PRODUCED    1
#define CONSUMED    0

#define Ix       16
#define Iy       16

char command_astro ; // comandi astronave
int  AstroCmdState ;

struct argAlien {
  int orig_x ; // coordinate iniziali
  int orig_y ;
  int a_type ; // tipo di alieno
};

int     mother_period =   50000 ;     /* task period                  */
int     mother_wcet   =   10000 ;     /* task wcet                    */

int     Alien_period =    40000 ;     /* task period                  */
int     Alien_wcet   =     1000 ;     /* task wcet                    */

int     Astro_period =    40000 ;     /* task period                  */
int     Astro_wcet =       2000 ;     /* task wcet                    */

int     missile_period =  40000 ;
int     missile_wcet =     1000 ;


PID     pid_Madre, pid_Alien, pid_Astro, pid_Missile, pid_Monitor ;
sem_t   grx_mutex, keyb_mutex, astro_mutex, alien_mutex, score_mutex;
sem_t   missile_mutex[MAX_MISSIL];

/*--------------------------------------------------------------*/

// Risorse condivise

struct s_Astronave {
  int x, y, FlagCollisione, FlagAstronave ;
} AstronavePosition ;

struct s_Missile {
  int x, y, FlagCollisione ;
} MissilePosition[MAX_MISSIL] ;

struct s_Score {
  int total, type[5] ;
} Score ;

int alieni_vivi ;  // numero di alieni attualmente in vita

/*--------------------------------------------------------------*/

// Disegna l'astronave a partire dalla "poppa" x,y di colore c
void    draw_Astronave(int x, int y, int c)
{
  // Il disegno degli oggetti e' fatto sotto mutex per migliorare
  // l'aspetto del sistema.

  if (x < 3) x = 3;
  if (y < 8) y = 8;

  sem_wait(&grx_mutex);
    grx_line(x, y-8, x, y+8, c);
    grx_line(x, y-8, x+5, y-4, c);
    grx_line(x, y+8, x+5, y+4, c);
    grx_line(x+5, y-4, x+10, y-4, c);
    grx_line(x+5, y+4, x+10, y+4, c);
    grx_line(x+10, y-4, x+15, y, c);
    grx_line(x+10, y+4, x+15, y, c);
    grx_line(x+15, y, x+17, y, c);
    grx_box(x-3, y-6, x, y-2, c);
    grx_box(x-3, y+2, x, y+6, c);
    grx_box(x+8, y-3, x+10, y-1, c);
    grx_box(x+8, y+1, x+10, y+3, c);
    grx_line(x+3, y-4, x+8, y-1, c);
    grx_line(x+3, y+4, x+8, y+1, c);
  sem_post(&grx_mutex);
}

// disegno del generico alieno "centro" x,y colore
void    draw_Alieno(int x, int y, int c)
{
  if (x < DD) x = DD;
  if (y < 0) y = 0;

  sem_wait(&grx_mutex);
    grx_disc(x, y, D, c); // disco
    grx_line(x-DD, y, x+DD, y, c); // linea
  sem_post(&grx_mutex);
}

// disegno della madre alieni
void    draw_Mother(int x, int y, int c, int d)
{
  int i;

  if (x < 10) x = 10;
  if (y < 8) y = 8;

  sem_wait(&grx_mutex);
    grx_box(x-10, y-10, x-5, y+5, c); // box
    grx_box(x+5, y-10, x+10, y+5, c); // box
    grx_disc(x, y, 5, c); // disco
    grx_line(x, y+8, x, y-8, c); // linea
    for (i = 0; i < d ; i++) {
      grx_disc(x + (rand()%20)-10, y + (rand()%10)-5, d/2, 0);
    }
  sem_post(&grx_mutex);
}

void    draw_Missile(int x, int y, int c)
{
  if (y < 3) y = 3;

  sem_wait(&grx_mutex);
    grx_box (x, y-1, x+6, y+1, c);
    grx_line(x+1, y-3, x+1, y+3, c);
    grx_line(x+1, y+3, x+3, y, c);
    grx_line(x+1, y-3, x+3, y, c);
    grx_disc(x+6, y, 1, c);
  sem_post(&grx_mutex);
}
/******************************************************************/

// ------------------------------------------------------------------->

//                              ALIENO

// ------------------------------------------------------------------->

TASK    Alieno(void *arg)
{
  int     x, y          ;
  int     xa1, ya1      ;
  int     ox, oy        ;
  int     x1 = 0        ;   /* variabile di appoggio */
  int     dx, dy, da    ;
  int     teta = 0      ;
  int     col           ;
  int     outx, outy    ;
  double  r             ;
  int     j = 0         ;
  int     morto = FALSE ;
  int     score = 0     ;

  int x_MissilePosition ;
  int y_MissilePosition ;
  int FlagCollisione    ;

  int x_AstronavePosition ;
  int y_AstronavePosition ;

  int xi,yi ;

  int FlagAstro ;

  float Kp = 0.01     ;
  float Ki = 0.005    ;
  float Kd = 0.00005  ;

  float ex_k, ey_k, ex_sum, ey_sum, ex_km1, ey_km1 ;

  ex_k = ey_k = ex_sum = ey_sum = ex_km1 = ey_km1 = 0 ;

  struct argAlien *arg_Alieno = (struct argAlien *)arg ;

  // Punto di partenza dell'alieno
  x = ox = arg_Alieno->orig_x ;
  y = oy = arg_Alieno->orig_y ;
  col = arg_Alieno->a_type    ;   /* tipo alieno */


  // Ciclo infinito
  while (1) {


    // Lettura valori Astronave
    sem_wait(&astro_mutex);
      x_AstronavePosition = AstronavePosition.x   ;
      y_AstronavePosition = AstronavePosition.y   ;
      FlagAstro = AstronavePosition.FlagAstronave ;
    sem_post(&astro_mutex);

    switch (col)
    {
      case STUPID :
      {    // Parametri di spostamento

        dx = -VEL;
        x += dx;
        if (x <= XMIN + DD) x = XMAX - DD;

        score = 1 ;

      }
      break;

      case NORMAL :
      {  // Spostamento oggetto
        dx = -VEL                ;
        dy = VEL * (rand()%3 -1) ;
        x += dx                  ;
        y += dy                  ;

        outy = (y >= YMAX) || (y <= YMIN);
        if (outy) y = y - dy;

        if (x <= XMIN + DD) x = XMAX - DD;

        score = 2 ;

      }
      break;

      case BAD :
      {
        da = rand()%(2*ANG) - ANG;  /*  da = [-ANG,ANG] */
        teta += da;

        if (teta > 360) teta -= 360;
        if (teta < 0) teta += 360;
        r = (double)teta * PI / 180.;
        dx = (float)(-VEL * cos(r));
        dy = (float)(VEL * sin(r));
        x += dx;
        y += dy;

        outx = (x >= XMAX-DD) || (x <= XMIN+DD);
        outy = (y >= YMAX) || (y <= YMIN);

        if (outy) {
          y = y - dy;
          teta = -teta;
          if (teta > 360) teta -= 360;
          if (teta < 0) teta += 360;
          r = (double)teta * PI / 180.;

          dy = (float)(VEL * sin(r));

          y += dy;
        }

        if (outx) {
          x = x - dx;

          if (x+dx >= XMAX-DD) x1 = XMIN + DD;
          if (x <= XMIN+DD) x1 = XMAX - DD;

          x = x1 + dx;
        }

        score = 3 ;

      }
      break;

      case BASTARD : // alieno bastardo
      {

          xa1 = x_AstronavePosition ;
          ya1 = y_AstronavePosition ;

        if (!FlagAstro) col = BAD;

// PID di inseguimento asse X

        ex_k =(float) (xa1 - x);
        if (ex_k >  50) ex_k =  50 ; // saturazione simmetrica dell'errore
        if (ex_k < -50) ex_k = -50 ;

        ex_sum = ex_sum + ex_k ;       // aggiornamento dell'errore integrale
        dx = (int) ( ex_k * Kp + ex_sum * Ki + (ex_k - ex_km1) *Kd ); // PID classico
        ex_km1 = ex_k ; // salvataggio dell'errore vecchio x il termine derivativo

// PID di inseguimento asse Y
        ey_k = (float) (ya1 - y);
        if (ey_k >  50) ey_k =  50 ; // saturazione simmetrica dell'errore
        if (ey_k < -50) ey_k = -50 ;

        ey_sum = ey_sum + ey_k ;       // aggiornamento dell'errore integrale
        dy = (int) ( ey_k * Kp + ey_sum * Ki + (ey_k-ey_km1) *Kd ) ;
        ey_km1 = ey_k ;

        x = x + dx ; // aggiornamento delle posizioni
        y = y + dy ;

        outx = (x >= XMAX-DD) || (x <= XMIN+DD); // flag di schianto
        outy = (y >= YMAX) || (y <= YMIN);

        if (outy)
        {
            y = y - dy;
            ey_sum = 0;
        }

        if (outx)
        {
            x = x - dx;

            if (x+dx >= XMAX-DD) x1 = XMIN + DD;
            if (x <= XMIN+DD) x1 = XMAX - DD;

             x = x1 + dx;
        }

        score = 4 ;

      } // chiude il CASE BASTARD
      break;

    } //chiude lo switch

    // Disegno l'alieno
    draw_Alieno(ox, oy, 0);             /* cancello il vecchio alieno */



    // Rilevatore di collisioni con l'Astronave



    if (FlagAstro)
    {
        // verifica della presenza dell'astronave nell'intorno
           xi = ( (abs(x - x_AstronavePosition)) < Ix ) ;
           yi = ( (abs(y - y_AstronavePosition)) < Iy ) ;
        if (xi && yi)
          {
             sem_wait(&astro_mutex)   ;
                AstronavePosition.FlagCollisione = TRUE    ;
             sem_post(&astro_mutex)   ;
         break ; // morto x collisione astronave
          }
     }

    // Controllo di collisione dell'ALIENO con i missili
    for (j = 0; j < MAX_MISSIL; j++)
      {

      sem_wait(&missile_mutex[j]);
        x_MissilePosition = MissilePosition[j].x ;
        y_MissilePosition = MissilePosition[j].y ;
        FlagCollisione = MissilePosition[j].FlagCollisione;
      sem_post(&missile_mutex[j]);

      if (FlagCollisione == FALSE) {

        // verifica della presenza nell'intorno
        xi = ( (x - x_MissilePosition) > 0 && (x - x_MissilePosition) < Ix ) ;
        yi = ( (abs(y - y_MissilePosition)) < Iy )                           ;

        if (xi && yi) {
          sem_wait(&missile_mutex[j])   ;
            MissilePosition[j].FlagCollisione = TRUE    ;
          sem_post(&missile_mutex[j])   ;

          morto = TRUE ;

        }
      }
      else break ;  // esco dal ciclo for
    }

    if (morto == TRUE) break ;  // esco dal ciclo while

    draw_Alieno(x, y, col);             /* disegno il nuovo alieno */
    ox = x; oy = y;

    task_endcycle();    /* fine del ciclo */

  } // chiusura del while

     sem_wait(&alien_mutex) ;
       alieni_vivi--        ;
     sem_post(&alien_mutex) ;

     sem_wait(&score_mutex) ;
       Score.total+=score   ;
       Score.type[score-1]++;
     sem_post(&score_mutex) ;

     pid_Alien = NIL ;

  return 0 ; // morte dell'alieno

}


// ------------------------------------------------------------------->

//                              MADRE ALIENI

// ------------------------------------------------------------------->


TASK    MadreAlieni(void *arg)
{

  int v = 0;
  int a_v ;
  int i = 150;
  int conta_spari = 0;
  int xi, yi;
  int j = 0;

  int x_MissilePosition ;
  int y_MissilePosition ;
  int FlagCollisione ;

  int x_AstronavePosition ;
  int y_AstronavePosition ;
  int FlagAstro ;

  int     x, y;
  int     ox, oy;
  int     dx, dy, da;
  int     teta = 0;
  int     outx, outy;
  double  r;

  struct argAlien arg_Alieno;

  struct argAlien *p_Alien;

  p_Alien = &arg_Alieno;

  HARD_TASK_MODEL Alien;

  // Punto di partenza della Madre alieni

  x = ox = (rand()%XMIN) + (rand()%(XMAX-2*XMIN)) + XMIN;
  y = oy = (rand()%YMIN) + (rand()%(YMAX-2*YMIN)) + YMIN;


  // Ciclo infinito
  while (1)
    {

    // Punto di partenza dell'alieno (dal culo della Madre alieni)

    arg_Alieno.orig_x = x;
    arg_Alieno.orig_y = y + 15;

    // Tipo alieno casuale
    v = rand()%4;

    arg_Alieno.a_type = tipo[v];

    sem_wait(&alien_mutex) ;
      a_v = alieni_vivi   ;
    sem_post(&alien_mutex) ;

    if ((a_v < MAX_ALIEN) && (i == 0))
      {

      hard_task_default_model(Alien);
      hard_task_def_ctrl_jet (Alien);
      hard_task_def_arg      (Alien, (void *)p_Alien);
      hard_task_def_wcet     (Alien, Alien_wcet);
      hard_task_def_mit      (Alien, Alien_period);
      hard_task_def_group    (Alien, ALIEN_GROUP);
      hard_task_def_usemath  (Alien);

      pid_Alien = task_create("Alieno", Alieno, &Alien, NULL);

      if (pid_Alien == NIL)
        {
        grx_text("pid_Alien == NIL", 200, 80 ,  4, 0);
        return 0;
        //grx_close();
        //perror("Could not create task <Alieno>\n");
        //sys_abort(1);
      }

      task_activate(pid_Alien);

      i = 40 ; // count down alla generarazione di un alieno

      sem_wait(&alien_mutex) ;
        alieni_vivi++   ;
      sem_post(&alien_mutex) ;

    }

    // Spostamento madre alieni
    da = rand()%(2*ANG) - ANG;  /*  da = [-ANG,ANG] */
    teta += da;

    if (teta > 360) teta -= 360;
    if (teta < 0) teta += 360;
    r = (double)teta * PI / 180.;
    dx = (float)(2 * cos(r));
    dy = (float)(2 * sin(r));
    x += dx;
    y += dy;

    outx = (x >= XMAX - 20) || (x <= XMIN + 20);
    outy = (y >= YMAX - 20) || (y <= YMIN + 20);

    if (outx || outy)
      {
      x = x - dx;
      y = y - dy;
      if (outx) teta = 180 - teta;
      if (outy) teta = -teta;
      if (teta > 360) teta -= 360;
      if (teta < 0) teta += 360;
      r = (double)teta * PI / 180.;

      dx = (float)(2 * cos(r));
      dy = (float)(2 * sin(r));

      x += dx;
      y += dy;
    }

    draw_Mother(ox, oy, 0, 0);

    // Controllo di collisione della MADRE con i missili
    for (j = 0; j < MAX_MISSIL; j++)
      {

      sem_wait(&missile_mutex[j]);
        x_MissilePosition = MissilePosition[j].x ;
        y_MissilePosition = MissilePosition[j].y ;
        FlagCollisione = MissilePosition[j].FlagCollisione;
      sem_post(&missile_mutex[j]);

      if (FlagCollisione == FALSE)
        {

        // verifica della presenza nell'intorno
        xi = ( (x - x_MissilePosition) > 0 && (x - x_MissilePosition) < Ix ) ;
        yi = ( (abs(y - y_MissilePosition)) < Iy )                           ;

        if (xi && yi)
          {
          sem_wait(&missile_mutex[j])   ;
            MissilePosition[j].FlagCollisione = TRUE    ;
          sem_post(&missile_mutex[j])   ;

          conta_spari++;

        }
      }

      if (FlagCollisione == TRUE) break ;  // esco dal ciclo for
    }

    if (conta_spari == 5) {

      sem_wait(&score_mutex) ;
        Score.total+=10      ;
        Score.type[4]++      ;
      sem_post(&score_mutex) ;

      pid_Madre = NIL ;
      return 0 ;

    }

    // Controllo di collisione della madre con l'astronave
    // Lettura valori Astronave
    sem_wait(&astro_mutex);
      x_AstronavePosition = AstronavePosition.x ;
      y_AstronavePosition = AstronavePosition.y ;
      FlagAstro = AstronavePosition.FlagAstronave ;
    sem_post(&astro_mutex);

    if (FlagAstro)
      {
      // verifica della presenza dell'astronave nell'intorno
      xi = ( (abs(x - x_AstronavePosition)) < Ix ) ;
      yi = ( (abs(y - y_AstronavePosition)) < Iy ) ;
      if (xi && yi)
        {
        sem_wait(&astro_mutex)   ;
          AstronavePosition.FlagCollisione = TRUE    ;
        sem_post(&astro_mutex)   ;
        conta_spari++ ;
      }
    }

    if (conta_spari == 5) {

      sem_wait(&score_mutex) ;
        Score.total+=10      ;
        Score.type[4]++      ;
      sem_post(&score_mutex) ;

      pid_Madre = NIL ;
      return 0 ;

    }

    draw_Mother(x, y, 15, conta_spari);
    ox = x; oy = y;

    i-- ;

    task_endcycle();    /* fine del ciclo while */
  }
}

// ------------------------------------------------------------------->

//                              ASTRONAVE

// ------------------------------------------------------------------->


TASK    Astronave(void *arg)
{
  int     x, y;
  int     ox, oy;
  int     dx, dy;
  int     col;
  int     outy;
  char          c;

  int FlagCollisione ;

  x = ox = XMIN + 10;
  y = oy = (YMIN+YMAX)/2;
  col = 15;

  while (1) {

    sem_wait(&keyb_mutex);
       if (AstroCmdState == PRODUCED)
         {
           c = command_astro;
           AstroCmdState = CONSUMED ;
         }
        else
         {
           c = 0 ;
         }
    sem_post(&keyb_mutex);

    dx = VEL ;
    dy = 0   ;

    switch (c)
    {
      case 'w' :
      {
        dy = -VEL;
      }
      break;

      case 's' :
      {
        dy = VEL;
      }
      break;
     }


    x += dx;
    y += dy;

    outy = (y >= YMAX-DD) || (y <= YMIN+DD);

    if (outy) y = y - dy;

    if (x >= XMAX - DD) x = XMIN + DD;


    sem_wait(&astro_mutex);
      AstronavePosition.x = x   ;
      AstronavePosition.y = y   ;
      FlagCollisione = AstronavePosition.FlagCollisione ;
    sem_post(&astro_mutex);

    draw_Astronave(ox, oy, 0);

    if (FlagCollisione)
       break ;

    draw_Astronave(x, y, col);
    ox = x; oy = y;

    task_endcycle();

  } // chiusura del while

    sem_wait(&astro_mutex)                   ;
       AstronavePosition.FlagCollisione = FALSE  ;
       AstronavePosition.FlagAstronave  = FALSE  ;
    sem_post(&astro_mutex)                   ;

       pid_Astro = NIL ; // cleanup
  return 0 ;

} // chiusura dell'astronave

// ------------------------------------------------------------------->

//                              MISSILE

// ------------------------------------------------------------------->


TASK    Missile(void *arg)
{
  int     x, y;
  int     ox, oy;
  int     dx;
  int     col;
  int     xa1;
  int     ya1;

  int     FlagCollisione ;

  int     i = (int)arg;

  // Punto di partenza del missile (la punta dell'astronave)
  col = 15;                    /* colore missile (bianco) */

  sem_wait(&astro_mutex);
     xa1 = AstronavePosition.x ;
     ya1 = AstronavePosition.y ;
  sem_post(&astro_mutex);

  x = ox = xa1 + 15;
  y = oy = ya1;

  // Ciclo infinito
  while (1) {

    // Parametri di spostamento

    dx = 2*VEL;
    x += dx;

    sem_wait(&missile_mutex[i])                           ;
       MissilePosition[i].x = x ; // aggiorno posizione
       MissilePosition[i].y = y ;
       FlagCollisione = MissilePosition[i].FlagCollisione ; // leggo collisione
    sem_post(&missile_mutex[i])   ;

    // Esplosione del missile : a) per raggimento del bordo dx
    //                          b) per collisione con un alieno

    // Disegno l'alieno
    draw_Missile(ox, oy, 0);            /* cancello il vecchio missile */

    if ( (x >= XMAX - D) || FlagCollisione )
       break ;

    draw_Missile(x, y, col);            /* disegno il nuovo missile */
    ox = x; oy = y;

    task_endcycle();    /* fine del ciclo */

  } // chiusura del while(1): quando il missile arriva alla fine della sua esistenza
    // (bordo dx o collisione) temina cancellandosi.
    //

    sem_wait(&missile_mutex[i])                   ;
       MissilePosition[i].FlagCollisione = FALSE  ;
       MissilePosition[i].x = 0                   ;
       MissilePosition[i].y = 0                   ;  // Missile fuori dall'area di gioco
    sem_post(&missile_mutex[i])                   ;

  return 0 ;
}

// ------------------------------------------------------------------->

//                              M O N I T O R

// ------------------------------------------------------------------->


TASK    Monitor(void *arg)
{
  int stat1,stat2;
  int giri = 0 ;
  TIME T_Astro_Sum, T_Astro_Max, T_Astro_Curr ;
  TIME T_Madre_Sum, T_Madre_Max, T_Madre_Curr ;

  char s[400] ;

  // Ciclo infinito
  while (1)
    {
     stat1 = jet_getstat(pid_Astro, &T_Astro_Sum , &T_Astro_Max , &giri , &T_Astro_Curr);

       if (stat1==0)
         {
           sprintf(s,"Astro->TimeMax = %d ", (int) T_Astro_Max);
           grx_text(s , XMIN+350, YMENU+20,  4, 0);
         }
        else
        {
           sprintf(s,"                        ")   ;
           grx_text(s , XMIN+350, YMENU+20,  4, 0) ;
        }


//--------------------------------------------------->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>


       stat2 = jet_getstat(pid_Madre, &T_Madre_Sum , &T_Madre_Max , &giri , &T_Madre_Curr);

       if (stat2==0)
         {
           sprintf(s,"Madre->TimeMax = %d ", (int) T_Madre_Max);
           grx_text(s , XMIN+350, YMENU+30,  4, 0);
         }
        else
        {
           sprintf(s,"                        ")   ;
           grx_text(s , XMIN+350, YMENU+30,  4, 0) ;
        }


//-----------------------------------------------------------------------------

     }
}
/****************************************************************/

/* This function is called when the system exits */
void byebye(void *arg)
{
  grx_close();
  cprintf("Bye Bye!\n");
}

/****************************** MAIN ******************************/

int main(int argc, char **argv)

{
  HARD_TASK_MODEL m,a,ms; // Task hard

  NRT_TASK_MODEL  monitor ; // Task non real time

  char c      ;             /* character from keyboard      */
  int  i = 0  ;         /* missile numero      */
  TIME seme   ;          /* used to init the random seed */
  int miss = 0;
  int totalscore = 0;
  int typescore[5] = {0,0,0,0,0};

  char s[30]  ;
  char s1[30] ;
  char s2[30] ;
  char s3[30] ;
  char s4[30] ;
  char s5[30] ;


  AstroCmdState = CONSUMED ;
  for (i = 0; i < MAX_MISSIL; i++) {
    MissilePosition[i].FlagCollisione = FALSE ;
  }

  AstronavePosition.FlagCollisione = FALSE    ;
  AstronavePosition.FlagAstronave = FALSE     ;

  pid_Madre = NIL ;
  pid_Astro   = NIL ;

  Score.total = 0 ;
/* */
  nrt_task_default_model(monitor) ; // inizializza il task monitor

  pid_Monitor = task_create("Monitor", Monitor, &monitor, NULL);

          if (pid_Monitor == NIL) {
            grx_close();
            perror("Could not create task <Monitor>\n");
            sys_abort(1);
          }

  task_activate(pid_Monitor); // parte immediatamente


  /* Set the closing function */
  sys_atrunlevel(byebye, NULL, RUNLEVEL_BEFORE_EXIT);

  /* Semaphore Initialization */
  sem_init(&grx_mutex,0,1);
  sem_init(&keyb_mutex,0,1);
  sem_init(&astro_mutex,0,1);
  sem_init(&alien_mutex,0,1);
  sem_init(&score_mutex,0,1);
  for (i = 0; i < MAX_MISSIL; i++) {
    sem_init(&missile_mutex[i],0,1);
  }

  /* graphic card Initialization */
  if (grx_init() < 1) {
    cprintf("GRX Init\n");
    sys_abort(1);
  }

  if (grx_open(640, 480, 8) < 0) {
    cprintf("GRX Err\n");
    sys_abort(1);
  }

  /* The scenario */
  grx_line(XMIN-D-1, YMIN-D-1, XMAX+D+1, YMIN-D-1, 14);
  grx_line(XMIN-D-1, YMAX+D+1, XMAX+D+1, YMAX+D+1, 14);

  grx_text("Simulation of Defender Game", XMIN, YMENU+10,  1, 0);
  grx_text("a -> crea Astronave"        , XMIN, YMENU+20,  3, 0);
  grx_text("m -> crea Madre alieni"     , XMIN, YMENU+30, 13, 0);
  grx_text("space -> sparo"             , XMIN, YMENU+40, 14, 0);
  grx_text("ESC   exit to DOS"          , XMIN, YMENU+50,  4, 0);
  grx_text("SCORE  "                    , XMIN, YMENU+60,  4, 0);

  c = keyb_getch(BLOCK);

  /* randomize!!!! */
  seme = sys_gettime(NULL);
  srand(seme);

  do {
           //barra spazio lancia il task missile
    if ((c == ' ') && AstronavePosition.FlagAstronave==TRUE) {

      for (i = 0; i < MAX_MISSIL; i++) {

        sem_wait(&missile_mutex[i])   ;
          miss = MissilePosition[i].x ;
        sem_post(&missile_mutex[i])   ;

        if (miss == 0) {

          hard_task_default_model(ms);
          hard_task_def_ctrl_jet (ms);
          hard_task_def_arg      (ms, (void *)i);
          hard_task_def_wcet     (ms, missile_wcet);
          hard_task_def_mit      (ms, missile_period);
          hard_task_def_group    (ms, MISSILE_GROUP);
          hard_task_def_usemath  (ms);

          pid_Missile = task_create("Missile", Missile, &ms, NULL);

          if (pid_Missile == NIL) {
            grx_close();
            perror("Could not create task <Missile>\n");
            sys_abort(1);
          }

          task_activate(pid_Missile);

          break ;
        }
      }
    }

    if ((c == 'm') && (pid_Madre == NIL) ) {

      hard_task_default_model(m);
      hard_task_def_ctrl_jet (m);
      hard_task_def_arg      (m, (void *)i);
      hard_task_def_wcet     (m, mother_wcet);
      hard_task_def_mit      (m, mother_period);
      hard_task_def_group    (m, M_GROUP);
      hard_task_def_usemath  (m);

      pid_Madre = task_create("MadreAlieni", MadreAlieni, &m, NULL);

      if (pid_Madre == NIL) {
        grx_close();
        perror("Could not create task <MadreAlieni>\n");
        sys_abort(1);
      }
      task_activate(pid_Madre);
    }

    if ((c == 'a') && !AstronavePosition.FlagAstronave) { // creazione del task Astronave

      hard_task_default_model(a);
      hard_task_def_ctrl_jet (a);
      hard_task_def_arg      (a, (void *)i);
      hard_task_def_wcet     (a, Astro_wcet);
      hard_task_def_mit      (a, Astro_period);
      hard_task_def_usemath  (a);

      pid_Astro = task_create("Astronave", Astronave, &a, NULL);

      if (pid_Astro == NIL) {
        grx_close();
        perror("Could not create task <Astronave>\n");
        sys_abort(1);
      }

      AstronavePosition.FlagAstronave = TRUE ;
      task_activate(pid_Astro);
    }

     sem_wait(&score_mutex);
       totalscore = Score.total;
       for (i = 0; i < 5; i++) {
         typescore[i] = Score.type[i];
       }
     sem_post(&score_mutex);

     sprintf ( s, "SCORE = %d", totalscore);
     sprintf ( s1, "STUPID = %d", typescore[0]);
     sprintf ( s2, "NORMAL = %d", typescore[1]);
     sprintf ( s3, "BAD = %d", typescore[2]);
     sprintf ( s4, "BASTARD = %d", typescore[3]);
     sprintf ( s5, "MOTHER = %d", typescore[4]);

     grx_text( s , XMIN, YMENU+60,  4, 0);

     grx_text("Nemici uccisi", XMIN+250, YMENU+10,  1, 0);
     grx_text(s1 , XMIN+250, YMENU+20,  1, 0);
     grx_text(s2 , XMIN+250, YMENU+30,  1, 0);
     grx_text(s3 , XMIN+250, YMENU+40,  1, 0);
     grx_text(s4 , XMIN+250, YMENU+50,  1, 0);
     grx_text(s5 , XMIN+250, YMENU+60,  1, 0);

     c = keyb_getch(BLOCK);

     sem_wait(&keyb_mutex);
         command_astro = c ;
         AstroCmdState = PRODUCED ;
     sem_post(&keyb_mutex);

  } while (c != ESC);

  sys_end();

  return 0;
}

/*--------------------------------------------------------------*/