//
// biscia.js
// gestione gioco interattivo 'La biscia'
//

// **********************************************
//                   DATI LOCALI
// **********************************************
MAX_COLONNE     = 10; // numero massimo colonne schema
MAX_RIGHE       = 10; // numero massimo righe schema
SCAMBI_COLONNA  =  4; // scambi (x2) colonna-colonna
SCAMBI_RIGA     =  4; // scambi (x2) riga-riga
SCAMBI_TOTALI   =  SCAMBI_COLONNA + SCAMBI_RIGA;
                      // scambi (x2) riga-riga e colonna-colonna

Dim=35;

var primac, primar,     // indice prima colonna, riga scelta
    secondac, secondar, // indice seconda colonna, riga scelta
    selezionatec = 0,   // numero di colonne scelte
    selezionater = 0,   // numero di righe scelte

    disposizione = new Array(SCAMBI_TOTALI),
                   // scambi casuali colonne e righe
                   // 0..SCAMBI_RIGA-1: indici righe
                   // SCAMBI_RIGA..SCAMBI_TOTALI (=SCAMBI_RIGA+SCAMBI_COLONNA)
                   //                 : indici colonne
          indici = new Array(MAX_COLONNE*MAX_RIGHE),
                   // indici posizioni caratteri

    colonne, // miglior numero colonne schema da visualizzare
    righe,   // miglior numero righe schema da visualizzare

    pcsl,    // indice aggancio delle div con contenuto schema;
             // e' indice X di div con id eitX che corrisponde a prima
             // casella lettere contenute in schema da risolvere
             // Necessario perche' lo schema disegnato include anche numeri
             // righe e numeri colonne

    SchemaGiocato = new Array(MAX_RIGHE+MAX_COLONNE);
    // schema giocato da utente (lista indici righe + indici colonne)

// **********************************************
// FUNZIONI COMUNI, ADATTATE AL SINGOLO GIOCO
// **********************************************
function reset_schema()
// imposta strutture dati per (ri)partire col gioco
{
// CODICE COMUNE
  if (Risolto || SoluzioneVista || VediSoluzione || VediInfo)
    return;

// CODICE LOCALE
  for (i=0;i<colonne*righe;i++)
    indici[i]=i;
  // inizializza array indici

  for (i=0;i<MAX_RIGHE;i++)
    SchemaGiocato[i]=i;
  for (i=0;i<MAX_COLONNE;i++)
    SchemaGiocato[MAX_RIGHE+i]=i;
  // inizializzazione schema giocato: tutti indici a posto

  // qui effettua scambi indici posizioni caratteri secondo disposizioni
  // appena scelte e validate
  for (i=0;i<SCAMBI_TOTALI/2;i++)
  {
    if (i>=(SCAMBI_TOTALI/4))
    // se sta a colonne essere scambiate
    {
      temp=
        SchemaGiocato[MAX_RIGHE+disposizione[i*2]];
      SchemaGiocato[MAX_RIGHE+disposizione[i*2]]=
        SchemaGiocato[MAX_RIGHE+disposizione[i*2+1]];
      SchemaGiocato[MAX_RIGHE+disposizione[i*2+1]]=temp;
      for (j=0;j<righe;j++)
      {
        temp=indici[j*colonne+disposizione[i*2]];
        indici[j*colonne+disposizione[i*2]]=
          indici[j*colonne+disposizione[i*2+1]];
       indici[j*colonne+disposizione[i*2+1]]=temp;
      }
      // scambia colonne
    }
    else
    // altrimenti sta a righe essere scambiate
    {
      temp=SchemaGiocato[disposizione[i*2]];
      SchemaGiocato[disposizione[i*2]]=
        SchemaGiocato[disposizione[i*2+1]];
      SchemaGiocato[disposizione[i*2+1]]=temp;
      for (j=0;j<colonne;j++)
      {
        temp=indici[colonne*disposizione[i*2]+j];
        indici[colonne*disposizione[i*2]+j]=
          indici[colonne*disposizione[i*2+1]+j];
        indici[colonne*disposizione[i*2+1]+j]=temp;
      }
      // scambia righe
    }
  }
  // scambia elementi array in sequenza: colonne, righe, colonne, righe

// CODICE COMUNE
  vedi_schema();
}

function nuovo_schema()
// calcola parametri schema scelto e lo visualizza
{
  var dim;

  dim=Esposto.length;                 // acquisisce dimensioni frase
  colonne=Math.floor(Math.sqrt(dim)); // calcola prima approssimazione

  while ((dim/colonne)!=(Math.floor(dim/colonne)))
    colonne--;
  // cerca migliore scomposizione, ottenendo numero colonne

  righe=dim/colonne;

  pcsl=righe+colonne;

  disposizione_casuale();
  // crea sequenza casuale non banale righe e colonne schema
}

