/* Nived: l'éditeur de niveaux de BomberInstinct */
/* Nived: The editor of nives for BomberInstinct */

/* Note: */
/* Meaning of various comments */

//x means, it can be remowed in future
//xx means, it shell be removed now
//? I don't know, if it might be needed in the future
//T a temporary change
//L Language notes

// !! needs repair
// ?? i don't uderstand


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

#include <SDL/SDL.h>
#include <SDL/SDL_mixer.h>

/* P.K. */
#include "types.h"
#include "common.h"
#include "macros.h"

/* P.K. */
//? #include "main.h" // will be instead of fakes.h
#include "fakes.h"

#include "niveaux.h" // P.K.
#include "sprites.h"

/* P.K. Various languages localization */
#include <locale.h>
#include <libintl.h>

/* P.K. number of objects in the menu */
#define N_CHOIX 8 // P.K. For the menu on the right site

/* The legend and all the *.niv files should be in english */
const char legende[]="DESCRIPTION :\n"
"_              space\n"
"+[index]       wall\n"
"§[index]       hidden passage\n"
"#              bloc\n"
"T[case]        teleportation[case between 0 and 240]\n"
"O[case]        button[idem]\n"
"0[case]        hidden button[idem]\n"
">[sens]        one way[0:up, 1:down, 2:left, 3:right]\n"
"=[direction]   tunnel[0:<v>, 1:<^>,  2:^v>, 3:<^v, 4:<^, 5:^>, 6:<v, 7:v>, 8:^v, 9:<>, 10:<^v>]\n"
"*              fontaine(regeneration)\n";
//?[sens] 	one way[0:haut, 1:bas, 2:gauche, 3:droite]

int NB_PERSO, VITESSE, REGEN, LFLAMMES, NBOMBES, REBOURS; //, BONUSFREQ; P.K.
extern float bonus_freq; // P.K. enable even float numbers (in common.h)
int pleinecran;          // 0 .. window, 1 .. full screen
int danslemenu=0;        // in the menu ??

Uint32 flags;            // SDL flags
//x char repertoire[256]; moved to main()
char prefixeniv[MAX_STRING_LENGTH], prefixespr[MAX_STRING_LENGTH]; // part of tha paths
char niv[MAX_STRING_LENGTH];           // name of the *.niv file

//x Case pl[NIVEWIDTH+2][NIVEHEIGHT];
Plan plan;                 // game plan - dynamic

//x Coord persopos[8];
Coord actif;             // choosen element

Sprite *nived;           // sprite containing nived symbols
//x Sprite *elemliste[50]; // moved to initliste()
//x Sprite *nb[8];
Sprite *nb[MAX_NPERSO];  // players (= citrouilles)

char graphtype[MAX_STRING_LENGTH];     // grotte file = motif file
int decl;                // ?? for color palette ??
SDL_Rect tout, plateau, recdroite; // ??

SDL_Surface *ecran;      // ??
Uint8 *clavier;          // keyboard

//x int compteur;            // moved to common.c
int encore;              // boolean

//x Case elemactif;
PlateauElement elemactif;    // actvive elements
//x int *paramsbuf, nparamsbuf; // P.K.
Parameter *paramsbuf = NULL; // for yanking parametres (during future calls)
int nparamsbuf = 0;          // number of yanking parametres

//x int dx[4]={ 0, 0,-1, 1};     // four directions - moved to comon.c
//x int dy[4]={-1, 1, 0, 0};

int aleat(int max);
//x void erreur(char message[200], char param[20]);
//x void animsplus(Sprite *sprite, int anim, int vitesse, int duree, int x, int y);
//? void rscaseplus(int x, int y);
//x void rdplateau(void);
void initliste(void);

/* Resolution variables */
Resolution resolution;


/*  void erreur_(char message[200], char param[20]) */
/*  { */
/*  //x  printf ("\nErreur :\n%s", message); */
/*    printf (gettext("\nErreur :\n%s"), message); */
/*    if (param) printf(" : %s", param); */
/*    printf (".\n%s\n", SDL_GetError()); */
/*    exit(0); */
/*  } */

/*--Initialiser l'écran--*/
int init_sdl_nived(void)
{
  Uint32 params;
  int ok;
  char titre[MAX_STRING_LENGTH];

  flags=SDL_HWSURFACE|SDL_HWPALETTE;
  params = pleinecran ? flags|SDL_FULLSCREEN : flags;

  if ( SDL_Init(SDL_INIT_VIDEO) < 0 ) {
    //x    erreur("Impossible d'initialiser SDL", NULL);
    errormessage(gettext("Impossible d'initialiser SDL"), NULL);
    //L    erreur("Unable to initialize SDL!", NULL);
  }

  //x  sprintf(titre, "Nived - l'éditeur de niveaux de BomberInstinct - %s - v1.0", niv);
  sprintf(titre, gettext("Nived - l'éditeur de niveaux de BomberInstinct - %s - v1.0"), niv);
  SDL_WM_SetCaption(titre, "Nived");

  //x  ok=SDL_VideoModeOK(640, 480, 8, params);
  ok=SDL_VideoModeOK(resolution.window_width, resolution.window_height, 8, params);
  if (ok==0)
    //x    erreur("Le mode vidéo requis n'est pas disponible (640x480)", NULL);
    errormessage(gettext("Le mode vidéo requis n'est pas disponible (640x480)"), NULL);
  //x  ecran = SDL_SetVideoMode(640, 480, 8, params);
  ecran = SDL_SetVideoMode(resolution.window_width, resolution.window_height, 8, params);
  if ( ecran == NULL ) {
    //x    erreur("Impossible d'initialiser l'écran en mode 640*480 8 bits", NULL);
    errormessage(gettext("Impossible d'initialiser l'écran en mode 640*480 8 bits"), NULL);
    return 1;
  }

  atexit(SDL_Quit);
  SDL_EnableKeyRepeat(0,0);
  SDL_ShowCursor(1);
  return 0;
}


/* integer random number */
int aleat(int max)
{
  int num;
  num=(int)(max  *  ((float)rand()) / ((float)RAND_MAX) );
  return num;
}


void passenpleinecran()
{
  int i, ncoul;
  SDL_Surface *sauvegarde;
  SDL_Color *pal;
  ncoul=ecran->format->palette->ncolors;
  pal=(SDL_Color *)calloc(ncoul, sizeof(SDL_Color));
  for (i=0; i<ncoul; i++)
    {
      pal[i].r=ecran->format->palette->colors[i].r;
      pal[i].g=ecran->format->palette->colors[i].g;
      pal[i].b=ecran->format->palette->colors[i].b;
    }

  sauvegarde=SDL_DisplayFormat(ecran);
  SDL_FreeSurface(ecran);
  if ((ecran->flags & SDL_FULLSCREEN)==SDL_FULLSCREEN) {
    //x    ecran = SDL_SetVideoMode(640, 480, 8, SDL_HWSURFACE|SDL_HWPALETTE);
    ecran = SDL_SetVideoMode(resolution.window_width, resolution.window_height, 8, SDL_HWSURFACE|SDL_HWPALETTE);
  }
  else {
    //x    ecran = SDL_SetVideoMode(640, 480, 8, SDL_HWSURFACE|SDL_HWPALETTE|SDL_FULLSCREEN);
    ecran = SDL_SetVideoMode(resolution.window_width, resolution.window_height, 8, SDL_HWSURFACE|SDL_HWPALETTE|SDL_FULLSCREEN);
  }

  SDL_SetColors(ecran, pal, 0, ncoul);
  free(pal);
  SDL_BlitSurface(sauvegarde, NULL, ecran, NULL);
  SDL_Flip(ecran);
  SDL_FreeSurface(sauvegarde);
  return;
}


