/*************************************
**                                  **
**           - DEMINEUR -           **
**                                  **
**          Développé  par          **
**         Gilles  BASSIERE         **
**           aka "Gilux"            **
**                                  **
**                                  **
*************************************/


// Variables globales

var jeuEnCours, temps, nbMine, i, j, nbDecouvert, hauteur, largeur, qMine ;
var b1, b2, b3, b4, b5, b6, b7, b8, bErr, bMine, bMineBoum, bLibre, bVierge, bMarque ;
var etat, mine ;


// Pré-chargement des images

b1 = new Image ;
b1.src = "./dmin_b1.gif" ;
b2 = new Image ;
b2.src = "./dmin_b2.gif" ;
b3 = new Image ;
b3.src = "./dmin_b3.gif" ;
b4 = new Image ;
b4.src = "./dmin_b4.gif" ;
b5 = new Image ;
b5.src = "./dmin_b5.gif" ;
b6 = new Image ;
b6.src = "./dmin_b6.gif" ;
b7 = new Image ;
b7.src = "./dmin_b7.gif" ;
b8 = new Image ;
b8.src = "./dmin_b8.gif" ;
bErr = new Image ;
bErr.src = "./dmin_bErr.gif" ;
bLibre = new Image ;
bLibre.src = "./dmin_bLibre.gif" ;
bMarque = new Image ;
bMarque.src = "./dmin_bMarque.gif" ;
bMine = new Image ;
bMine.src = "./dmin_bMine.gif" ;
bMineBoum = new Image ;
bMineBoum.src = "./dmin_bMineBoum.gif" ;
bVierge = new Image ;
bVierge.src = "./dmin_bVierge.gif" ;



// Fonctions

function getParam() {
// Récupère les dimensions passée par l'URL (methode GET)
     var get, n ;
     get = window.location.href ;
     n = get.indexOf("?");
     if (n > 0) {
          get = get.substr(n+1) ;
          hauteur = get.substr(0, get.indexOf("-")) ;
          get = get.substr(get.indexOf("-")+1) ;
          largeur = get.substr(0, get.indexOf("-")) ;
          get = get.substr(get.indexOf("-")+1) ;
          qMine = get ;
     }
}

function reinit() {
// Recharge la page avec les dimensions en paramètres quand le joueur les modifie
     var adr, n, h, l, q ;
     h = document.getElementById("hInput").value ;
     l = document.getElementById("lInput").value ;
     q = document.getElementById("qInput").value ;
     if (isNaN(h) || isNaN(l) || isNaN(q) || (h == "") || (l == "") || (q == "")) { 
          alert("Erreur de saisie\nvotre demande ne peut ?tre prise en considŽration") ;
     } else if ((l > 50) || (h > 26) || (l < 0) || (h < 0) || (q < 0) || (q > l*h)) {
          alert("Hors limite") ;
     } else {
          adr = window.location.href ;
          n = adr.indexOf("?") ;
          if (n > 0) adr = adr.substr(0, n) ;
          adr += "?" ;
          adr += document.getElementById("hInput").value ;
          adr += "-" ;
          adr += document.getElementById("lInput").value ;
          adr += "-" ;
          adr += document.getElementById("qInput").value ;
          window.location.href = adr ;
     }
}

function defaultParam() {
     var adr, n ;
     adr = window.location.href ;
     n = adr.indexOf("?") ;
     if (n > 0) {
          adr = adr.substr(0, n) ;
          window.location.href = adr ;
     }
}

function zap(s, msg) {
// affiche ou cache la notice en fonction du contexte
     if (document.getElementById(s).style.display != 'block') {
          document.getElementById(s).style.display = 'block';
          document.getElementById(s + "Button").value = 'Masquer ' + msg;
     } else {
          document.getElementById(s).style.display = 'none';
          document.getElementById(s + "Button").value = 'Afficher ' + msg;
     }
}

