
/*                  BOMBER INSTINCT               */


/* Copyright © 2000 by Louis Gesbert and TeraSoft */

/*
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */

/*
 *  Contact me at : metagribouille@netcourrier.com.
 *
 *                    +----------------------+
 *        Web site :  |www.bomberinstinct.org|
 *                    +----------------------+
 */

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

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

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

//x #include "main.h" // teporary for "Plateau" type

#include "sprites.h"
#include "pouvoirs.h"
#include "niveaux.h" // P.K.
//xx #include "niveaux2.h"
#include "evenements.h"
#include "options.h"
#include "son.h"
#include "gamelogic.h"
#include "intro.h"

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


/***********************************/
/*-----D é c l a r a t i o n s-----*/
/***********************************/

/*--Variables globales de configuration--*/

/* des options */
Uint32 flags = SDL_HWSURFACE|SDL_HWPALETTE;

/* des fichiers */
//x char repertoire[256]; // path to bi
char repertoire[MAX_STRING_LENGTH]; // path to bi
//x char prefixeniv[256], prefixeimg[256]; // prefix paths
char prefixeniv[MAX_STRING_LENGTH], prefixeimg[MAX_STRING_LENGTH]; // prefix paths
//xchar prefixespr[256], prefixeson[256];
char prefixespr[MAX_STRING_LENGTH], prefixeson[MAX_STRING_LENGTH];

/*--Structures qui servent en continu dans le jeu--*/

//x P.K. Plateau pl[16][15]; /* Toutes les cases qui constituent le niveau */
Plan plan; // dynamic allocated gameplan

//x P.K. Personnage perso[8]; /* Description de l'état des personnages */
Personnage perso[MAX_NPERSO]; /* Description de l'état des personnages */
int nperso = 2; /* réglage du nb de joueurs ds le menu */

//x Coord rscase[2][260]; int nrscase[2]={0,0}; /* Les cases à redessiner */
Coord rscase[2][MAX_NIVEWIDTH*MAX_NIVEHEIGHT+4];
int nrscase[2] = {0,0}; /* Les cases à redessiner */
//x Coord rstunnel[2][260]; int ntunnel[2]={0,0}; /* pareil, mais par-dessus le reste */
Coord rstunnel[2][MAX_NIVEWIDTH*MAX_NIVEHEIGHT+4];
int ntunnel[2] = {0,0}; /* pareil, mais par-dessus le reste */
//x SDL_Rect rsrect[512]; int nrsrect=0; /* Parties de l'écran à mettre à jour */
SDL_Rect rsrect[2*MAX_NIVEWIDTH*MAX_NIVEHEIGHT];
int nrsrect = 0; /* Parties de l'écran à mettre à jour */

int nrs = 0; /* sur quel buffer est le double-buffering */

Anims * anims = NULL; /* Animations à l'écran */
//x Anims * animsfin = NULL; /* On garde un pointeur sur le dernier élément
Anims * animsfin; /* On garde un pointeur sur le dernier élément
			  pour que les animations plus récentes passent par-dessus */

/*--Trucs dont le programme a besoin de se souvenir--*/

char **spritliste; 
SDL_Surface * bande;
SDL_Surface * fondecran;
SDL_Surface * txtmodesjeu[NMODES];
//x P.K.int score[8];
int score[MAX_NPERSO];
int enpause = 0;

/*--Entrées/Sorties--*/

SDL_Surface *ecran;
Uint8 *clavier;
SDL_Joystick **joystick;
int numjoys;

/*--Variables qui servent en cours de jeu--*/

int compteur;
int encore;

/*--Variables des autres trucs dont on doit se souvenir quelque temps--*/

int danslemenu;
int options;
int choisi = 0;
//x Coord fauxperso[8];
Coord fauxperso[MAX_NPERSO];

/* Resolution variables */
Resolution resolution;

//x const int dx[4]={ 0, 0,-1, 1}; // moved to common.c P.K.
/* Donne le déplacement en x à partir de la direction */
//x const int dy[4]={-1, 1, 0, 0};
/* Donne le déplacement en y à partir de la direction */


/********************************/
/*-------F o n c t i o n s------*/
/********************************/

/*--Initialiser SDL--*/
int init_sdl(void)
{
  Uint32 params;
  SDL_Surface *icone;
  //x  char chemin[256], titre[256]; // P.K.
  char chemin[MAX_STRING_LENGTH], titre[MAX_STRING_LENGTH];
  char resolutionstring[MAX_STRING_LENGTH];
  int ok;

  params = avecson ? SDL_INIT_VIDEO|SDL_INIT_AUDIO : SDL_INIT_VIDEO;
  if (avecjoy) params |= SDL_INIT_JOYSTICK;
  
  if ( SDL_Init(params) < 0 ) {
    printf(gettext("Impossible d'initialiser SDL: %s\n"), SDL_GetError());
    exit(1);
  }
  if (avecjoy) {
    numjoys=SDL_NumJoysticks();
    printf(gettext("%i joysticks détectés: support %s.\n"), numjoys, numjoys>0 ? "activé" : "désactivé");
  }
  else {
    numjoys=0;
    printf(gettext("Support du joystick désactivé.\n"));
  }

  sprintf(titre, "Bomber Instinct - v%s", VERSION);
  SDL_WM_SetCaption(titre, "BomberInstinct");
  sprintf(chemin, "%s/icone.bmp", prefixeimg);
  icone = SDL_LoadBMP(chemin);
  SDL_SetColorKey(icone, SDL_SRCCOLORKEY, 0);
  SDL_WM_SetIcon(icone, NULL);
  SDL_FreeSurface(icone);

  if (dblebuf) {
    flags |= SDL_DOUBLEBUF;
  }
  params = pleinecran ? flags|SDL_FULLSCREEN : flags;

  //x  ok=SDL_VideoModeOK(640, 480, 8, params);
  ok = SDL_VideoModeOK(resolution.window_width, resolution.window_height, 8, params);
  if (!ok) {
    errormessage("Le mode vidéo requis n'est pas disponible", resolutionstring);
  }
#ifdef DEBUG
  else if (ok!=8) {
    printf("Impossible de passer en mode couleurs 8 bits.\n");
    printf("Le jeu tournera, mais en émulation donc plus lentement.\n"); }
#endif
  //x  ecran = SDL_SetVideoMode(640, 480, 8, params);
  ecran = SDL_SetVideoMode(resolution.window_width, resolution.window_height, 8, params);
  if ( ecran == NULL ) {
    printf("Impossible de choisir le mode 640*480 8 bits!\n%s\n", SDL_GetError());
    return 1;
  }
  if ((ecran->flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF) {
    dblebuf = 1;
    printf("Double buffering: activé.\n");
  }
  else if (dblebuf<2) {
    dblebuf = 0;
    printf("Double buffering: désactivé.\n");
  }
  else {
    dblebuf = 1;
  }

  atexit(SDL_Quit);
  atexit(SDL_CloseAudio);
  SDL_EventState(SDL_APPMOUSEFOCUS | SDL_MOUSEBUTTONDOWN | SDL_MOUSEBUTTONUP | SDL_MOUSEMOTION | SDL_SYSWMEVENT, SDL_IGNORE);
  SDL_EnableKeyRepeat(0,0);
  SDL_ShowCursor(0);
  return 0;
}


/*--Initialisation des joysticks--*/
void initjoy(void)
{
  int i;

  joystick=(SDL_Joystick **)calloc(sizeof(SDL_Joystick *), numjoys);
  for (i=0; i<numjoys; i++) {
    joystick[i] = SDL_JoystickOpen(i);
  }
  return;
}


/*--Quitte avec un message d'erreur--*/
/*
void erreur_(char *message, char *param)
{
  printf ("\nErreur :\n%s", message);
  if (param) printf(" : %s", param);
  printf (".\n%s\n", SDL_GetError());
  exit(0);
}
*/

/*--Message d'information sur les options de démarrage--*/
void msg_info(void)
{
  printf("Bomber Instinct - version %s, by TeraSoft\n", VERSION);
  printf("Syntax : bi [+/-][esmjd]\n");
  printf("\t+\tactivates an attribute\n");
  printf("\t-\tdesactivates an attribute\n");
  printf("\te\tfullscreen mode\n");
  printf("\ts\tsound support\n");
  printf("\tm\tmusic support\n");
  printf("\tj\tjoystick support\n");
  printf("\td\tdouble-buffering (try it if the screen flickers)\n");
  exit(0);
}


/*--Tire un nb aléatoire entre 0 et (max-1)--*/
int aleat(int max)
{
  int num;
  num=(int)(max  *  ((float)rand()) / (RAND_MAX+1.0) );
  return num;
}


/*--Tire un nb aléatoire entre 0 et (max-1)--*/
int aleatfloat(float max)
{
  int num;
  num=(int)(max  *  ((float)rand()) / (RAND_MAX+1.0) );
  return num;
}


/*--Passe de la fenêtre au plein-écran et vice-versa (touche F1)--*/
void passenpleinecran()
{
  SDL_WM_ToggleFullScreen(ecran);

  if (pleinecran) pleinecran=0;
  else pleinecran=1;

  if ((ecran->flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF) 
    dblebuf=1;
  else
    dblebuf=0;

  return;
}


/*--Attend que le délai de boucle principale soit au moins VITESSE pour repartir--*/
int ajustevitesse(void)
{
  static int repart=0;
  int t;

#ifdef DEBUG
  int ecoule=repart ? SDL_GetTicks()-repart+VITESSE : VITESSE-1;
#endif

  do {
    t = SDL_GetTicks();
  } while (t<repart);
  repart = t+VITESSE;

#ifdef DEBUG
  return ecoule;
#else
  return 0;
#endif
}


/*--Met le jeu en pause et assombrit l'écran--*/
void pauseifie(void)
{
  SDL_Event evt;
  paletsg pal;

  while (SDL_PollEvent(&evt)); /* Vider la file d'évènements */

  pal = changepalette(0.8, 0.8, 0.8, 0, 0, 1, ecran->format->palette->ncolors, 10);
  SDL_PauseAudio(1);

  do
    SDL_WaitEvent(&evt);
  while (evt.type != SDL_KEYDOWN || !(SDL_GetAppState()&SDL_APPACTIVE));
  restorepalette(pal, 50);
  SDL_PauseAudio(0);
  enpause=0;
  return;
}


/*--Affiche des informations, pose une question--*/
void dialogue(char * texte, int estunequestion)
{
  //  int nlignes=0;
  //x  const char delim[]="#";
  SDL_Event evt;
  paletsg pal;
  //  char * lignes[256];
  SDL_Surface *surf;
  
  //x  surf=SDL_CreateRGBSurface (0, 640, 480, 16, 0,0,0,0); 
  surf = SDL_CreateRGBSurface (0, resolution.window_width, resolution.window_height, 16, 0,0,0,0); 

  while (SDL_PollEvent(&evt)); /* Vider la file d'évènements */
  pal=changepalette(0.8, 0.8, 0.8, 0, 0, 1, ecran->format->palette->ncolors, 10);
  
  //  while (lignes[nlignes]=strtok(texte, &delim)) nlignes++;
  
  XCenteredString(surf, 100,"Bonjour\nComment ça va ?");

  SDL_BlitSurface(surf, NULL, ecran, NULL);

  rafraichit();

  do
    SDL_WaitEvent(&evt);
  while (evt.type!=SDL_KEYDOWN || !(SDL_GetAppState()&SDL_APPACTIVE));
  restorepalette(pal, 50);
  SDL_PauseAudio(0);
  enpause=0;
  return;
}


/*--Met en place des raccourcis-clavier--*/
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_F10)
	exit(0);
      if (evt->key.keysym.sym == SDLK_F1)
	passenpleinecran();
      if (evt->key.keysym.sym == SDLK_PAUSE)
	enpause=1;
    }
  if (evt->type == SDL_ACTIVEEVENT) {
    if (evt->active.type == SDL_APPACTIVE && !evt->active.gain) {
      enpause = 1;
    }
  }
  return 1;
}