int filtr_evt(const SDL_Event *evt)
{
  if (evt->type == SDL_QUIT)
    exit(0);
  if (evt->type == SDL_KEYDOWN)
    {
      if (evt->key.keysym.sym==SDLK_c)
	if (evt->key.keysym.mod==KMOD_LCTRL)
	  exit(0);
      if (evt->key.keysym.sym==SDLK_F10)
	exit(0);
      if (evt->key.keysym.sym==SDLK_F1)
	passenpleinecran();
    }
  return 1;
}


void videcran(void)
{
  SDL_FillRect(ecran, &tout, 0);
  SDL_Flip(ecran);
  return;
}


/*--Redessine une case (x, y) du plateau--*/
void dessinecase_nived(int x, int y)
{
  int xx=x*32;

  if (x>(plan.nivewidth-1)) xx+=32; // ?? not necesary ??
  
  if (plan.element[x][y].sol)            // space as background
    blitsprit(sol, 0, 0, xx, y*32);

  blitsprit(plan.element[x][y].elem, plan.element[x][y].anim, plan.element[x][y].frame, xx, y*32);

  if (plan.element[x][y].type == SECRETPASSAGE) // secret passage P.K.
    blitsprit(nived, 0, 4, xx, y*32); // door

  if (plan.element[x][y].fixe == 1) // one fixed kind of sprite
    blitsprit(nived, 0, 0, xx, y*32); // anchor = symbol for fixed sprites

  return;
}


void rdicones(void)
{
  int x, y;

  /* here should be the "choix field" used */

  //x  for (y=0; y < niveheight; y++) 
  x = plan.nivewidth;
  for (y = 0; y < N_CHOIX; y++) {
    //x    for (x=nivewidth; x < (nivewidth+2); x++) {
      dessinecase_nived(x, y);
    }
  blitsprit(nb[0], 1, 0, (plan.nivewidth+1)*32, (plan.niveheight-1)*32); // citrouille
  blitsprit(nived, 0, 3, (plan.nivewidth+2)*32, (plan.niveheight-1)*32); // next motif
  return;
}


void rdplateau_nived(void)
{
  int x, y;

  for (y = 0; y < plan.niveheight; y++) 
    for (x = 0; x < plan.nivewidth; x++) {
      dessinecase_nived(x, y);
    }
  rdicones();
  return;
}


void chargeniv_(FILE *fich, int tete)
{
  int x, y, i;
  char niv, c;

  if (tete) // whether to read parametres from the fich file
    {
      fscanf(fich, "REGEN=%i\n", &REGEN); // testing for errors missing! P.K.
      //x      fscanf(fich, "BONUSFREQ=%i\n", &BONUSFREQ); P.K.
      fscanf(fich, "BONUSFREQ=%g\n", &bonus_freq);
      fscanf(fich, "NBOMBES=%i\n", &NBOMBES);
      fscanf(fich, "REBOURS=%i\n", &REBOURS);
      
      for (i=0; i<numperso; i++) {
	fscanf(fich, "perso[%*i]:(%i,%i)\n", &x, &y);
	//x	persopos[i].x=x;
	//x	persopos[i].y=y;
	perso[i].pos.x=x;
	perso[i].pos.y=y;
      }
    }
      
  do // read till the nive array
    fread(&niv, 1, 1, fich);
  while (niv!='{');

  fread(&c, 1, 1, fich);
  for(y=0; y<plan.niveheight; y++)
    for(x=0; x<plan.nivewidth; x++)
      {
	int params[260];
	int nparams=0;
	niv=c;

	while (niv=='\n' || niv==' ') // skip the white space (newlines and spaces)
	  fread(&niv, 1, 1, fich);

	fread(&c, 1, 1, fich); // the parametres
	while (c=='[') {
	  fscanf(fich, "%i]", &params[nparams]);
	  nparams++; // maybe multiple?
	  fread(&c, 1, 1, fich);
	}

	plan.element[x][y].elem=sol;
	plan.element[x][y].type=LIBRE;
	plan.element[x][y].anim=0;
	plan.element[x][y].frame=0;
	plan.element[x][y].sol=0;
	plan.element[x][y].fixe=0;
	for (i=0; i<nparams; i++)
	  plan.element[x][y].params[i]=params[i];
	plan.element[x][y].nparams=nparams;

	switch (niv)
	  {
	  case '_' : // space
	    {
	      if (!nparams)
		{
		  //x		  if (rand()>0.9*RAND_MAX)
		  if (rand() > SPACE_VARIATIONS*RAND_MAX) // sometimes some variations from anim[1]
		    plan.element[x][y].anim = 1;
		  plan.element[x][y].frame = aleat(sol->anims[plan.element[x][y].anim]->nframes);
		}
	      else
		{
		  plan.element[x][y].anim=2;
		  plan.element[x][y].frame=params[0];
		  plan.element[x][y].fixe=1;
		}
	    }break;
	  case '#' : // block
	    {
	      plan.element[x][y].elem=bloc;
	      plan.element[x][y].type=DESTRUCTIBLE;
	      plan.element[x][y].anim=0;
	      plan.element[x][y].sol=1;
	      if (!nparams)
		plan.element[x][y].frame=aleat( bloc->anims[0]->nframes);
	      else {
		plan.element[x][y].frame=params[0];
		plan.element[x][y].fixe=1;}
	    }break;
	  case '+' : // wall
	    {
	      plan.element[x][y].elem=mur;
	      plan.element[x][y].type=INDESTRUCTIBLE;
	      if (!nparams)
		plan.element[x][y].frame=aleat( mur->anims[0]->nframes);
	      else {
		plan.element[x][y].frame=params[0];
		plan.element[x][y].fixe=1;}
	    }break;
	    // insert the secret passages P.K.
	  case '§' : // hidden pasage
	    {
	      plan.element[x][y].elem=mur; //like an ordinary wall  P.K.
	      plan.element[x][y].type=SECRETPASSAGE; // P.K.
	      if (!nparams)
		plan.element[x][y].frame=aleat( mur->anims[0]->nframes);
	      else {
		plan.element[x][y].frame=params[0];
		plan.element[x][y].fixe=1;}
	    }break;
	  case '=' : // tunnel
	    {
	      plan.element[x][y].elem=tunnel;
	      plan.element[x][y].type=TUNNEL;
	      plan.element[x][y].frame=params[0];
	      plan.element[x][y].fixe=-1;
	    }break;
	  case '>' : // one-way
	    {
	      plan.element[x][y].type=SENSUNIQUE;
	      plan.element[x][y].elem=fleche;
	      plan.element[x][y].anim=params[0];
	      plan.element[x][y].sol=1;
	      plan.element[x][y].fixe=-1;
	    }break;
	  case 'T' : // teleport
	    {
	      plan.element[x][y].type=EVENEMENT;
	      plan.element[x][y].sol=1;
	      plan.element[x][y].elem=teleport;
	      plan.element[x][y].fixe=-1;
	    }break;
	  case 'O' : // button
	    {
	      plan.element[x][y].elem=bouton;
	      plan.element[x][y].sol=1;
	      plan.element[x][y].type=EVENEMENT;
	      plan.element[x][y].fixe=-1; // visible
	    }break;
	  case '0' : // invisible button P.K.
	    {
	      plan.element[x][y].elem=bouton; // at first like an ordinary button - to be repaired! P.K.
	      plan.element[x][y].sol=1; //?
	      plan.element[x][y].type=EVENEMENT;
	      plan.element[x][y].fixe=-2; // invisible
	      plan.element[x][y].frame=bouton->anims[0]->nframes-1;
	    }break;
	  case '*' : // fontaine
	    {
	      plan.element[x][y].type=EVENEMENT;
	      plan.element[x][y].sol=1;
	      plan.element[x][y].elem=fontaine;
	      plan.element[x][y].fixe=-1;
	    }break;
	  default :
	    {
	      //x	      erreur("Ce niveau contient des éléments spéciaux. "
	      //x                     "Vous ne pouvez pas l'éditer avec nived", NULL);
	      errormessage(gettext("Ce niveau contient des éléments spéciaux. "
                                   "Vous ne pouvez pas l'éditer avec nived"), NULL);
	      //L	      erreur(gettext("Nive contents an invalid element spedification. "
	      //L                     "The editor nived is unable to handle this file."), NULL);
	    }break;
	  }
      }
  
  do // read till the end of the nive array
    fread(&niv, 1, 1, fich);
  while (niv!='}');

  return;
}


