﻿/*History
  Description: 
  Mill is a PC-Game written in HTML and JavaScript
  
  Author:
  (c) Copyright, Lutz Tautenhahn
  
  
  Adaptation for the usage with the 'Nine Men's Morris Cube'
  12.03.2010, Walter Randelshofer
*/



/* Variables */
var i, j, best_i, best_j, val, IsOver = true, Start, NextStart = 0, LastEvent = "";
var NeedToMove, NeedToRemove, MoveCount, MaxMoveCount, MaxMove = 1000;

I_Sel = new Array(4);
J_Sel = new Array(4);

NumPieces = new Array(2);
for (j=0; j<2; j++) {
  NumPieces[j]=new Array(3);
}

Level = new Array(2);
Level[0] = 1;
Level[1] = 2;

IsPlayer = new Array(2);
IsPlayer[0] = true;
IsPlayer[1] = false;

// Structure of the playfield and men's array:
// Fld[0..2]       = [0] = Inner Ring; [1] = Middle Ring; [2] = Outer Ring.
// Fld[0..2][0..8] = Elements of the playfield rings starting at 12 o'clock in clockwise direction, 8 elements [0..7], element [8] is not used.
//                   Values: -1 = Blank field; 0 = Red (White) Men; 1 = Blue (Black) Men.
// Fld[3..4]       = [3] = Red (White )Men's; [4] = Blue (Black) Men's.
// Fld[3..4][0..8] = Items of the Red (White) and Blue (Black) Men's, 9 elements [0..8].
//                   Values: -1 = Blank field; 0 = Red (White) Men; 1 = Blue (Black) Men.
// Fld[0..4][0..8][0..2] = Indicates if the element belongs to a mill.
Fld = new Array(5);
for (i = 0; i < 5; i++) {
  Fld[i] = new Array(9);
} 
for (i = 0; i < 5; i++) {
  for (j = 0; j < 9; j++) {
    Fld[i][j] = new Array(3);
  }
}

Pic = new Array(5);
for (i = 0; i < 5; i++) {
  Pic[i] = new Image();
  //Pic[i].src = "mill_" + i + ".gif";
  Pic[i].src = "images/mill_" + i + ".gif";
} 

History = new Array(2);
for (i=0; i < 2; i++) {
  History[i] = new Array(MaxMove + 19);
}




/* *************************************************** */
/* Additional Variables for the Nine Men's Morris Cube */


var debug = false;

// Structure of the cube 'playfield' and array:
// Sticker[0..2]       = [0] = Inner Ring; [1] = Middle Ring; [2] = Outer Ring.
// Sticker[0..2][0..7] = Elements of the playfield rings starting at 12 o'clock in clockwise direction, 8 elements [0..7]
//                       Values: -1 = Blank field; 0 = Red (White) Men; 1 = Blue (Black) Men.
var Sticker = [0];
Sticker = new Array(3);
for (i = 0; i < 3; i++) {
  Sticker[i] = new Array(8);
}

if (language == "") {
  language = "eng";  // Language: eng = English (default); fra = French; deu = German;
}




/* Function Init */
function Init() { 
  var ii, jj;
  for (ii=0; ii < 3; ii++) {
    for (jj=0; jj < 9; jj++) {
      Fld[ii][jj][0] = -1;
    }
  }
  for (ii = 3; ii < 5; ii++) {
    for (jj = 0; jj < 9; jj++) {
      Fld[ii][jj][0] = ii-3;
    }
  }
  for (ii = 0; ii < 4; ii++) {
    I_Sel[ii] = -1;
    J_Sel[ii] = -1;
  }
  Start           = NextStart;
  LastEvent       = "";
  NumPieces[0][0] = 9;
  NumPieces[1][0] = 9;
  MoveCount       = 0;
  MaxMoveCount    = 0;
  NeedToMove      = 0;
  NeedToRemove    = false;
  RefreshScreen();
  IsOver          = false;
}


/* Function SetLevel */
function SetLevel(nn, mm) {
  Level[nn] = mm;
}


/* Function SetOption */
function SetOption(nn, mm) {
  if (nn < 2) {
    IsPlayer[nn] = mm;
  } else {
    NextStart = 1 - mm;
  }
}


/* Function ImgNum */
function ImgNum(ii, jj) {
  var cc = 33;
  if (ii < 3) {
    if (jj == 0) { return(cc-(ii+1)*7); }
    if (jj == 1) { return(cc-(ii+1)*7+(ii+1)); }
    if (jj == 2) { return(cc+(ii+1)); }
    if (jj == 3) { return(cc+(ii+1)*7+(ii+1)); }
    if (jj == 4) { return(cc+(ii+1)*7); }
    if (jj == 5) { return(cc+(ii+1)*7-(ii+1)); }
    if (jj == 6) { return(cc-(ii+1)); }
    if (jj == 7) { return(cc-(ii+1)*7-(ii+1)); }
  }
  if (ii == 3) { return(jj); }
  if (ii == 4) { return(jj + 58); }
  return(0);
}


/* Function MoveString */
function MoveString(nn) {
  if (nn >= 100) { return(eval(nn)); }
  if (nn >= 10)  { return(" " + eval(nn) + " "); }
  return("  " + eval(nn) + "  ");
}