/*--Affiche un écran noir--*/
void videcran(void)
{
  //x  SDL_Rect tout={0, 0, 640, 480};
  SDL_Rect tout={0, 0, resolution.window_width, resolution.window_height}; // !! only plan + bande? !!
  SDL_FillRect(ecran, &tout, 0);
  SDL_Flip(ecran);
  if (dblebuf) {
    SDL_FillRect(ecran, &tout, 0);
    SDL_Flip(ecran);
  }
  return;
}


/*--Remet les structures utilisées pendant le jeu à zéro--*/
void reinit(void)
{
  int i;
  Anims * a;
  Evenement * e;
  while (anims) {
      a=anims->suiv; free(anims); anims=a;
  }
  while (evts[AVANT]) {
      e=evts[AVANT]->suiv; free(evts[AVANT]); evts[AVANT]=e;
  }
  while (evts[APRES]) {
      e=evts[APRES]->suiv; free(evts[APRES]); evts[APRES]=e;
  }

  for (i=0; i<NB_PERSO; i++)
    {
      Bombe * pt;
      while (perso[i].bombes) {
	pt=perso[i].bombes->suiv; free(perso[i].bombes); perso[i].bombes=pt;
      }
    }

  danslemenu=0;
  compteur=0;
  encore=1;
  nrsrect=0;
  nrscase[0]=0;
  nrscase[1]=0;
  nrs=0;
  ntunnel[0]=0;
  ntunnel[1]=0;
  decl=0;
  return;
}


/*--Règle les joysticks pour les joueurs--*/
void initjoy_persos()
{
  int i;

  //x P.K.  for (i=0; i<8; i++) {
  for (i=0; i < MAX_NPERSO; i++) {
    perso[i].cmd.joy=NULL;
    if (perso[i].cmd.bas==0 || perso[i].cmd.gauche==0 || perso[i].cmd.droite==0 || perso[i].cmd.b1==0 || perso[i].cmd.b2==0)
      {
	int njoy=perso[i].cmd.haut;
	if (njoy>=numjoys || joystick[njoy]==NULL)
	  printf("Attention : Impossible d'initialiser le joystick %i demandé.\n", njoy);
	else perso[i].cmd.joy=joystick[njoy];
      }
  }
  return;
}


/*--Initialise la structure perso avant chaque partie--*/
void initperso(int n)
{
  perso[n].dir=BAS;
  perso[n].anim=BAS;
  perso[n].mv=0;
  perso[n].statut=VIVANT;
  perso[n].animdroite=REPOS;
  perso[n].energie=100;
  perso[n].lflammes=2;
  perso[n].bombes=NULL;
  perso[n].pos.x=perso[n].pos.y=0;

  if (spritliste[n]) initpouv(n);
  return;
}


/*--Ajoute un rectangle à rafraichir--*/
void rsrectplus(int x, int y, int w, int h)
{
  rsrect[nrsrect].x = x;
  rsrect[nrsrect].y = y;
  rsrect[nrsrect].w = w;
  rsrect[nrsrect].h = h;
  nrsrect++;
  return;
}


/*--Ajoute une case du plateau à redessiner--*/
void rscaseplus(int x, int y)
{
  int i;

  if (plan.element[x][y].type == TUNNEL)
    {
      /* On vérifie que la case n'est pas déjà présente car
       * le blit est le truc le plus lent. */
      for (i = 0; i < ntunnel[nrs]; i++) {
	if (rstunnel[nrs][i].x == x && rstunnel[nrs][i].y == y) {
	  return;
	}
      }
      //x      if (ntunnel[nrs]<260) {
      if (ntunnel[nrs] < MAX_NIVEWIDTH*MAX_NIVEHEIGHT+4) {
	rstunnel[nrs][ntunnel[nrs]].x = x;
	rstunnel[nrs][ntunnel[nrs]].y = y;
	ntunnel[nrs]++;
      }
    }
  else
    {
      /* Idem */
      for (i = 0; i < nrscase[nrs]; i++) {
	if (rscase[nrs][i].x == x && rscase[nrs][i].y == y) {
	  return;
	}
      }
      //x      if (nrscase[nrs] < 260) {
      if (nrscase[nrs] < MAX_NIVEWIDTH*MAX_NIVEHEIGHT+4) {
	rscase[nrs][nrscase[nrs]].x = x;
	rscase[nrs][nrscase[nrs]].y = y;
	nrscase[nrs]++;
      }
    }
  x *= 32;
  y *= 32;
  //x  if ((!dblebuf) && nrsrect < 512)
  if ((!dblebuf) && nrsrect < 2*MAX_NIVEWIDTH*MAX_NIVEHEIGHT)
    {
      for (i = 0; i < nrsrect; i++) {
	if (rsrect[i].x == x && rsrect[i].y == y) {
	  return;
	}
      }
      /* Ça marche parce que tous les rsrect 
       * du plateau font au moins 32*32. */
      rsrect[nrsrect].x = x;
      rsrect[nrsrect].y = y;
      rsrect[nrsrect].w = rsrect[nrsrect].h = 32;
      nrsrect++;
    }
  return;
}


/*--Ajoute une animation à la liste--*/
Anims * animsplus(Sprite *sprite, int anim, int vitesse, int duree, int x, int y)
{
  Anims * nouv;
  nouv = (Anims *)malloc(sizeof(Anims));
  if (anims) {
    anims->prec=nouv;
  }
  else {
    animsfin = nouv;
  }
  nouv->suiv=anims;
  nouv->prec=NULL;
  nouv->pos.x=x;
  nouv->pos.y=y;
  nouv->anim=anim;
  nouv->frame=0;
  nouv->vitesse=vitesse;
  nouv->duree=duree;
  nouv->sprite=sprite;
  if (vitesse) {
    nouv->compteur=0;
  }
  else {
    nouv->compteur=1;
  }
  anims = nouv;
  return
    nouv;
}


/*--Supprime l'animation a (a!=NULL)--*/
void animsmoins(Anims * a)
{
  if (a == NULL) errormessage("Erreur interne 4654132 : veuillez contacter le programmeur", NULL);
  rscaseplus(a->pos.x, a->pos.y);

  if (a->suiv) {
    a->suiv->prec = a->prec;
  }
  if (a->prec) {
    a->prec->suiv = a->suiv;
  }
  else {
    if (a->suiv == NULL) {
      animsfin = NULL;
    }
    anims = a->suiv;
  } /* a est le premier élément de anims. anims doit maintenant pointer sur le suivant */
  free(a);

  return;
}


/*--Redessine une case (x, y) du plateau--*/
void dessinecase(int ncases, Coord *co)
{
  int i;

  for (i = 0; i < ncases; i++) {
    //x    if ((danslemenu || !dblebuf) && nrsrect < 512) {
    if ((danslemenu || !dblebuf) && nrsrect < 2*MAX_NIVEWIDTH*MAX_NIVEHEIGHT) {
      //?      rsrect[nrsrect].x = danslemenu ? 32*(co[i].x+2) : 32*co[i].x;
      rsrect[nrsrect].x = resolution.x_offset + (danslemenu ? 32*(co[i].x+2) : 32*co[i].x);
      //?      rsrect[nrsrect].y = 32*co[i].y;
      rsrect[nrsrect].y = resolution.y_offset + 32*co[i].y;
      rsrect[nrsrect].w = rsrect[nrsrect].h = 32;
      nrsrect++;
    }

    if (danslemenu) {
      //?      SDL_Rect rectorig = {rsrect[nrsrect-1].x-64, rsrect[nrsrect-1].y, 
      //?			   rsrect[nrsrect-1].w   , rsrect[nrsrect-1].h};
      SDL_Rect rectorig = {rsrect[nrsrect-1].x-resolution.x_offset-64, rsrect[nrsrect-1].y-resolution.y_offset, 
			   rsrect[nrsrect-1].w,                        rsrect[nrsrect-1].h};
      SDL_Rect rectdest=rsrect[nrsrect-1];
      //?      SDL_Rect rectdest = {rsrect[nrsrect-1].x+resolution.x_offset, rsrect[nrsrect-1].y+resolution.y_offset, 
      //?			   rsrect[nrsrect-1].w                    , rsrect[nrsrect-1].h};
      SDL_BlitSurface(fondecran, &rectorig, ecran, &rectdest);
    }
    else {
      if (plan.element[co[i].x][co[i].y].sol) {
	blitsprit(sol, 0, 0, co[i].x*32, co[i].y*32);
      }
      blitsprit(plan.element[co[i].x][co[i].y].elem, plan.element[co[i].x][co[i].y].anim,
		plan.element[co[i].x][co[i].y].frame, co[i].x*32, co[i].y*32);
    }
  }
  return;
}