void sauveniv(char *nom)
{
  int x, y, i;
  int ncar;
  FILE *fich;
  char *extension = ".spr"; // P.K.

  //x  printf("Sauvegarde du niveau dans: %s...", nom);
  printf(gettext("Sauvegarde du niveau dans: %s..."), nom);
  //L  printf("Saving the nive: %s...", nom);
  fich = fopen(nom, "wb");
  if (fich == NULL) {
    //x    erreur("Impossible d'ouvrir le fichier en écriture", nom);
    errormessage(gettext("Impossible d'ouvrir le fichier en écriture"), nom);
    //L    erreur("Unable to open output file", nom);
  }

  fprintf(fich, "sol: %s%s\n", sol->nom, extension);
  fprintf(fich, "bloc: %s%s\n", bloc->nom); 
  fprintf(fich, "mur: %s%s\n", mur->nom);
  fprintf(fich, "fleche: %s%s\n", fleche->nom); 
  fprintf(fich, "teleport: %s%s\n", teleport->nom); 
  fprintf(fich, "tunnel: %s%s\n", tunnel->nom);
  fprintf(fich, "bouton: %s%s\n", bouton->nom);
  fprintf(fich, "fontaine: %s%s\n", fontaine->nom);

  fputc('\n', fich);

  fprintf(fich, "REGEN=%i\n", REGEN);
  //x  fprintf(fich, "BONUSFREQ=%i\n", BONUSFREQ);
  fprintf(fich, "BONUSFREQ=%g\n", bonus_freq); // P.K. enable float number
  fprintf(fich, "NBOMBES=%i\n", NBOMBES);
  fprintf(fich, "REBOURS=%i\n", REBOURS);

  fputc('\n', fich);

  //#ifdef new_nive_syntax
  fprintf(fich, "XSIZE=%i\n", plan.nivewidth); // P.K. size of the gameplan
  fprintf(fich, "YSIZE=%i\n", plan.niveheight);
  fputc('\n', fich);
  //#endif // new_nive_syntax

  for (i=0; i < numperso; i++) {
    //x    fprintf(fich, "perso[%i]:(%i,%i)\n", i, persopos[i].x, persopos[i].y);
    fprintf(fich, "perso[%i]:(%i,%i)\n", i, perso[i].pos.x, perso[i].pos.y);
  }
  
  fprintf(fich, "\n\n{\n\n");

  for(y=0; y < plan.niveheight; y++) {
    for(x=0; x < plan.nivewidth; x++) {
      ncar = 6-1;
      //xx      printf("x=%i, y=%i\n", plan.niveheight, plan.nivewidth);
      switch (plan.element[x][y].type) {
	case LIBRE :
	  {
	    fputc('_', fich);
	    ncar--;
	    if (plan.element[x][y].fixe)
	      ncar -= fprintf(fich, "[%i]", plan.element[x][y].frame);
	  }break;
	case DESTRUCTIBLE :
	  {
	    fputc('#', fich);
	    ncar--;
	    if (plan.element[x][y].fixe)
	      ncar -= fprintf(fich, "[%i]", plan.element[x][y].frame);
	  }break;
	case INDESTRUCTIBLE :
	  {
	    fputc('+', fich);
	    ncar--;
	    if (plan.element[x][y].fixe)
	      ncar -= fprintf(fich, "[%i]", plan.element[x][y].frame);
	  }break;
	case SECRETPASSAGE : // P.K.
	  {
	    fputc('§', fich);
	    ncar--;
	    if (plan.element[x][y].fixe)
	      ncar -= fprintf(fich, "[%i]", plan.element[x][y].frame);
	  }break;
	case TUNNEL :
	  {
	    fputc('=', fich);
	    ncar--;
	    ncar -= fprintf(fich, "[%i]", plan.element[x][y].frame);
	  }break;
	case SENSUNIQUE :
	  {
	    fputc('>', fich);
	    ncar--;
	    ncar -= fprintf(fich, "[%i]", plan.element[x][y].anim);
	  }break;
	case EVENEMENT :
	  {
	    if (plan.element[x][y].elem==teleport) {
	      fputc('T', fich);
	      ncar--;
	      for (i=0; i < plan.element[x][y].nparams; i++) {  // there might be no parametres
		ncar -= fprintf(fich, "[%i]", plan.element[x][y].params[i]);
	      }
	      /*
	      i=0;
	      do
		ncar -= fprintf(fich, "[%i]", plan.element[x][y].params[i]);
	      while(++i<plan.element[x][y].nparams);
	      */
	    }
	    else if (plan.element[x][y].elem==bouton) {
	      if (plan.element[x][y].fixe==-2) { // hidden button P.K.
		fputc('0', fich);
	      }
	      else { // visible button P.K.
		fputc('O', fich);
	      }
	      ncar--;
	      for (i=0; i < plan.element[x][y].nparams; i++) {  // there might be no parametres
		ncar -= fprintf(fich, "[%i]", plan.element[x][y].params[i]);
	      }
	      /*
	      i=0;
	      do
		ncar -= fprintf(fich, "[%i]", plan.element[x][y].params[i]);
	      while(++i<plan.element[x][y].nparams);
	      */
	    }
	    else if (plan.element[x][y].elem==fontaine) {
	      fputc('*', fich);
	      ncar--; }
	  }break;
      }

      // spaces between elements
      //x      while (ncar>0) {
      while (ncar>=0) { // at least one
	fputc(' ', fich);
	ncar--; }
    }
    fprintf(fich, "\n\n");
  }

  fprintf(fich, "}\n\n");
  fprintf(fich, legende); // description of the the symbols
  printf("OK\n");

  fclose(fich);
  return;
}


