/*
Cubix Javascript-Teil:

Entwicklung mit Netbeans, Grafiken mit Paintshop und Gimp, Tests mit Mozilla Firefox 3
12.9.09: Basisspiel mit einfachen/einfarbigen Kuben auf Brett 7x7x5, Trennung Javascript von HTML
13.9.09: Animationen soweit vorhanden getunt, eingebaut: Hiscore,laden,speichern, Bonussystem Fibonacci, so angepasst dass 3 == 3
14.9.09: bei längeren Aktionen scheint Mozilla Probleme mit 3-dim-Feldern zu haben,
         bei heftigerem Gebrauch von normalen Feldern und Vektoren treten Speicherfehler auf.
         daher Umschreiben der Felder vorrat und f auf Klasse point3d
         f und v beinhalten zusätzlich die fürs Level verbratenen Cubi-Ids
15.9.09: Übungslevels und mainloop-Zweige angepasst, Block-Steine getestet
16.9.09: Ani-Loop optimiert, Hooks für Erweiterungen, Leveleditor, weitere Levels mit Blöcken, entworfen und einprogrammiert: Bombe einfach, Splitterbombe, pause/weiter
18.9.09: Entwerfen Einprogrammieren und Test: Joker und Farbbombe mit Hilfslevels
20.9.09: Bug bei Splitterbomben entfernt, Doppelsteine mit Türkis entworfen, Doppler einprogrammiert und getestet, Anleitung geschrieben
21.9.09: Doppler getestet und 3 levels erstellt (jetzt 21 Levels in Reihe)

Todo:
Levels zu Joker und Farbbomben
*/

var ofx=32,ofy=160;
var xmax=7,ymax=7,zmax=5,max=xmax*ymax*zmax;
var vlen=3;

var i,j,k,k0;
var fliste=new Array(); // Kubenfarben des Levels als counted Array
var liste =new Array(); // Counted Array mit Sprite-Ids für eine Auswertung oder Animation
var v=new Array(); for (i=0; i<vlen; i++) if (i>0) v[i]=new point3d(192-i*64,320,5); else v[i]=new point3d(240,320,5); // Kuben-Vorschau
var f=new Array(); k0=0; for (k=0; k<zmax; k++) for (j=0; j<ymax; j++) for (i=0; i<xmax; i++) { f[k0]=new point3d(i,j,k); k0++; } // Kuben-Brett
var cubi=new Array(); for (i=0; i<max; i++) cubi[i]=new sprite(i); // Kuben an sich
var crsr=new sprite(max+vlen); crsr.prio=255;                      // Cursor für Zug

var zeit=60,punkte=0,punkte0=0,level=0,lname,timrec1,tic=50,ticspsec=20,ticount,aktiv,whatnext=0,pausiert,sonderflag;
var aktchip1=-1,aktchip2=-1;

// ----- Sprites und Zubehör: --------------------------------------------------------------------------------------------------------------
function point3d(x,y,z)
{ this.x=x; this.y=y; this.z=z; this.inhalt=-1;
  this.set_koo=function(x,y,z) { this.x=x; this.y=y; this.z=z; }
  this.linear=function(xm,ym) { return this.x+xm*(this.y+ym*this.z); } 
}