/* A-t-on le droit de se rendre dans la case (x, y)
 * en allant dans la direction dir ? */
int partir(int x, int y, int dir)
{
  int px, py;

  if (dir < 4) {
    px = x - dx[dir];
    py = y - dy[dir];
    //x P.K.    if (px<0 || 15<px || py<0 || 14<py) return 0;
    if (px < 0 || plan.nivewidth <= px || py < 0 || plan.niveheight <= py) {
      return 0;
    }
    else if (plan.element[px][py].type == TUNNEL)
      {
	if (dir == BAS && (plan.element[px][py].frame == 1 || plan.element[px][py].frame == 4 ||
	                   plan.element[px][py].frame == 5 || plan.element[px][py].frame == 9 )) {
	  return 0;
	}
	else if (dir == HAUT && (plan.element[px][py].frame==0 || plan.element[px][py].frame==6 ||
		                 plan.element[px][py].frame==7 || plan.element[px][py].frame==9 )) {
	  return 0;
	}
	else if (dir == GAUCHE && (plan.element[px][py].frame==2 || plan.element[px][py].frame==5 ||
		                   plan.element[px][py].frame==7 || plan.element[px][py].frame==8 )) {
	  return 0;
	}
	else if (dir == DROITE && (plan.element[px][py].frame==3 || plan.element[px][py].frame==4 ||
		                   plan.element[px][py].frame==6 || plan.element[px][py].frame==8 )) {
	  return 0;
	}
      }
    else if (plan.element[px][py].type == SENSUNIQUE)
      {
	if (dir != plan.element[px][py].anim) {
	  return 0;
	}
      } 
  }
  return 1;
}


/*--La case (x,y) est-elle libre ?--*/
/* <=0 -> non libre */
/*   1 -> libre */
/*  -1 -> non libre mais destructible */
/*  -2 -> non libre à cause d'une bombe */
int libre(int x, int y, int dir)
{
  int ret=0;

  //x P.K.  if (x<0 || 15<x || y<0 || 14<y)
  if (x < 0 || plan.nivewidth <= x || y < 0 || plan.niveheight <= y) {
    return 0;
  }
  else if (!partir(x, y, dir)) {
    return 0;
  }
      
  //x  else if (plan.element[x][y].type == LIBRE || plan.element[x][y].type == EVENEMENT || plan.element[x][y].type == CONTINU || plan.element[x][y].type == BONUS) // P.K.
  else if (plan.element[x][y].type == LIBRE || plan.element[x][y].type == EVENEMENT || plan.element[x][y].type == CONTINU || plan.element[x][y].type == BONUS || plan.element[x][y].type == SECRETPASSAGE) {
    ret=1;
  }
  else if (plan.element[x][y].type == DESTRUCTIBLE) {
    return -1;
  }
  else if (plan.element[x][y].type == SENSUNIQUE) {
    if (dir == plan.element[x][y].anim || dir == 4) {
      ret = 1;
    }
  }

  else if (plan.element[x][y].type == TUNNEL)
    {
      if (dir == 4 || plan.element[x][y].frame == 10) {
	ret = 1;
      }
      else if (dir == BAS &&
	       (plan.element[x][y].frame!=0 && plan.element[x][y].frame!=6 &&
		plan.element[x][y].frame!=7 && plan.element[x][y].frame!=9 )) ret = 1;
      else if (dir == HAUT && 
	       (plan.element[x][y].frame!=1 && plan.element[x][y].frame!=4 &&
		plan.element[x][y].frame!=5 && plan.element[x][y].frame!=9 )) ret = 1;
      else if (dir == DROITE &&
	       (plan.element[x][y].frame!=2 && plan.element[x][y].frame!=5 &&
		plan.element[x][y].frame!=7 && plan.element[x][y].frame!=8 )) ret = 1;
      else if (dir == GAUCHE &&
	       (plan.element[x][y].frame!=3 && plan.element[x][y].frame!=4 &&
		plan.element[x][y].frame!=6 && plan.element[x][y].frame!=8 )) ret = 1;
    }

  if (ret == 1 && plan.element[x][y].bombe == BOMBE) {
    ret = -2;
  }
  if (plan.element[x][y].bombe == EXPL) {
    ret = 0;
  }
  return ret;
}


/*--Le joueur n veut-il poser une bombe ?--*/
Bombe * posebombe(int x, int y, int n)
{
  Bombe * nouv;
  if (!(perso[n].statut & DETONATEUR || perso[n].energie >= NBOMBES) || (plan.element[x][y].bombe)) { // && libre(x, y, 4)>0
    return NULL;
  }
  perso[n].energie -= NBOMBES;
  nouv=(Bombe *)malloc(sizeof(Bombe));
  if (perso[n].bombes) {
    perso[n].bombes->prec=nouv;
  }
  nouv->suiv=perso[n].bombes;
  nouv->prec=NULL;
  nouv->pos.x = x;
  nouv->pos.y = y;
  if (perso[n].statut & ETEINT) {
    nouv->rebours = -1;
  }
  else {
    nouv->rebours = REBOURS;
  }
  nouv->lflammes = perso[n].lflammes;
  nouv->car=0;
  
  if (perso[n].statut & DETONATEUR)
    {
      nouv->rebours = -1;
    }
  if (perso[n].statut & SUPERBOMBE)
    {
      nouv->car=SUPERBOMBE;
      perso[n].pouvactif[0]+=ACTIVATION;
    }
  perso[n].bombes=nouv;
  
  plan.element[x][y].bombe = BOMBE;
  return nouv;
}


/*--Supprime l'animation d'un bonus--*/
void bonusmoins(int x, int y)
{
  Anims * pt=anims;
  while (pt)
    {
      if (pt->sprite==bonus && pt->pos.x==x && pt->pos.y==y)
	{ animsmoins(pt); break; }
      pt=pt->suiv;
    }
  //animsplus destruction du bonus...
  return;
}

/*--Ramassage d'un bonus par un joueur--*/
void prendbonus(int n)
{
  int x, y;

  x=perso[n].pos.x;
  y=perso[n].pos.y;
  bruitsplus(s_bonus, 1);
  switch(plan.element[x][y].params[0]) {
    case FLAMMESB: {
      perso[n].lflammes++;
    }break;
    case ENERGIEB: {
      perso[n].energie += (50+aleat(40));
      if (perso[n].energie > 255)
	perso[n].energie = 255;
    }break;
    case POUVOIRB: {
      pouvoirplus(n, 0, 0);
    }break;
  }
  plan.element[x][y].type = LIBRE;
  bonusmoins(x,y);

  return;
}


/*--Affichage d'un joueur à l'écran--*/
void afficheperso(int n, int frame)
{
  if (perso[n].statut&INVISIBLE)
    return;
  else if (perso[n].statut&DEGUISE)
    blitsprit(mur,2,0,perso[n].pixpos.x, perso[n].pixpos.y);
  else if (sprit[n]->anims[0]->nframes<8) /* Autrement dit, le personnage est une citrouille */
    blitsprit(sprit[n], 0, (compteur/2)%sprit[n]->anims[0]->nframes, perso[n].pixpos.x,perso[n].pixpos.y);
  else
    blitsprit(sprit[n],perso[n].anim,frame,perso[n].pixpos.x,perso[n].pixpos.y);
  return;
}


/*--Anime les mouvements des joueurs--*/
void animouv(int n)
{
  int dirx, diry;
  int mv, frame=0;
  int x, y;
  x=perso[n].pos.x;
  y=perso[n].pos.y;
  perso[n].pixpos.x = x*32;
  perso[n].pixpos.y = y*32;

  dirx=dx[perso[n].dir]; diry=dy[perso[n].dir];
  mv=perso[n].mv;
  //if (perso[n].action!=RIEN || perso[n].action==INVINCIBLE)
  perso[n].anim=perso[n].dir;

  /* Si le personnage est déguisé, pour lui les propriétés */
  /* de sa case restent les mêmes même si elles changent pour */
  /* les autres. */
  if (perso[n].statut & DEGUISE) {
    plan.element[x][y].type = perso[n].pouvoirparam;
  }

  rscaseplus(x, y);
  
  if (mv > 0)
    {
      perso[n].pixpos.x+=4*mv*dirx;
      perso[n].pixpos.y+=4*mv*diry;
      rscaseplus(x+dirx, y+diry);
      frame=mv;
    }
  if (mv == -1 || (perso[n].statut&RAPIDE && mv == -2) )
    {
      if (plan.element[x][y].type == EVENEMENT) {
	evtsplus(plan.element[x][y].evt, n, x, y, 0, 1, plan.element[x][y].nparams ? plan.element[x][y].params[0] : 0, APRES, NULL);
      }
      if (plan.element[x][y].type == BONUS) {
	prendbonus(n);
      }
    }

  if (mv<0)
    {
      mv++;
      /* mv est artificiellement minoré de 1 pour distinguer */
      /* quand le personnage arrive sur une case ou s'il y est déjà */
      perso[n].pixpos.x+=4*mv*dirx;
      perso[n].pixpos.y+=4*mv*diry;
      if (mv) {
	rscaseplus(x-dirx, y-diry);
	frame = 8+mv;
      } /* (mv<=0) */
      else {
	frame = 0;
      }
    }

  afficheperso(n, frame);

  /* Le personnage est déguisé, les autres le prennent donc pour un mur */
  if (perso[n].statut & DEGUISE) {
    perso[n].pouvoirparam=plan.element[x][y].type;
    plan.element[x][y].type=CAMOUFL;
  }

  if (perso[n].mv)
    {
      perso[n].mv++;
    }

  /* Les 4 premières frames de mouvement sont positives (1..4) */
  /* et les 4 dernières négatives (-5..-1 -> -4..-0) */
  /* Comme ça le personnage est considéré comme étant sur la case */
  /* dont il est le plus proche. */
  if (perso[n].mv==4)
    {
      if (perso[n].statut & DEGUISE)
	{
	  plan.element[x][y].type=perso[n].pouvoirparam;
	  perso[n].pouvoirparam=plan.element[x+dirx][y+diry].type;
	  plan.element[x+dirx][y+diry].type=CAMOUFL;
	}
      perso[n].pos.y+=diry;
      perso[n].pos.x+=dirx;
      perso[n].mv=-5;
    }
  
  if (perso[n].mv && perso[n].statut&RAPIDE)
    perso[n].mv++;

  return;
}