function dminDraw() {
// dessine la matrice de case
     document.write("<table class=\"dmin\">");
     for (i=0; i<hauteur; i++) {
         c = String.fromCharCode(i+97) ;
    	 document.write("<tr>");
         for (j=0; j<largeur; j++) {
	        document.write("<td class=\"dmin\">");
         	document.write("<img id=\"" + c + j + "\" class=\"dmin\" src=\"" + bVierge.src + "\" width=\"30px\" height=\"30px\" onclick=\"clic(" + j + ", " + i + ", event)\"><\/img>") ;
	        document.write("<\/td>");
         }
	     document.write("<\/tr>");
     }
     document.write("<\/table>");
}

function chrono() {
// affiche l'écoulement du temps dans la zone de texte timer
     document.getElementById("timer").value = temps ;
     temps++ ;
     if (jeuEnCours == 0) setTimeout("chrono()", 1000) ;
}

function name(x, y) {
// Détermine le nom d'un élément ˆ partir de ses coordonées
     return String.fromCharCode(y + 97) + x ;
}

function gagne() {
// Met fin au jeu quand le joueur a gagné
     jeuEnCours = -1 ;
     alert("Bravo !\nVous avez gagné\nen " + temps + " secondes") ;
}

function decouvert() {
// Met à jour le nombre de case découverte
     nbDecouvert++ ;
     if (nbDecouvert == (hauteur*largeur-qMine)) gagne() ;
}

function marque(n) {
// Met à jour le nombre de cases marquée et vérifie éventuellement si le jeu est fini
     var i, j ;
     nbMine = nbMine + n ;
     document.getElementById("nb").value = nbMine ;      // Affichage du nb de case à déminer
     if (nbMine <= 0) {
          for (i=0; i<hauteur; i++) {
               for (j=0; j<largeur; j++) if ((etat[j][i] == 1) && (mine[j][i] != -1)) return ;
          }
          gagne() ;
     }
}

function devoilerMines() {
// Fait apparaître toutes les mines quand le joueur a perdu
     var i, j ;
     for (j=0; j<hauteur; j++) {
          for (i=0; i<largeur; i++) {
               if ((etat[i][j] == 0) && (mine[i][j] == -1)) document.getElementById(name(i, j)).src = bMine.src ;
               if ((etat[i][j] == 1) && (mine[i][j] != -1)) document.getElementById(name(i, j)).src = bErr.src ;
          }
     }
}

function devoiler1a8(x, y) {
// Découvre une case qui contient un chiffre
     eval("document.getElementById('" + name(x, y) + "').src = b" + mine[x][y] + ".src") ;
     decouvert() ;
     etat[x][y] = 2 ;
}

function zoneLibre(x, y) {
// DŽcouvre toutes les cases non minŽes ˆ cotŽ d'une case libre
     if (etat[x][y] == 0) {                                              // Si la case est un bouton vierge
          if (mine[x][y] == 0) {                                         // Si c'est une case vide
               document.getElementById(name(x, y)).src = bLibre.src ;    // Met ˆ jour l'affichage
               decouvert() ;
               etat[x][y] = 2 ;                                          // enregistre que la case est dŽcouverte 
               if (x > 0) {
                    zoneLibre(x-1, y) ;
                    if (y < (hauteur-1)) zoneLibre(x-1, y+1) ;
                    if (y > 0) zoneLibre(x-1, y-1) ;
               }
               if (x < (largeur-1)) {
                    zoneLibre(x+1, y) ;
                    if (y < (hauteur-1)) zoneLibre(x+1, y+1) ;
                    if (y > 0) zoneLibre(x+1, y-1) ;
               }
               if (y < (hauteur-1)) {
                    zoneLibre(x, y+1) ;
               }
               if (y > 0) {
                    zoneLibre(x, y-1) ;
               }
          } else devoiler1a8(x, y) ;                      // si la case n'est pas vide, on affiche le nombre et on arr?te d'explorer dans cette direction
     }
}