function sprite(id)
{ this.id=id;
  this.posi=new point3d(-1,-1,-1);    // Brettkoordinaten
  this.scrpos=new point3d(0,0,0);   // Screenkoordinaten
  this.speed=new point3d(0,0,0);    // Bewegung
  this.farbe=1;                     // bisher 0: Block, 1-7: normaler Farbstein
  this.variante="";                 // bisher: "":normal, "trans": halbdurchsichtig
  this.zustand=0;                   // 0:off, 1:on
  this.ima='i'+id;                  // DOM-Interface Bild
  this.lay='l_'+id;                 // DOM-Interface Container
  this.on=function()  { document.getElementById(this.lay).style.visibility="visible"; this.zustand=1; }
  this.off=function() { document.getElementById(this.lay).style.visibility="hidden"; this.zustand=0; }
  this.show=function()
  { document.getElementById(this.lay).style.zIndex=this.scrpos.z;
    document.getElementById(this.lay).style.top=this.scrpos.y;
    document.getElementById(this.lay).style.left=this.scrpos.x;
    this.on();
  }
  this.set_farbe=function(farbe,xtra)
  { this.farbe=farbe; this.variante=xtra;
    if (xtra=="trans") document.images[this.ima].src=imat[this.farbe].src;
    else document.images[this.ima].src=ima[this.farbe].src;
  }
  this.set_at=function(xx,yy,zz)
  { this.posi.set_koo(xx,yy,zz);
    this.scrpos.set_koo(16*xx+32*yy+ofx,ofy-28*zz+16*xx-8*yy,(ymax-yy)*(xx+1)*(zz+1));
  }
// nur Anzeige:
  this.wandern=function()
  { this.set_at(this.posi.x+this.speed.x,this.posi.y+this.speed.y,this.posi.z+this.speed.z);
    this.show();
  }  
// nur Cursor:
  this.snap=function(mx) 
  { var xx=mx-ofx;
    if (xx<112) { xx=Math.floor(xx/16); if (xx<0) xx=0; this.set_at(xx,-1,0); this.speed.set_koo(0,1,0); }
    else { xx=xx-112; xx=Math.floor(xx/32); if (xx>=ymax) xx=ymax-1; this.set_at(xmax,xx,0); this.speed.set_koo(-1,0,0); }
    this.scrpos.z=255;
    this.show();
  }

}

function freier_cubi() { var i,k=-1; for (i=1; i<max; i++) if (k<0) if (cubi[i].zustand<1) k=i; return k; }
function init_vorrat() { for (var i=0; i<3; i++) v[i].inhalt=get_neustein(fliste); }
function neuer_stein() { for (var i=1; i<3; i++) v[i-1].inhalt=v[i].inhalt; v[2].inhalt=get_neustein(fliste); }
function get_neustein(l) { var k=freier_cubi(); with(cubi[k]) { set_farbe(l[Math.floor(l[0]*Math.random())%l[0]+1],""); zustand=1; }  return k; }


// ----- DOM-Kram und andere Anzeigen ------------------------------------------------------------------------------------------
var ima=new Array(); 
var imat=new Array();
for (i=0; i<25; i++)
{ ima[i]=new Image(); ima[i].src='wue'+i+'.gif';
  imat[i]=new Image(); imat[i].src='wue'+i+'trans.gif';
}

function toggle_pause()
{ pausiert=(!pausiert);
  if (pausiert)
  { aktiv=false; 
    document.getElementById("bgr").style.zIndex=254;
    document.getElementById("pause").firstChild.nodeValue="weiter";
  }
  else
  { aktiv=true; 
    document.getElementById("bgr").style.zIndex=0;
    document.getElementById("pause").firstChild.nodeValue="Pause";
  }
}

function set_scene(nr)
{ switch(nr%4)
  { case 1: document.getElementById("bgr").style.backgroundImage="url(backgr_nordlicht.jpg)"; break;
    case 2: document.getElementById("bgr").style.backgroundImage="url(backgr_flammen.jpg)"; break;
    case 3: document.getElementById("bgr").style.backgroundImage="url(backgr_roterdrache.jpg)"; break;
    default: document.getElementById("bgr").style.backgroundImage="url(backgr_safir.jpg)";
  }
}

function updat_level() { document.form1.level.value=lname; }
function updat_zeit()  { document.form1.zeit.value=zeit; }
function updat_punkte() { document.form1.punkte.value=punkte; }
function mauskoords(mx,my) { if (crsr.zustand>0) crsr.snap(mx); }

function zeige_vorrat()
{ crsr.off();
  for (var i=0; i<3; i++) with(cubi[v[i].inhalt]) { scrpos.set_koo(v[i].x,v[i].y,v[i].z); set_farbe(farbe,""); show(); }
  with(crsr) { set_farbe(cubi[v[0].inhalt].farbe,"trans"); on(); }
}