/*--Tentative d'assassinat du personnage "tue" par une bombe de "tueur"--*/
void mort(int tueur, int tue)
{
  int i, n_en_vie=0;

  if (perso[tue].statut&INVINCIBLE || !(perso[tue].statut&VIVANT)) {
    return;
  }
  if (perso[tue].statut&DEGUISE) {
    plan.element[perso[tue].pos.x][perso[tue].pos.y].type=perso[tue].pouvoirparam;
  }

  if (modejeu == MODE_DEATHMATCH_GORE || (modejeu == MODE_DEATHMATCH && tueur!=tue)) {
    score[tueur]++;
  }

  perso[tue].statut = MORT;
  perso[tue].animdroite = AGONIE;
  if (sprit[tue]->nanims > 7) {
    animsplus(sprit[tue], ANIM_MORT, 4, 1, perso[tue].pos.x, perso[tue].pos.y);
  }
  bruitsplus(s_mort, 1);
  for (i=0; i < NB_PERSO; i++) {
    if (perso[i].statut&VIVANT)
      {
	n_en_vie++;
      }
  }
  if (n_en_vie<2)
    {
      evtsplus(termine, 0, 0, 0, 100, 1, 0, APRES, NULL);
    }
  return;
}


/*--Effet mortel sur la case (x,y), à cause du joueur n--*/
void tue(int x, int y, int n)
{
  int i;

  for (i=0; i < NB_PERSO; i++) {
    if (perso[i].pos.x == x && perso[i].pos.y == y) {
      mort(n, i);
    }
  }
  return;
}


/*--Explosion d'une bombe--*/
void explose(int n, Bombe * b)
{
  void propagflam(int, int, int, int, int);
  
  plan.element[b->pos.x][b->pos.y].bombe = EXPL;
  evtsplus(destruction, n, b->pos.x, b->pos.y, 0, 1, 0, AVANT, NULL);
  bruitsplus(s_expl, 1);
  
  if (b->suiv) {
    b->suiv->prec=b->prec;
  }
  if (b->prec) {
    b->prec->suiv=b->suiv;
  }
  else { // b est la première bombe, "bombes" pointe maintenant sur b->suiv
    perso[n].bombes = b->suiv;
  }

  tue(b->pos.x, b->pos.y, n);
  propagflam(n, b->pos.x, b->pos.y, b->lflammes, b->car == SUPERBOMBE);
  free(b);

  return;
}


/*--Détecte la bombe de la case (x,y) pour la faire exploser--*/
void explosebombe(int x, int y)
{
  int i;
  Bombe * pt;

  for (i=0; i < NB_PERSO; i++)
    {
      pt = perso[i].bombes;
      while (pt)
	{
	  if (pt->pos.x == x && pt->pos.y == y) {
	    pt->rebours = 1;
	    return;
	  }
	  pt = pt->suiv;
	}
    }
  return; /* Ne devrait servir à rien */
}


/*--Casse un mur destructible--*/
void detruitbloc(int x, int y)
{
  int param;
  plan.element[x][y].elem = sol;
  plan.element[x][y].anim = 0;
  plan.element[x][y].frame = 0;
  plan.element[x][y].type = LIBRE;
  plan.element[x][y].bombe = EXPL;
  evtsplus(destruction, 0, x, y, 0, 1, 0, AVANT, NULL);
  animsplus(bloc, 1, 2, 1, x, y);
  //*  if (aleat(BONUSFREQ)==0)
  if (aleatfloat(bonus_freq)==0)
    {
      param=aleat(10);
      plan.element[x][y].params=(int *)malloc(sizeof(int));
      plan.element[x][y].nparams=1;
      if (0<=param && param<5) plan.element[x][y].params[0] = FLAMMESB;
      else if (5<=param && param<9)  plan.element[x][y].params[0] = ENERGIEB;
      else if (9<=param && param<10) plan.element[x][y].params[0] = POUVOIRB;
      plan.element[x][y].type=BONUS;
      animsplus(bonus, plan.element[x][y].params[0], 2, 0, x, y);
    }
  return;
}


/*--Propagation des flammes des bombes--*/
void propagflam(int n, int ox, int oy, int lflammes, int sup)
{
  int i, j;
  int x, y;
  int type;
  int anim;
  int caselibre;
  
  for (i=0; i < 4; i++) // four directions
    {
      for (j = 1; j <= lflammes; j++) // length of the flame
	{
	  x = ox+dx[i]*j;
          y = oy+dy[i]*j;
	  //x P.K.	  if (x<0 || x>15 || y<0 || y>14)
	  if (x < 0 || x >= plan.nivewidth || y < 0 || y >= plan.niveheight) {
	    break;
	  }

	  if (!partir(x, y, i)) {
	    break;
	  }

	  caselibre = libre(x, y, i);
	  type = plan.element[x][y].type;

	  /* Contrairement aux personnages,
	   * les flammes font peu de cas du déguisement */
	  if (plan.element[x][y].type == CAMOUFL) {
	    caselibre = 1;
	  }

	  if (caselibre == -2) {
	    /* S'il y a une bombe mais que ç'aurait été libre sinon */
	    tue(x, y, n);
	    explosebombe(x,y);
	    if (!sup) {
	      break;
	    }
	  }
	  else if (!caselibre && plan.element[x][y].type == TUNNEL) {
	    /* Il y a un tunnel qui empêche le passage de la flamme */
	    break;
	  }
	  else if (plan.element[x][y].bombe == EXPL) {
	    /* L'élément a été détruit à ce round */
	    tue(x, y, n);
	    if (!sup) {
	      break;
	    }
	  }
	  else if (type == BONUS)
	    {
	      tue(x, y, n);
	      plan.element[x][y].type = LIBRE;
	      plan.element[x][y].bombe = EXPL;
	      evtsplus(destruction, n, x, y, 0, 1, 0, AVANT, NULL);
	      bonusmoins(x,y);

	      if (!sup) { 
                break; /* Les super-flammes continuent leur chemin */
	      }
	      else {
		anim = (j == lflammes) ? (i+3) : (i/2+1);
		animsplus(flammes, anim, 2, 1, x, y);
	      }
	    }
	  else if (caselibre>0 && plan.element[x][y].elem!=mur) {
	    tue(x, y, n);
	    anim = (j==lflammes) ? (i+3) : (i/2+1);
	    animsplus(flammes, anim, 2, 1, x, y);
	  }
	  else if (plan.element[x][y].elem == mur) {
	    int animbrule = plan.element[x][y].frame+1;
	    tue(x, y, n);
	    if (animbrule < mur->nanims && 
		mur->anims[animbrule]->nframes> 1  && plan.element[x][y].anim == 0)
	      {
		animsplus(mur, animbrule, 2, 1, x, y);
		plan.element[x][y].anim = animbrule;
		plan.element[x][y].frame = mur->anims[animbrule]->nframes-1;
	      }
	    break;
	  }
	  else if (type == DESTRUCTIBLE) {
	    tue(x, y, n);
	    detruitbloc(x, y);
	    if (sup) {
	      anim = (j == lflammes) ? (i+3) : (i/2+1);
	      animsplus(flammes, anim, 2, 1, x, y);
	    }
	    else break;
	  }
	  else break;
	}
    }
  animsplus(bombe, 5, 2, 1, ox, oy);
  return;
}


/*--Rafraichir l'écran (à chaque frame), suivant le mode--*/
int rafraichit(void)
{
  if (dblebuf) {
    SDL_Flip(ecran);
    nrsrect=0;
    nrs=!nrs;
  }
  else {
    SDL_UpdateRects(ecran, nrsrect, rsrect);
    nrsrect=0;
    nrs=0;
  }

  return;
}


