/***********************************************************/
/************** parse Parameter () *************************/
/***********************************************************/
function get_C_ROW() {
      PositionOfQuestionMark = window.location.href.indexOf("?");
      Parameter = window.location.href.substr(PositionOfQuestionMark+1);
      if( Parameter.length != 0 && PositionOfQuestionMark != -1 ) {
          /*** Parameter Format: breite;höhe;win ***/
          Pos = Parameter.indexOf(";"); Parameter = Parameter.substr(Pos+1);
          Pos = Parameter.indexOf(";");
          Hoehe = Parameter.substring(0,Pos);
          var C_ROW = parseInt(Hoehe)
          if( !isNaN(C_ROW) ) {
             if( C_ROW > 10 ) C_ROW = 10;
             if( C_ROW < 2 ) C_ROW = 2;
             return C_ROW;
          }
          return 6;
      }
      return 6;
}

function get_C_COL() {
      PositionOfQuestionMark = window.location.href.indexOf("?");
      Parameter = window.location.href.substr(PositionOfQuestionMark+1);
      if( Parameter.length != 0 && PositionOfQuestionMark != -1 ) {
          /*** Parameter Format: breite;höhe;win ***/
          Pos = Parameter.indexOf( ";");
          Breite = Parameter.substring(0,Pos);
          var C_COL = parseInt(Breite)
          if( !isNaN(C_COL) ) {
              if( C_COL > 10 ) C_COL = 10;
              if( C_COL < 2 ) C_COL = 2;
              return C_COL;
          }
          return 7;
      }
      return 7;
}

function get_C_WIN() {
      POQM = window.location.href.indexOf("?");
      Parameter = window.location.href.substr(POQM+1);
      if( Parameter.length != 0 && POQM != -1 ) {
          /*** Parameter Format: breite;höhe;win ***/
          Pos = Parameter.indexOf(";"); Parameter = Parameter.substr(Pos+1);
          Pos = Parameter.indexOf(";");
          Win = Parameter.substr(Pos+1);
          var C_WIN = parseInt(Win)
          if( !isNaN(C_WIN) ) {
              cwinmax = Math.max(get_C_ROW(), get_C_COL());
              if( C_WIN > cwinmax ) C_WIN = cwinmax;
              if( C_WIN < 2 ) C_WIN = 2;
              return C_WIN;
          }
          return 4;
      }
      return 4;
}

/*************************************************************************/
/******************** B E G I N N E R ( ) ********************************/
/*************************************************************************/
function beginner(v) {
         if( isbusy != 2 ) return;
         if( v == HUMANPLAYER ) isbusy = 0;
         if( v == COMPUTERPLAYER ) {
            checkBeginn = true;
            window.setTimeout("incTime()",1000);
            window.setTimeout("computerplayer("+COMPUTERPLAYER+")",100);
         }
}

/*************************************************************************/
/******************** M E L D U N G ( ) **********************************/
/*************************************************************************/
/* wrapper um Anzeige auszuschalten */
function meldung(text) {
         return;
         alert(text);
}

/*************************************************************************/
/******************** R E F R E S H ( ) **********************************/
/*************************************************************************/
/* wrapper um Anzeige auszuschalten */
function refresh() {
         if( isbusy == 1 ) return;
         isbusy=2;
         activecol=-1;
         countStones = 0;
         checkBeginn = false;
         document.ltime.time.value = 0;
         /* field = new Array(C_COL); */
         /* for(t=0; t<C_COL; t++) { field[t]=new Array(C_ROW); } */
         for(t=0; t<C_COL; t++) for(s=0; s<C_ROW; s++) field[t][s]=s-(C_ROW-1);
         /* set_cols = new Array(C_COL*C_ROW); */
         //for(t=0; t<C_COL*C_ROW; t++) set_cols[t]=0;
         //set_cols_ptr=0;
         set_cols="";
         for( x=0; x<C_COL; x++ ) {
              for( y=0; y<C_ROW; y++ ) {
                   gsetxyv(x,y,0);
              }
         }
}

/*************************************************************************/
/***************** W I N M E S S A G E ( ) *******************************/
/*************************************************************************/
function winmessage() {
     checkBeginn = false;
     if( document.lform.elements[0].checked == true || parseInt(countStones) > 10) {
         alert("glückwunsch! sie haben gegen den computer gewonnen.\n\ntipp: versuchen sie doch einmal den computer im\nmodus 'schwer' bei 7x6 Feldern in maximal 10 zügen zu bezwingen.\ndann erscheinen sie in der bestenliste von 4 gewinnt.");
         return;
     }
     if( C_COL != 7 || C_ROW != 6) {
         alert("sie müssen gegen den computer im modus schwer mit\n7x6 feldern gewinnen, um in der bestenliste zu stehen.");
         return;
     }
     // Das semaphorFormular füllen und dann das Win Fenster aufrufen.
     text1 = "4gewinnt";
     text2 = countStones;
     text3 = "7x6";
     text4 = "BHW=" + C_COL + "," + C_ROW + "," + C_WIN + " | " + set_cols;
     // Nun den Namen erfragen un bei OK das Formular abschicken lassen
     oeffneListenFenster();
}


/*************************************************************************/
/***************** R E A D X Y ( ) ***************************************/
/*************************************************************************/
function readxy(x,y) {
/* Rückgabewerte: */
/* >0  Wert an Stelle x,y */
/* <=0 = frei bis zum nächsten Stein */
/* OUTFIELD = außerhalb */
         if (x<0 || y<0 || x>(C_COL-1) || y>(C_ROW-1) ) return OUTFIELD;
         return field[x][y];
}

/*************************************************************************/
/***************** S E T X Y V ( ) ***************************************/
/*************************************************************************/
function setxyv(x,y,v) {
         field[x][y]=v;
}

/*************************************************************************/
/***************** S E T X V ( ) *****************************************/
/*************************************************************************/
function setxv(x,v) {
         y=nexty(x);
         if( y==-1 ) return -1; /* Spalte voll */
         setxyv(x,y,v);
         for(t=0; t<y; t++) setxyv(x,t,t-y+1);
         return 0;
}

/*************************************************************************/
/***************** G S E T X Y V ( ) *************************************/
/*************************************************************************/
function gsetxyv(x,y,v) { /* setze graphische den Spielstein */
         switch(v) {
         case 1:  document.images[firstfield+(y*C_COL)+x].src=yellow.src;
                  break
         case 2:  document.images[firstfield+(y*C_COL)+x].src=red.src;
                  break
         case 100:
                  if(isbusy!=0) { activecol=x; break; }
                  document.images[firstfield+(y*C_COL)+x].src=sthuman.src;
                  break
         case 101:
                  if(isbusy!=0) { activecol=-1; break; }
                  document.images[firstfield+(y*C_COL)+x].src=stempty.src;
                  break
         default:  document.images[firstfield+(y*C_COL)+x].src=empty.src;
                   break
         }
}

/*************************************************************************/
/********** A N I M A T E _ I N S E R T ( )*******************************/
/*************************************************************************/
function animate_insert(x,y,v) {
         /* Teste ob Zielposition schon erreicht */
         gsetxyv(x,y,v); /* aktuelles Feld setzen */
         if( y > 0 ) gsetxyv(x,y-1,EMPTY); /* vorheriges löschen aber nur wenn nicht 0*/
         if( y != nexty(x) ) {
             window.setTimeout("animate_insert("+x+","+(y+1)+","+v+")",100);
         } else { /* Animation beenden */
             setxv(x,v); /* im Berechnungsspielfeld setzen */
             if( testwinner() == 1 ) {
                   checkBeginn = false;
                   return; /* schaue ob jemand gewonnen hat */
             }
             if( v==HUMANPLAYER ) {
                 window.setTimeout("computerplayer("+COMPUTERPLAYER+")",100);
             } else {
                 isbusy=0; /* Animation beendet, HUMANPLAYER ist wieder an der Reihe */
                 if( activecol!=-1) gsetxyv(activecol,-1,STHUMAN); /*Animation über Spielfeld wieder einblenden */
             }
         }
}