/* where to teleport and what to switch */
/*  void configurevt_(int x, int y) */
/*  { */
/*    int i=0, j; */
/*    Parameter *params = pl[x][y].params; // pointer */
/*    //x  int nparams=pl[x][y].nparams; */
/*    int *nparams = &(pl[x][y].nparams); // pointer */
/*    int xs[260], ys[260]; // Dynamic allocation !! */
/*    SDL_Event evt; */
/*    int n; */
/*    int clx, cly; */


/*    if (x>=nivewidth)  // out of range */
/*      return; */


/*    //x  for (i=0; i<nparams; i++) { // tables of coordinates (not resizable) */
/*    for (i=0; i < *nparams; i++) { // tables of coordinates (not resizable) */
/*      xs[i]=pl[x][y].params[i]%nivewidth; */
/*      ys[i]=pl[x][y].params[i]/nivewidth; */
/*    } */

/*    do { */
/*      blitsprit(nived, 0, 2, x*32, y*32); // show the mark */
/*      //x    for (j=0; j<nparams; j++) { // show the already defined parametres */
/*      for (j=0; j < *nparams; j++) { // show the already defined parametres */
/*        dessinecase(xs[j], ys[j]); */
/*        blitsprit(nived, 1, ((i+100)/5)%nived->anims[1]->nframes, xs[j]*32, ys[j]*32); */
/*      } */
/*      SDL_Flip(ecran); */
/*      SDL_PumpEvents(); */

/*      if (SDL_PollEvent(&evt)) { */
/*        if (evt.type==SDL_MOUSEBUTTONDOWN) { */
/*  	if (evt.button.button==1 && evt.button.x<(nivewidth+1)*32) { */
/*  	  n=0; */
/*  	  clx=evt.button.x/32; */
/*  	  cly=evt.button.y/32; */
/*  	  do {  */
/*  	    (SDL_WaitEvent(&evt)); */
/*  	  } */
/*  	  while (evt.type!=SDL_MOUSEBUTTONUP); */
		
/*  	  //x	  while (n<nparams) { // look it up among the parametres */
/*  	  while (n < *nparams) { // look it up among the parametres */
/*  	    if (xs[n]==clx && ys[n]==cly) break; */
/*  	    n++; */
/*  	  } */

/*  	  //x	  if (n<nparams) /* Suppression d'un paramètre */ 
/*  	  if (n<*nparams) /* Suppression d'un paramètre */ 
/*  	    { */
/*  	      dessinecase(clx, cly); */
/*  	      //x	      while (n<nparams-1) { */
/*  	      while (n < (*nparams)-1) { */
/*  		params[n]=params[n+1]; */
/*  		xs[n]=xs[n+1]; */
/*  		ys[n]=ys[n+1]; */
/*  		n++; */
/*  	      } */
/*  	      //x	      nparams--; */
/*  	      (*nparams)--; */
/*  	      //x pl[x][y].nparams--; */
/*  	      // Do NOT free memory, it will be reallocated by the next addition of parametres */
/*  	      //?	      params = (Parameter *)realloc(params, sizeof(Parameter)*(*nparams)); // reallocate memory P.K. */
/*  	    } */
/*  	  //x	  else if (n==nparams) /* Ajout d'un paramètre */ 
/*  	  else if (n == *nparams) /* Ajout d'un paramètre */ 
/*  	    { */
/*  	      //x	      nparams++; pl[x][y].nparams++; */
/*  	      (*nparams)++; */
/*  	      dessinecase(clx, cly); */
/*  	      params = (Parameter *)realloc(params, sizeof(Parameter)*(*nparams)); // reallocate memory P.K. */
/*  	      params[n] = cly*nivewidth + clx; */
/*  	      xs[n] = clx; */
/*  	      ys[n] = cly; */
/*  	    } */
/*  	} */
/*  	else // if (evt.button.button==3) */
/*  	  i=-1; // this is the last loop */
/*        } */
/*        else if (evt.type==SDL_KEYDOWN) */
/*  	if (evt.key.keysym.sym==SDLK_y) */
/*  	  { */
/*  	    for (j=0; j<nparamsbuf; j++) */
/*  	      { */
/*  		params[j]=paramsbuf[j]; */
/*  		xs[j]=paramsbuf[j]%nivewidth; */
/*  		ys[j]=paramsbuf[j]/nivewidth; */
/*  	      } */
/*  	    //x	    nparams=pl[x][y].nparams=nparamsbuf; */
/*  	    *nparams = pl[x][y].nparams = nparamsbuf; */
/*  	  } */
/*      } */
/*      i++; */
/*    } */
/*    while (i); */

/*    paramsbuf = params; */
/*    //x  nparamsbuf=nparams; */
/*    nparamsbuf = *nparams; */

/*    rdplateau(); */
/*    return; */
/*  } */