// ----- Interaktionen: -------------------------------------------------------------------------------------------------------

function neu() { level=0; punkte=0; whatnext=0; starte_level(); }

function klick()
{ aktchip1=v[0].inhalt;
  aktchip2=-1;
  with(crsr) if (move_at(posi.x,posi.y))
  { cubi[aktchip1].speed.x=speed.x;
    cubi[aktchip1].speed.y=speed.y;
    cubi[aktchip1].speed.z=0;
    cubi[aktchip1].set_at(posi.x,posi.y,0);
    off();
    sonderflag=0;
    if (farbe==8) sonderflag=1;        // einfache Bombe, killt den getroffenen Stein oder verpufft am Rand
    else if (farbe==9) sonderflag=2;   // Splitterbombe, killt bei Auftreffen alle Nachbarn oder verpufft am Rand
    else if (farbe==10) sonderflag=3;  // Geisterfuffi, Farbe in Zustand, wandelt sich bei Misserfolg in normalen Stein um
    else if (farbe==11) sonderflag=4;  // Joker, nimmt Farbe des getroffenen Kubus an
    else if ((farbe>11) && (farbe<19)) sonderflag=5; // Farbbombe
    whatnext=1; // bewegen
    liste[0]=0; // Liste der abgeschossenen Kuben initialisieren 
  }
  else whatnext=0; // Warten auf Zug
}

// ----- Spielverlauf -------------------------------------------------------------------------------------------------------------------------------

function starte_level()
{ var i,ind;
  aktiv=false;
  leeren();
  set_scene((Math.floor(level/3))%4);
  lname=mach_level(level);
  if (lname!="") for (i=0; i<f0.length; i++)
  { ind=1;
    for (i=0; i<max; i++) if (f0[i]>-1) with(cubi[ind])
    { set_farbe(f0[i],""); 
      set_at(f[i].x,f[i].y,f[i].z);
      f[i].inhalt=id;
      show();
      ind++;
    }
    init_vorrat(fliste);
    zeige_vorrat();
    punkte0=punkte;
    updat_level();
    updat_zeit();
    updat_punkte();
    pausiert=true;
    toggle_pause(); 
    ticount=0;
    whatnext=0;
  }
  else gameover(4);
}