/*************************************************************************/
/*************************** N E X T Y ( ) *******************************/
/*************************************************************************/
function nexty(x) {
/* Rückgabewert == -1 heisst Spalte voll */
         ny=readxy(x,0)
         if(ny>0) return -1; else return -ny;
}

/*************************************************************************/
/****************** O T H E R _ P L  A Y E R ( ) *************************/
/*************************************************************************/
function other_player(v) {
         switch(v) {
         case 1: return COMPUTERPLAYER; break;
         case 2: return HUMANPLAYER; break;
         default: return v; break;
         }
         return v;
}

/*************************************************************************/
/************************* B L I N K ( ) *********************************/
/*************************************************************************/
function blink(x1,y1,x2,y2,v) {
         if( isbusy != 3 ) return;
         dx=(x2-x1)/(C_WIN-1);
         dy=(y2-y1)/(C_WIN-1);
         x=x1; y=y1
         if( readxy(x1,y1) <=0 ) {  /* fülle wieder mit steine */
             for(t=0; t<C_WIN; t++) {
                      gsetxyv(x,y,v);
                      setxyv(x,y,v)
                      x+=dx; y+=dy;
             }
         } else {                        /* lösche steine wieder */
             for(t=0; t<C_WIN; t++) {
                      gsetxyv(x,y,EMPTY);
                      setxyv(x,y,EMPTY)
                      x+=dx; y+=dy;
             }
         }
         window.setTimeout("blink("+x1+","+y1+","+x2+","+y2+","+v+")",100);
}

/******************************************************************/
/******************* I N C T I M E ( ) ****************************/
/******************************************************************/
function incTime() {
         if( ! checkBeginn ) return;
         if( isbusy != 1 ) {
            actTime = parseInt(document.ltime.time.value);
            document.ltime.time.value = actTime + 1;
         }
         timeTimeout = window.setTimeout("incTime()",1000);
}

/*************************************************************************/
/******************* T E S T W I N N E  R ( ) ****************************/
/*************************************************************************/
function testwinner() {
         /* horizontale Reihe? */
         for(y=0; y<C_ROW; y++) {
             for(x=0; x<C_COL; x++) {
                 for(l=0; l<4; l++) { /* direction */
                     for(k=0; k<C_WIN; k++) { /* position */
                         if(fill_line(x,y,l,k)==-1 ) continue;
                         if(count_line(HUMANPLAYER)==C_WIN || count_line(COMPUTERPLAYER)==C_WIN){
                             x1=x-k*getdx(l);
                             y1=y-k*getdy(l);
                             x2=x1+(C_WIN-1)*getdx(l);
                             y2=y1+(C_WIN-1)*getdy(l);
                             isbusy=3;
          window.setTimeout("blink("+x1+","+y1+","+x2+","+y2+","+line[0]+")",100);
          checkBeginn = false;
          if( count_line(HUMANPLAYER)==C_WIN ) window.setTimeout("winmessage()",1000);
                             return 1;
                         }
                      }
                  }
             }
         }
         for( tt=0; tt < C_COL; tt++ ) if(nexty(tt) != -1) break;
         if( tt == C_COL ) {
             alert("es steht unteschieden...");
             isbusy=3;
             return 1;
         }
         return 0;
}

/*************************************************************************/
/****************************** G E T D X ( ) ****************************/
/*************************************************************************/
function getdx(d) {
/* d = direction: 0=- 1=/ 2=| 3=\ */
   switch(d) {
   case 0: return 1;
   case 1: return 1;
   case 2: return 0;
   case 3: return -1;
   }
}

/*************************************************************************/
/******************* G E T D Y ( ) ***************************************/
/*************************************************************************/
function getdy(d) {
/* d = direction: 0=- 1=/ 2=| 3=\ */
   switch(d) {
   case 0: return 0;
   case 1: return -1;
   case 2: return -1;
   case 3: return -1;
   }
}

/*************************************************************************/
/******************* F I L L _ L I N E ( ) *******************************/
/*************************************************************************/
function fill_line(x,y,d,p) {
/* x,y = Koordinaten des zu untersuchenden Loches
   d = direction: 0=- 1=/ 2=| 3=\
   p = position: welche position hat P(x;y) innerhalb der 4er Reihe
   return -1 = zeile außerhalb des Bereiches
*/
   dx=getdx(d); dy=getdy(d);
   for(pointer=0; pointer<C_WIN; pointer++) {
            v=readxy( x-(p*dx)+(pointer*dx) , y-(p*dy)+(pointer*dy) );
            if( v==OUTFIELD ) return -1;
            line[pointer]=v
   }
   return 0;
}

/*************************************************************************/
/******************* C O U N T _ L I N E ( ) *****************************/
/*************************************************************************/
function count_line(v) {
/* liefert anzahl von v in line[] zurück */
   count=0;
   for(pointer=0; pointer<C_WIN; pointer++) if(line[pointer]==v) count++;
   return count;
}

/*************************************************************************/
/******************* H U M A N P L A Y E R ( ) ***************************/
/*************************************************************************/
function humanplayer(x,v) {
         if( isbusy == 2 ) isbusy=0;
         if( isbusy != 0 ) return; /* beschäftigt! */
         if( nexty(x) < 0 ) return; /* spalte voll! */
         if( ! checkBeginn ) {
             checkBeginn = true;
             window.setTimeout("incTime()",10);
         }
         countStones++;
         activecol=x;
         gsetxyv(x,-1,STEMPTY) /* lösche animation über spielfeld */
         isbusy=1; /* ab jetzt ist browser beschäftigt */
         set_cols+="M("+x+"); ";
         animate_insert(x,0,v); /* beginne mit Animation des Steineinwurfes */
}

