simul_seq.c

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <unistd.h>



/*
 * Ce petit simulateur est fourni comme exemple, SANS GARANTIE: il se
 * peut qu'il contiennent des erreurs.  
 * Si vous en trouvez, de les envoyer à Loris.Marchal@ens-lyon.fr pour
 * que je les mette sur la page web.
 *
 */



/* 
 * les paramètres de la simulation 
 *
 * (ce sont des valeurs choisies au hasard: 
 * adaptez-les tant que vous voulez !)
 *
 */

/* age de reprodution des requins */

#define BREEDING_AGE_SHARK 50

/* age de reprodution des sardines */

#define BREEDING_AGE_SARDINE 15

/* probabilité de reprodution des requins */

#define PROBA_SHARK 0.1

/* probabilité de reprodution des sardines */

#define PROBA_SARDINE 0.3

/* période de famine des requins */

#define T_FAMINE 20



/*
 * Variables globales
 */
#define SARDINE 1
#define SHARK 2

int ocean_size;


struct fish_struct_t {
  char type;
  char age;
  char age_before_starvation;
  char not_to_treat;
};

typedef struct fish_struct_t *fish_t;

fish_t *ocean;

int nb_of_sharks = 0;
int nb_of_sardines = 0;

/*
 * parse_file(filename)
 *
 * Lit le fichier de description de l'océan 
 * et initialise les données.
 *
 */
void parse_file(char *filename) {
  FILE *input_file;
  int x,y,age;
  char type[20];
  int line=1;
  


  input_file = fopen(filename,"r");

  if (!input_file) {
    fprintf(stdout,"Unable to open file %s\n",filename);
    abort();
  }

  if (fscanf(input_file, "%d\n", &ocean_size) != 1) {
    fprintf(stdout,"Unable to read ocean_size in %s\n",filename);
    abort();
  }

  ocean = (fish_t*) calloc(ocean_size * ocean_size,sizeof(fish_t));

  while (fscanf(input_file, "%d %d %s %d\n", &x, &y, type, &age)==4) {
    fish_t fish;
    fish = (fish_t) malloc(sizeof(struct fish_struct_t));
    if (strcmp(type,"shark")==0) {
      fish->type = SHARK;
      nb_of_sharks++;
    } else if (strcmp(type,"sardine")==0) {
      fish->type = SARDINE;
      nb_of_sardines++;
    } else {
      fprintf(stdout,"Unknown type of fish \"%s\"\n",type);
      abort();
    }
    fish->age = age;
    fish->age_before_starvation = T_FAMINE;
    line++;
    ocean[(y*ocean_size)+x] = fish;
  }
  
  if (!feof(input_file)) {
    fprintf(stdout,"Problem while parsing line %d of file %s\n",line,filename);
    abort();
  }
}

/*
 * simul_one_step()
 *
 * Effectue une étape de simulation
 *
 */