void configurevt(int x, int y)
{
  int i=0, j;
  //x  int nparams=pl[x][y].nparams;
  //x static int xs[MAXNIVEWIDTH], ys[MAXNIVEHEIGHT];           // Dynamic allocation !!
  SDL_Event evt;
  int n;
  int clx, cly;    // position where clicked

  if (x >= plan.nivewidth)  // out of range
    return;

  //x  for (i=0; i<nparams; i++) { // tables of coordinates (not resizable)
  //x    xs[i]=pl[x][y].params[i]%nivewidth;
  //x    ys[i]=pl[x][y].params[i]/nivewidth;
  //x  }

  do {
    blitsprit(nived, 0, 2, x*32, y*32); // show the mark
    //x    for (j=0; j<nparams; j++) { // show the already defined parametres
    for (j=0; j < plan.element[x][y].nparams; j++) { // show the already defined parametres
      //x      dessinecase(xs[j], ys[j]);
      dessinecase_nived(plan.element[x][y].params[j]%plan.nivewidth, plan.element[x][y].params[j]/plan.nivewidth);
      //x      blitsprit(nived, 1, ((i+100)/5)%nived->anims[1]->nframes, xs[j]*32, ys[j]*32);
      blitsprit(nived, 1, ((i+100)/5)%nived->anims[1]->nframes, (plan.element[x][y].params[j]%plan.nivewidth)*32, plan.element[x][y].params[j]/plan.nivewidth*32);
    }
    SDL_Flip(ecran);
    SDL_PumpEvents(); // here it might be done a bit faster

    if (SDL_PollEvent(&evt)) {
      if (evt.type == SDL_MOUSEBUTTONDOWN) {
	//x	if (evt.button.button==1 && evt.button.x < (nivewidth+1)*32) {
	if (evt.button.button==1 && (evt.button.x-resolution.x_offset) < (plan.nivewidth+1)*32) {
	  n=0;
	  //x	  clx=evt.button.x/32;
	  clx = (evt.button.x-resolution.x_offset)/32;
	  //x	  cly=evt.button.y/32;
	  cly = (evt.button.y-resolution.y_offset)/32;
	  do { 
	    (SDL_WaitEvent(&evt));
	  } while (evt.type!=SDL_MOUSEBUTTONUP);
		
	  //x	  while (n<nparams) { // look it up among the parametres
	  while (n < plan.element[x][y].nparams) { // look it up among the parametres
	    //x	    if (xs[n]==clx && ys[n]==cly) break;
	    if ((plan.element[x][y].params[n]%plan.nivewidth) == clx && (plan.element[x][y].params[n]/plan.nivewidth) == cly) break;
	    n++;
	  }

	  //x	  if (n<nparams) /* Suppression d'un paramètre */
	  if (n < plan.element[x][y].nparams) /* Suppression d'un paramètre */
	    {
	      dessinecase_nived(clx, cly);
	      //x	      while (n<nparams-1) {
	      while (n < (plan.element[x][y].nparams)-1) {
		//x		params[n]=params[n+1];
		plan.element[x][y].params[n]=plan.element[x][y].params[n+1];
		//x		xs[n]=xs[n+1];
		//x		ys[n]=ys[n+1];
		n++;
	      }
	      //x	      nparams--;
	      (plan.element[x][y].nparams)--;
	      //x plan.element[x][y].nparams--;
	      // Free memory, it will be reallocated by the next addition of parametres
	      plan.element[x][y].params = (Parameter *)realloc(plan.element[x][y].params, sizeof(Parameter)*(plan.element[x][y].nparams)); // reallocate memory P.K.
	    }
	  //x	  else if (n==nparams) /* Ajout d'un paramètre */
	  else if (n == plan.element[x][y].nparams) /* Ajout d'un paramètre */
	    {
	      //x	      nparams++; plan.element[x][y].nparams++;
	      (plan.element[x][y].nparams)++;
	      dessinecase_nived(clx, cly);
	      //x	      params = (Parameter *)realloc(params, sizeof(Parameter)*(*nparams)); // reallocate memory P.K.
	      plan.element[x][y].params = (Parameter *) realloc(plan.element[x][y].params, sizeof(Parameter)*(plan.element[x][y].nparams)); // reallocate memory P.K.
	      //x	      params[n] = cly*nivewidth + clx;
	      plan.element[x][y].params[n] = cly*plan.nivewidth + clx;
	      //x	      xs[n] = clx;
	      //x	      ys[n] = cly;
	    }
	}
	else // if (evt.button.button==3)
	  i=-1; // this is the last loop
      }
      else if (evt.type == SDL_KEYDOWN) {
	if (evt.key.keysym.sym == SDLK_y) {
	  //x	    nparams=pl[x][y].nparams=nparamsbuf;
	  plan.element[x][y].nparams = nparamsbuf; // copy the number of parametres
	  free(plan.element[x][y].params); // free the memory P.K.
          plan.element[x][y].params = (Parameter *) malloc(sizeof(Parameter)*(plan.element[x][y].nparams)); // allocate memory P.K.
	  for (j=0; j < nparamsbuf; j++) {
	    //x		params[j]=paramsbuf[j];
	    plan.element[x][y].params[j] = paramsbuf[j]; // copy the parametres
	    //x	    xs[j]=paramsbuf[j]%nivewidth;
	    //x	    ys[j]=paramsbuf[j]/nivewidth;
	  }
	}
      }
    }
    i++;
  } while (i);
  //x  paramsbuf = params;
  paramsbuf = plan.element[x][y].params;
  //x  nparamsbuf=nparams;
  nparamsbuf = plan.element[x][y].nparams;

  rdplateau_nived();
  return;
}


/* the next element variant */
void tournelem(int x, int y)
{
  if (plan.element[x][y].fixe==0 && plan.element[x][y].type!=LIBRE) { // random motive
    plan.element[x][y].fixe=1; // make it fixed
  }
  else if (plan.element[x][y].type==SENSUNIQUE) {
    plan.element[x][y].anim++;
    if (plan.element[x][y].anim==plan.element[x][y].elem->nanims) {
	plan.element[x][y].anim=0;
    }
  }
  else if (plan.element[x][y].type!=EVENEMENT && plan.element[x][y].type!=LIBRE) {
    plan.element[x][y].frame++;
    if (plan.element[x][y].frame==plan.element[x][y].elem->anims[plan.element[x][y].anim]->nframes) {
      if (plan.element[x][y].fixe==1) // if it was fixed, now make random
	plan.element[x][y].fixe=0;
      plan.element[x][y].frame=0;
    }
  }
  else if (plan.element[x][y].elem==teleport) {
    SDL_Event evt;
    do (SDL_WaitEvent(&evt));
    while (evt.type!=SDL_MOUSEBUTTONUP);
    configurevt(x, y);
  }
  else if (plan.element[x][y].elem==bouton) { // P.K.
    if (x==(plan.nivewidth)) {
      plan.element[x][y].frame+=2; // visible or hidden, not switched off
      plan.element[x][y].fixe=-2; // invisible
      if (plan.element[x][y].frame>=plan.element[x][y].elem->anims[plan.element[x][y].anim]->nframes) {
        plan.element[x][y].frame=0; // button again visible
	plan.element[x][y].fixe=-1; // visible
      }
    }
    else {
      SDL_Event evt;
      do (SDL_WaitEvent(&evt));
      while (evt.type!=SDL_MOUSEBUTTONUP);
      configurevt(x, y);
    }
  }

  return;
}