/*************************************************************************/
/******************* F I L L _ T R A P ( )********************************/
/*************************************************************************/
function fill_trap(trap,v) {
/* Diese Funktion füllt das 2-dimensionale Array trap[][] mit den C_TRAP besten Fallen. */
/* Definition Falle: 1.) gleichzeitig 2 mögliche 4er Reihen (nur eine kann verhindert werden)
                     2.) durch das verhindern einer 4er Reihe, eine weitere ermöglichen
   zu 1.) 2 nicht in der gleichen spalte liegende freie felder, welche jeweils für sich
          aus einer 3er Reihe bestehen und im nächsten Zug zu 4 gleiche ergänzt werden können.
          Eine Falle ist das aber nur, wenn mit einem Stein der obige Zustand hergestellt werden
          kann, sprich die 2 möglichen 4er mind. durch einen Stein verbunden sind.
   zu 2.) wie erstens, hier besteht die aktivirungsspalte aus einer senkrechten 3er Reihe
          NACHTEIL zu 1 und 2: diese Fallen können bis zur aktivierung noch zerstört werden
   zu 3.) 2 senkrecht übereinander liegende freie felder, wobei sowohl das untere als auch das
          obere eine schon vorhandene Reihe aus 3 gleichen Steinen zu 4 gleichen ergänzt.
          VORTEIL: stehen diese Fallen einmal, kann sie gegner nicht mehr verhindern */
xyz=0
   /* Suche Falle vom Typ 1,2, und 4! d.h. prüfe alle übereinander liegenden freien felder*/
   for(x=0; x<C_COL; x++) {                 /* über alle Spalten */
      for(y=nexty(x); y>=0; y--) {                /* alle freien übereinander liegenden Felder */
         for(c1=0; c1<4; c1++)  {                 /* Richtung in erster Reihe*/
            for(b1=0; b1<C_WIN; b1++) {        /* Position in erster Reihe */
               for(c2=c1; c2<4; c2++) {           /* Richtung in zweiter Reihe, ohne wiederholung*/
                  for(b2=0; b2<C_WIN; b2++) {  /* Position in zweiter Reihe*/

                     /*** allgemeine Bedingungen ***/
                     /*** beide gleiche Richtung und gleiche Position macht keinen Sinn */
                     if( c1==c2 && b1==b2 ) continue;
                     /*** beide senkrecht macht keinen Sinn! */
                     if( c1==2 && c2==2 ) continue;

                     /*** Fallentyp 4 Plausibilitäten***/
                     /*** = beide gleiche Richtung aber nicht senkrecht ***/
                     if( c1 == c2 && c1!=2 && c2!=2 ) {
                          /*** Position darf max 1 auseinander sein */
                          if( Math.abs(b1-b2)!=1 ) continue;
                          /*** links und rechts von AS muss mind. 1 frei sein ***/
                          if(  x < 1 || x > (C_COL-2) ) continue;
                          /*** ganz außen muss jeweil links und rechts mind 1 frei sein ***/
                          if( b1 > b2 ) { pos_s1 = b1; pos_s2 = b2; }
                          if( b2 > b1 ) { pos_s1 = b2; pos_s2 = b1; }
                          dir = c1; // c1 und c2 sind gleich, deswegen egal was direction bekommt

                          x_s1 = x - pos_s1*getdx(dir);
                          x_s2 = x + (C_WIN-1-pos_s2)*getdx(dir)
                          y_s1 = y - pos_s1*getdy(dir);
                          y_s2 = y + (C_WIN-1-pos_s2)*getdy(dir)

                          side_1 = readxy( x_s1 , y_s1 )
                          if( side_1 == OUTFIELD || side_1 > 0 ) continue;
                          side_2 = readxy( x_s2 , y_s2 )
                          if( side_2 == OUTFIELD || side_2 > 0 ) continue;
                     }

                     /*** Fallentyp 2 Plausibilitäten ***/
                     /*** = einer senkrecht und rest diagonal oder waagerecht ***/
                     if( (c1 == 2 && c2 != 2) ||  (c2 == 2 && c1 != 2) ) {
                          /*** wenn einer senkrecht dann muss freies loch ganz oben


                           sein */
                          if( (c1==2 && b1!=C_WIN-2) || (c2==2 && b2!=C_WIN-2) ) continue;
                     }

                     /*** Fallentyp 1 Plausibilitäten ***/
                     /*** = beide nicht senkrecht und nicht identisch ***/
                     if( c1 != c2 && c1 != 2 && c2 != 2 ) {
                          /*** links und rechts von AS mus mind. 1 frei sein ***/
                          if(  x < 1 || x > (C_COL-2) ) continue;
                     }

                     /*** line[] für erstes loch füllen, wenn außerhalb (==-1) dann abbrechen */
                     if( fill_line(x,y,c1,b1) == -1) continue;

                     /*** nur wenn gegner noch nichts in der Reihe hat gehts weiter */
                     if( count_line(other_player(v)) != 0 ) continue;

                     /*** wenn durch aktivierung schon 4 zustande kommen, machts keinen Sinn */
                     if( count_line(v) > (C_WIN-2) ) continue;

                     /*** fülle zunächst row_trap mit anzahl zügen für untere reihe */
                     for(t=0; t<C_COL; t++) row_trap[t]=0; /* initialisieren */
                     for(t=C_COL; t<C_COL+C_COL; t++) row_trap[t]=-1;
                     dx=getdx(c1);
                     dy=getdy(c1);
                     for(t=0; t<C_WIN; t++) {
                        stone=line[t];
                        ber_x = x+dx*t-dx*b1;
                        ber_y = y-b1*dy+t*dy;
                        row_trap[C_COL+ber_x]=nexty(ber_x)-ber_y;
                        if( stone==v ) { row_trap[ber_x]=0; continue; }
                        if( stone==0 ) { row_trap[ber_x]=1; continue; }
                        if( stone<0 ) {  row_trap[ber_x]=(-stone)+1; continue; }
                     }
                     /*** line[] für zweite reihe füllen, wenn außerhalb (==-1) dann abbrechen */
                     if( fill_line(x,y,c2,b2) == -1) continue;

                     /*** nur wenn gegner noch nichts in der Reihe hat gehts weiter */
                     if( count_line(other_player(v)) != 0 ) continue;

                     /*** wenn durch aktivierung schon 4 zustande kommen, machts keinen Sinn */
                     if( count_line(other_player(v)) > (C_WIN-2) ) continue;

                     /*** row_trap um zweite Reihe erweitern */
                     dx=getdx(c2);
                     dy=getdy(c2);
                     for(t=0; t<C_WIN; t++) {
                        stone=line[t];
                        /* nur wenn für diese reihe mehr züge notwendig, dies eintragen */
                        ber_x = x+dx*t-dx*b2;
                        ber_y = y-b2*dy+t*dy;
                        if( stone<=0  && (-stone+1)>row_trap[x+dx*t-dx*b2] )
                            row_trap[ber_x]=-stone+1;
                        if( nexty(ber_x)- ber_y >= 0 &&
                            (row_trap[ber_x+C_COL] > nexty(ber_x)- ber_y || row_trap[ber_x+C_COL] < 0) )
                            row_trap[ber_x+C_COL] = nexty(ber_x)- ber_y;
                       // row_trap[C_COL+x+dx*t-dx*b2] = "X"; // x+dx*t-dx*b2;//nexty(x+dx*t-dx*b1);//(y-(b2*dy)+(t*dy));//nexty(x+dx*t-dx*b2);//-(y-(b2*dy)+(t*dy));
                     }

                     /*** 30.10.2001 Schnittspalte ermitteln */
                     /*** und von wo bis wo sich die jeweils 2 Felder übereinander befinden ***/
                     Schnittpunkt = -1;
                     Startpunkt = -1;
                     Endpunkt = -1;
                     if( c1 != c2 ) {
                         Schnittpunkt = x;
                         X1min = x-b1*getdx(c1); X2min = x-b2*getdx(c2)
                         X1max = x-b1*getdx(c1)+(C_WIN-1)*getdx(c1);
                         X2max = x-b2*getdx(c2)+(C_WIN-1)*getdx(c2);
                         Startpunkt = Math.min(Math.max(X1min,X2min),Math.min(X1max,X2max));
                         Endpunkt = Math.max(Math.max(X1min,X2min),Math.min(X1max,X2max));
                         /* Wenn Schnittpunkt, dann nur links oder rechts davon 2 übereinander */
                         Startpunkt = Math.max( Startpunkt, Schnittpunkt-1 )
                         Endpunkt = Math.min( Endpunkt, Schnittpunkt+1 )
                     }

                     /*** suche Falle mit den meisten Zügen, diese dann ersetzen */
                     nmax=0; zmax=0;
                     for(z=0; z<C_TRAP; z++) {
                         if(trap[z][3]==-1) { zmax=z; break; }
                         if(trap[z][3]==nmax && Math.random() > 0.5) { zmax=z; continue; }
                         if(trap[z][3]>nmax) { nmax=trap[z][3]; zmax=z; }
                     }

                     /*** Anzahl n an Zügen zählen, aber Spalte x auch mit! */
                     n=0; for(col=0; col<C_COL; col++) n+=row_trap[col];
                     n-=2; /* Korektur, da Fallen vom Typ 1 und 2 zwei freie Felder brauchen */

                     /*** die gefundenen Falle in row_trap[] in trap[][] eintragen */
                     if( trap[zmax][3]==-1 || trap[zmax][3]>n ) {
                         if(c1==2 || c2==2) { /* wenn eins von beiden senkrecht ist */
                                  trap[zmax][0]=2;
                         } else if( c1 == c2 ) { /* wenn Richtung gleich ist */
                                  trap[zmax][0]=4;
                         } else {
                                  trap[zmax][0]=1;
                         }
                         trap[zmax][1]=x;
                         trap[zmax][2]=n;
                         trap[zmax][3]=n;
                         trap[zmax][4]=v;
                         trap[zmax][5]=Schnittpunkt;
                         trap[zmax][6]=Startpunkt;
                         trap[zmax][7]=Endpunkt;
                         for(a=0; a<C_COL+C_COL; a++) {
                            trap[zmax][a+TRAP_PRE]=row_trap[a];
                         }
                     }


                  }
               }
            }
         }
      }
   }

   /* Suche Falle vom Typ 3 und 5! d.h. prüfe alle 2 übereinander liegenden freien felder*/
   for(x=0; x<C_COL; x++) {                 /* über alle Spalten */
      for(y=nexty(x); y>0; y--) {                 /* alle 2 freien übereinander liegenden Felder */
         for(c1=0; c1<4; c1++)  {                 /* Richtung in unterer Reihe*/
            for(b1=0; b1<C_WIN; b1++) {        /* Position in unterer Reihe */
               for(c2=0; c2<4; c2++) {            /* Richtung in oberer Reihe */
                  for(b2=0; b2<C_WIN; b2++) {  /* Position in oberer Reihe*/

                     /*** senkrechte Reihen machen nur für untere reihe bei pos C_WIN-1 Sinn */
                     if( c2==2 || (c1==2 && b1!=C_WIN-1 ) ) continue;

                     /*** line[] für unteres loch füllen, wenn außerhalb (==-1) dann abbrechen */
                     if( fill_line(x,y,c1,b1) == -1) continue;

                     /*** nur wenn gegner noch nichts in der Reihe hat gehts weiter */
                     if( count_line(other_player(v)) != 0 ) continue;

                     /*** fülle zunächst row_trap mit anzahl zügen für untere reihe */
                     for(t=0; t<C_COL; t++) row_trap[t]=0; /* initialisieren */
                     for(t=C_COL; t<C_COL+C_COL; t++) row_trap[t]=-1;
                     dx=getdx(c1);
                     dy=getdy(c1);
                     for(t=0; t<C_WIN; t++) {
                        stone=line[t];
                        ber_x = x+dx*t-dx*b1;
                        ber_y = y-b1*dy+t*dy;
                        row_trap[C_COL+ber_x] = nexty(ber_x)-ber_y;
                        if( stone==v ) { row_trap[ber_x]=0; continue; }
                        if( stone==0 ) { row_trap[ber_x]=1; continue; }
                        if( stone<0 ) { row_trap[ber_x]=(-stone)+1; continue; }
                     }

                     /*** line[] für oberes loch füllen, wenn außerhalb (==-1) dann abbrechen */
                     if( fill_line(x,y-1,c2,b2) == -1) continue;

                     /*** nur wenn gegner noch nichts in der Reihe hat gehts weiter */
                     if( count_line(other_player(v)) != 0 ) continue;


                     /*** 30.10.2001 Schnittspalte ermitteln */
                     /*** und von wo bis wo sich die jeweils 2 Felder übereinander befinden ***/
                     Schnittpunkt = -1;
                     X1min = x-b1*getdx(c1); X2min = x-b2*getdx(c2)
                     X1max = x-b1*getdx(c1)+(C_WIN-1)*getdx(c1);
                     X2max = x-b2*getdx(c2)+(C_WIN-1)*getdx(c2);
                     Startpunkt = Math.min(Math.max(X1min,X2min),Math.min(X1max,X2max));
                     Endpunkt = Math.max(Math.max(X1min,X2min),Math.min(X1max,X2max));
                     if( c1 != c2 ) {
                         for( Idx1=0; Idx1 < C_WIN; Idx1++ ) {
                            dx1=getdx(c1); dy1=getdy(c1);
                            X1=x-(b1*dx1)+(Idx1*dx1);  Y1=y-(b1*dy1)+(Idx1*dy1);
                            for( Idx2=0; Idx2 < C_WIN; Idx2++ ) {
                                dx2=getdx(c2); dy2=getdy(c2);
                                X2=x-(b2*dx2)+(Idx2*dx2);  Y2=y-(b2*dy2)+(Idx2*dy2)-1;
                                if( X1==X2 && Y1==Y2 ) Schnittpunkt=X1;
                            }
                         }
                         /* Wenn Schnittpunkt, dann nur links oder rechts davon 2 übereinander */
                         Startpunkt = Math.max( Startpunkt, Schnittpunkt-1 )
                         Endpunkt = Math.min( Endpunkt, Schnittpunkt+1 )
                     }

                     /*** row_trap um obere Reihe erweitern */
                     dx=getdx(c2);
                     dy=getdy(c2);
                     for(t=0; t<C_WIN; t++) {
                        stone=line[t];
                        ber_x = x+dx*t-dx*b2;
                        ber_y = y-b2*dy+t*dy;
                        /* nur wenn für diese reihe mehr züge notwendig, dies eintragen */
                        Reihe1 = (-stone+1); Reihe2 = row_trap[ber_x];
                        if( stone<=0  && Reihe1 > Reihe2 ) row_trap[ber_x] = Reihe1;
                        if( nexty(ber_x)-ber_y >= 0 &&
                            (row_trap[ber_x+C_COL] > nexty(ber_x)- ber_y || row_trap[ber_x+C_COL] < 0) )
                            row_trap[ber_x+C_COL] = nexty(ber_x)- ber_y;
                      }
                      /*** Anzahl n an Zügen zählen, aber  Spalte x nicht mit! */
                      n=0; for(col=0; col<C_COL; col++) if(col!=x) n+=row_trap[col];

                      /*** suche Falle mit den meisten Zügen, diese dann ersetzen */
                      nmax=0; zmax=0;
                      for(z=0; z<C_TRAP; z++) {
                         if(trap[z][3]==-1) { zmax=z; break; }
                         if(trap[z][3]==nmax && Math.random() > 0.5) { zmax=z; continue; }
                         if(trap[z][3]>nmax) { nmax=trap[z][3]; zmax=z; }
                      }

                      /*** die gefundenen Falle in rowtrap[] in trap[][] eintragen */
                      if( trap[zmax][3]==-1 || trap[zmax][3]>n ) {
                         if(c1==2 || c2==2) { /* wenn eins von beiden senkrecht ist */
                                  trap[zmax][0]=5;
                         } else {
                                  trap[zmax][0]=3;
                         }
                         trap[zmax][1]=x;
                         trap[zmax][2]=n+nexty(x)-y;
                         trap[zmax][3]=n;
                         trap[zmax][4]=v;
                         trap[zmax][5]=Schnittpunkt;
                         trap[zmax][6]=Startpunkt;
                         trap[zmax][7]=Endpunkt;
                         for(a=0; a<C_COL+C_COL; a++) {
                            if(a==x) trap[zmax][a+TRAP_PRE]=nexty(x)-y;
                            else trap[zmax][a+TRAP_PRE]=row_trap[a];
                         }
                      }
                  }
               }
            }
         }
      }
   }
}