function mainloop()
{ var i,j,k;
  if (aktiv)
  { switch(whatnext)
    { case 0: ticount++; if (ticount>ticspsec) { ticount=0; zeit--; updat_zeit(); if (zeit<1) whatnext=99; } break; // Warten auf Zug 
      case 1: k=checkwandern(aktchip1);
              if (k==-1) cubi[aktchip1].wandern();
              else if (k==-2) switch(sonderflag) // hängt am Rand
              { case 1: cubi[aktchip1].off(); whatnext=2; break;                                       // einfache Bombe
                case 2: cubi[aktchip1].off(); liste=splitterbombe(cubi[aktchip1]); whatnext=3; break;  // Splitterbombe
                case 3: with(cubi[aktchip1]) // Fuffi
                        { var kk=-1; while ((kk<1) || (kk>7)) kk=fliste[Math.floor(fliste[0]*Math.random())%fliste[0]+1];
                          set_farbe(kk,""); show(); f[posi.linear(xmax,ymax)].inhalt=id; zustand=sonderflag;
                        }
                        whatnext=2;
                        break;
                case 4: with(cubi[aktchip1])                                     // Joker
                        { j=-1; while ((j<0) || (j>7)) j=fliste[Math.floor(fliste[0]*Math.random())%fliste[0]+1];
                          set_farbe(j,""); show(); f[posi.linear(xmax,ymax)].inhalt=aktchip1;
                        }
                        whatnext=2;
                        break;
                case 5: with(cubi[aktchip1]) { set_farbe(farbe-11,""); show(); f[posi.linear(xmax,ymax)].inhalt=id; zustand=sonderflag; } whatnext=2;  break; 
                default: f[cubi[aktchip1].posi.linear(xmax,ymax)].inhalt=aktchip1; whatnext=2; // normaler Chip, nur fixieren
              }  
              else // berührt Chip(Id)
              { if (aktchip2>=0)
                { with(cubi[aktchip2])
                  { speed.set_koo(cubi[aktchip1].speed.x,cubi[aktchip1].speed.y,cubi[aktchip1].speed.z);
                    f[posi.linear(xmax,ymax)].inhalt=-1; wandern(); f[posi.linear(xmax,ymax)].inhalt=id;
                  }  
                  cubi[aktchip1].wandern(); 
                }
                with(cubi[aktchip1]) switch(sonderflag)
                { case 1: cubi[aktchip1].off(); liste=Array(1,k); whatnext=3; break;                 // einfache Bombe
                  case 2: cubi[aktchip1].off(); liste=splitterbombe(cubi[id]); whatnext=3; break;    // Splitterbombe
                  case 3: f[posi.linear(xmax,ymax)].inhalt=id;                                       // Fuffi
                          var j=-1; while ((j<1) || (j>7)) j=fliste[Math.floor(fliste[0]*Math.random())%fliste[0]+1];
                          set_farbe(j,""); show(); zustand=sonderflag; whatnext=2;
                          break; 
                  case 4: f[posi.linear(xmax,ymax)].inhalt=id; set_farbe(cubi[k].farbe,""); show(); whatnext=2; break;   // Joker        
                  case 5: f[posi.linear(xmax,ymax)].inhalt=id; set_farbe(farbe-11,""); show(); whatnext=2; break;        // Farbbombe 
                  default: f[posi.linear(xmax,ymax)].inhalt=aktchip1; whatnext=2;                                        // normaler Chip, nur fixieren
                }
              }
              break;
      case 2: liste=check_triplett();
              if (liste[0]>0)
              { k=liste[0];
                punkte=punkte+bonus(k); updat_punkte(); // Auswertung normaler Steine
                // for (i=1; i<=k; i++) if (liste[i]>18) && (liste[i]<40) sub_liste(liste[i],liste);
                cubis_faden();
                switch(sonderflag)
                { case 3: punkte=punkte+50; updat_punkte(); break;
                  case 5: var fb,fa=cubi[aktchip1].farbe;
                          for (i=0; i<max; i++) if (f[i].inhalt>0) with(cubi[f[i].inhalt])
                          { if (fa==farbe) add_liste(id,liste);  
                            else if ((farbe>18) && (farbe<40)) { fb=restfarbe(fa,farbe); if (fb>0) set_farbe(fb,""); }
                          }
                }
                whatnext=3; 
              }
              else whatnext=4;
              break;                               
      case 3: cubis_loeschen(); whatnext=7; break; 
      case 4: if (levelfertig()) whatnext=9; else whatnext=6; break;
      case 6: neuer_stein(fliste); zeige_vorrat(); if (!checkmove()) { aktiv=false; gameover(3); } else whatnext=0; break;
      case 7: if (dropdown()) whatnext=2; else whatnext=4; break;
      case 9: punkte=punkte+zeit; updat_punkte(); level++; starte_level(); break;
      case 99: gameover(1); break;
    }
  }
  timrec1=setTimeout('mainloop()',50);
}