void simul_one_step(void) {
  int x,y;
  for(x=0; x<ocean_size; x++) 
    for(y=0; y<ocean_size; y++) 
      if (ocean[(y*ocean_size)+x]) {
	fish_t fish, fish_at_target;
	int direction, x_target, y_target;

	fish = ocean[(y*ocean_size)+x];
	if (fish->not_to_treat) {
	  fish->not_to_treat = 0;
	  continue;
	}
	fish->age++;
	switch (fish->type) {
	case SHARK:
	  fish->age_before_starvation--;
	  if (fish->age > BREEDING_AGE_SHARK) {
	    fish->age--; /* to avoid overflow: no need to consider shark older than this age */
	  }

	  if (fish->age_before_starvation == 0) {
	    free(fish);
	    ocean[(y*ocean_size)+x]=NULL;
	    nb_of_sharks--;
	  } else {	    
	    direction = (int) (4.0*rand()/(RAND_MAX+1.0));
	    x_target = x; y_target =y;
	    switch (direction) {
	    case 0: x_target++; break;
	    case 1: y_target++; break;
	    case 2: x_target--; break;
	    case 3: y_target--; break;
	    }
	    if (x_target < 0) 
	      x_target+=ocean_size;
	    if (y_target < 0) 
	      y_target+=ocean_size;
	    if (x_target == ocean_size)
	      x_target = 0;
	    if (y_target == ocean_size)
	      y_target = 0;

	    fish_at_target = ocean[y_target * ocean_size + x_target];
	    if ((fish_at_target != NULL) && (fish_at_target->type == SARDINE)) {
	      free(fish_at_target);
	      nb_of_sardines--;
	      ocean[y_target * ocean_size + x_target] = NULL;
	      fish_at_target = NULL;
	      fish->age_before_starvation = T_FAMINE;
	    }
	    
	    if (fish_at_target == NULL) { 
	      /* moving */
	      if ((direction == 0) || (direction == 1)) {
		/* if the fish moves right or down, take care not to treat it a second time in this step */
		fish->not_to_treat = 1;
	      }
	      ocean[y_target * ocean_size + x_target] = fish;
	      ocean[y * ocean_size + x] = 0;
	      /* breeding ? */
	      if (fish->age >= BREEDING_AGE_SHARK) {
		if (((1.0*rand())/(RAND_MAX+1.0)) < PROBA_SHARK) { 
		  /* a new shark ! */
		  fish_t new_shark = (fish_t) malloc(sizeof(struct fish_struct_t));
		  new_shark->type = SHARK;
		  new_shark->age = 0;
		  new_shark->age_before_starvation = T_FAMINE;
		  ocean[y * ocean_size + x] = new_shark;
		  nb_of_sharks++;
		}
	      }
	    }
	  }
	  break;
	  
	case SARDINE:
	  if (fish->age > BREEDING_AGE_SARDINE) {
	      fish->age--; /* to avoid overflow: no need to consider sardine older than this age */
	  }
	  direction = (int) (4.0*rand()/(RAND_MAX+1.0));
	  x_target = x; y_target =y;
	  switch (direction) {
	  case 0: x_target++; break;
	  case 1: y_target++; break;
	  case 2: x_target--; break;
	  case 3: y_target--; break;
	  }
	  if (x_target<0) 
	    x_target+=ocean_size;
	  if (y_target<0) 
	    y_target+=ocean_size;
	    if (x_target == ocean_size)
	      x_target = 0;
	    if (y_target == ocean_size)
	      y_target = 0;

	  
	  fish_at_target = ocean[y_target * ocean_size + x_target];
	  if (fish_at_target == NULL) { 
	    /* moving */
	      if ((direction == 0) || (direction == 1)) {
		/* if the fish moves right or down, take care not to treat it a second time in this step */
		fish->not_to_treat = 1;
	      }
	    ocean[y_target * ocean_size + x_target] = fish;
	    ocean[y * ocean_size + x] = 0;
	    /* breeding ? */
	    if (fish->age >= BREEDING_AGE_SARDINE) {
	      if (((1.0*rand())/(RAND_MAX+1.0)) < PROBA_SARDINE) { 
		/* a new sardine ! */
		fish_t new_sardine = (fish_t) malloc(sizeof(struct fish_struct_t));
		new_sardine->type = SARDINE;
		new_sardine->age = 0;
		new_sardine->age_before_starvation = T_FAMINE;
		ocean[y * ocean_size + x] = new_sardine;
		nb_of_sardines++;
	      }
	    }
	  }
	  
	  break;
	}
      }
      	
}

/*
 * print_ocean()
 * 
 * Permet l'affichage de la grille, si celle-ci est de petite taille.
 *
 */

void print_ocean(void) {
  int x,y;
  int requins = 0;
  int sardines = 0;

  fprintf(stdout," ");  
  for(x=0; x<ocean_size+2; x++) fprintf(stdout,"-");
  fprintf(stdout,"\n");

  for(y=0; y<ocean_size; y++) {
    fprintf(stdout,"%d|",y%10);
    for(x=0; x<ocean_size; x++) {
      if (ocean[y * ocean_size + x] != NULL) {
	if (ocean[y * ocean_size + x]->type == SHARK) {
	  fprintf(stdout,"\033[31mR\033[00m");
	  requins++;
	} else {
  	  fprintf(stdout,"S");
	  sardines++;
	}
      } else 
	fprintf(stdout," ");
    }
    fprintf(stdout,"|\n");
  }

  fprintf(stdout," ");  
  for(x=0; x<ocean_size+2; x++) 
    fprintf(stdout,"-");
  fprintf(stdout,"\n");
    fprintf(stdout,"%d requins et %d sardines.\n\n",requins,sardines);
}

int main(int argc, char **argv) {
  int step, max_step;
  
  if (argc != 3) {
    fprintf(stdout,"Usage: %s <ocean_filename> <nb_of_steps>\n",argv[0]);
    exit(1);
  }
  parse_file(argv[1]);
  max_step = atoi(argv[2]);

  for(step=0; step<max_step; step++) {
    fprintf(stdout,"step %d:\n",step);
    simul_one_step();
    /*    print_ocean(); */
    fprintf(stdout,"%d requins et %d sardines.\n\n",nb_of_sharks,nb_of_sardines);

  }
  
  return 0;
}

Generated by GNU enscript 1.6.3.