/*************************************************************************/
/******************* I S _ T R A P _ G T ( ) *****************************/
/*************************************************************************/
function is_trap_gt(trap1,trap2) {  /* hat falle trap1 eine größere Priorität als Falle trap2? */
        if( trap1[3]==-1 && trap2[3]==-1 ) return 0;
        if( trap1[3]==-1 && trap2[3]!=-1 ) return 0;
        if( trap1[3]!=-1 && trap2[3]==-1 ) return 1;

        nmin1 = trap1[3];
        if( trap1[0]==3 && trap1[3] < trap1[2] ) nmin1++;
        if( trap1[0]==5 ) nmin1=trap1[2];
        nmin2 = trap2[3];
        if( trap2[0]==3 && trap2[3] < trap2[2] ) nmin2++;
        if( trap2[0]==5 ) nmin2=trap2[2];
        if( nmin1 < nmin2 ) return 1; /* nmin ist kleiner --> besser */
        if( nmin1 > nmin2 ) return 0; /* nmin ist größer --> schlecher */
        /* ab hier sind trap1[3] == trap2[3] gleich */
        if( trap1[0]==3 && trap2[0]!=3 ) return 1; /* Falle 3 besser als 1,2,4 */
        if( trap1[0]!=3 && trap2[0]==3 ) return 0;
        /* ab hier müssen trap1[0] == trap2[0] gleich sein */
        if( trap1[4]==COMPUTERPLAYER && trap2[4]==HUMANPLAYER ) return 0;
        if( trap1[4]==HUMANPLAYER && trap2[4]==COMPUTERPLAYER ) return 1;
        /* ab hier ist Spieler identisch */
        /* nmax entscheidet hier über priorität */
        if( trap1[2] < trap2[2] ) return 1; /* nmax ist kleiner --> besser */
        if( trap1[2] > trap2[2] ) return 0; /* nmax ist größer --> schlecher */
        /* je weniger Spalten beteiligt sind, desto besser ist priorität */
        col_count1 = 0; col_count2 = 0;
        for( ll=0; ll < C_COL; ll++ ) {
             if( ll != trap1[1] && trap1[ll + TRAP_PRE] > 0 ) col_count1++;
             if( ll != trap2[1] && trap2[ll + TRAP_PRE] > 0 ) col_count2++;
        }
        if( col_count1 < col_count2 ) return 1;
        if( col_count1 > col_count2 ) return 0;
        /* je mehr AS in der Mitte desto besser */
        //if( Math.abs(trap1[1]-(C_COL/2)) < Math.abs(trap2[1]-(C_COL/2)) ) return 1;
        //if( Math.abs(trap1[1]-(C_COL/2)) > Math.abs(trap2[1]-(C_COL/2)) ) return 0;
        /* ab hier sind trap1 und trap 2 identisch */
        return 0;
}