/* choose the number of the person */
void persodepart(void)
{
  int i;
  SDL_Event evt;
  int nactif=0;
  int encore=1;
  int x, y;
  do
    {
      for (i=0; i < numperso; i++)
	{
	  //x	  blitsprit(nb[i], 0, 1, persopos[i].x*32, persopos[i].y*32);
	  blitsprit(nb[i], 0, 1, perso[i].pos.x*32, perso[i].pos.y*32);
	  blitsprit(sol, 0, 0, (plan.nivewidth+1)*32, i*32);
	  blitsprit(nb[i], 0, 1, (plan.nivewidth+1)*32, i*32);
	}
      blitsprit(nived, 0, 1, (plan.nivewidth+1)*32, nactif*32);
      SDL_Flip(ecran);
      SDL_WaitEvent(&evt);
      if (evt.type==SDL_MOUSEBUTTONDOWN)
	{
	  //x	  x=evt.button.x/32;
	  x = (evt.button.x-resolution.x_offset)/32;
	  //x	  y=evt.button.y/32;
	  y = (evt.button.y-resolution.y_offset)/32;
	  if (evt.button.button==3)
	    encore=0;
	  else if (x == (plan.nivewidth+1) && y < N_CHOIX)
	    nactif=y;
	  else if (x<plan.nivewidth && plan.element[x][y].type==LIBRE) {
	    //x	    dessinecase(persopos[nactif].x, persopos[nactif].y);
	    dessinecase_nived(perso[nactif].pos.x, perso[nactif].pos.y);
	    //x	    persopos[nactif].x=x;
	    //x	    persopos[nactif].y=y;
	    perso[nactif].pos.x=x;
	    perso[nactif].pos.y=y;
	  }
	}
    }
  while (encore);
  
  rdplateau_nived();
  return;
}


/* select the next theme of the nive */
void changegraphs(void)
{
  int i, x, y;
  char nom[MAX_STRING_LENGTH];
  FILE *chgraphs, *svg;

  videcran();
  sprintf(nom, "nived~");
  sauveniv(nom);
  detruit_sprites();

  nived=charge_sprite("nived.spr", 0);
  sprintf(nom, "%s/electr.g", prefixeniv);
  if (strcmp(graphtype, nom))
    strcpy(graphtype, nom);
  else
    sprintf(graphtype, "%s/grotte.g", prefixeniv);
  chgraphs=fopen(graphtype, "rb");
  if (chgraphs==NULL) {
    //x    erreur("Impossible d'ouvrir le fichier", graphtype);
    errormessage(gettext("Impossible d'ouvrir le fichier"), graphtype);
  }
  charge_graphs(chgraphs);
  fclose(chgraphs);

  sprintf(nom, "nived~");
  svg=fopen(nom, "rb");
  freeplan(&plan);  // P.K.
  chargeniv_dynamic(svg, &plan, 0, 0, 0);
  //x  chargeniv_(svg, 0);
  fclose(svg);

  initliste();
  for (i=0; i < NPERSO; i++) {
    sprintf(nom, "%i.spr", i+1);
    nb[i]=charge_sprite(nom, decl);
  }
  elemactif.elem=sol;
  elemactif.type=LIBRE;
  elemactif.anim=0;
  elemactif.frame=0;
  elemactif.bombe=0;
  elemactif.sol=0;
  elemactif.fixe=0; // ??
  elemactif.elemsg=NULL;
  elemactif.params=NULL;
  elemactif.nparams=0;

  for (y=0; y<plan.niveheight; y++)
    for (x=0; x<plan.nivewidth; x++) {
      plan.element[x][y].anim %= plan.element[x][y].elem->nanims;
      plan.element[x][y].frame %= plan.element[x][y].elem->anims[plan.element[x][y].anim]->nframes;
    }

  rdplateau_nived();
  return;
}


/* elements in the nive */
void cliccase(int x, int y, int b)
{
  int i;

  if (b==1 && plan.element[x][y].type==LIBRE) // left button
    {
      plan.element[x][y].elem=elemactif.elem;
      plan.element[x][y].type=elemactif.type;
      plan.element[x][y].anim=elemactif.anim;
      plan.element[x][y].frame=elemactif.frame;
      plan.element[x][y].bombe=elemactif.bombe;
      plan.element[x][y].sol=elemactif.sol;
      plan.element[x][y].fixe=elemactif.fixe;
      plan.element[x][y].elemsg=elemactif.elemsg;
      plan.element[x][y].nparams=elemactif.nparams; // is it correct? !!

      if (plan.element[x][y].params != NULL) { // fistr free the memory if used
	free(plan.element[x][y].params);
      }

      if (plan.element[x][y].nparams > 0) {
        plan.element[x][y].params = (Parameter *) malloc(sizeof(Parameter)*plan.element[x][y].nparams); // allocate new memory
	for (i=0; i < plan.element[x][y].nparams; i++) {
          plan.element[x][y].params[i]=elemactif.params[i]; // copy the params
	}
      }
      else {
        plan.element[x][y].params = NULL; // don't forget to initialize the NULL pointer
      }

    }
  else if (b==3) // right button = erase
    {
      plan.element[x][y].elem=sol;
      plan.element[x][y].type=LIBRE;
      plan.element[x][y].anim=0;
      //x      if (rand()>0.9*RAND_MAX)
      if (rand() > SPACE_VARIATIONS*RAND_MAX) // sometimes some variations from anim[1]
	plan.element[x][y].anim = 1;
      plan.element[x][y].frame = aleat(sol->anims[plan.element[x][y].anim]->nframes);
      plan.element[x][y].sol=0;
      plan.element[x][y].fixe=0;
      // free the allocated memory for parametres
      plan.element[x][y].nparams = 0;
      free(plan.element[x][y].params);
      nparamsbuf = 0;
      paramsbuf = NULL;
    }
  else if (b==2) { // P.K. midle button make it to hidden passage
    if (plan.element[x][y].elem==mur && plan.element[x][y].type==INDESTRUCTIBLE) { // switch to secret passage
      plan.element[x][y].type=SECRETPASSAGE;
    }
    else if (plan.element[x][y].elem==mur && plan.element[x][y].type==SECRETPASSAGE) { // switch to an ordiary wall
      plan.element[x][y].type=INDESTRUCTIBLE;
    }
  }
  else {
    tournelem(x, y);
  }
  dessinecase_nived(x, y);

  return;
}


/* choose within the element list */
void clicchoix(int x, int y, int b)
{
  if (plan.element[x][y].elem==NULL)
    return;

  if (elemactif.elem==plan.element[x][y].elem) // next variant
    tournelem(x, y);
  elemactif.elem=plan.element[x][y].elem;
  elemactif.type=plan.element[x][y].type;
  elemactif.anim=plan.element[x][y].anim;
  elemactif.frame=plan.element[x][y].frame;
  elemactif.bombe=plan.element[x][y].bombe;
  elemactif.sol=plan.element[x][y].sol;
  elemactif.fixe=plan.element[x][y].fixe;
  elemactif.elemsg=plan.element[x][y].elemsg;
  elemactif.params=plan.element[x][y].params;
  elemactif.nparams=plan.element[x][y].nparams;
  actif.x=x;
  actif.y=y;

  return;
}