function vedi_schema()
// visualizza schema
{
  var i, j, sorg;

  ss='<table align="center" width="100%"><tr><td><table align="center">';
  // corpo tabelle contenenti schema

  ss+='<tr><td><div class="csl" id="eit0"></div></td>';
  // elemento riga che sta sopra colonna contenente numeri righe
  for (j=1;j<=colonne;j++)
    ss+='<td><div class="csl" onClick="cliccata('+j+'); return false;" '+
        'id="'+eittag(j)+'"></div></td>';
  // numeri colonne
  ss+='</tr>';
  // riga contenente numeri colonne

  for (i=0;i<righe;i++)
  {
    ss+='<tr>';   // inizio riga
    ss+='<td><div class="csl" onClick="cliccata('+(i+colonne+1)+
        '); return false;" id="'+eittag(i+colonne+1)+'"></div></td>';
    // numero riga
    for (j=0;j<colonne;j++)
      ss+='<td><div class="csl" id="'+eittag(i*colonne+j+pcsl+1)+
        '"></div></td>';
    ss+='</tr>';
  }
  // righe contenenti indici righe e frase da ricostruire

  ss+='</table></td></tr></table>';
  // chiusura tabelle

  document.getElementById('eitsk').innerHTML=ss;
  // inserisce codice html intero schema

  zooma_font(0);

  for (j=1;j<=colonne;j++)
    document.getElementById(eittag(j)).innerHTML=j;
  // visualizza numeri colonne schema scelto

  for (i=0;i<righe;i++)
  {
    document.getElementById(eittag(colonne+i+1)).innerHTML=i+1;

    for (j=0;j<colonne;j++)
    {
      sorg=Esposto.charAt(indici[i*colonne+j]).toUpperCase();
      document.getElementById(eittag(i*colonne+j+pcsl+1)).innerHTML=sorg;
      // visualizza effettivamente quanto selezionato
    }
  }
  // visualizza lettere schema scelto
}

function cliccata(c)
// reagisce a clic utente
{
  if (Risolto || VediSoluzione)
    return;

  if (c<=colonne)
  // se (cliccato indice colonna)
    scambia_colonne(c);
  else
  // altrimenti
    scambia_righe(c-colonne);

  controlla();
}

function inkeys(e)
// gestore pressione tasti
{
  if (Risolto || SoluzioneVista || VediSoluzione || VediInfo)
    return;

  return false;
}

function controlla()
// controlla soluzione parziale costruita da utente
{
  i=0;
  while (SchemaGiocato[i]==i && i<MAX_RIGHE)
    i++;
  // controlla quante righe sono al loro posto

  if (i<MAX_RIGHE)
    return(false);
  // se almeno una riga sbagliata, ritorna false

  while (SchemaGiocato[i]==(i-MAX_RIGHE) && i<(MAX_RIGHE+MAX_COLONNE))
    i++;
  // controlla quante colonne sono al loro posto

  if (i==MAX_RIGHE+MAX_COLONNE)
  // se indici corrispondono tutti (righe e colonne al loro posto)
  {
    Risolto=true;
    stopTimer();
    // gioco risolto
    vediApplauso();
    // richiama animazione sfinge Kidi che applaude
    // confirm("Ottimo!");
  }
}

function soluzione()
// mostra soluzione schema scelto
{
  if (VediInfo)
    return;

  SoluzioneVista=true;
  VediSoluzione=!VediSoluzione;

  for (i=0;i<righe;i++)
    for (j=0;j<colonne;j++)
    {
      if (VediSoluzione)
        c=Esposto.charAt(i*colonne+j).toUpperCase();
      else
        c=Esposto.charAt(SchemaGiocato[i]*colonne+
                                SchemaGiocato[MAX_RIGHE+j]).toUpperCase();
      document.getElementById(eittag(i*colonne+j+1+pcsl)).innerHTML=c;
    }

  stopTimer();
}

// -------------------------------
// INIZIO CODICE LOCALE AGGIUNTIVO
// -------------------------------
// CODICE DIPENDENTE DAL SINGOLO GIOCO

document.onkeydown=inkeys;
// aggancia gestore pressione tasti alla pagina