/*************************************************************************/
/******************* C H A N G E _ T R A P ( ) ***************************/
/*************************************************************************/
function change_trap(trap1,trap2) {
        /* tausche die Werte von trap2 mit denen von trap1 */
        for(index=0; index<TRAP_PRE+C_COL + C_COL; index++) {
           temp=trap1[index]; trap1[index]=trap2[index]; trap2[index]=temp;
        }
}

/*************************************************************************/
/******************* S O R T _ T R A P ( ) *******************************/
/*************************************************************************/
function sort_trap(trap) {
        /* Bubble Sort Algorithmus */
        do {
          changes=0;
          for(t=C_TRAP-1; t>0; t--) {
             if( is_trap_gt(trap[t],trap[t-1]) == 1 ) { /* hat trap[t] Priorität vor trap[t-1] ? */
                 /* Wenn ja, dann tausche beide aus */
                 change_trap(trap[t],trap[t-1]);
                 changes++;
             }
          }
        } while (changes!=0);
}

/*************************************************************************/
/******************* L I N E _ P R I O R I T Y ( ) ***********************/
/*************************************************************************/
function line_priority(d,v) {
         /* Rückgabewert ist Priorität einer Linie */
         /* verhindern ist zunächst genau so hoch wie aufbauen */
         /* ist in line[] etwas anders als v enthalten ist priorität == 0 */
         your_line=count_line(other_player(v));
         if( your_line > 0 ) return 0;

         /* Anzahl der Steine exponential einrechnen */
         my_line=count_line(v);
         field_ctr=3;
         for( aa=0; aa < my_line; aa++) field_ctr *= 4;

         /* Anzahl der direkt verbundenen Steine einrechnen */
         is_block=0; /* zeigt bei 1 an, das vorhergehendes Feld v war */
         for( aa=0; aa < C_WIN; aa++ ) {
            if( line[aa] == v ) {
                if( is_block==1 ) {
                    field_ctr *= 2
                } else {
                    is_block = 1;
                }
            } else {
              is_block = 0;
            }
         }

         if( d == 1 || d == 3 ) return field_ctr*2;
         if( d == 0 ) return field_ctr*1.5;
         if( d == 2 ) return field_ctr*1.0;
         return field_ctr;
}

/*************************************************************************/
/******************* S I D E _ E F F E C T ( ) **************************/
/*************************************************************************/
function side_effect(x,v) {
         /* je größer rückgabewert desto größer nebeneffekt und desto größer pritorität */
         abs_se=0; /* absoluter seiteneffekt */
         anz_moeg=0; /* anzahl der möglichkeiten */
         se1=0; se2=0; se3=0; se4=0;

         /* Frage: Werfe ich in Spalte x einen Stein v, was kann Gegner dann machen oder was
                   kann Gegner mir hier verhindern, sowohl in dem aktuellen Loch als auch
                   oben drüber */
         if( (freey = nexty(x)) == -1 ) return 0; /* Priorität = 0, da Spalte voll */

         /* temporär meinen Stein setzen */
         setxyv(x,freey,v);
         anz_moeg = 0; abs_se = 0;
         for( dd=0; dd < 4; dd++ ) { /* Direction */
              for( pp=0; pp<C_WIN; pp++ ) { /* Position */
                   if( fill_line(x,freey,dd,pp) == -1 ) continue;
                   l_p = line_priority(dd,v)
                   /* senkrecht erhöht hier bei 3er einen Sonderbonus!!! */
                   if( dd == 2 && l_p > 3*3*3) l_p *= 1.2;
                   abs_se += l_p;
                   if( l_p != 0) anz_moeg++;
              }
         }
         se1 = abs_se;

         /* temporär deinen Stein setzen */
         setxyv(x,freey,other_player(v));
         anz_moeg = 0; abs_se = 0;
         for( dd=0; dd < 4; dd++ ) { /* Direction */
              for( pp=0; pp<C_WIN; pp++ ) { /* Position */
                   if( fill_line(x,freey,dd,pp) == -1 ) continue;
                   l_p = line_priority(dd,other_player(v))
                   abs_se += l_p;
                   anz_moeg++;
              }
         }
         se2 = abs_se ;

         if( freey > 0 ) {

             /* temporär meinen Stein über meinen gedachten setzen (was kann mir gegner verhindern?)*/
             setxyv(x,freey,v);
             setxyv(x,freey-1,v);
             anz_moeg = 0 ; abs_se = 0;
             for( dd=0; dd < 4; dd++ ) { /* Direction */
                   for( pp=0; pp<C_WIN; pp++ ) { /* Position */
                        /* senkrecht darf hier keine Rolle spielen, da es das Ergebnis verfälscht!!! */
                        if( dd == 2 && pp==C_WIN-1) continue;
                        if( fill_line(x,freey-1,dd,pp) == -1 ) continue;
                        l_p = line_priority(dd,v)
                        abs_se += l_p;
                        anz_moeg++;
                   }
             }
             se3 = abs_se; /* relativer seiteneffekt zaehlt! */

             /* temporär deinen Stein über meinen gedachten setzen  */
             setxyv(x,freey,v);
             setxyv(x,freey-1,other_player(v));
             anz_moeg = 0; abs_se = 0;
             for( dd=0; dd < 4; dd++ ) { /* Direction */
                   for( pp=0; pp<C_WIN; pp++ ) { /* Position */
                        if( fill_line(x,freey-1,dd,pp) == -1 ) continue;
                        l_p = line_priority(dd,other_player(v));
                        abs_se += l_p
                        anz_moeg++;
                   }
             }
             se4 = abs_se; /* relativer seiteneffekt zaehlt! */

             /* temporären Stein rückgängig */
             setxyv(x,freey-1,-1);

         }
         /* temporären Stein rückgängig */
         setxyv(x,freey,0);

         /* 30.10.2001 koeffizienten abgeändert */
         /* alt: se = ( 2 * ( 2.2*se1 + 0.7*se2 ) - ( 0.8*se3 + 2.4*se4 )  ) */
         se = ( 2.5 * ( 2*se1 + 1*se2 ) - ( 1*se3 + 2*se4 )  )
         /* wenn es die Spalte nur noch eines frei hat, wird ja nichts abgezogen, deshalb wird der
            Wert hier pauschal halbiert!!! */
         if( freey == 0 ) se /= 2;

         return se;
}