/* Function Timer */
function Timer() {
  if (IsOver) { return; }
  if ((NeedToMove == 0) && (! NeedToRemove)) {
    if (! IsPlayer[(MoveCount + Start)%2]) {
      if (LastEvent == "")       { MakeBestMove(0, Level[(MoveCount + Start)%2], 31000); }
      if (LastEvent == "Back")   { Back();   LastEvent = ""; }
      if (LastEvent == "Replay") { Replay(); LastEvent = ""; }
    }
  }
  if (NeedToMove > 0) {
    if (NeedToMove == 6) {
      window.document.images[ImgNum(I_Sel[0], J_Sel[0])].src = Pic[Fld[I_Sel[0]][J_Sel[0]][0]+3].src;
    }
    if (NeedToMove == 5) {
      window.document.images[ImgNum(I_Sel[1], J_Sel[1])].src = Pic[Fld[I_Sel[0]][J_Sel[0]][0]+3].src;
      window.document.images[ImgNum(I_Sel[0], J_Sel[0])].src = Pic[0].src;
    }
    if (NeedToMove == 4) {
      window.document.images[ImgNum(I_Sel[1], J_Sel[1])].src = Pic[Fld[I_Sel[0]][J_Sel[0]][0]+1].src;
    }
    if (NeedToMove == 3) {
      window.document.images[ImgNum(I_Sel[2], J_Sel[2])].src = Pic[Fld[I_Sel[2]][J_Sel[2]][0]+3].src;
    }
    if (NeedToMove == 2) {
      window.document.images[ImgNum(I_Sel[3], J_Sel[3])].src = Pic[Fld[I_Sel[2]][J_Sel[2]][0]+3].src;
      window.document.images[ImgNum(I_Sel[2], J_Sel[2])].src = Pic[0].src;
    }
    if (NeedToMove == 1)
      window.document.images[ImgNum(I_Sel[3], J_Sel[3])].src = Pic[Fld[I_Sel[2]][J_Sel[2]][0]+1].src;
    NeedToMove--;
    if ((NeedToMove == 3) && (! NeedToRemove)) { NeedToMove=0; }
    if (NeedToMove == 0) {
      window.document.OptionsForm.Moves.value = MoveString(MoveCount+1);
      MakeMove();
      if (IsOver) {
        window.document.OptionsForm.Msg.value = " ";
      } else {
if (debug) { ShowArray(); } // Additional Statement for Nine Men's Morris Cube (wr 17.03.2010)
RefreshCube(); // Additional Statement for Nine Men's Morris Cube (wr 17.03.2010)
        if ((MoveCount + Start)%2 == 0) {
          if (language == "deu") {
            window.document.OptionsForm.Msg.value = " Rot ist am Zug!";
          } else if (language == "fra") {
            window.document.OptionsForm.Msg.value = " Au Rouge de jouer!";
          } else {
            //window.document.OptionsForm.Msg.value = " White's turn.";
            window.document.OptionsForm.Msg.value = " Red's turn!";
          }
        } else {
          if (language == "deu") {
            window.document.OptionsForm.Msg.value = " Blau ist am Zug!";
          } else if (language == "fra") {
            window.document.OptionsForm.Msg.value = " Au Bleu de jouer!";
          } else {
            //window.document.OptionsForm.Msg.value = " Black's turn.";
            window.document.OptionsForm.Msg.value = " Blue's turn!";
          }
        }
      }
    }
  }
}


/* Function Back */
function Back() {
  var hh, ii0, ii1, jj0, jj1;
  if (NeedToMove != 0) { LastEvent = "Back"; return; }
  if (MoveCount == 0) { return; }
  IsOver = false;
  MoveCount--;
  hh = History[0][MoveCount];
  jj1 = hh%10; hh = (hh-jj1)/10;
  ii1 = hh%10; hh = (hh-ii1)/10;
  jj0 = hh%10; hh = (hh-jj0)/10;
  ii0 = hh%10;
  Fld[ii0][jj0][0] = Fld[ii1][jj1][0];
  Fld[ii1][jj1][0] = -1;
  window.document.images[ImgNum(ii0, jj0)].src = Pic[Fld[ii0][jj0][0]+1].src;
  window.document.images[ImgNum(ii1, jj1)].src = Pic[Fld[ii1][jj1][0]+1].src;
  if ((hh = History[1][MoveCount]) > 0) {
    jj1 = hh%10; hh = (hh-jj1)/10;
    ii1 = hh%10; hh = (hh-ii1)/10;
    jj0 = hh%10; hh = (hh-jj0)/10;
    ii0 = hh%10;
    Fld[ii0][jj0][0] = Fld[ii1][jj1][0];
    Fld[ii1][jj1][0] = -1;
    window.document.images[ImgNum(ii0, jj0)].src = Pic[Fld[ii0][jj0][0]+1].src;
    window.document.images[ImgNum(ii1, jj1)].src = Pic[Fld[ii1][jj1][0]+1].src;
    NumPieces[(MoveCount + Start + 1)%2][0]++;
  }
  window.document.OptionsForm.Moves.value = MoveString(MoveCount);
if (debug) { ShowArray(); } // Additional Statement for Nine Men's Morris Cube (wr 17.03.2010)
RefreshCube(); // Additional Statement for Nine Men's Morris Cube (wr 17.03.2010)
  if ((MoveCount + Start)%2 == 0) {
    if (language == "deu") {
      window.document.OptionsForm.Msg.value = " Rot ist am Zug!";
    } else if (language == "fra") {
      window.document.OptionsForm.Msg.value = " Au Rouge de jouer!";
    } else {
      //window.document.OptionsForm.Msg.value = " White's turn.";
      window.document.OptionsForm.Msg.value = " Red's turn!";
    }
  } else {
    if (language == "deu") {
      window.document.OptionsForm.Msg.value = " Blau ist am Zug!";
    } else if (language == "fra") {
      window.document.OptionsForm.Msg.value = " Au Bleu de jouer!";
    } else {
      //window.document.OptionsForm.Msg.value = " Black's turn.";
      window.document.OptionsForm.Msg.value = " Blue's turn!";
    }
  }
}