/*--Dessine la jauge d'énergie du joueur n à droite de l'écran--*/
void jauge(int n)
{
  SDL_Rect jauge;
  SDL_Rect energie;

  //x  jauge.x = 523;
  jauge.x = resolution.x_offset+resolution.plan_width+11;
  //x  jauge.y = n*48+114;
  jauge.y = resolution.y_offset+n*48+114;
  jauge.w = 106;
  jauge.h = 10;

  //  energie.x = 525;
  energie.x = resolution.x_offset+resolution.plan_width+13;
  //x  energie.y = n*48+116;
  energie.y = resolution.y_offset+n*48+116;
  energie.w = 102;
  energie.h = 6;

  if (!(perso[n].statut&VIVANT))
    {
      SDL_FillRect(ecran, &jauge, 1);
      return;
    }

  if (perso[n].pouvactif[0]) {
    //x    blitsprit(sprit[n], ICONES, 2*((compteur/3)%2), 567, 48*n+80);
    blitsprit(sprit[n], ICONES, 2*((compteur/3)%2), resolution.plan_width+55, 48*n+80);
  }
  else if (perso[n].energie>=perso[n].pouv[0].energie) {
    //x    blitsprit(sprit[n], ICONES, 0, 567, 48*n+80);
    blitsprit(sprit[n], ICONES, 0, resolution.plan_width+55, 48*n+80);
  }
  else {
    //x    blitsprit(sprit[n], ICONES, 2, 567, 48*n+80);
    blitsprit(sprit[n], ICONES, 2, resolution.plan_width+55, 48*n+80);
  }

  if (perso[n].pouvactif[1]) {
    //x    blitsprit(sprit[n], ICONES, 1+2*((compteur/3)%2), 599, 48*n+80);
    blitsprit(sprit[n], ICONES, 1+2*((compteur/3)%2), resolution.plan_width+87, 48*n+80);
  }
  else if (perso[n].energie>=perso[n].pouv[1].energie) {
    //x    blitsprit(sprit[n], ICONES, 1, 599, 48*n+80);
    blitsprit(sprit[n], ICONES, 1, resolution.plan_width+87, 48*n+80);
  }
  else {
    //x    blitsprit(sprit[n], ICONES, 3, 599, 48*n+80);
    blitsprit(sprit[n], ICONES, 3, resolution.plan_width+87, 48*n+80);
  }

  energie.w = perso[n].energie/2.5;
  SDL_FillRect(ecran, &jauge, 1);
  SDL_FillRect(ecran, &energie, 2);
  return;
}


/*--Dessine la bande de droite (jauges, etc.)--*/
void dessinebande(void)
{
  int i;
  //x  SDL_Rect recdroite={512, 0, 128, 480};
  //?  SDL_Rect recdroite={resolution.plan_width+resolution.x_offset, resolution.y_offset, 128, 480};
  SDL_Rect recdroite = {resolution.plan_width+resolution.x_offset, resolution.y_offset, 128, resolution.plan_height};
  //x  SDL_Rect recbande={512, 0, 128, 80};
  SDL_Rect recbande = {resolution.plan_width+resolution.x_offset, resolution.y_offset, 128, 80};
  SDL_FillRect(ecran, &recdroite, 0);
  SDL_BlitSurface(bande, NULL, ecran, &recbande);

  rsrectplus(recdroite.x, recdroite.y,
	     recdroite.w, recdroite.h);

  for (i=0; i < NB_PERSO; i++)
    {
      int y = 48*i+80;
      jauge(i);
      
      if (!(perso[i].statut&VIVANT))
	{
	  if (sprit[i]->nanims <= ANIM_MORT) 
	    //x	    blitsprit(bombe, 7, (compteur/3)%4, 525, y);
	    blitsprit(bombe, 7, (compteur/3)%4, resolution.plan_width+13, y);
	  else if (AGONIE <= perso[i].animdroite) {
	    //x	    blitsprit(sprit[i], ANIM_MORT, (perso[i].animdroite-AGONIE)/3, 525, y);
	    blitsprit(sprit[i], ANIM_MORT, (perso[i].animdroite-AGONIE)/3, resolution.plan_width+13, y);
	    if ( (++perso[i].animdroite - AGONIE)/3 >= sprit[i]->anims[ANIM_MORT]->nframes) {
	      perso[i].animdroite = ANIM_MORT;
	    }
	  }
	  else {
	    //x	    blitsprit(sprit[i], ANIM_MORT, sprit[i]->anims[ANIM_MORT]->nframes-1, 525, y);
	    blitsprit(sprit[i], ANIM_MORT, sprit[i]->anims[ANIM_MORT]->nframes-1, resolution.plan_width+13, y);
	  }
	}
     else {
       if (perso[i].animdroite >= sprit[i]->nanims) {
	 perso[i].animdroite = BAS;
       }
       //x       blitsprit(sprit[i], perso[i].animdroite, (compteur/4) % sprit[i]->anims[perso[i].animdroite]->nframes, 525, y);
       blitsprit(sprit[i], perso[i].animdroite, (compteur/4) % sprit[i]->anims[perso[i].animdroite]->nframes, resolution.plan_width+13, y);
      }

      //x      rsrect[nrsrect].x = 523;
      rsrect[nrsrect].x = resolution.plan_width+9;
      rsrect[nrsrect].y = y;
      rsrect[nrsrect].w = 106;
      rsrect[nrsrect].h = 32+12;
      nrsrect++;
    }
}


/*--Annonce que tout devra être redessiné à la prochaine frame--*/
void rdtout(void)
{
  int x, y;

  //x P.K.  for (y=0; y<15; y++)
  for (y=0; y < plan.niveheight; y++)
    //x P.K.    for (x=0; x<16; x++)
    for (x=0; x < plan.nivewidth; x++) {
      if (plan.element[x][y].type == TUNNEL) {
	rstunnel[nrs][ntunnel[nrs]].x = x;
	rstunnel[nrs][ntunnel[nrs]].y = y;
	ntunnel[nrs]++;
      }
      else {
	rscase[nrs][nrscase[nrs]].x = x;
	rscase[nrs][nrscase[nrs]].y = y;
	nrscase[nrs]++;
      }
    }
  return;
}


/*--Redessiner les cases de décor--*/
void rdplateau(int rien)
{
  nrscase[0]=0;
  nrscase[1]=0;
  ntunnel[0]=0;
  ntunnel[1]=0;
  nrsrect=0;

  rdtout();
  if (dblebuf) {
    nrs = !nrs;
    rdtout();
  }

  return;
}


/*--Gère les bombes--*/
void anibombes()
{
  Bombelist * anibombes2(int n, Bombe * b);
  void anibombes3(int n, Bombelist * b);
  int i=0;
  Bombelist * imminent[NB_PERSO];

  while (i < NB_PERSO) {
    imminent[i]=anibombes2(i, perso[i].bombes);
    i++;
  }
  /* On met à jour les états de toutes les bombes */
  i=0;
  while (i < NB_PERSO) {
    anibombes3(i, imminent[i]);
    i++;
  }
  /* Puis on fait exploser celles qui en ont besoin */
  return;
}


Bombelist * anibombes2(int n, Bombe * b)
{
  int frame, anim;
  Bombe * suiv;

  if (b == NULL) {
    return NULL;
  }
  suiv=b->suiv;
  
  if (b->rebours)
    {
      if (b->rebours>0) {
	anim= (5 * (REBOURS - b->rebours)) / REBOURS;
	b->rebours--;
	frame=((REBOURS - b->rebours) /3) % bombe->anims[anim]->nframes;
      }
      else {
	anim=7;
	frame=(compteur/3)%bombe->anims[anim]->nframes;
      }
	  
      rscaseplus(b->pos.x, b->pos.y);
      blitsprit(bombe, anim, frame, b->pos.x*32, b->pos.y*32);
      return anibombes2(n,suiv);
    }
  else
    {
      Bombelist * nouv=(Bombelist *)malloc(sizeof(Bombelist));
      nouv->contenu=b;
      nouv->suiv=anibombes2(n,suiv);
      return nouv;
    }
}


void anibombes3(int n, Bombelist * bl)
{
  Bombelist * suiv;

  if (bl == NULL) {
    return;
  }
  suiv = bl->suiv;
  explose (n,bl->contenu);
  free(bl);
  anibombes3(n,suiv);
  return;
}


/*--Gère la structures anims--*/
void anime(Anims * a)
{
  Anims * prec;
  /* On parcourt la liste des animations en ordre inverse pour que
     les plus récentes soient affichées au-dessus des plus anciennes */
  if (a == NULL) {
    return;
  }
  prec = a->prec;

  rscaseplus(a->pos.x, a->pos.y);
  blitsprit(a->sprite, a->anim, a->frame, a->pos.x*32, a->pos.y*32);
  if (a->vitesse) {
    a->compteur++;
  }
  if (a->compteur == a->vitesse)
    {
      a->compteur=0;
      if (a->frame < a->sprite->anims[a->anim]->nframes-1) {
	a->frame++;
      }
      else
	{
	  a->frame=0;
	  if (a->duree)
	    {
	      a->duree--;
	      if (!a->duree) animsmoins(a);
	    }
	}
    }
  anime(prec);
  return;
}


/*--trie les volontés de déplacement des joueurs--*/
void mouvement(int n, int dir)
{
  int x, y, stat;
  x=perso[n].pos.x+dx[dir];
  y=perso[n].pos.y+dy[dir];

  if (perso[n].statut & DEGUISE)
    plan.element[perso[n].pos.x][perso[n].pos.y].type=perso[n].pouvoirparam;

  stat=libre(x, y, dir);
  if (stat>0)
    perso[n].mv=1;
  else if (perso[n].statut & FURIEDESTRUCTRICE && stat==-1)
    {
      detruitbloc(x, y);
      bruitsplus(s_expl, 1);
      perso[n].mv=1;
    }
  else if (perso[n].statut & PASSEMURAILLES
	   //x P.K.	   && 0<=perso[n].pos.x+dx[dir] && perso[n].pos.x+dx[dir]<16
	   && 0 <= perso[n].pos.x+dx[dir] && perso[n].pos.x+dx[dir] < plan.nivewidth
	   //x P.K.	   && 0<=perso[n].pos.y+dy[dir] && perso[n].pos.y+dy[dir]<15)
	   && 0 <= perso[n].pos.y+dy[dir] && perso[n].pos.y+dy[dir] < plan.niveheight)
    perso[n].mv=1;

  if (perso[n].statut & DEGUISE) {
    perso[n].pouvoirparam=plan.element[perso[n].pos.x][perso[n].pos.y].type;
    plan.element[perso[n].pos.x][perso[n].pos.y].type=CAMOUFL;
  }
  
  return;
}