/*************************************************************************/
/******************* P R I O R I T Y _ X ( ) *****************************/
/*************************************************************************/
function priority_x(trap,nr,x,v) {

         /* wenn x == -1, dann wurde er schon ignoriert */
         if( x == -1 ) return -1;

         /* wenn Fallentyp == 0, dann letzte Falle um Seiteneffekt entscheiden zu lassen */
         if( trap[nr][0] == 0 ) return 1;

         /* wenn Typ 3 und n>3, dann alle x gleiche Prior, da diese Fallen sinnlos sind */
         if( trap[nr][0]==3 && trap[nr][3] > 1 && trap[nr][2] > 4 ) return 1;
         if( trap[nr][0]==3 && trap[nr][3] > 2 ) return 1;

         /* wenn Typ 5 nur dann weiter verfolgen, wenn waage- bzw senkrechte schon vorhanden und
            nmax < 2, sonst ist Falle fast sinnlos */
         if( trap[nr][0]==5 && ( trap[nr][3]>0 || ( trap[nr][3]==0 && trap[nr][2]>1 )) ) return 1;

         /* wenn Typ 4 und n>1, dann alle x gleiche Prior, da diese Fallen sinnlos sind */
         if( trap[nr][0]==4 && trap[nr][3] > 1) return 1;

         /* wenn  Typ 1 und n>2, dann alle x gleiche Prior, da diese Fallen sinnlos sind */
         if( trap[nr][0] == 1 && trap[nr][3] > 2 ) return 1;

         /* wenn  Typ 2 und n>2, dann alle x gleiche Prior, da diese Fallen sinnlos sind */
         if( trap[nr][0] == 1 && trap[nr][3] > 2 ) return 1;

         /*** Fallentyp 4 ***/
         if( trap[nr][0] == 4 ) {
             /* benötigte Variablen */
             ASx  = trap[nr][1];
             AS = trap[nr][ASx + TRAP_PRE]
             Sn=0; NS=0;
             for(t=0; t<C_COL; t++) if( trap[nr][t + TRAP_PRE] > 0 && t != ASx ) {
                      Sn++;
                      NS+=trap[nr][t + TRAP_PRE]
             }
             for(S1x=0; S1x<ASx; S1x++) if( trap[nr][S1x + TRAP_PRE] > 0 ) break;
             for(S2x=C_COL-1; S2x>ASx; S2x--) if( trap[nr][S2x + TRAP_PRE] > 0 ) break;
             S1 = trap[nr][S1x + TRAP_PRE]
             S2 = trap[nr][S2x + TRAP_PRE]
             is_build=0; if( trap[nr][4] == v ) is_build=1;

             /* Plausibilität */
             if( Math.abs(S2x - S1x) != C_WIN ) return -1;

             /* Prioritäten */
             if( Sn == 2 && S1 == 1 && S2 == 1 ) {
                 if( is_build == 1 ) {
                     if( x == ASx ) return 100;
                 } else {
                     if( x == ASx && AS == 1 ) return 100;
                     if( x == S1x || x == S2x ) return 100;
                 }
             }
             if( Sn >= 2 && NS > 2 ) {
                 if( is_build == 1 ) {
                     if( x != ASx && trap[nr][x + TRAP_PRE] == 1 && x != S1x && x != S2x ) return 95;
                     if( x != ASx && trap[nr][x + TRAP_PRE] > 2 ) return 90;
                     if( x == ASx && AS > 2 ) return 90;
                     if( x != ASx && trap[nr][x + TRAP_PRE] == 2 ) return 80;
                     if( x == ASx && AS == 2 ) return 80;
                 } else {
                     if( x == ASx && AS == 1 ) return 85;
                     if( x == S1x && S1 == 1 ) return 85;
                     if( x == S2x && S2 == 1 ) return 85;
                     if( x != ASx && trap[nr][x + TRAP_PRE] == 1 ) return 85;
                 }
             }
             /* Rest ignorieren */
             return -1;
         }

         /*** Fallentyp 3 ***/
         if( trap[nr][0] == 3 ) {
             /* benötigte Variablen */
             ASx  = trap[nr][1];
             AS = trap[nr][ASx + TRAP_PRE]
             NS=0;
             NScount=0; /* Wie viele Spalten sind > 0 (ausser AS) */
             NScountX=0; /* Wie viele Spalten sind > 0 (ausser AS) */
             for(t=0; t<C_COL; t++) if( trap[nr][t + TRAP_PRE] > 0 && t != ASx ) {
                      NS+=trap[nr][t + TRAP_PRE];
                      if( trap[nr][t + TRAP_PRE] > 0 ) { NScount++; NScountX = t; }
             }
             is_build=0; if( trap[nr][4] == v ) is_build=1;

             /* Prioritäten */
             /** am 30.10.2001 Nachträglich eingefügt **/
             if( is_build == 0 ) {
                 if( x != ASx && x != trap[nr][5] && x >= trap[nr][6] && x <= trap[nr][7] ) {
                     if( trap[nr][x + TRAP_PRE] == 2 ) return 95;
                 }
             }

             if( AS > 0 && NS == 0 ) {
                 if( is_build == 1 ) {
                     if( x == ASx ) return 100;
                 }
             }
             if( NS > 0 ) {
                 if( is_build == 1 ) {
                     if( x != ASx && trap[nr][x + TRAP_PRE] == 1 ) return 95;
                     if( x != ASx && trap[nr][x + TRAP_PRE] > 2 ) return 90;
                     if( x == ASx && AS > 2 ) return 90;
                     if( x != ASx && trap[nr][x + TRAP_PRE] == 2 ) return 80;
                 } else {
                     if( x != ASx && trap[nr][x + TRAP_PRE] == 1 ) return 95
                 }
             }
             /* Rest ignorieren */
             return -1;
         }

         /*** Fallentyp 1 ***/
         if( trap[nr][0] == 1 ) {
             /* benötigte Variablen */
             ASx  = trap[nr][1];
             AS = trap[nr][ASx + TRAP_PRE]
             Sn=0; NS=0;
             for(t=0; t<C_COL; t++) if( trap[nr][t + TRAP_PRE] > 0 && t != ASx ) {
                      Sn++;
                      NS+=trap[nr][t + TRAP_PRE]
             }
             /* x1 und x2 nur wenn Sn == 2 */
             S1x=0; S2x=C_COL-1;
             if( Sn == 2 ) {
                 for(S1x=0; S1x<C_COL; S1x++)
                     if( trap[nr][S1x + TRAP_PRE] > 0 && S1x != ASx ) break;
                 for(S2x=C_COL-1; S2x>=0; S2x--)
                     if( trap[nr][S2x + TRAP_PRE] > 0 && S2x != ASx ) break;
                 S1 = trap[nr][S1x + TRAP_PRE]
                 S2 = trap[nr][S2x + TRAP_PRE]
             }
             is_build=0; if( trap[nr][4] == v ) is_build=1;

             /* Prioritäten */
             /** am 30.10.2001 Nachträglich eingefügt **/
             if( is_build == 0 ) {
                 if( x != ASx && x != trap[nr][5] && x >= trap[nr][6] && x <= trap[nr][7] ) {
                     if( trap[nr][x + TRAP_PRE] == 2 ) return 90;
                 }
             }

             if( S1x == S2x ) return -1;
             if( Sn == 2 && S1 == 1 && S2 == 1 ) {
                 if( is_build == 1 ) {
                     if( x == ASx ) return 100;
                 } else {
                     if( x == ASx && AS == 1 ) return 100;
                     if( x == S1x || x == S2x ) return 100;
                 }
             }
             if( Sn == 2 && NS > 2 ) {
                 if( is_build == 1 ) {
                     if( x != ASx && trap[nr][x + TRAP_PRE] > 2 ) return 90;
                     if( x == ASx && AS > 2 ) return 85;
                     if( x != ASx && trap[nr][x + TRAP_PRE] == 2 ) return 80;
                     if( x == ASx && AS == 2 ) return 80;
                 } else {
                     if( x == ASx && AS == 1 ) return 90;
                     if( x == S1x && trap[nr][S1x + TRAP_PRE] == 1 ) return 90;
                     if( x == S2x && trap[nr][S2x + TRAP_PRE] == 1 ) return 90;
                 }
             }
             if( Sn > 2 ) {
                 if( is_build == 1 ) {
                     if( x != ASx && trap[nr][x + TRAP_PRE] == 1 ) return 90;
                     if( x != ASx && trap[nr][x + TRAP_PRE] > 2 ) return 85;
                     if( x == ASx && AS > 2 ) return 85;
                     if( x != ASx && trap[nr][x + TRAP_PRE] == 2 ) return 80;
                     if( x == ASx && AS == 2 ) return 80;
                 } else {
                     if( x == ASx && AS == 1 ) return 90;
                     if( x == S1x && trap[nr][x + TRAP_PRE] == 1 ) return 90;
                 }
             }
             /* alles andere ignorieren */
             return -1;
         }


         /*** Fallentyp 2 ***/
         if( trap[nr][0] == 2 ) {
             /* benötigte Variablen */
             ASx  = trap[nr][1];
             AS = trap[nr][ASx + TRAP_PRE]
             Sn=0; NS=0;
             for(t=0; t<C_COL; t++) if( trap[nr][t + TRAP_PRE] > 0 && t != ASx ) {
                      Sn++;
                      NS+=trap[nr][t + TRAP_PRE]
             }
             /* x1 nur wenn Sn == 1 */
             S1x=0;
             if( Sn == 1 ) {
                 for(S1x=0; S1x<C_COL; S1x++)
                     if( trap[nr][S1x + TRAP_PRE] > 0 && S1x != ASx ) break;
                 S1 = trap[nr][S1x + TRAP_PRE]
             }
             is_build=0; if( trap[nr][4] == v ) is_build=1;

             /* Prioritäten */
             if( Sn == 1 && S1 == 1 ) {
                 if( is_build == 1 ) {
                     if( x == ASx ) return 100;
                 } else {
                     if( x == ASx && AS == 2 ) return 100;
                     if( x == S1x ) return 100;
                 }
             }
             if( Sn == 1 && S1 > 1 ) {
                 if( is_build == 1 ) {
                     if( x != ASx && trap[nr][x + TRAP_PRE] > 2 ) return 90;
                     if( x == ASx && AS > 3 ) return 90;
                     if( x != ASx && trap[nr][x + TRAP_PRE] == 2 ) return 80;
                     if( x == ASx && AS == 3 ) return 80;
                 } else {
                     if( x == ASx && AS == 2 ) return 90;
                 }
             }
             if( Sn > 1 ) {
                 if( is_build == 1 ) {
                     if( x != ASx && trap[nr][x + TRAP_PRE] == 1 ) return 90;
                     if( x != ASx && trap[nr][x + TRAP_PRE] > 2 ) return 85;
                     if( x == ASx && AS > 3 ) return 85;
                     if( x != ASx && trap[nr][x + TRAP_PRE] == 2 ) return 80;
                     if( x == ASx && AS == 3 ) return 80;
                 } else {
                     if( x == ASx && AS == 2 ) return 90;
                 }
             }
             /* rest ignorieren */
             return -1;
         }
         /* rückgabewert == -1 heißt x ignorieren */
         return -1;
}