function clic(x, y, evt) {     
// Le joueur déclenche l'évennement evt en cliquant sur la case de coordonnées (x, y)
// Gère les événements clic gauche (dévoiler une case) et shift+clic gauche (marquer une case)
     if (temps == 0) chrono() ;
     if ((jeuEnCours == 0) && (etat[x][y] == 0)) {
          if (evt.shiftKey) {                                                 // Si shift+clic sur une case non marquée
               document.getElementById(name(x, y)).src = bMarque.src ;        // on met à jour l'affichage
               etat[x][y] = 1 ;                                               // on enregistre que la case est marquée
               marque(-1) ;                                                   // Calcul du nb de case à déminer
          } else {
               if (mine[x][y] == -1) {                                            // clic sur une mine
                    jeuEnCours = -1;                                              // arrêt du jeu
                    document.getElementById(name(x, y)).src = bMineBoum.src;      // met à jour l'affichage
                    etat[x][y] = -1 ;                                             // la case affiche l'image bMineBoum
                    devoilerMines();                                              // on dévole la position des autres mines et des éventuelle erreurs de marquage
               } else if (mine[x][y] == 0) {                                      // clic sur une case libre (cad avec 0 mines autour)
                    zoneLibre(x, y) ;                                             // Le traitement de ce cas est pris en charge par une fonction indépendante (récursive)
               } else devoiler1a8(x, y) ;                                         // La case n'est ni minée ni vide, on affiche le chiffre correspondant au nombre de mines autour
          }
     } else if ((jeuEnCours == 0) && (evt.shiftKey) && (etat[x][y] == 1)) {             // Si shift+clic sur une case marquée
          document.getElementById(name(x, y)).src = bVierge.src;                                       // met à jour l'affichage
          etat[x][y] = 0 ;                                                              // enregistre que la case n'est plus marquée
          marque(1);                                                                    // Calcul du nb de case restaant à déminer
     }
     return true ;
}


// initialisations

// Dimensions par défaut du démineur
hauteur = 12 ;
largeur = 20 ;
qMine = 19 ;
nbDecouvert = 0 ;
// Modifie les dimensions si le joueur l'a demandé
getParam() ;

jeuEnCours = 0 ;    // vaut 1 quand le joueur a gagné, -1 quand il a perdu et 0 pendant qu'il joue

temps = 0 ;     // nb de secondes depuis le début de la partie

// Instanciation de deux matrices [16, 30]. Toutes les cases sont initialisées à zéro
etat = new Array(largeur) ;     // Action de l'utilisateur sur la case : aucune (0), marqué (1), découvert(2)
for (i=0; i<largeur; i++) {
     etat[i] = new Array(hauteur) ;
     for (j=0; j<hauteur; j++) etat[i][j] = 0 ;
}
mine = new Array(largeur) ;     // Ce qu'il y a dans la case (une mine, un 6, rien...)
for (i=0; i<largeur; i++) {
     mine[i] = new Array(hauteur) ;
     for (j=0; j<hauteur; j++) mine[i][j] = 0 ;
}

nbMine = 0 ;                      // Compte le nombre de mines non marquées
while (nbMine < qMine) {          // Placement alŽatoire des mines dans la matrice mine
     j = Math.round(Math.random() * (hauteur-1)) ;
     i = Math.round(Math.random() * (largeur-1)) ;
     if (mine[i][j] == 0) {
          mine[i][j] = -1 ;
          nbMine = nbMine + 1 ;
     }
}

// Dans chaque case non minées, on inscrit le nombre de mine autour
for (i=0; i<largeur; i++) for (j=0; j<hauteur; j++) if (mine[i][j] == 0) {
     if ((i>0) && (mine[i-1][j] == -1)) mine[i][j]++ ;
     if ((j>0) && (mine[i][j-1] == -1)) mine[i][j]++ ;
     if ((i<(largeur-1)) && (mine[i+1][j] == -1)) mine[i][j]++ ;
     if ((j<(hauteur-1)) && (mine[i][j+1] == -1)) mine[i][j]++ ;
     if ((i>0) && (j>0) && (mine[i-1][j-1] == -1)) mine[i][j]++ ;
     if ((i>0) && (j<(hauteur-1)) && (mine[i-1][j+1] == -1)) mine[i][j]++ ;
     if ((i<(largeur-1)) && (j>0) && (mine[i+1][j-1] == -1)) mine[i][j]++ ;
     if ((i<(largeur-1)) && (j<(hauteur-1)) && (mine[i+1][j+1] == -1)) mine[i][j]++ ;
}