/*--trie les commandes des joueurs et renvoie un bitmask--*/
int commande(int n)
{
  int cmd=0x0;

  perso[n].cmd.precedent=perso[n].cmd.actif;

  if (perso[n].joueurIA)
    return perso[n].cmd.actif=gamelogic_main(n);

  else if (perso[n].cmd.joy==NULL)
    {
      if (clavier[perso[n].cmd.haut]==SDL_PRESSED) cmd|=CMD_HAUT;
      if (clavier[perso[n].cmd.bas]==SDL_PRESSED) cmd|=CMD_BAS;
      if (clavier[perso[n].cmd.gauche]==SDL_PRESSED) cmd|=CMD_GAUCHE;
      if (clavier[perso[n].cmd.droite]==SDL_PRESSED) cmd|=CMD_DROITE;
      if (clavier[perso[n].cmd.b1]==SDL_PRESSED) cmd|=CMD_B1;
      if (clavier[perso[n].cmd.b2]==SDL_PRESSED) cmd|=CMD_B2;
    }
  else
    {
      int var=SDL_JoystickGetAxis(perso[n].cmd.joy, 1);
      if (var < -100) cmd|=CMD_HAUT;
      if (var > 100) cmd|=CMD_BAS;
      var=SDL_JoystickGetAxis(perso[n].cmd.joy, 0);
      if (var < -100) cmd|=CMD_GAUCHE;
      if (var > 100) cmd|=CMD_DROITE;
      if (SDL_JoystickGetButton(perso[n].cmd.joy, 0)) cmd|=CMD_B1;
      if (SDL_JoystickGetButton(perso[n].cmd.joy, 1)) cmd|=CMD_B2;
    }
  return perso[n].cmd.actif=cmd;
}


/*--Gère les commandes des joueurs--*/
void touches(int n)
{
  int p=0;
  int cmd=commande(n);
  if (!danslemenu)
    {
      if (cmd&CMD_B2)
	{
	  p=1;
	  if (cmd&CMD_GAUCHE)
	    pouvoirplus(n, 0, 1);
	  if (cmd&CMD_DROITE)
	    pouvoirplus(n, 1, 1);
	  if (cmd&CMD_HAUT)
	    pouvoirplus(n, 2, 1);
	  if (cmd&CMD_BAS)
	    pouvoirplus(n, 3, 1);
	}
    }
  
  if (p);
  else if (cmd&CMD_HAUT && !perso[n].mv) {
    perso[n].dir=HAUT;
    mouvement(n, HAUT);
  }
  else if (cmd&CMD_BAS && !perso[n].mv) {
    perso[n].dir=BAS;
    mouvement(n, BAS);
  }
  else if (cmd&CMD_GAUCHE && !perso[n].mv) {
    perso[n].dir=GAUCHE;
    mouvement(n, GAUCHE);
  }
  else if (cmd&CMD_DROITE && !perso[n].mv) {
    perso[n].dir=DROITE;
    mouvement(n, DROITE);
  }
  if (!danslemenu)
    if (cmd&CMD_B1)
      {
	if (perso[n].statut & DETONATEUR)
	  {
	    Bombe * pt = perso[n].bombes;
	    evtsplus(restorestatut, n, 0, 0, 6, 1, DETONATEUR, APRES, NULL);
	    while (pt) {
	      if (pt->rebours==-1)
		pt->rebours=0;
	      pt=pt->suiv;
	    }
	  }
	else if(!(perso[n].statut&PASBOMBES))
	  posebombe(perso[n].pos.x, perso[n].pos.y, n);
      }
  return;
}


/*--Écran de menu des choix de personnages--*/
int choix(char *nom, char *image)
{
  int i;
  FILE *niveau;
  //x  char chemin[256];
  char chemin[MAX_STRING_LENGTH];
  SDL_Rect recfond;
  SDL_Color pal[255];

  danslemenu=2;
  compteur=0;
  nrsrect=0;
  nrscase[0]=0;
  nrscase[1]=0;
  nrs=0;
  ntunnel[0]=0;
  ntunnel[1]=0;
  options=0;
  encore=1;

  videcran();
  
  if (Mix_PlayingMusic) Mix_HaltMusic();
  //if (avecmusique) Mix_PlayMusic(muschoix, -1);

  for (i=0; i<NB_PERSO; i++) {
    sprintf(spritliste[i], "%i.spr", i+1);
  }
  sprintf(chemin, "%s/%s", prefixeniv, nom);
  niveau = fopen(chemin, "r");
  if (niveau == NULL) {
    errormessage("Impossible d'ouvrir le fichier menu", nom);
  }
  decl = 0;
  couleurs = charge_sprite("infos.spr", decl);
  sprintf(chemin, "%s/%s", prefixeimg, image);
  fondecran = SDL_LoadBMP(chemin);
  SDL_SetColors(ecran, fondecran->format->palette->colors, decl, fondecran->format->palette->ncolors);
  decl += fondecran->format->palette->ncolors;

  charge_graphs(niveau);
  charge_sprites(sprit, spritliste, NB_PERSO);
  charge_sprites(fauxsprit, persoliste, nsprit);

  for (i=0; i < NB_PERSO; i++) {
    initperso(i);
  }
  //x  chargeniv(niveau); // P.K.
  freeplan(&plan);
  chargeniv_dynamic(niveau, &plan, 1, danslemenu, 0);
  fclose(niveau);

  //?  recfond.x=recfond.y=0;
  recfond.x = resolution.x_offset;
  recfond.y = resolution.y_offset;
  //?  recfond.w=512; recfond.h=480;
  recfond.w = resolution.plan_width;
  recfond.h = resolution.plan_height;

  /* Mettre en noir et blanc */
  for (i=1; i < 256 && i<ecran->format->palette->ncolors; i++)
    {
      SDL_Color *colors = ecran->format->palette->colors;
      float moy = (colors[i].r+colors[i].g+colors[i].b)/3.0;

      moy = ((moy-30-127)*0.68)+127;
      /* luminosité -20 contraste -40 */
      pal[i-1].r = (moy >= 225) ? 255 : moy+30;
      pal[i-1].g = moy;
      pal[i-1].b = (moy <= 30) ? 0 : moy-30;
    }
  SDL_SetColors(ecran, pal, 1, 256);

  rdplateau(0);

  do {
    ajustevitesse();

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

    dessinecase(nrscase[nrs], rscase[nrs]);
    if (dblebuf) {
      dessinecase(nrscase[!nrs], rscase[!nrs]);
    }
    nrscase[nrs] = 0;
      
    anime(animsfin);
    SDL_PumpEvents();
    clavier = SDL_GetKeyState(NULL);

    for (i=0; i < nsprit; i++) {
      if (strcmp(persoliste[i], "citrouille.spr")) {
	blitsprit(fauxsprit[i], 1, 0, fauxperso[i].x*32, fauxperso[i].y*32);
      }
    }
    for (i=0; i < NB_PERSO; i++) {
      if (perso[i].statut&VIVANT) {
	touches(i);
	animouv(i);
      }
    }
    //dessinecase(ntunnel, rstunnel);
    //ntunnel=0;
    agit(evts[APRES], APRES);

    rafraichit();
  }
  while(encore && clavier[SDLK_ESCAPE]!=SDL_PRESSED && clavier[SDLK_F8]!=SDL_PRESSED);

  reinit();
  detruit_sprites();
  SDL_FreeSurface(fondecran);
  
  if (clavier[SDLK_ESCAPE] == SDL_PRESSED) {
    while(clavier[SDLK_ESCAPE] == SDL_PRESSED) {
      SDL_PumpEvents();
      clavier=SDL_GetKeyState(NULL);
    }
    return 1;
  }
  else if (clavier[SDLK_F8] == SDL_PRESSED) {
    while(clavier[SDLK_ESCAPE] == SDL_PRESSED || clavier[SDLK_F8] == SDL_PRESSED) {
      SDL_PumpEvents();
      clavier=SDL_GetKeyState(NULL);
    }
    return 2;
  }

  choisi = 1;
  return 0;
}