/*************************************************************************/
/******************* F I L L _ B E S T _ X ( ) ***************************/
/*************************************************************************/
function fill_best_x(trap,nr,v) {
       /* fülle best_x[] mit den x-werten der Spalten und ignoriere gleich welche */
       for( bx_ptr=0; bx_ptr<C_COL; bx_ptr++) best_x[bx_ptr]=bx_ptr;
       /* bubble sort */
       do {
          changes=0;
          for( bx_ptr=C_COL-1; bx_ptr>0; bx_ptr--) {
               if( (p_x1=priority_x(trap,nr,best_x[bx_ptr],v)) == -1 ) {
                    best_x[bx_ptr]=-1;
               }
               if( (p_x2=priority_x(trap,nr,best_x[bx_ptr-1],v)) == -1 ) {
                    best_x[bx_ptr-1]=-1;
               }
               if( p_x1 > p_x2 ) { /* ist einer == -1, dann ist die P auch kleiner */
                   dummy = best_x[bx_ptr];
                   best_x[bx_ptr] = best_x[bx_ptr-1];
                   best_x[bx_ptr-1] = dummy;
                   changes++;
               }
               if( p_x1 == p_x2 && p_x1 != -1 && p_x2 != -1 ) {
                   se_x1=side_effect(best_x[bx_ptr],v)
                   se_x2=side_effect(best_x[bx_ptr-1],v)
                   if( se_x1 > se_x2 ) {
                       dummy = best_x[bx_ptr];
                       best_x[bx_ptr] = best_x[bx_ptr-1];
                       best_x[bx_ptr-1] = dummy;
                       changes++;
                   }
               }
          }
       } while (changes != 0);
}

/*************************************************************************/
/******************* F I L L _ I N D I R E C T _ T R A P ( ) *************/
/*************************************************************************/
// Parameter:
//   nr = Bei welcher Falle soll begonnen werden. Die davorliegenden spielen keine Rolle mehr.
// Setzt voraus, dass das Array all_trap gefüllt ist.
function fill_indirect_trap(trap,v) {
   var fit_idx;
   var tmp_prior_x;
   for( xx=0; xx<C_COL; xx++) indirect_trap[xx] = 0;
   for( fit_idx=0; fit_idx<C_TRAP; fit_idx++) {
        if( trap[fit_idx][0] == 0 || trap[fit_idx][3] == -1 ) break; /* Ende der gefundenen Fallen erreicht */
        /* Wenn eine Falle nur noch <= 2 Züge zur Vollendung hat, dann darf man keinen
        Stein in eine Spalte werfen, wo nur noch 1 Stein fehlt. */
        /* Verhindert der Stein hingegen eine Falle, muss man diese Spalte positiv bewerten */
        /* Verhindere ich mir indirekt eine Falle, dann wird dies zunächst neutrl mit 0 bewertet.
        Momentan sollen nur negative Bewertungen beachtet werden, also die, wo man dem Gegner indirekt
        beim Fallenbau hilft. */
        if( trap[fit_idx][3] <= 2 && trap[fit_idx][4] != v) {
                /* Schleife über alle Spalten */
                for( xx=0; xx<C_COL; xx++) {
                        /* Wenn eine Priorität -1, dann ist dieses X = -1 */
                         if( trap[fit_idx][TRAP_PRE+C_COL+xx] == 1 ) indirect_trap[xx] = -1;
                        if( trap[fit_idx][TRAP_PRE+C_COL+xx] == 0 && indirect_trap[xx] >= 0 ) indirect_trap[xx] = 0;
                }
        }
   }
}