/* Function Replay */
function Replay() {
  var hh;
  if (NeedToMove != 0) { LastEvent = "Replay"; return; }
  if (MoveCount == MaxMoveCount) { return; }
  hh = History[0][MoveCount];
  J_Sel[1] = hh%10; hh = (hh-J_Sel[1])/10;
  I_Sel[1] = hh%10; hh = (hh-I_Sel[1])/10;
  J_Sel[0] = hh%10; hh = (hh-J_Sel[0])/10;
  I_Sel[0] = hh%10;
  window.document.images[ImgNum(I_Sel[1], J_Sel[1])].src = Pic[Fld[I_Sel[0]][J_Sel[0]][0]+1].src;
  window.document.images[ImgNum(I_Sel[0], J_Sel[0])].src = Pic[0].src;
  if ((hh = History[1][MoveCount]) > 0) {
    J_Sel[3] = hh%10; hh = (hh-J_Sel[3])/10;
    I_Sel[3] = hh%10; hh = (hh-I_Sel[3])/10;
    J_Sel[2] = hh%10; hh = (hh-J_Sel[2])/10;
    I_Sel[2] = hh%10;
    window.document.images[ImgNum(I_Sel[3], J_Sel[3])].src = Pic[Fld[I_Sel[2]][J_Sel[2]][0]+1].src;
    window.document.images[ImgNum(I_Sel[2], J_Sel[2])].src = Pic[0].src;
    NeedToRemove = true;
  } else {
    NeedToRemove = false;
  }
  window.document.OptionsForm.Moves.value = MoveString(MoveCount + 1);
  MakeMove();
  if (IsOver) {
    window.document.OptionsForm.Msg.value=" ";
  } else {
if (debug) { ShowArray(); } // Additional Statement for Nine Men's Morris Cube (wr 17.03.2010)
RefreshCube(); // Additional Statement for Nine Men's Morris Cube (wr 17.03.2010)
    if ((MoveCount + Start)%2 == 0) {
      if (language == "deu") {
        window.document.OptionsForm.Msg.value = " Rot ist am Zug!";
      } else if (language == "fra") {
        window.document.OptionsForm.Msg.value = " Au Rouge de jouer!";
      } else {
        //window.document.OptionsForm.Msg.value = " White's turn.";
        window.document.OptionsForm.Msg.value = " Red's turn!";
      }
    } else {
      if (language == "deu") {
        window.document.OptionsForm.Msg.value = " Blau ist am Zug!";
      } else if (language == "fra") {
        window.document.OptionsForm.Msg.value = " Au Bleu de jouer!";
      } else {
        //window.document.OptionsForm.Msg.value = " Black's turn.";
        window.document.OptionsForm.Msg.value = " Blue's turn!";
      }
    }
  }
}


/* Function MakeMove */
function MakeMove() {
  var hh;
  Fld[I_Sel[1]][J_Sel[1]][0] = Fld[I_Sel[0]][J_Sel[0]][0];
  Fld[I_Sel[0]][J_Sel[0]][0] = -1;
  hh = I_Sel[0]*1000+J_Sel[0]*100+I_Sel[1]*10+J_Sel[1];
  if (History[0][MoveCount] != hh) {
    History[0][MoveCount] = hh;
    MaxMoveCount = MoveCount + 1;
  }
  if (NeedToRemove) {
    Fld[I_Sel[3]][J_Sel[3]][0] = Fld[I_Sel[2]][J_Sel[2]][0];
    Fld[I_Sel[2]][J_Sel[2]][0] = -1;
    hh = I_Sel[2]*1000+J_Sel[2]*100+I_Sel[3]*10+J_Sel[3];
    if (History[1][MoveCount] != hh) {
      History[1][MoveCount] = hh;
      MaxMoveCount = MoveCount + 1;
    }
    NumPieces[(MoveCount + Start + 1)%2][0]--;
    if (NumPieces[(MoveCount + Start + 1)%2][0] < 3) {
if (debug) { ShowArray(); } // Additional Statement for Nine Men's Morris Cube (wr 17.03.2010)
RefreshCube(); // Additional Statement for Nine Men's Morris Cube (wr 17.03.2010)
      if ((MoveCount + Start)%2 == 0) {
        if (language == "deu") {
          alert("Rot hat gewonnen!");
        } else if (language == "fra") {
          alert("Le Rouge a gagné!");
        } else {
          //alert("White has won!");
          alert("Red has won!");
        }
      } else {
        if (language == "deu") {
          alert("Blau hat gewonnen!");
        } else if (language == "fra") {
          alert("Le Bleu a gagné!");
        } else {
          //alert("Black has won!");
          alert("Blue has won!");
        }
      }
      IsOver = true;
    }
  } else {
    History[1][MoveCount] = 0;
  }
  NeedToRemove = false;
  if ((MoveCount >= 17) && (NumPieces[(MoveCount + Start + 1)%2][0] > 3)) {
    if (AllValidMoves((MoveCount + Start + 1)%2,0) == 0) {
if (debug) { ShowArray(); } // Additional Statement for Nine Men's Morris Cube (wr 17.03.2010)
RefreshCube(); // Additional Statement for Nine Men's Morris Cube (wr 17.03.2010)
      if ((MoveCount + Start)%2 == 0) {
        if (language == "deu") {
          alert("Rot hat gewonnen!");
        } else if (language == "fra") {
          alert("Le Rouge a gagné!");
        } else {
          //alert("White has won!");
          alert("Red has won!");
        }
      } else {
        if (language == "deu") {
          alert("Blau hat gewonnen!");
        } else if (language == "fra") {
          alert("Le Bleu a gagné!");
        } else {
          //alert("Black has won!");
          alert("Blue has won!");
        }
      }
      IsOver = true;
    }
  }
  MoveCount++;
  if (MaxMoveCount<MoveCount) MaxMoveCount=MoveCount;
  if (MoveCount==MaxMove) {
    if (language == "deu") {
      alert("Das Spiel endet unentschieden!");
    } else if (language == "fra") {
      alert("Match nul!");
    } else {
      alert("It's a draw!");
    }
    IsOver=true;
  }
}