function disposizione_casuale()
// crea sequenza casuale non banale con cui disporre colonne e righe schema
{
  var i,                               // di comodo
      min_dist,                        // minima distanza fra indici scambiati
      temp;                            // di comodo
  var presec = new Array(MAX_COLONNE), // colonne prese in scambi
      preser = new Array(MAX_RIGHE),   // righe prese in scambi
      dispt  = new Array(MAX_COLONNE+MAX_RIGHE);
                                       // disposizione indice: a posizione i
                                       // prende valore di indice colonna o
                                       // riga presa a iterazione i

  // qui calcola scambio colonne
  do
  // ripeti
  {
    for (i=0;i<colonne;i++)
      presec[i]=0;
    // inizializza flag colonne prese: nessun indice ancora inserito in
    // disposizione

    for (i=0;i<SCAMBI_COLONNA;i++)
    {
      do
        temp=Math.floor(Math.random()*colonne);
      while (presec[temp]!=0);
      // qui ha scelto numero casuale entro [0..colonne-1]
      presec[temp]=1;   // contrassegna come presa colonna appena scelta
      dispt[i]=temp;    // acquisisce indice
    }
    // calcola disposizione

    // qui esamina validita' disposizione scelta
    min_dist=MAX_COLONNE+1;
    for (i=1;i<(colonne-1);i++)
    {
      temp=Math.abs(dispt[i]-dispt[i-1]);
      if (temp<min_dist)
        min_dist=temp;
    }
    // calcola minima distanza in disposizione colonne
  }
  while (min_dist<2);
  // finche' minima distanza < 2

  for (i=0;i<SCAMBI_COLONNA;i++)
    disposizione[SCAMBI_RIGA+i]=dispt[i];
  // memorizza disposizione casuale colonne appena scelta

  // qui calcola scambio righe
  do
  // ripeti
  {
    for (i=0;i<righe;i++)
      preser[i]=0;
    // inizializza flag righe prese: nessun indice ancora inserito in
    // disposizione

    for (i=0;i<SCAMBI_RIGA;i++)
    {
      do
        temp=Math.floor(Math.random()*righe);
      while (preser[temp]!=0);
      // qui ha scelto numero casuale entro [0..righe-1]
      preser[temp]=1;   // contrassegna come presa riga appena scelta
      dispt[i]=temp;    // acquisisce indice
    }
    // calcola disposizione

    // qui esamina validita' disposizione scelta
    min_dist=MAX_RIGHE+1;
    for (i=1;i<(colonne-1);i++)
    {
      temp=Math.abs(dispt[i]-dispt[i-1]);
      if (temp<min_dist)
        min_dist=temp;
    }
    // calcola minima distanza in disposizione righe
  }
  while (min_dist<2);
  // finche' minima distanza < 2

  for (i=0;i<SCAMBI_RIGA;i++)
    disposizione[i]=dispt[i];
  // memorizza disposizione casuale righe appena scelta
}

function scambia_colonne(num)
// scambia due colonne schema, se deve
{
  var i, temp;

  switch(selezionatec)
  {
    case 0: 
      if ((num>0)&&(num<=colonne))
      {
        primac=num;
        // ancora nessuna colonna selezionata
        selezionatec=1;
      }
      break;
    case 1:
      if ((num>0)&&(num<=colonne))
      {
        if (primac==num)
        // selezionata una seconda colonna ma uguale alla prima
          selezionatec=0;
        else
         // selezionata una seconda colonna diversa dalla prima
         {
           secondac=num;
           for (i=0;i<righe;i++)
           {
             temp=
               document.getElementById(eittag(i*colonne+pcsl+
               primac)).innerHTML;
             document.getElementById(eittag(i*colonne+pcsl+
             primac)).innerHTML=
               document.getElementById(eittag(i*colonne+pcsl+
               secondac)).innerHTML;
             document.getElementById(eittag(i*colonne+pcsl+
               secondac)).innerHTML=temp;
           } // scambia colonne
           temp=SchemaGiocato[MAX_RIGHE+primac-1];
           SchemaGiocato[MAX_RIGHE+primac-1]=
             SchemaGiocato[MAX_RIGHE+secondac-1];
           SchemaGiocato[MAX_RIGHE+secondac-1]=temp;
           // scambia indici colonne in schema giocato da utente
           selezionatec=0;
             // reimposta contatore colonne selezionate
         }
      }
      break;
   default: 
      break;
  }
}

function scambia_righe(num)
// scambia due righe schema, se deve
{
  var i, temp;

  switch(selezionater)
  {
    case 0: 
      if (num<=righe)
      {
        primar=num;
        // ancora nessuna riga selezionata
        selezionater=1;
      }
      break;
    case 1:
      if (num<=righe)
      {
        if (primar==num)
        // selezionata una seconda riga ma uguale alla prima
          selezionater=0;
        else
         // selezionata una seconda riga diversa dalla prima
         {
           secondar=num;
           for (i=0;i<colonne;i++)
           {
             temp=
               document.getElementById(eittag((primar-1)*colonne+pcsl
                 +1+i)).innerHTML;
               document.getElementById(eittag((primar-1)*colonne+pcsl
                 +1+i)).innerHTML=
               document.getElementById(eittag((secondar-1)*colonne+pcsl
                 +1+i)).innerHTML;
               document.getElementById(eittag((secondar-1)*colonne+pcsl
                 +1+i)).innerHTML=temp;
           } // scambia righe
           temp=SchemaGiocato[primar-1];
           SchemaGiocato[primar-1]=SchemaGiocato[secondar-1];
           SchemaGiocato[secondar-1]=temp;
           // scambia indici righe in schema giocato da utente
           selezionater=0;
             // reimposta contatore righe selezionate
         }
      }
      break;
   default: 
      break;
  }
}