function splitterbombe(obj)
{ var p1=new point3d(obj.posi.x,obj.posi.y,obj.posi.z); 
  var liste=new Array(0,0);
  with(p1) 
  { x++; if (x>=0) if (y>=0) if (z>=0) if (x<xmax) if (y<ymax) if (z<zmax) if (f[linear(xmax,ymax)].inhalt>-1) add_liste(f[linear(xmax,ymax)].inhalt,liste); x--;
    x--; if (x>=0) if (y>=0) if (z>=0) if (x<xmax) if (y<ymax) if (z<zmax) if (f[linear(xmax,ymax)].inhalt>-1) add_liste(f[linear(xmax,ymax)].inhalt,liste); x++;
    y++; if (x>=0) if (y>=0) if (z>=0) if (x<xmax) if (y<ymax) if (z<zmax) if (f[linear(xmax,ymax)].inhalt>-1) add_liste(f[linear(xmax,ymax)].inhalt,liste); y--;
    y--; if (x>=0) if (y>=0) if (z>=0) if (x<xmax) if (y<ymax) if (z<zmax) if (f[linear(xmax,ymax)].inhalt>-1) add_liste(f[linear(xmax,ymax)].inhalt,liste); y++;
    z++; if (x>=0) if (y>=0) if (z>=0) if (x<xmax) if (y<ymax) if (z<zmax) if (f[linear(xmax,ymax)].inhalt>-1) add_liste(f[linear(xmax,ymax)].inhalt,liste); z--;
    z--; if (x>=0) if (y>=0) if (z>=0) if (x<xmax) if (y<ymax) if (z<zmax) if (f[linear(xmax,ymax)].inhalt>-1) add_liste(f[linear(xmax,ymax)].inhalt,liste); z++;
  }
  for (i=1; i<=liste[0]; i++) cubi[liste[i]].set_farbe(cubi[liste[i]].farbe,'trans');
  return liste;
}

function restfarbe(fa,fdopp)
{ var k1=fa,k2=fdopp,ret=-1;
  if (k1>k2) { k2=fa; k1=fdopp; }
  switch(k2)
  { case 19: if (k1==1) ret=2; else if (k1==2) ret=1; break;
    case 20: if (k1==1) ret=3; else if (k1==3) ret=1; break;
    case 21: if (k1==1) ret=4; else if (k1==4) ret=1; break;
    case 22: if (k1==1) ret=5; else if (k1==5) ret=1; break;
    case 23: if (k1==1) ret=6; else if (k1==6) ret=1; break;
    case 24: if (k1==1) ret=7; else if (k1==7) ret=1; break;
    case 25: if (k1==2) ret=3; else if (k1==3) ret=2; break;
    case 26: if (k1==2) ret=4; else if (k1==4) ret=2; break;
    case 27: if (k1==2) ret=5; else if (k1==5) ret=2; break;
    case 28: if (k1==2) ret=6; else if (k1==6) ret=2; break;
    case 29: if (k1==2) ret=7; else if (k1==7) ret=2; break;
    case 30: if (k1==3) ret=4; else if (k1==4) ret=3; break;
    case 31: if (k1==3) ret=5; else if (k1==5) ret=3; break;
    case 32: if (k1==3) ret=6; else if (k1==6) ret=3; break;
    case 33: if (k1==3) ret=7; else if (k1==7) ret=3; break;
    case 34: if (k1==4) ret=5; else if (k1==5) ret=4; break;
    case 35: if (k1==4) ret=6; else if (k1==6) ret=4; break;
    case 36: if (k1==4) ret=7; else if (k1==7) ret=4; break;
    case 37: if (k1==5) ret=6; else if (k1==6) ret=5; break;
    case 38: if (k1==5) ret=7; else if (k1==7) ret=5; break;
    case 39: if (k1==6) ret=7; else if (k1==7) ret=6; break;
 }
 return ret;
}

function levelup() { aktiv=false; punkte=punkte+zeit; updat_punkte(); level++; starte_level(); }

function gameover(nr)
{ aktiv=false;
  switch(nr)
  { case 1: alert("Deine Zeit ist abgelaufen!"); break;
    case 3: alert("Kein Zug mehr möglich!"); break;
    case 4: alert("Alle Levels durchgespielt!"); break;
  }
  try { eintrag('form1'); } catch (err) { alert('lokale Version, kein Eintrag!'); }
}


// ----- Testereien ------------------------------------------------------------------------------------------------------