/* where was the click? */
int clic(int x, int y, int b)
{
  if (x<32*plan.nivewidth) { // in the nive
    cliccase(x/32, y/32, b);
  }
  //x  else if (512+32<=x && x<512+64 && y<448)
  //xx  else if (32*nivewidth+32<=x && x<32*nivewidth+64 && y<(niveheight-1)*32) {
  else if (32*(plan.nivewidth+1) <= x && x < 32*(plan.nivewidth+2) && y < (plan.niveheight-1)*32) {
    clicchoix(x/32-1, y/32, b); // choice of the elements
  }
  //x  else if (17*32<=x && x<18*32 && y>=14*32)
  else if ((plan.nivewidth+1)*32<=x && x<(plan.nivewidth+2)*32 && (plan.niveheight-1)*32<=y && y<=plan.niveheight*32) {
    persodepart(); // placement of characters
  }
  //x  else if (18*32<=x && x<19*32 && y>=14*32)
  else if ((plan.nivewidth+2)*32<=x && x<(plan.nivewidth+3)*32 && (plan.niveheight-1)*32<=y && y<=plan.niveheight*32) {
    changegraphs(); // change the theme
  }
  return 0;
}

/* initialization of the nived menuliste */
void initliste(void)
{
  int i;
  Sprite *elemliste[50];

  /* What is in the list */
  elemliste[0]=sol;
  elemliste[1]=bloc;
  elemliste[2]=mur;
  elemliste[3]=fleche;
  elemliste[4]=teleport;
  elemliste[5]=tunnel;
  elemliste[6]=bouton;
  elemliste[7]=fontaine;

  /* Initialize the list elements */
  for (i=0; i < N_CHOIX; i++) { // all wariants in the menu list
    plan.element[plan.nivewidth][i].elem=elemliste[i];
    plan.element[plan.nivewidth][i].anim=0;
    plan.element[plan.nivewidth][i].frame=0;
    plan.element[plan.nivewidth][i].fixe=-1;
    plan.element[plan.nivewidth][i].type=LIBRE;
    plan.element[plan.nivewidth][i].sol=0;
    plan.element[plan.nivewidth][i].nparams=0;
    plan.element[plan.nivewidth][i].params = NULL;
    //x   pl[nivewidth][i].params = (Parameter *) malloc(sizeof(Parameter));
    //x    pl[nivewidth][i].params[0]=0;
  }
  
  plan.element[plan.nivewidth][0].fixe=0;
  plan.element[plan.nivewidth][1].type=DESTRUCTIBLE;
  plan.element[plan.nivewidth][1].sol=1;
  plan.element[plan.nivewidth][1].fixe=0;
  plan.element[plan.nivewidth][2].type=INDESTRUCTIBLE;
  plan.element[plan.nivewidth][2].fixe=0;
  plan.element[plan.nivewidth][3].type=SENSUNIQUE;
  plan.element[plan.nivewidth][3].sol=1;
  plan.element[plan.nivewidth][4].type=EVENEMENT;
  plan.element[plan.nivewidth][4].sol=1;
  //  pl[nivewidth][4].nparams=1;
  plan.element[plan.nivewidth][5].type=TUNNEL;
  plan.element[plan.nivewidth][6].type=EVENEMENT;
  plan.element[plan.nivewidth][6].sol=1;
  //  pl[nivewidth][6].nparams=1;
  plan.element[plan.nivewidth][7].type=EVENEMENT;
  plan.element[plan.nivewidth][7].sol=1;
  
  return;
}  


//x void creeniveau(void)
void creeniveau(void)
{
  int i, x, y;
  FILE *fich;
  //xx  Plan plan; // game plan

  /* moved to open_nive
  // enter size of the new nive
  do {
    printf(gettext("Enter x-size of the nive: ")); // P.K. lang
    scanf("%i", &nivewidth);
  } while (nivewidth < 1 || nivewidth > MAX_NIVEWIDTH); // not too small or large
  do {
    printf(gettext("Enter y-size of the nive: ")); // P.K. lang
    scanf("%i", &niveheight);
  } while (niveheight < 9 || niveheight > MAX_NIVEHEIGHT); // not too small or large
  */

  // Allocate memory for the game plan and the menubar
  //x  allocplan(&plan);
  plan.nivewidth += 2;
  allocplan(&plan);
  plan.nivewidth -= 2;

  sprintf(graphtype, "%s/electr.g", prefixeniv);
  fich = fopen(graphtype, "rb");
  charge_graphs(fich);
  fclose(fich);

  for (y=0; y < plan.niveheight; y++)
    for (x=0; x < plan.nivewidth; x++) {	
      plan.element[x][y].elem=sol;
      plan.element[x][y].type=LIBRE;
      plan.element[x][y].anim=0;
      //x      if (rand()>0.9*RAND_MAX)
      if (rand() > SPACE_VARIATIONS*RAND_MAX) // sometimes some variations from anim[1]
	plan.element[x][y].anim = 1;
      plan.element[x][y].frame = aleat(sol->anims[plan.element[x][y].anim]->nframes);
      plan.element[x][y].sol=0;
      plan.element[x][y].fixe=0;
      plan.element[x][y].elemsg=NULL;
      plan.element[x][y].params=NULL;
      plan.element[x][y].nparams=0;
    }

  for (i=0; i<numperso; i++) {
    //x    persopos[i].x=0;
    //x    persopos[i].y=0;
    perso[i].pos.x=0;
    perso[i].pos.y=0;
  }

  REGEN=5;
  //x  BONUSFREQ=2; P.K.
  bonus_freq = 2.0;
  NBOMBES=20;
  REBOURS=90;
  return;
}


void initedite(void)
{
  //x  FILE *niveau; // move to open_nive
  int i;
  //  char nomniveau[MAX_STRING_LENGTH];  // moved to open_nive
  char nom[MAX_STRING_LENGTH];
  compteur=0;          // counter
  encore=1;            // to be repeated

  /* moved to open_nive
  strcpy(nomniveau, niv);
  */
  videcran();

  /* moved to open_nive
  //  printf("Ouverture du niveau: %s\n", nomniveau);
  printf(gettext("Ouverture du niveau: %s\n"), nomniveau); //P.K.
  //L  printf("Opening the nive file: %s\n", nomniveau);
  niveau = fopen(nomniveau, "rb");
  if (niveau==NULL) {
    pl = creeniveau();
    sauveniv(niv);
  }
  else {
    charge_graphs(niveau);
    pl = chargeniv_dynamic(niveau, 1, 0, 0, &nivewidth, &niveheight);
    //x      chargeniv_(niveau, 1);
    fclose(niveau);
    if (!strcmp(sol->nom, "circuit.spr"))
      sprintf(graphtype, "%s/electr.g", prefixeniv);
    else
      sprintf(graphtype, "%s/grotte.g", prefixeniv);
  }
  */

  initliste();

  for (i=0; i < NPERSO; i++) {
    sprintf(nom, "%i.spr", i+1);
    nb[i]=charge_sprite(nom, decl);
  }
  rdplateau_nived();
  SDL_Flip(ecran);
  
  elemactif.elem=sol;
  elemactif.type=LIBRE;
  elemactif.anim=0;
  elemactif.frame=0;
  elemactif.bombe=0;
  elemactif.sol=0;
  elemactif.fixe=0;
  elemactif.elemsg=NULL;
  elemactif.params=NULL;
  elemactif.nparams=0;
  actif.x=plan.nivewidth;
  actif.y=0;

  return;
}