/*--Écran de menu principal et options--*/
int menu(int principal, char *nom, char *image)
{
  int i;
  int preums;
  FILE *niveau;
  //x  char chemin[256];
  char chemin[MAX_STRING_LENGTH];
  //x  SDL_Rect recmodejeu = {225+resolution.x_offset, 320+resolution.y_offset, 341, 31};
  SDL_Rect recmodejeu = {225+resolution.x_offset, 320+resolution.y_offset, 341, 31};

  danslemenu=1;
  compteur=0;
  nrsrect=0;
  nrscase[0]=0;
  nrscase[1]=0;
  nrs=0;
  ntunnel[0]=0;
  ntunnel[1]=0;
  options=0;
  encore=1;
//x P.K.  for (i=0; i<8; i++)
  for (i=0; i < MAX_NPERSO; i++) {
    score[i] = 0;
  }
  nperso = NB_PERSO;

  videcran();

  decl = 0;
  couleurs = charge_sprite("infos.spr", decl);
  sprintf(chemin, "%s/%s", prefixeniv, nom);
  niveau = fopen(chemin, "r");
  if (niveau == NULL) {
    errormessage("Impossible d'ouvrir le fichier menu", nom);
  }

  sprintf(chemin, "%s/%s", prefixeimg, image);
  fondecran = SDL_LoadBMP(chemin);
  if (fondecran == NULL) {
    errormessage("Impossible de charger l'image", image);
  }
  SDL_SetColors(ecran, fondecran->format->palette->colors, decl, fondecran->format->palette->ncolors);
  decl += fondecran->format->palette->ncolors;
  if (!principal) {
    for (i=0; i < NMODES; i++) {
      sprintf(chemin, "%s/mode_%i.bmp", prefixeimg, i);
      txtmodesjeu[i] = SDL_LoadBMP(chemin);
      if (txtmodesjeu[i] == NULL) {
	errormessage("Impossible de charger l'image", image);
      }
    }
  }

  charge_graphs(niveau);
  sprit[0] = charge_sprite("citrouille.spr", decl);
  for (i=0; i < NB_PERSO; i++) {
    initperso(i);
  }
  //x  chargeniv(niveau); // P.K.
  freeplan(&plan);
  chargeniv_dynamic(niveau, &plan, 1, danslemenu, 0);
  fclose(niveau);

  rdplateau(0);

  preums = 1+dblebuf;
  
  do {
    ajustevitesse();

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

    dessinecase(nrscase[nrs], rscase[nrs]);
    if (dblebuf) {
      dessinecase(nrscase[!nrs], rscase[!nrs]);
    }
    nrscase[nrs] = 0;

    anime(animsfin);
    if (principal) {
      blitsprit(couleurs, 1, 0, (3+nperso)*32, 9*32);
    }

    agit(evts[AVANT], AVANT);

    SDL_PumpEvents();
    clavier = SDL_GetKeyState(NULL);
    touches(0);
    animouv(0);

    agit(evts[APRES], APRES);
    //dessinecase(ntunnel, rstunnel);
    //ntunnel=0;

    if (preums && !principal) { /* c-à-d menu des options */
      SDL_BlitSurface(txtmodesjeu[modejeu], NULL, ecran, &recmodejeu);
      rsrectplus(161, 320, 341, 31);
      //?      rsrectplus(161+resolution.x_offset, 320+resolution.y_offset, 341, 31);
    }

    rafraichit();

    if (clavier[SDLK_ESCAPE] == SDL_PRESSED) {
      exit(0);
    }

    if (preums) preums--;
  }
  while(encore);

  reinit();
  detruit_sprites();
  SDL_FreeSurface(fondecran);
  if (!principal) {
    for (i=0; i < NMODES; i++) {
      SDL_FreeSurface(txtmodesjeu[i]);
    }
  }

  if (principal) {
    NB_PERSO = nperso;
  }
  if (options) {
    menu(0, "options.niv", choixlangue(chemin, "Options", "bmp"));
    return 1;
  }
  
  return 0;
}


/*--Évenements déclenchés dans les menus--*/
void menuevt(Evenement * e)
{
  int val, i, n_restant=0;
  int x = e->pos.x;
  int y = e->pos.y;
  int p = e->proprietaire;
  int param = plan.element[x][y].params[0];

  if (param == SUIVANT) {
    encore=0;
    bruitsplus(s_teleport, 1);
  }
  else if (MINNB < param && param < MAXNB) {
    rdplateau(0);
    nperso = param-110;
    bruitsplus(s_bouton, 1);
  }
  else if (MINTOUCHES < param && param < MAXTOUCHES) {
    touchescfg(x, y, param-221);
  }
  else if (param == SAUVECONFIG) {
    sauvecfg();
  }
  else if (param == OPTIONS) {
    options = 1;
    encore = 0;
  }
  else if (param == MODEDEJEU || param == MODEDEJEUPLUS) {
    //x    SDL_Rect recmodejeu = {225, 320, 341, 31};
    SDL_Rect recmodejeu = {225+resolution.x_offset, 320+resolution.y_offset, 341, 31};
    if (param == MODEDEJEUPLUS) {
      modejeu = NMODES -1;
    }
    else {
      modejeu = (modejeu+1) % (NMODES-1);
    }
    SDL_BlitSurface(txtmodesjeu[modejeu], NULL, ecran, &recmodejeu);
    if (dblebuf) {
      SDL_Flip(ecran);
      SDL_BlitSurface(txtmodesjeu[modejeu], NULL, ecran, &recmodejeu);
      SDL_Flip(ecran);
    }
    else {
      //x      rsrectplus(161, 320, 341, 31);
      rsrectplus(161+resolution.x_offset, 320+resolution.y_offset, 341, 31);
    }
    bruitsplus(s_bouton, 1);
  }      
  else if (param == QUITTER) {
    exit(0);
  }
  else if (MINPERSO < param && param < MAXPERSO) {
    val = param-121;
    if (val<nsprit) {
      if (strcmp(spritliste[p],"citrouille.spr")) {
	strcpy(spritliste[p], persoliste[val]);
	sprit[p] = fauxsprit[val];
      }
    }
  }
  else if (param == CESTPARTI) {
    perso[p].statut = MORT;
    for (i=0; i < NB_PERSO; i++) {
      if (perso[i].statut&VIVANT) {
	n_restant++;
	e->proprietaire = i; /* ??? */
      }
    }
    if (!n_restant) {
      encore = 0;
      if (Mix_PlayingMusic) {
	Mix_HaltMusic();
      }
    }
    else {
      bruitsplus(s_teleport, 1);
    }
  }
  return;
}


/*--Boucle principale du jeu--*/
int jeu(void)
{
  paletsg pal;
  int preums=1;
  int i;

#ifdef DEBUG
  int i;
  Uint32 stat[10000];
  int nstat=0;
  int nral=0;
  float moy=0;
#endif

  if (!dblebuf) {
    pal = changepalette(0.0, 0.0, 0.0, 1, 256, 256, 256, 0); /* tout noir */
  }
  rdplateau(0);

  bruitsplus(s_debut, 1);
  do
    {
#ifdef DEBUG
      if (nstat<10000) {
	stat[nstat++] = ajustevitesse();
      }
      else {
	ajustevitesse();
      }
#else
      ajustevitesse();
#endif

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

      dessinecase(nrscase[nrs], rscase[nrs]);
      if (dblebuf) {
	dessinecase(nrscase[!nrs], rscase[!nrs]);
      }
      nrscase[nrs] = 0;
      
      SDL_PumpEvents();
      clavier = SDL_GetKeyState(NULL);

      agit(evts[AVANT], AVANT);
      anime(animsfin);
      anibombes();
      //x      while (i < NB_PERSO) // for is better P.K.
      for (i=0; i < NB_PERSO; i++)
	{
	  if (perso[i].statut&VIVANT)
	    {
	      if (compteur%REGEN == 0) {
		if (perso[i].energie < 255) {
		  perso[i].energie++;
		}
	      }
	      touches(i);
	      animouv(i);
	    }
	  //x	  i++;
	}
      agit(evts[APRES], APRES);

      dessinecase(ntunnel[nrs], rstunnel[nrs]);
      if (dblebuf) {
	dessinecase(ntunnel[!nrs], rstunnel[!nrs]);
      }
      ntunnel[nrs] = 0;
      
      gerepouvoirs();
      dessinebande();

      rafraichit();

      if (preums) {
	if (!dblebuf) {
	  restorepalette(pal, 60);
	}
	preums = 0;
      }

      if (enpause == 1) {
	pauseifie();
      }
    }
  while(encore && clavier[SDLK_ESCAPE] != SDL_PRESSED && clavier[SDLK_F8] != SDL_PRESSED);
  if (Mix_PlayingMusic) {
    Mix_HaltMusic();
  }

#ifdef DEBUG
  /*--Faisons un peu de statistiques sur les performances--*/
  for (i=0; i<nstat; i++) {
    moy+=stat[i];
    if (stat[i]>VITESSE) {
      nral++;
    }
  }
  moy /= (float)nstat;
  printf("Statistiques sur %i rafraichissements d'écran:\n", nstat);
  printf("%.2f frames par seconde en moyenne, ", 1000/moy);
  printf("limitées par le maximum de %i fps\n", 1000/VITESSE);
  printf("%i frame%s(%.2f%%) étai%st au-delà du maximum.\n",
	 nral, nral>1 ? "s " : " ", (100.0*nral)/nstat, nral>1 ? "en" : "");
#endif

  reinit();
  SDL_FreeSurface(bande);

  //  if (!encore) bruitsplus(s_fin, 1);

  if (clavier[SDLK_F8] == SDL_PRESSED)
    {
      while(clavier[SDLK_F8] == SDL_PRESSED) {
	SDL_PumpEvents();
	clavier = SDL_GetKeyState(NULL);
      }
      detruit_sprites();
      return 2;
    }
  else if (clavier[SDLK_ESCAPE] == SDL_PRESSED)
    {
      while(clavier[SDLK_ESCAPE] == SDL_PRESSED) {
	SDL_PumpEvents();
	clavier=SDL_GetKeyState(NULL);
      }
      return 0;
    }
  else {
    return 1;
  }
}


/*--Initialisation de chaque partie--*/
int initpartie(void)
{
  int i;
  FILE *niveau;
  //x  char chemin[256];
  char chemin[MAX_STRING_LENGTH];
  //x  char nomniveau[256];
  char nomniveau[MAX_STRING_LENGTH];
  int ret;

  enpause = 0;

  if (!choisi)
    {
      do {
	ret = choix("choix.niv", "Choix.bmp");
      } while (ret == 2);
      if (ret == 1) {
	return 0;
      }
    }

  i = aleat(nb_niveaux);
  strcpy(nomniveau, niveaux[i]);
  //printf("C'est parti : niveau %s [%i/%i].\n", nomniveau, i, nb_niveaux);

  videcran();

  reinit();
  detruit_sprites();

  couleurs = charge_sprite("infos.spr", decl);
  sprintf(chemin, "%s/%s", prefixeniv, nomniveau);
  niveau = fopen(chemin, "r");
  if (niveau == NULL) {
    errormessage("Impossible d'ouvrir le niveau", nomniveau);
  }
  
  sprintf(chemin, "%s/Bande.bmp", prefixeimg);
  bande = SDL_LoadBMP(chemin);
  if (bande == NULL) {
    errormessage("Impossible de charger l'image", chemin);
  }
  SDL_SetColors(ecran, bande->format->palette->colors, decl, bande->format->palette->ncolors);
  decl += bande->format->palette->ncolors;

  charge_graphs(niveau);
  charge_sprites(sprit, spritliste, NB_PERSO);
  for (i = 0; i < NB_PERSO; i++) {
    initperso(i);
  }
  //x   chargeniv(niveau); // P.K.
  animsfin = NULL; // no animation
  freeplan(&plan);
  chargeniv_dynamic(niveau, &plan, 1, danslemenu, 1);
  fclose(niveau);

  dessinebande();

  if (Mix_PlayingMusic) {
    Mix_HaltMusic();
  }
  //if (avecmusique) Mix_PlayMusic(muschoix, -1);

  return jeu();
}