function checkwandern(chip) // gibt die Art der Bremse aus, -2:Rand, -1:Wandern, Chip-Id:hängt hier, ist aktchip2 besetzt, dann Schiebung  
{ var ret=0,xx,yy,ko1=-1,ko2=-1;
  aktchip2=-1;  
  with(cubi[chip]) { xx=posi.x+speed.x; yy=posi.y+speed.y; }     if (xx>=0) if (xx<xmax) if (yy>=0) if (yy<ymax) ko1=xx+xmax*yy; // Zielposition 1
  with(cubi[chip]) { xx=posi.x+2*speed.x; yy=posi.y+2*speed.y; } if (xx>=0) if (xx<xmax) if (yy>=0) if (yy<ymax) ko2=xx+xmax*yy; // Zielposition 2
  if (ko1<0) ret=-2; else if (f[ko1].inhalt<0) ret=-1; else { ret=f[ko1].inhalt; if (ko2>=0) if (f[ko2].inhalt<0) aktchip2=f[ko1].inhalt; }
  if (aktchip2>=0) if (cubi[aktchip2].farbe==0) aktchip2=-1; 
  return ret;
}

function check_triplett() // Check auf Triplett, normale Steine und Doppler
{ var i,j,k0,k1,k2;
  var liste=new Array(0,0);
  var hliste=new Array(0,0);
  for (i=0; i<max; i++) if (f[i].inhalt>=0) with(cubi[f[i].inhalt]) if (farbe>0)
  { if (farbe<8) { hliste=get_kette(id,farbe); if (hliste[0]>2) concat_listen(farbe,hliste,liste); }
    else if ((farbe>18) && (farbe<40)) // Doppler
    { if (farbe<25) k0=1; else if (farbe<30) k0=2; else if (farbe<34) k0=3; else if (farbe<37) k0=4; else if (farbe<39) k0=5; else k0=6;
      k1=restfarbe(farbe,k0);
      hliste=get_kette(id,k0); if (hliste[0]>2) concat_listen(k0,hliste,liste);
      hliste=get_kette(id,k1); if (hliste[0]>2) concat_listen(k1,hliste,liste);
    }
  }
  return liste;
}

function concat_listen(fa,l1,l2)
{ var j,k1,k2=l1[0];
  for (j=1; j<=k2; j++) with(cubi[l1[j]])
  { k1=restfarbe(farbe,fa);
    if (k1>0) set_farbe(k1,''); else add_liste(id,l2);
  }
}
 

function checkmove() // Test, ob Zug möglich
{ var i,ismove=((cubi[v[0].inhalt].farbe==8) || (cubi[v[0].inhalt].farbe==9)); // 8,9:Bomben
  if (!ismove) for (i=0; i<xmax; i++) if (move_at(i,-1)) ismove=true;
  if (!ismove) for (i=0; i<ymax; i++) if (move_at(xmax,i)) ismove=true;
  return ismove;
}

function move_at(xx,yy) // Test ob Zug hier möglich:
{ var ismove=((crsr.farbe==8) || (crsr.farbe==9)),ko,ko1; // 8=Bombe
  if (!ismove)
  { if (yy<0) // Schieben auf x-Reihe nach positivem y
    { ko=xx; ko1=ko+xmax;
      if (f[ko].inhalt<0) ismove=true;
      else if ((cubi[f[ko].inhalt].farbe>0) && (f[ko1].inhalt<0)) ismove=true;
    }
    else 
    { ko=xmax-1+yy*xmax;
      ko1=ko-1;
      if (f[ko].inhalt<0) ismove=true; else if ((cubi[f[ko].inhalt].farbe>0) && (f[ko1].inhalt<0)) ismove=true;
    }
  }
  return ismove;
}

function levelfertig() { var i,ok=true; for (i=0; i<max; i++) if (f[i].inhalt>0) if (cubi[f[i].inhalt].farbe>0) ok=false; return ok; }

// ----- Helferlein --------------------------------------------------------------------------------------------------

function speichern() { set_cookie('cubix',level,punkte0); if (document.cookie) alert('Spielstand gespeichert'); }
function laden()     { aktiv=false; get_cookie('cubix'); punkte=punkte0; starte_level(); }
function leeren()    { for (var i=0; i<max; i++) { f[i].inhalt=-1; cubi[i].off(); } }

function bonus(nr)   { var i,k=0,k1=0,k2=1; for (i=1; i<=nr; i++) { k=k1+k2; k1=k2; k2=k; } return k; } // Fibonacci-Reihe
function cubis_faden() { for (var i=1; i<=liste[0]; i++) with(cubi[liste[i]]) set_farbe(farbe,"trans"); }