/*************************************************************************/
/******************* C O M P U T E R P L A Y E R ( ) *********************/
/*************************************************************************/
function computerplayer(v) {
         isbusy=1; /* manuellen Einwurf sperren */

     /*** Ablaufplan für Computer
     1. kann ich im nächsten Zug gewinnen?
        Ja: dann setzte dieses Feld
        Nein: weiter...
     ***/
     for(x=0; x<C_COL; x++){
       for(c=0; c<C_WIN; c++){ /* Position */
         for(z=0; z<4; z++) { /* Richtung */
            if(fill_line(x,nexty(x),z,c)==-1) continue;
            if(count_line(COMPUTERPLAYER)==C_WIN-1) {
                     meldung("ich gewinne in "+x);
                     if( document.lform.elements[0].checked == true ) {
                         set_cols+="Cleicht("+x+"); ";
                     } else {
                         set_cols+="C("+x+"); ";
                     }
                     animate_insert(x,0,v);
                     return;
            }
          }
       }
     }

     /***
     2. kann Gegner im nächsten Zug direkt gewinnen?
        Ja: dann verhindere das
        Nein: weiter...
     ***/
     for(x=0; x<C_COL; x++){
       for(c=0; c<C_WIN; c++){
         for(z=0; z<4; z++) { /* Richtung */
            if(fill_line(x,nexty(x),z,c)==-1) continue;
            if(count_line(HUMANPLAYER)==C_WIN-1 ) {
                     meldung("du würdest in "+x+" gewinnen");
                     if( document.lform.elements[0].checked == true ) {
                         set_cols+="Cleicht("+x+"); ";
                     } else {
                         set_cols+="C("+x+"); ";
                     }
                     animate_insert(x,0,v);
                     return;
            }
         }
       }
     }

     /***
     3. kann Gegner im nächsten Schritt indirekt gewinnen
        d.h. ich setze einen Stein, worauf er eine komplette reihe bilden kann
        Ja: dann darf dieses Loch nicht besetzt werden!
           Es wäre denkbar, den Gegner zu zwingen dieses Loch zu besetzen, damit
           man ihm dann die reihe "verderben" kann
       Nein: weiter...
    ***/
    for(j=0; j<C_COL; row_h_indirect[j++]=0); /* Bewertungszeile löschen */
    for(j=0; j<C_COL; row_c_indirect[j++]=0); /* Bewertungszeile löschen */
    for(x=0; x<C_COL; x++){
       if( nexty(x) < 1 ) continue; /*es gibt kein indirektes gewinnen mer da mind. nur noch 1frei*/
       y = nexty(x)-1;
       for(c=0; c<C_WIN; c++){ /* Position */
         for(z=0; z<4; z++) { /* Richtung */
            if(fill_line(x,y,z,c)==-1) continue;
            if(count_line(HUMANPLAYER)==C_WIN-1 ) {
                 meldung("du würdest beim nächsten mal in "+x+" gewinnen ("+x+","+y+","+z+","+c+")");
                 row_h_indirect[x]=-1; /* Spalte als indirekt markieren */
            }
            if(count_line(COMPUTERPLAYER)==C_WIN-1 ) {
                 meldung("ich würde beim nächsten mal in "+x+" gewinnen ("+x+","+y+","+z+","+c+")");
                 row_c_indirect[x]=-1; /* Spalte als indirekt markieren */
            }
         }
       }
     }

    /***
    4. wo kann ich Fallen bauen????
    ***/

   /* trap[][] initialisieren (-1 == nicht belegt)*/
   for(t=0; t<C_TRAP; t++) all_trap[t][3]=-1;

   /* Schwierigkeitsgrad beachten, wenn leicht, dann keine Falle berücksichtigen */
   if( document.lform.elements[0].checked == false ) {
       fill_trap(all_trap,COMPUTERPLAYER);
       fill_trap(all_trap,HUMANPLAYER);
       sort_trap(all_trap)
   }

   /* die letzte Falle muss immer alle ermöglichen (Fallentyp 0) */
   for( trap_ptr=0; trap_ptr<C_TRAP; trap_ptr++) {
        if( all_trap[trap_ptr][3] == -1 ) { trap_ptr++; break; }
   }
   all_trap[trap_ptr-1][0] = 0; /* wird in priority_x() immer mit gleicher prior gewertet */
   all_trap[trap_ptr-1][3] = 0; /* wird in priority_x() immer mit gleicher prior gewertet */

   /* Fallen auswerten !!! */
   /* suche nach der  besten Falle */
   set_x=-1;
   for( trap_ptr=0; trap_ptr<C_TRAP; trap_ptr++) {
        if( all_trap[trap_ptr][3] == -1 ) break; /* Ende der gefundenen Fallen erreicht */
        /* Wenn die AS der Falle durch indirekten Wurf des Gegners gesperrt, dann weiter... */
        /* D.h. ich darf die Aktivierungsspalte nich teufel komm raus füllen, wenn Gegner dadurch
           sofot gewinnen kann */
        myAS=all_trap[trap_ptr][1];
        if( all_trap[trap_ptr][0] != 0 && all_trap[trap_ptr][0] != 3 &&
            all_trap[trap_ptr][4] == COMPUTERPLAYER && row_h_indirect[myAS] == -1 ) continue;
        // Neu: Beachte die Auswirkungen auf andere Fallen.
        // Wenn meine Falle durch einen indirekten Zug des Gegners gesperrt wird, dann darf dieser
        // Zug nicht vorgenommen werden. Wenn diese Falle die Falle des Gegners ermöglicht, dann darf
        // Dieser Zug ebenfalls nicht vorgenommen werden. Dazu wird das Feld indirect_trap[] gefüllt.
        // dabei wird ebenfalls eine Priorität vergeben. Siehe Beschreibung bei Deklaration von indirect_trap[]
        fill_indirect_trap(all_trap,COMPUTERPLAYER);
        fill_best_x(all_trap, trap_ptr, COMPUTERPLAYER);
        for( best_x_ptr=0; best_x_ptr<C_COL; best_x_ptr++ ) {
             if( best_x[best_x_ptr] == -1 ) break;
             if( row_h_indirect[ best_x[best_x_ptr] ] == -1 ) continue;
             if( nexty(best_x[best_x_ptr]) == -1 ) continue;
             /* 28.01.2004: indirekte Fallen */
             if( indirect_trap[ best_x[best_x_ptr] ] == -1 ) continue;
             set_x = best_x[best_x_ptr];
             break;
        }
        if( set_x != -1 ) break;
   }

   /* fallen Anzeigen */
   text="Computer:\n"
   for(t=0; t<C_TRAP; t++) {
      text+=t+": "+all_trap[t][0]+","+all_trap[t][1]+","+all_trap[t][2]+", <"+all_trap[t][3]+"> "+all_trap[t][4]+", ("+all_trap[t][5]+", "+all_trap[t][6]+", "+all_trap[t][7]+") = "
      for(tt=0; tt<C_COL + C_COL; tt++) {
          text+=all_trap[t][tt+TRAP_PRE]+" ";
          if( tt == C_COL-1 ) text+="| ";
      }
      text+="\n";
   }
   for(tt=0; tt<C_COL; tt++) {
       text+=best_x[tt]+" ";
   }
   text+="\n"
   for(tt=0; tt<C_COL; tt++) {
       text+=row_h_indirect[tt]+" ";
   }
   text+="\nSeiten Effekt: "
   for(tt=0; tt<C_COL; tt++) {
       text+=side_effect(tt,COMPUTERPLAYER)+" ";
   }
   text+="\nIndirekte Fallen: "
   for(tt=0; tt<C_COL; tt++) {
       text+=indirect_trap[tt] + " ";
   }
   text+="\nEntscheide mich für Falle "+trap_ptr+" und setze "+set_x;
   meldung(text);


   /* wenn keine Spalte durch falle entschieden, dann suche erstes freies loch ohne indirecten wurf
      zu ermöglichen */
   is_h_indirect = -1; // zeigt an ob indirekter Wurf möglich ist
   if( set_x == -1 ) {
       for( tt=0; tt < C_COL; tt++ ) {
            if( nexty(tt) != -1 && row_h_indirect[tt] != -1 ) { set_x = tt; break; }
            if( nexty(tt) != -1 && row_h_indirect[tt] == -1) { is_h_indirect = tt; }
       }
       if( tt == C_COL ) {
           if( is_h_indirect == -1 ) {
               // alert("es steht unteschieden...");
               isbusy=1;
               return;
           } else {
               set_x = is_h_indirect;
           }
       }
   }

   if( document.lform.elements[0].checked == true ) {
       set_cols+="Cleicht("+set_x+"); ";
   } else {
       set_cols+="C("+set_x+"); ";
   }
   animate_insert(set_x,0,v);
   return;
}