/*--Fin d'un round, affichage du score...--*/
int fin(int ret)
{
  int matchfini=0;
  int i, j; 
  int a, r, p;
  int n=-1;  // nobody wins
  //x  char texte[8][20], chemin[256], nom[256];
  char texte[8][20], chemin[MAX_STRING_LENGTH], nom[MAX_STRING_LENGTH];
  int ord;
  Coord middle;

  SDL_Rect g;
  Sprite *gagnant;

  middle.x = (resolution.plan_width+64)/2;
  //xx  middle.x = resolution.window_width/2;
  middle.y = (resolution.plan_height-40*NB_PERSO)/2;
  //xx  middle.y = (resolution.window_height-40*NB_PERSO)/2;

  g.w = g.h = 32;
  //x  g.x=(640-32)/2; g.y=(480-40*NB_PERSO)/2;
  g.x = resolution.x_offset+middle.x;
  g.y = resolution.y_offset+middle.y;

  videcran();

  if (changepersos) {
    choisi=0;
  }

  if (!ret) {
    return 1;
  }
  
  for (i=0; i<NB_PERSO; i++) {
    if (perso[i].statut&VIVANT) { 
      n=i;
    }
  }
  if (n == -1) {
    gagnant = bombe;
    a=6;
    r=1;
    p=0;
  }
  else {
    gagnant = sprit[n];
    a = GAGNE >= sprit[n]->nanims ? BAS : GAGNE;
    r=3;
    p=1;
    if (modejeu == MODE_STD) {
      score[n]++;
    }
  }
  
  for (i=0; i<NB_PERSO; i++)
    if (score[i] >= 16)
      {
	for (j=0; j<NB_PERSO;j++)
	  if (score[j]>score[i]-15) {
	    score[j]-=score[i]-15;
	  }
	  else {
	    score[j]=0;
	  }
      }

  for (i=0; i<NB_PERSO; i++)
    {
      //x      ord = 440-40*(NB_PERSO-i-1);
      //x      ord = resolution.plan_height-40*(NB_PERSO-i);
      ord = resolution.window_height-resolution.y_offset-40*(NB_PERSO-i);
      blitsprit(sprit[i], BAS, 0, 64-resolution.x_offset, ord);
      for (j=0; j<score[i]; j++) {
	blitsprit(bombe, 0, 0, 112-resolution.x_offset+j*32, ord);
	//x	blitsprit(bombe, 0, 0, 112-resolution.x_offset+j*32, ord);
      }
    }

  SDL_Flip(ecran);

  if (dblebuf) {
    for (i = NB_PERSO-1; i>=0; i--)
      {
	//x	ord = 440-40*(NB_PERSO-i-1);
	//x        ord = resolution.plan_height-40*(NB_PERSO-i);
	//x        ord = resolution.window_height-40*(NB_PERSO-i);
        ord = resolution.window_height-resolution.y_offset-40*(NB_PERSO-i);
	blitsprit(sprit[i], BAS, 0, 64-resolution.x_offset, ord);
	for (j=0; j<score[i]; j++) {
	  blitsprit(bombe, 0, 0, 112-resolution.x_offset+j*32, ord);
	  //x	  blitsprit(bombe, 0, 0, 112-resolution.x_offset+j*32, ord);
	}
      }
    SDL_Flip(ecran);
  }

  for (i=0; i < gagnant->anims[a]->nframes*r+p; i++)
    {
      SDL_PumpEvents();
      SDL_FillRect(ecran, &g, 0);

      if (strcmp(gagnant->nom,"Magus")) { // Le gagnant n'est pas Magus
	//x	blitsprit(gagnant, a, i%gagnant->anims[a]->nframes, g.x, g.y);
	blitsprit(gagnant, a, i%gagnant->anims[a]->nframes, middle.x, middle.y);
      }
      else
	{ /* C'est un bricolage pour l'anim de Magus */
	  int u = i/2;
	  if (u >= 14) {
	    u = (u < 22) ? (6 + u%2) : (u - 8);
	  }
	  if (u < gagnant->anims[a]->nframes) {
	    //x	    blitsprit(gagnant, a, u, g.x, g.y);
	    blitsprit(gagnant, a, u, middle.x, middle.y);
	  }
	}
      SDL_Flip(ecran);
      SDL_Delay(70);
    }

  SDL_Delay(500);

  /* Match fini ? */
  for (i=0, n=0; i<NB_PERSO; i++) {
    if (score[i]>score[n]) {
      n=i;
    }
  }
  
  if (score[n] >= NROUNDS)
    {
      matchfini=1;
      for (i=0; i<NB_PERSO; i++) {
	if (score[i]>score[n]-1-pointdavance && i!=n) {
	  matchfini = 0;
	}
      }
      if (matchfini)
	{
	  videcran();
	  sprintf(nom, "%s", sprit[n]->nom);
	  nom[0]=toupper(nom[0]);
	  //	  printf("Gagnant joueur %i, personnage %s.\n", n+1, sprit[n]->nom);
	  printf("Gagnant joueur %i, personnage %s.\n", n+1, nom);
	  //	  strcpy(texte[0], sprit[n]->nom);
	  strcpy(texte[0], nom);
	  for (j=1; j<7; j++) {
	    strcpy(texte[j],"\0");
	  }
	  sprintf(texte[7], "Wins !!!");
	  //	  sprintf(chemin, "%s.bmp", sprit[n]->nom);
	  sprintf(chemin, "%s.bmp", nom);
	  ecrantexte(texte, chemin, 8, 0);
	}
    }
  
  detruit_sprites();

  clavier=SDL_GetKeyState(NULL);
  if (matchfini) {
    return 1;
  }
  if (clavier[SDLK_SPACE] == SDL_PRESSED) {
    while(clavier[SDLK_SPACE] == SDL_PRESSED) {
      SDL_PumpEvents();
      clavier=SDL_GetKeyState(NULL);
    }
    return 2;
  }
  else if (clavier[SDLK_ESCAPE] == SDL_PRESSED) {
    while(clavier[SDLK_ESCAPE] == SDL_PRESSED) {
      SDL_PumpEvents();
      clavier = SDL_GetKeyState(NULL);
    }
    return 1;
  }
  return  2;
  }


int main(int argc, char **argv)
{
  int i;
  int ret;
  int canal;
  //x  char textecr[8][20], chemin[256];
  char textecr[8][20], chemin[MAX_STRING_LENGTH];

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

  chargeconfig();

  sprintf(prefixeniv, "%s/Niveaux", repertoire);
  sprintf(prefixeimg, "%s/Decors", repertoire);
  sprintf(prefixespr, "%s/Sprites", repertoire);
  sprintf(prefixeson, "%s/Bruitages", repertoire);
  VITESSE=1000/VITESSE;

  //x P.K.  spritliste=(char **)calloc(8, sizeof(char *));
  spritliste=(char **)calloc(MAX_NPERSO, sizeof(char *));
  //x P.K.  for (i=0; i<8; i++)
  for (i=0; i<MAX_NPERSO; i++)
    spritliste[i]=(char *)calloc(256, sizeof(char));

  for (i=1; i<argc; i++)
    {
      if (argv[i][0]=='-')
	{
	  if (strchr(argv[i], 'e'))
	    pleinecran=0;
	  if (strchr(argv[i], 's'))
	    avecson=0;
	  if (strchr(argv[i], 'm'))
	    avecmusique=0;
	  if (strchr(argv[i], 'd'))
	    dblebuf=0;
	  if (strchr(argv[i], 'j'))
	    avecjoy=0;
	  if (strchr(argv[i], 'h'))
	    msg_info();
	}
      else if (argv[i][0]=='+')
	{
	  if (strchr(argv[i], 'e'))
	    pleinecran=1;
	  if (strchr(argv[i], 's'))
	    avecson=1;
	  if (strchr(argv[i], 'm'))
	    avecmusique=1;
	  if (strchr(argv[i], 'd'))
	    dblebuf=2;
	  if (strchr(argv[i], 'j'))
	    avecjoy=1;
	}
      else msg_info();
    }

  // initialization of the window sizes
  init_resolution(&resolution);

  init_sdl();
  if (numjoys) initjoy();
  
  srand((unsigned int)SDL_GetTicks());
  SDL_SetEventFilter(filtr_evt);
  printf("Salut !\n");

  initson();
  chargebruitages();

  intro();
  bruitsplus(s_expl, 1);
  canal=bruitsplus(s_ecrantit, 0);
  if (numjoys) {
    initjoy_persos();
  }
  sprintf(textecr[0], "Bomber");
  sprintf(textecr[1], "Instinct");
  ecrantexte(textecr, "Titre.bmp", 2, 1);
  Mix_HaltChannel(canal);
  bruitsplus(s_grosrire,1);

  // initialization of the gameplan
  initplan(&plan);

  do {
    if (Mix_PlayingMusic)
      Mix_HaltMusic();

    while (menu(1, "menu.niv", choixlangue(chemin, "Menu", "bmp")));

    choisi = 0;
    do {
      do {
	ret = initpartie();
      } while (ret == 2);
    } while (fin(ret) == 2);
  } while (1);
  
  exit(0);
}
/*--C'est fini !--*/