function cubis_loeschen()
{ var fa=cubi[liste[1]].farbe;
  for (var i=1; i<=liste[0]; i++) with(cubi[liste[i]])
  { if ((farbe<19) || (fa>18)) { f[posi.linear(xmax,ymax)].inhalt=-1; off(); fa=farbe; }
    else  { fa=restfarbe(fa,farbe); if (fa>-1) set_farbe(fa,""); }
  } 
}

function dropdown() // nach Entfernen etwaiger Kuben Steine fallenlassen
{ var i,j,k,k0,k1,dk=xmax*ymax;
  var drop,gedroppt=false;
  var vec=new Array();
  for (i=0; i<xmax; i++) for (j=0; j<ymax; j++)
  { k0=i+j*xmax;
    for (k=0; k<zmax; k++) vec[k]=-1;
    k1=0; for (k=0; k<zmax; k++) if (f[k0+k*dk].inhalt>-1) { vec[k1]=f[k0+k*dk].inhalt; k1++; } 
    for (k=0; k<zmax; k++) if (f[k0+k*dk].inhalt!=vec[k])
    { gedroppt=true; f[k0+k*dk].inhalt=vec[k];
      if (vec[k]>=0) with(cubi[vec[k]]) { set_at(i,j,k); show(); }
    }
  }
  return gedroppt;
}

// ===============================================================================================================
// Fill-Algo rechtwinkliges System 3D, einfach - braucht _listen.js
// ---------------------------------------------------------------------------------------------------------------

function get_kette(nr,fa)
{ var i,ptr0,ptr1=0;
  var liste=new Array(1,nr); // Liste mit Sprite-IDs
  while (ptr1<liste[0]) { ptr0=ptr1+1; ptr1=liste[0]; for (i=ptr0; i<=ptr1; i++) check_nachbarn(fa,liste[i],liste); }
  return liste;
}

function check_nachbarn(fa,nr,liste) // N,O,S,W,o,u
{ with(cubi[nr]) if (zustand>0)
  { var i=posi.linear(xmax,ymax),k;
    if (posi.x>0)      { k=i-1;         if (f[k].inhalt>=0) if (passt(cubi[f[k].inhalt].farbe,fa)) add_liste(cubi[f[k].inhalt].id,liste); }
    if (posi.x<xmax-1) { k=i+1;         if (f[k].inhalt>=0) if (passt(cubi[f[k].inhalt].farbe,fa)) add_liste(cubi[f[k].inhalt].id,liste); }
    if (posi.y>0)      { k=i-xmax;      if (f[k].inhalt>=0) if (passt(cubi[f[k].inhalt].farbe,fa)) add_liste(cubi[f[k].inhalt].id,liste); }
    if (posi.y<ymax-1) { k=i+xmax;      if (f[k].inhalt>=0) if (passt(cubi[f[k].inhalt].farbe,fa)) add_liste(cubi[f[k].inhalt].id,liste); }
    if (posi.z>0)      { k=i-xmax*ymax; if (f[k].inhalt>=0) if (passt(cubi[f[k].inhalt].farbe,fa)) add_liste(cubi[f[k].inhalt].id,liste); }
    if (posi.z<zmax-1) { k=i+xmax*ymax; if (f[k].inhalt>=0) if (passt(cubi[f[k].inhalt].farbe,fa)) add_liste(cubi[f[k].inhalt].id,liste); }
  }
}

// variabler Teil:
function passt(n1,n2)
{ var flag=((n1>0) && (n2>0));
  if (flag)
  { flag=(n1==n2); // normale Steine und vor der Auswertung "korrigierte" Steine wie Farbbomben, Geister und Joker
    if (!flag) // Doppelsteine
    { if ((n1>18) || (n2>18)) flag=(restfarbe(n2,n1)>0);
    }
  }
  return flag;
}

// ---------------------------------------------------------------------------------------------------------------