int edite(void)
{
  int x, y, bouton;
  SDL_Event evt;

  initedite();

  do {
    if (compteur<65536) compteur++;
    else compteur=0;

    SDL_WaitEvent(&evt);

    if (evt.type == SDL_MOUSEMOTION) { // faster editing P.K.
      continue;
    }

    if (evt.type == SDL_MOUSEBUTTONDOWN) {
      bouton = evt.button.button;
      //x      x=evt.button.x; y=evt.button.y;
      x = evt.button.x-resolution.x_offset; y=evt.button.y-resolution.y_offset;
      clic(x,y,bouton); 
    } else if (evt.type == SDL_KEYDOWN) {
      if (evt.key.keysym.sym == SDLK_s)
	sauveniv(niv);
    }
    rdicones();
    blitsprit(nived, 0, 1, actif.x*32+32, actif.y*32);

    SDL_Flip(ecran);
  }
  while(encore);

  return 0;
}


/*--Recherche du répertoire d'installation--*/
char * rep_install(char * home)
     // determine the path to data files
{
  char dir[MAX_STRING_LENGTH];
  sprintf (dir, "%s/data/Sprites/citrouille.spr", ".");
  if (fopen(dir, "r")) return "./data";
  sprintf (dir, "%s/data/Sprites/citrouille.spr", "..");
  if (fopen(dir, "r")) return "../data";
  sprintf (dir, "%s/Sprites/citrouille.spr", DIR);
  if (fopen(dir, "r")) return DIR;
  sprintf (dir, "%s/BomberInstinct/data/Sprites/citrouille.spr", home);
  if (fopen(dir, "r")) return strcat(home,"/BomberInstinct/data");
  //x  erreur("Le programme ne peut déterminer son répertoire d'installation.\nVérifiez qu'il est correctement installé",NULL);
  errormessage(gettext("Le programme ne peut déterminer son répertoire d'installation.\nVérifiez qu'il est correctement installé"),NULL);
  //L  erreur("The program was unable to determine the path to data files.\nPlease check if it correctly installed.",NULL);
  return NULL;
}

/* Open the nive file */
int open_nive(void)
{
  FILE *niveau;
  char nomniveau[MAX_STRING_LENGTH];

  // If no name given on the command line, ask for one!
  if (niv[0] == 0) {
    //x    printf("Nom du niveau à ouvrir (*.niv): "); // P.K. lang
    printf(gettext("Nom du niveau à ouvrir (*.niv): ")); // P.K. lang
    //L    printf("Name of the nive file to open (*.niv): ");
    scanf("%s", niv);
  }
  strcpy(nomniveau, niv);

  niveau = fopen(nomniveau, "rb");
  if (niveau == NULL) {
    // enter size of the new nive
    do {
      printf(gettext("Enter x-size of the nive: ")); // P.K. lang
      scanf("%i", &(plan.nivewidth));
    } while (plan.nivewidth < 1 || plan.nivewidth > MAX_NIVEWIDTH); // not too small or large
    do {
      printf(gettext("Enter y-size of the nive: ")); // P.K. lang
      scanf("%i", &(plan.niveheight));
    } while (plan.niveheight < 9 || plan.niveheight > MAX_NIVEHEIGHT); // not too small or large

    init_sdl_nived();
    nived = charge_sprite("nived.spr", 0);

    creeniveau();
    sauveniv(niv);

    // set the plan size
    resolution.plan_width = 32*plan.nivewidth;
    resolution.plan_height = 32*plan.niveheight;
    resolution.x_offset = (resolution.window_width-32*(plan.nivewidth+4))/2;
    resolution.y_offset = (resolution.window_height-32*plan.niveheight)/2;

  }
  else {
    init_sdl_nived();
    nived = charge_sprite("nived.spr", 0);

    charge_graphs(niveau);
    chargeniv_dynamic(niveau, &plan, 1, 0, 0);
    //x      chargeniv_(niveau, 1);
    fclose(niveau);
    if (!strcmp(sol->nom, "circuit.spr")) {
      sprintf(graphtype, "%s/electr.g", prefixeniv);
    }
    else {
      sprintf(graphtype, "%s/grotte.g", prefixeniv);
    }
  }

  return OK;
}

// usage: nived [+e/-e] [*.niv]
int main(int argc, char **argv)
{
  int i;
  char home[MAX_STRING_LENGTH];
  char repertoire[MAX_STRING_LENGTH];

  /* Various languages localization */
  setlocale (LC_MESSAGES, "");
  bindtextdomain (PACKAGE, LOCALEDIR);
  textdomain (PACKAGE);

  /*#ifndef win32
    strcpy(home,getenv("HOME"));
    #else*/
  sprintf(home, "");
  /*#endif*/

  strcpy(repertoire, rep_install(home));
  //x  printf("Données trouvées dans : %s.\n", repertoire);
  printf(gettext("Données trouvées dans : %s.\n"), repertoire); //P.K.
  //L  printf("Data files are located in : %s.\n", repertoire);

  sprintf(prefixeniv, "%s/Niveaux", repertoire);
  sprintf(prefixespr, "%s/Sprites", repertoire);

  pleinecran=0;
  init_resolution(&resolution);

  tout.x = tout.y = plateau.x = plateau.y = 0;
  //x  tout.h=plateau.h=480;
  tout.h = plateau.h = resolution.plan_height;
  //x  tout.w=640; plateau.w=512;
  tout.w = resolution.window_width;
  plateau.w = resolution.plan_width;
  //x  recdroite.x=512; recdroite.y=0;
  recdroite.x = resolution.plan_width;
  recdroite.y = 0;
  //x  recdroite.w=128; recdroite.h=480;
  recdroite.w = 4*32;
  recdroite.h = resolution.plan_height;

  for (i=1; i<argc; i++)
    {
      if (argv[i][0]=='-') // run nived in a window
	{
	  if (strchr(argv[i], 'e'))
	    pleinecran=0;
	}
      else if (argv[i][0]=='+') // run nived full screen
	{
	  if (strchr(argv[i], 'e'))
	    pleinecran=1;
	}
      else strcpy(niv, argv[i]); // the name of the nive file (*.niv)
    }

  /* Moved to open_nive P.K.
  if (niv[0] == 0) {
    //x    printf("Nom du niveau à ouvrir (*.niv): "); // P.K. lang
    printf(gettext("Nom du niveau à ouvrir (*.niv): ")); // P.K. lang
    //L    printf("Name of the nive file to open (*.niv): ");
    scanf("%s", niv);
  }
  */

  /* moved to open_nive
  init_sdl_nived();
  nived=charge_sprite("nived.spr", 0);
  */

  open_nive();

  SDL_SetEventFilter(filtr_evt);
  //x  printf("Salut !\n");
  printf(gettext("Salut !\n"));
  srand((unsigned int)SDL_GetTicks());
  //x  nived=charge_sprite("nived.spr", 0); // modev to open_nive

  edite();
  
  exit(0);
}