/* Function ValidMoves */
function ValidMoves(ii, jj, rr) {
  var nn=0;
  if (jj%2==0) {
    if (ii==1) {
      if (Fld[0][jj][rr]==-1) { nn++; }
      if (Fld[2][jj][rr]==-1) { nn++; }
    } else {
      if (Fld[1][jj][rr]==-1) { nn++; }
    }
  }
  if (Fld[ii][(jj+1)%8][rr]==-1) { nn++; }
  if (Fld[ii][(jj+7)%8][rr]==-1) { nn++; }
  return(nn);
}


/* Function AllValidMoves */
function AllValidMoves(cc, rr) {
  var ii, jj, nn=0;
  for (ii=0; ii < 3; ii++) {
    for (jj=0; jj < 8; jj++) {
      if (Fld[ii][jj][rr]==cc) {
        nn+=ValidMoves(ii, jj, rr);
      }
    }
  }
  return(nn);
}


/* Function PreMill */
function PreMill(cc, rr) {
  var ii, jj, nn=0;
  for (ii=0; ii < 3; ii++) {
    for (jj=0; jj < 8; jj++) {
      if (Fld[ii][jj][rr]==-1) {
        Fld[ii][jj][rr]=cc;
        if (IsMill(ii, jj, rr)) { nn++; }
        Fld[ii][jj][rr]=-1;
      }
    }
  }
  return(nn);
}


/* Function IsMill */
function IsMill(ii, jj, rr) {
  if (jj%2==0) {
    if ((Fld[0][jj][rr]==Fld[1][jj][rr])&&(Fld[0][jj][rr]==Fld[2][jj][rr])) { return(true); }
  }
  if ((jj==7)||(jj==0)||(jj==1)) {
    if ((Fld[ii][7][rr]==Fld[ii][0][rr])&&(Fld[ii][7][rr]==Fld[ii][1][rr])) { return(true); }
  }
  if ((jj==1)||(jj==2)||(jj==3)) {
    if ((Fld[ii][1][rr]==Fld[ii][2][rr])&&(Fld[ii][1][rr]==Fld[ii][3][rr])) { return(true); }
  }
  if ((jj==3)||(jj==4)||(jj==5)) {
    if ((Fld[ii][3][rr]==Fld[ii][4][rr])&&(Fld[ii][3][rr]==Fld[ii][5][rr])) { return(true); }
  }
  if ((jj==5)||(jj==6)||(jj==7)) {
    if ((Fld[ii][5][rr]==Fld[ii][6][rr])&&(Fld[ii][5][rr]==Fld[ii][7][rr])) { return(true); }
  }
  return(false);
}


/* Function CanRemove */
function CanRemove(nn, mm, rr) {
  var ii, jj, cc=Fld[nn][mm][rr];
  if (! IsMill(nn, mm, rr)) { return(true); }
  for (ii=0; ii < 3; ii++) {
    for (jj=0; jj < 8; jj++) {
      if (Fld[ii][jj][rr]==cc) {
        if (! IsMill(ii, jj, rr)) { return(false); }
      }
    }
  }
  return(true);
}


/* Function MakeVirtualMove */
function MakeVirtualMove(ii0,jj0,ii1,jj1,rr) {
  var ii, jj;
  if ((ii1<0)||(ii1>2)) { return(0); }
  if (Fld[ii1][jj1][rr-1]!=-1) { return(0); }
  for (ii=0; ii<5; ii++) {
    for (jj=0; jj<9; jj++) {
      Fld[ii][jj][rr]=Fld[ii][jj][rr-1];
    }
  }
  NumPieces[0][rr]=NumPieces[0][rr-1];
  NumPieces[1][rr]=NumPieces[1][rr-1];
  Fld[ii1][jj1][rr]=Fld[ii0][jj0][rr];
  Fld[ii0][jj0][rr]=-1;
  if (! IsMill(ii1,jj1,rr)) { return(1); }
  NumPieces[(MoveCount+Start+1)%2][rr]--;
  return(2);
}


/* Function VirtualRemove */
function VirtualRemove(ii0,jj0,ii1,jj1,rr) {
  var ii, jj;
  if (Fld[ii0][jj0][rr]!=(MoveCount+Start+1)%2) { return(0); }
  if (! CanRemove(ii0, jj0, rr)) { return(0); }
  Fld[ii1][jj1][rr]=Fld[ii0][jj0][rr];
  Fld[ii0][jj0][rr]=-1;
  return(1);
}


function MakeBestMove(nn, ll, vv_cut) {
  var ii0,jj0,ii1,jj1,ii2,jj2,ii3,jj3,rr=nn+1,vv,dd,act_val,best_val=-30000;
  var mm=(MoveCount+Start)%2, mm1=1-mm, zz;
  if (nn==ll) {
    act_val=200*(NumPieces[mm][nn]-NumPieces[mm1][nn]);
    if (ll<3) {
      if (MoveCount<16) {
        act_val+=20*PreMill(mm, nn);
        act_val-=15*PreMill(mm1, nn);
      } else {
        if (NumPieces[mm][nn]==3) {
          act_val+=40*PreMill(mm, nn);
          act_val-=30*PreMill(mm1, nn);
        }
      }
    }
    if (NumPieces[mm][nn]==3) { return(act_val); }
    act_val+=5*AllValidMoves(mm, nn);
    act_val-=3*AllValidMoves(mm1, nn);
    return(act_val);
  }
  if (MoveCount<18) {
    ii0=mm+3;
    jj0=0;
    while (Fld[ii0][jj0][nn]!=mm) jj0++;
    for (ii1=0; ii1<3; ii1++)
    { for (jj1=0; jj1<8; jj1++)
      { if ((vv=MakeVirtualMove(ii0,jj0,ii1,jj1,rr))>0)
        { isvalid=true;
          if (vv==1)
          { MoveCount++;
            zz=0;  
            if (rr==1) zz=Math.floor(Math.random()*3*(4-ll));
            act_val=zz-MakeBestMove(rr,ll,zz-best_val);
            MoveCount--;
            if (act_val>=vv_cut) return(act_val);
            if (best_val<act_val)
            { best_val=act_val;
              if (rr==1)
              { I_Sel[0]=ii0;
                J_Sel[0]=jj0;
                I_Sel[1]=ii1;
                J_Sel[1]=jj1;
                NeedToRemove=false;
              }
            }
          }
          else
          { ii3=mm+3;
            jj3=0;
            while (Fld[ii3][jj3][rr]!=-1) jj3++;
            for (ii2=0; ii2<3; ii2++)
            { for (jj2=0; jj2<8; jj2++)
              { if (VirtualRemove(ii2,jj2,ii3,jj3,rr)>0)  
                { MoveCount++;
                  zz=0;  
                  if (rr==1) zz=Math.floor(Math.random()*6*(4-ll));
                  act_val=zz-MakeBestMove(rr,ll,zz-best_val);
                  MoveCount--;
                  if (act_val>=vv_cut) return(act_val);
                  if (best_val<act_val)
                  { best_val=act_val;
                    if (rr==1)
                    { I_Sel[0]=ii0;
                      J_Sel[0]=jj0;
                      I_Sel[1]=ii1;
                      J_Sel[1]=jj1;
                      I_Sel[2]=ii2;
                      J_Sel[2]=jj2;
                      I_Sel[3]=ii3;
                      J_Sel[3]=jj3;
                      NeedToRemove=true;
                    }
                  }
                  Fld[ii2][jj2][rr]=Fld[ii3][jj3][rr];
                  Fld[ii3][jj3][rr]=-1;
                }
              }
            }
          }
        }
      }
    }
  }
  else
  { if (NumPieces[mm][nn]==3)
    { for (ii0=0; ii0<3; ii0++)
      { for (jj0=0; jj0<8; jj0++)
        { if (Fld[ii0][jj0][nn]==mm)
          { for (ii1=0; ii1<3; ii1++)
            { for (jj1=0; jj1<8; jj1++)
              { if ((vv=MakeVirtualMove(ii0,jj0,ii1,jj1,rr))>0)
                { isvalid=true;
                  if (vv==1)
                  { MoveCount++;
                    zz=0;  
                    if (rr==1) zz=Math.floor(Math.random()*3*(4-ll));
                    act_val=zz-MakeBestMove(rr,ll,zz-best_val);
                    MoveCount--;
                    if (act_val>=vv_cut) return(act_val);
                    if (best_val<act_val)
                    { best_val=act_val;
                      if (rr==1)
                      { I_Sel[0]=ii0;
                        J_Sel[0]=jj0;
                        I_Sel[1]=ii1;
                        J_Sel[1]=jj1;
                        NeedToRemove=false;
                      }
                    }
                  }
                  else
                  { ii3=mm+3;
                    jj3=0;
                    while (Fld[ii3][jj3][rr]!=-1) jj3++;
                    for (ii2=0; ii2<3; ii2++)
                    { for (jj2=0; jj2<8; jj2++)
                      { if (VirtualRemove(ii2,jj2,ii3,jj3,rr)>0)  
                        { MoveCount++;
                          zz=0;  
                          if (rr==1) zz=Math.floor(Math.random()*6*(4-ll));
                          act_val=zz-MakeBestMove(rr,ll,zz-best_val);
                          MoveCount--;
                          if (act_val>=vv_cut) return(act_val);
                          if (best_val<act_val)
                          { best_val=act_val;
                            if (rr==1)
                            { I_Sel[0]=ii0;
                              J_Sel[0]=jj0;
                              I_Sel[1]=ii1;
                              J_Sel[1]=jj1;
                              I_Sel[2]=ii2;
                              J_Sel[2]=jj2;
                              I_Sel[3]=ii3;
                              J_Sel[3]=jj3;                      
                              NeedToRemove=true;
                            }
                          }
                          Fld[ii2][jj2][rr]=Fld[ii3][jj3][rr];
                          Fld[ii3][jj3][rr]=-1;
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
    else
    { for (ii0=0; ii0<3; ii0++)
      { for (jj0=0; jj0<8; jj0++)
        { if (Fld[ii0][jj0][nn]==mm)
          { for (dd=0; dd<4-2*(jj0 % 2); dd++)
            { if (dd==0) { ii1=ii0; jj1=(jj0+7)%8; }
              if (dd==1) { ii1=ii0; jj1=(jj0+1)%8; }
              if (dd==2) { ii1=ii0-1; jj1=jj0; }
              if (dd==3) { ii1=ii0+1; jj1=jj0; }
              if ((vv=MakeVirtualMove(ii0,jj0,ii1,jj1,rr))>0)
              { isvalid=true;
                if (vv==1)
                { MoveCount++;
                  zz=0;  
                  if (rr==1) zz=Math.floor(Math.random()*3*(4-ll));
                  act_val=zz-MakeBestMove(rr,ll,zz-best_val);
                  MoveCount--;
                  if (act_val>=vv_cut) return(act_val);
                  if (best_val<act_val)
                  { best_val=act_val;
                    if (rr==1)
                    { I_Sel[0]=ii0;
                      J_Sel[0]=jj0;
                      I_Sel[1]=ii1;
                      J_Sel[1]=jj1;
                      NeedToRemove=false;
                    }
                  }              
                }
                else
                { ii3=mm+3;
                  jj3=0;
                  while (Fld[ii3][jj3][rr]!=-1) jj3++;
                  for (ii2=0; ii2<3; ii2++)
                  { for (jj2=0; jj2<8; jj2++)
                    { if (VirtualRemove(ii2,jj2,ii3,jj3,rr)>0)  
                      { MoveCount++;
                        zz=0;  
                        if (rr==1) zz=Math.floor(Math.random()*6*(4-ll));
                        act_val=zz-MakeBestMove(rr,ll,zz-best_val);
                        MoveCount--;
                        if (act_val>=vv_cut) return(act_val);
                        if (best_val<act_val)
                        { best_val=act_val;
                          if (rr==1)
                          { I_Sel[0]=ii0;
                            J_Sel[0]=jj0;
                            I_Sel[1]=ii1;
                            J_Sel[1]=jj1;
                            I_Sel[2]=ii2;
                            J_Sel[2]=jj2;
                            I_Sel[3]=ii3;
                            J_Sel[3]=jj3;                      
                            NeedToRemove=true;
                          }
                        }
                        Fld[ii2][jj2][rr]=Fld[ii3][jj3][rr];
                        Fld[ii3][jj3][rr]=-1;
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  }
  if (rr > 1) { return(best_val); }
  NeedToMove = 6;
} 


function Clicked(ii, jj) {
  if (IsOver) { return; }
  if (NeedToMove > 0) { return; }
  if (! IsPlayer[(MoveCount+Start)%2]) { return; }
  if (NeedToMove == 0) {
    if (MoveCount < 18) {
      if (ii!=(MoveCount+Start)%2+3) {
        if ((MoveCount + Start)%2 == 0) {
          if (language == "deu") {
            alert("Wähle einen neuen roten Stein von der linken Seite!");
          } else if (language == "fra") {
            alert("Sélectionnez une nouvelle pièce rouge sur le côté gauche!");
          } else {
            //alert("Select a new white piece from the left side!");
            alert("Select a new red piece from the left side!");
          }
        } else {
          if (language == "deu") {
            alert("Wähle einen neuen blauen Stein von der rechten Seite!");
         } else if (language == "fra") {
            alert("Sélectionnez une nouvelle pièce bleue sur le côté droit!");
          } else {
            //alert("Select a new black piece from the right side!");
            alert("Select a new blue piece from the right side!");
          }
        }
        return;
      }
      if (Fld[(MoveCount + Start)%2+3][jj][0] != (MoveCount + Start)%2) {
        if ((MoveCount + Start)%2 == 0) {
          if (language == "deu") {
            alert("Klicke auf einen roten Stein auf der linken Seite!");
          } else if (language == "fra") {
            alert("Cliquez sur une pièce rouge à gauche!");
          } else {
            //alert("Click on a white piece at the left side!");
            alert("Click on a red piece at the left side!");
          }
        } else {
          if (language == "deu") {
            alert("Klicke auf einen blauen Stein auf der rechten Seite!");
          } else if (language == "fra") {
            alert("Cliquez sur une pièce bleue à droite!");
          } else {
            //alert("Click on a black piece at the right side!");
            alert("Click on a blue piece at the right side!");
          }
        }
        return;
      }
    } else {
      if ((ii > 2) || (Fld[ii][jj][0] != (MoveCount + Start)%2)) {
        if ((MoveCount + Start)%2 == 0) {
          if (language == "deu") {
            alert("Wähle einen roten Stein vom Spielbrett!");
          } else if (language == "fra") {
            alert("Choisissez une pièce rouge sur le tablier!");
          } else {
            //alert("Choose a white piece from the game board!");
            alert("Choose a red piece from the game board!");
          }
        } else {
          if (language == "deu") {
            alert("Wähle einen blauen Stein vom Spielbrett!");
          } else if (language == "fra") {
            alert("Choisissez une pièce bleue sur le tablier!");
          } else {
            //alert("Choose black piece from the game board!");
            alert("Choose a blue piece from the game board!");
          }
        }
        return;
      }
    }
    I_Sel[0]=ii;
    J_Sel[0]=jj;
    window.document.images[ImgNum(I_Sel[0], J_Sel[0])].src = Pic[Fld[I_Sel[0]][J_Sel[0]][0]+3].src;
    NeedToMove=-1;
    return;
  }
  if (NeedToMove == -1) {
    if ((ii == I_Sel[0]) && (jj == J_Sel[0])) {
      window.document.images[ImgNum(I_Sel[0], J_Sel[0])].src = Pic[Fld[I_Sel[0]][J_Sel[0]][0]+1].src;
      NeedToMove=0;
      return;
    }
    if ((ii > 2) || (Fld[ii][jj][0] != -1)) {
      if (language == "deu") {
        alert("Der Stein muss auf ein leeres Feld auf dem Spielbrett bewegt werden!");
      } else if (language == "fra") {
        alert("Vous devez déplacer votre pièce vers un emplacement libre du tablier!");
      } else {
        alert("You must move your piece to an empty field on the game board!");
      }
      return;
    }
    if ((MoveCount >= 18) && (NumPieces[(MoveCount + Start)%2][0] > 3) && (((jj == J_Sel[0]) && (jj%2 == 1)) || (4-Math.abs(4 - (jj - J_Sel[0] + 8)%8) + Math.abs(ii - I_Sel[0]) > 1))) {
      if (language == "deu") {
        alert("Der Stein muss auf ein benachbartes Feld bewegt werden!");
      } else if (language == "fra") {
        alert("Vous devez déplacer votre pièce vers un emplacement voisin!");
      } else {
        alert("You must move your piece to a neighbouring field!");
      }
      return;
    }
    I_Sel[1]=ii;
    J_Sel[1]=jj;
    window.document.images[ImgNum(I_Sel[0], J_Sel[0])].src = Pic[0].src;
    window.document.images[ImgNum(I_Sel[1], J_Sel[1])].src = Pic[Fld[I_Sel[0]][J_Sel[0]][0]+3].src;
    Fld[I_Sel[1]][J_Sel[1]][0]=Fld[I_Sel[0]][J_Sel[0]][0];
    Fld[I_Sel[0]][J_Sel[0]][0]=-1;
    if (IsMill(ii, jj, 0)) {
if (debug) { ShowArray(); } // Additional Statement for Nine Men's Morris Cube (wr 17.03.2010)
RefreshCube(); // Additional Statement for Nine Men's Morris Cube (wr 17.03.2010)
      if ((MoveCount + Start)%2 == 0) {
        if (language == "deu") {
          window.document.OptionsForm.Msg.value=" Entferne einen blauen Stein!";
        } else if (language == "fra") {
          window.document.OptionsForm.Msg.value=" Retirez une pièce bleue!";
        } else {
          //window.document.OptionsForm.Msg.value=" Remove a black piece!";
          window.document.OptionsForm.Msg.value=" Remove a blue piece!";
        }
      } else {
        if (language == "deu") {
          window.document.OptionsForm.Msg.value=" Entferne einen roten Stein!";
        } else if (language == "fra") {
          window.document.OptionsForm.Msg.value=" Retirez une pièce rouge!";
        } else {
          //window.document.OptionsForm.Msg.value=" Remove a white piece!";
          window.document.OptionsForm.Msg.value=" Remove a red piece!";
        }
      }
      NeedToRemove = true;
      NeedToMove = -2;
    } else {
      NeedToRemove = false;
      NeedToMove = 4;
    }
    Fld[I_Sel[0]][J_Sel[0]][0]=Fld[I_Sel[1]][J_Sel[1]][0];
    Fld[I_Sel[1]][J_Sel[1]][0]=-1;
    return;
  }
  if (NeedToMove == -2) {
    if ((ii > 2) || (Fld[ii][jj][0] != (MoveCount + Start + 1)%2)) {
      if ((MoveCount + Start)%2 == 0) {
        if (language == "deu") {
          alert("Wähle einen blauen Stein vom Spielbrett!");
        } else if (language == "fra") {
          alert("Sélectionnez une pièce bleue sur le tablier!");
        } else {
          //alert("Select a black piece from the game board!");
          alert("Select a blue piece from the game board!");
        }
      } else {
        if (language == "deu") {
          alert("Wähle einen roten Stein vom Spielfeld!");
        } else if (language == "fra") {
          alert("Sélectionnez une pièce rouge sur le tablier!");
        } else {
          //alert("Select a white piece from the game board!");
          alert("Select a red piece from the game board!");
        }
      }
      return;
    }
    if (! CanRemove(ii, jj, 0)) {
      if (language == "deu") {
        alert("Entferne einen Stein ausserhalb einer Mühle!");
      } else if (language == "fra") {
        alert("Retirez une pièce extérieure au moulin!");
      } else {
        alert("Remove a piece from outside of a mill!");
      }
      return;
    }
    I_Sel[2]=ii;
    J_Sel[2]=jj;
    window.document.images[ImgNum(I_Sel[1], J_Sel[1])].src = Pic[Fld[I_Sel[0]][J_Sel[0]][0]+1].src;
    window.document.images[ImgNum(I_Sel[2], J_Sel[2])].src = Pic[Fld[I_Sel[2]][J_Sel[2]][0]+3].src;
    NeedToMove=-3;
    return;
  }
  if (NeedToMove == -3) {
    if ((ii == I_Sel[2]) && (jj == J_Sel[2])) {
      window.document.images[ImgNum(I_Sel[2], J_Sel[2])].src = Pic[Fld[I_Sel[2]][J_Sel[2]][0]+1].src;
      NeedToMove = -2;
      return;
    }
    if ((ii != (MoveCount + Start)%2+3) || ((Fld[ii][jj][0] != -1) && (jj != J_Sel[0]))) {
      if ((MoveCount + Start)%2 == 0) {
        if (language == "deu") {
          alert("Bitte, lege diesen Stein auf ein leeres Feld links neben dem Spielbrett!");
        } else if (language == "fra") {
          alert("Placez cette pièce sur un emplacement vide du côté gauche du tablier, svp!");
        } else {
          alert("Put that piece on an empty place at the left side of the game board, please!");
        }
      } else {
        if (language == "deu") {
          alert("Bitte, lege diesen Stein auf ein leeres Feld rechts neben dem Spielbrett!");
        } else if (language == "fra") {
          alert("Placez cette pièce sur un emplacement vide du côté droit du tablier, svp!");
        } else {
          alert("Put that piece on an empty place at the right side of the game board, please!");
        }
      }
      return;
    }
    I_Sel[3]=ii;
    J_Sel[3]=jj;
    window.document.images[ImgNum(I_Sel[2], J_Sel[2])].src = Pic[0].src;
    window.document.images[ImgNum(I_Sel[3], J_Sel[3])].src = Pic[Fld[I_Sel[2]][J_Sel[2]][0]+3].src;
    NeedToMove=1;
    return;
  }
}


/* Function RefreshScreen */
function RefreshScreen() {
  for (i = 0;  i < 9;  i++) { window.document.images[i].src = Pic[1].src; }
  for (i = 9;  i < 58; i++) { window.document.images[i].src = Pic[0].src; }
  for (i = 58; i < 67; i++) { window.document.images[i].src = Pic[2].src; }
  window.document.OptionsForm.Moves.value = MoveString(MoveCount);
if (debug) { ShowArray(); } // Additional Statement for Nine Men's Morris Cube (wr 17.03.2010)
RefreshCube(); // Additional Statement for Nine Men's Morris Cube (wr 17.03.2010)
  if ((MoveCount + Start)%2 == 0) {
    if (language == "deu") {
      window.document.OptionsForm.Msg.value=" Rot ist am Zug!";
    } else if (language == "fra") {
      window.document.OptionsForm.Msg.value=" Au Rouge de jouer!";
    } else {
      //window.document.OptionsForm.Msg.value=" White's turn.";
      window.document.OptionsForm.Msg.value=" Red's turn!";
    }
  } else {
    if (language == "deu") {
      window.document.OptionsForm.Msg.value=" Blau ist am Zug!";
    } else if (language == "fra") {
      window.document.OptionsForm.Msg.value=" Au Bleu de jouer!";
    } else {
      //window.document.OptionsForm.Msg.value=" Black's turn.";
      window.document.OptionsForm.Msg.value=" Blue's turn!";
    }
  }
}


/* Function Helo */
function Help() {
  if (language == "deu") {
    alert("Dieses Spiel gehört zu den ältesten Spielen der Welt.\n"+
          "Beide Spieler besitzen je neun Steine, die sie abwechselnd auf freie Schnittpunkte des Spielbretts legen. "+
          "Gelingt es einem der Spieler drei Steine auf eine Linie zu legen, hat er eine Mühle und darf einen "+
          "gegnerischen Stein vom Brett nehmen. Es dürfen dabei nur Steine entfernt werden, die nicht einer Mühle "+
          "angehören. Nur wenn alle gegnerischen Steine Teil einer Mühle sind, ist es erlaubt, auch diese Steine aus "+
          "dem Spiel zu nehmen.\n"+
          "Sobald die Steine gelegt sind, bewegen die Spieler abwechselnd einen ihrer Steine auf einen benachbarten "+
          "Platz. Kann ein Spieler drei seiner Steine auf eine Linie legen, darf er erneut einen gegnerischen Stein "+
          "entfernen. Eine Mühle kann bliebig oft geöffnet und geschlossen werden. Sobald ein Spieler nur noch über "+
          "drei Steine verfügt, darf er mit den verbleibenden Steinen auf jeden freien Punkt des Spielbretts springen.\n"+
          "Ein Spieler hat verloren, wenn er nur noch zwei Steine übrig hat oder wenn er nicht mehr in der Lage ist "+
          "einen Zug auszuführen.");
  } else if (language == "fra") {
    alert("Ce jeu est l'un des plus anciens jeux connus dans l'histoire.\n"+
          "Chacun des deux joueurs possède neuf pièces qu'ils placent à tour de rôle sur chaque emplacement libre du tablier de jeu. "+
          "Si un joueur arrive à aligner trois pièces, c'est-à-dire à réaliser un moulin, il retire du jeu une des pièces du joueur "+
          "adverse. Vous ne devez retirer une pièce qui ne fait pas partie d'un moulin que si toutes les pièces du joueur adverse sont dans des moulins, "+
          "vous pouvez même retirer une pièce d'un moulin.\n"+
          "Quand toutes les pièces ont été placées sur le tablier, les joueurs déplacent à tour de rôle une de leurs "+
          "pièces sur un emplacement voisin. Si un joueur réussit à aligner trois de ses pièces, il peut encore retirer une des pièces "+
          "du joueur adverse. Un moulin peut être ouvert ou fermé autant de fois que l'on veut. Si un joueur ne dispose plus que de "+
          "trois pièces, il peut déplacer ses pièces vers n'importe quel emplacement libre du tablier.\n"+
          "Un joueur a perdu s'il ne lui reste plus que deux pièces ou bien s'il ne lui est plus possible de déplacer l'une de ses "+
          "pièces restantes.");
  } else {
    alert("This game is one of the oldest games known in history.\n"+
          "Each of the two players has nine pieces, which they put alternately on any free point of the game board. "+
          "If a player gets three pieces in a line - a mill, he removes one of the opponent's pieces from the game "+
          "board. You must remove a piece which is not in a mill, only if all of the opponent's pieces are in mills, "+
          "you can remove a piece even from a mill.\n"+
          "When all the pieces have been entered on the game board, the players move alternately one of their "+
          "pieces on a neighbouring place. If a player gets three of his pieces in a line, he can remove one of "+
          "the opponent's pieces again. A mill can be opened and closed any number of times. If a player has only "+
          "three pieces left, he can jump with his pieces to any free point of the game board.\n"+
          "A player has lost, if he has only two pieces left or if he is not able to make a move with one of his "+
          "pieces.");
  }
}


/* Function Resize */
function Resize() {
  if (navigator.appName == "Netscape") { history.go(0); }
}









/* *************************************************** */
/* Additional Functions for the Nine Men's Morris Cube */

/* Function ShowArray */
function ShowArray() {
  var arraycontent = "";
  var txt = "";
  z = 1;
  for (i = 0; i < 5; i++) {
    for (j = 0; j < 9; j++) {
      txt = Fld[i][j][0];
      if (txt == 0) { txt = "R"; } // Red
      if (txt == 1) { txt = "B"; } // Blue
      if (txt < 1)  { txt = "_"; } // Blank
      if (i < 3 && ((z % 9) == 0)) { txt = ""; }
      
      if (z == 1)  {arraycontent = arraycontent + "Circle 1: ";}
      if (z == 10) {arraycontent = arraycontent + "Circle 2: ";}
      if (z == 19) {arraycontent = arraycontent + "Circle 3: ";}
      if (z == 28) {arraycontent = arraycontent + "Blue Men: ";}
      if (z == 37) {arraycontent = arraycontent + "Red Men: ";}
      
      arraycontent = arraycontent + txt + " " ;
      if ((z % 9) == 0) {arraycontent = arraycontent + "\n";}
      z = z + 1;
    }
  }
  
  window.document.OptionsForm.test.firstChild.data=arraycontent;
}


/* Function RefreshCube */
function RefreshCube() {
  var txt = "";
  for (i = 0; i < 3; i++) {
    for (j = 0; j < 8; j++) {
      txt = Fld[i][j][0];
      if (txt == 0) { txt = "2"; } // Red
      if (txt == 1) { txt = "1"; } // Blue
      if (txt < 1)  { txt = "0"; } // Blank
      Sticker[i][j] = txt;
    }
  }
  
  updateStateNow(Sticker[0][0], Sticker[0][1], Sticker[0][2], Sticker[0][3], Sticker[0][4], Sticker[0][5], Sticker[0][6], Sticker[0][7], 
                 Sticker[1][0], Sticker[1][1], Sticker[1][2], Sticker[1][3], Sticker[1][4], Sticker[1][5], Sticker[1][6], Sticker[1][7], 
                 Sticker[2][0], Sticker[2][1], Sticker[2][2], Sticker[2][3], Sticker[2][4], Sticker[2][5], Sticker[2][6], Sticker[2][7] );
}

