/* 
   --------------------------------------------------------------------
   Scripts for the GO game - Game Origination Unknown
   
   Author : Mark Boyden (mark.boyden@noise.org)
   Date   : 2001-03-01
   Version: 1.0
   
   Static Variables:
   BLANK           - Blank hole designation
   EXT             - Image file extension
   
   Global Variables:
   oBoard          - Array
      Board Holes and what they contain
   aMarbles        - Array
      Images (A-JJ, blank, no)
   aMoves          - Array
      List of Moves made (for replay and undo), array items are objects
   iMovePos        - Number (Integer)
      Position in Array aMoves. Tracks move position during undos and 
      redos.
   sPoSel          - String
      Position Selected - Currently selected oBoard.id (Hole) if any
   
   To Do:
   Undo
   Redo
   Replay
   Restart should be Rewind
   Randomize the marbles during start up
   Solve
   Sounds for: wrong move (Homer Doh!), Winning, marble move, others??
   --------------------------------------------------------------------
*/
var BLANK       = new String("blank");
var EXT         = new String(".gif");

var oBoard      = new Object();
var aMarbles    = new Array(39);
var aMoves      = new Array(35);
var iMovePos    = new Number();
var sPoSel      = new String();

/* 
   --------------------------------------------------------------------
   window.onload

   Initializes the Program

   Parameters: NONE

   Local Variables:
   i       - integer
      temp counter
   sMarble - String
      lettered name of the marble
   aNames  - Array
      array of Marble Names for loading
   --------------------------------------------------------------------
*/
function window.onload() {
   //initialize variables
   var i;
   var sMarble;// = new String();
   var aNames = new Array(36);
   sPoSel = null;
   iMovePos = -1;
   Count.innerText = 35 - iMovePos;
   //initialize board
   oBoard = {                 r1c3:BLANK, r1c4:BLANK, r1c5:BLANK,
                  r2c2:BLANK, r2c3:BLANK, r2c4:BLANK, r2c5:BLANK, r2c6:BLANK,
      r3c1:BLANK, r3c2:BLANK, r3c3:BLANK, r3c4:BLANK, r3c5:BLANK, r3c6:BLANK, r3c7:BLANK,
      r4c1:BLANK, r4c2:BLANK, r4c3:BLANK, r4c4:BLANK, r4c5:BLANK, r4c6:BLANK, r4c7:BLANK,
      r5c1:BLANK, r5c2:BLANK, r5c3:BLANK, r5c4:BLANK, r5c5:BLANK, r5c6:BLANK, r5c7:BLANK,
                  r6c2:BLANK, r6c3:BLANK, r6c4:BLANK, r6c5:BLANK, r6c6:BLANK,
                              r7c3:BLANK, r7c4:BLANK, r7c5:BLANK
   }
   //pre-load images and initialize Names array
   for (i = 0; i <= 35; i++) {
      //first see if single or double character, then build appropriately
      if (i < 26) {
         sMarble = String.fromCharCode(65+i);
      }
      else {
         sMarble = String.fromCharCode(65+i-26,65+i-26);
      }
      //create object and load image
      aMarbles[sMarble] = new Object();
      aMarbles[sMarble].src = sMarble + EXT;
      //add to array of names
      aNames[i] = sMarble;
   }
   //add blank, yes, no, and selected images into array
   sMarble = BLANK;
   aMarbles[sMarble] = new Object();
   aMarbles[sMarble].src = sMarble + EXT;
//   sMarble = "yes";
//   aMarbles[sMarble] = new Object();
//   aMarbles[sMarble].src = "green.gif";
   sMarble = "no";
   aMarbles[sMarble] = new Object();
   aMarbles[sMarble].src = "wrong.gif";
   sMarble = "selected";
   aMarbles[sMarble] = new Object();
   aMarbles[sMarble].src = "selected.gif";

   //load the board
   aNames.reverse(); //can remove after randomization - math.random
   for (i=1;i<=7;i++) {
      for (j=1;j<=7;j++) {
         //if marble spot exists, load one
         sName = "r"+i+"c"+j;
         if (MarbleCheck(i,j)) {
            //add randomization to popping process      <<-----------------------
            if (!(i==4 && j==4)) oBoard[sName] = aNames.pop();
               else oBoard[sName] = BLANK;
            self[sName].src = oBoard[sName]+EXT;
         }
      }
   }
}

/*
   --------------------------------------------------------------------
   MarbleClick
   --------------------------------------------------------------------
   Moves the marble. First waits for a marble to be selected. Next, 
   hightlights the marble, then shows if the move can be made or not 
   during a mouseover, then makes the move if possible. If the user 
   wants to choose another move, they select the marble originally 
   selected.
   
   Global Variables:
   sPoSel

   Parameters:
   oSpot - Object
      Board Spot in question

   Local Variables:
   oQSpot - Object
      Row and Column info for Board Spot in question
   oPoSel - Object
      Row and Column info for Board Spot currently selected
   --------------------------------------------------------------------
*/
function MarbleClick(oSpot) {
   var oSpot,oPoSel;
   //if from Position already selected then we are checking
   if (sPoSel) { //to see if a ball can be moved there, and if so do it
                 //or if it's a de-select request
      //if Selected Spot same as currently selected
      if (oSpot.id == sPoSel) { //then just un-highlight
         SetMarble(sPoSel,oBoard[sPoSel]);
         sPoSel = null;
      }
      else {//else see if legal move, and do so
         oQSpot = IDtoRC(oSpot.id);
         oPoSel = IDtoRC(sPoSel);
         //if no ball exists, possible legal move
         if (oBoard[oSpot.id] == BLANK) {
            //see if rows or columns match, otherwise not a good move
            if (oQSpot.row == oPoSel.row) { //see if columns difference is legal
               if ((Math.abs(oQSpot.col - oPoSel.col) == 2) && (oBoard["r" + oQSpot.row + "c" + (Math.abs(oQSpot.col)+Math.abs(oPoSel.col))/2] != BLANK)) MoveYES(oSpot.id); //make move
               else MoveNO(oSpot.id);
            }
            else if (oQSpot.col == oPoSel.col) { //see if rows difference is legal
               if ((Math.abs(oQSpot.row - oPoSel.row) == 2) && (oBoard["r" + (Math.abs(oQSpot.row)+Math.abs(oPoSel.row))/2 + "c" + oQSpot.col] != BLANK)) MoveYES(oSpot.id); //make move
               else MoveNO(oSpot.id);
            }
            else MoveNO(oSpot.id); //neither rows or columns match, so not a move
         }
         else MoveNO(oSpot.id); //not valid move
      }
   }
   else {//else to see if a ball exists to pick up (and set the selection)
      //if Board Spot isn't Blank
      if (oBoard[oSpot.id] != BLANK) {//ball is available, so select it
         self[oSpot.id].src = aMarbles.selected.src;
         sPoSel = oSpot.id;
      }
      else MoveNO(oSpot.id); //no ball available, show "no" and then reset
   }
}


/* 
   --------------------------------------------------------------------
   MoveNO
   --------------------------------------------------------------------
   Highlights the clicked marble as NOT an option and resets it.

   Parameters:
   sSpot - String
      Board Position ID
   sMiddle - String
      The partial string of the two

   Local Variables: NONE
   --------------------------------------------------------------------
*/
function MoveNO(sSpot) {
   var sSpot;
   SetMarble(sSpot, "no");
   window.setTimeout("SetMarble(\""+sSpot+"\", \""+oBoard[sSpot]+"\")",500);
}


/* 
   --------------------------------------------------------------------
   MoveYES
   --------------------------------------------------------------------
   Moves the ball and sets appropriate variables.
   
   Global Variables:
   sPoSel

   Parameters:
   sSpot - String
      Board Position ID Moving To

   Local Variables:
   oQSpot - Object
      Row and Column info for Board Spot Moving To
   oPoSel - Object
      Row and Column info for Board Spot Moving From
   --------------------------------------------------------------------
*/
function MoveYES(sSpot) {
   var sSpot;
   var oSpot = new Object();
   var oPoSel = new Object();
   //move ball - set oBoard (two places), change images
   oBoard[sSpot] = oBoard[sPoSel];
   SetMarble(sSpot,oBoard[sSpot]);
   oBoard[sPoSel] = BLANK;
   SetMarble(sPoSel,oBoard[sPoSel]);
   //Pickup Ball
   oSpot = IDtoRC(sSpot);
   oPoSel = IDtoRC(sPoSel);
   //calculate which ball to pick up
   if (oSpot.row == oPoSel.row) { //calculate based on column difference
      sSpotNew = "r" + oSpot.row + "c" + (Math.abs(oSpot.col)+Math.abs(oPoSel.col))/2; //make move
   }
   else { //calculate based on row difference
      sSpotNew = "r" + (Math.abs(oSpot.row)+Math.abs(oPoSel.row))/2 + "c" + oSpot.col;
   }
   //set aMoves
   aMoves[++iMovePos] = {from:sPoSel, to:sSpot, marble:oBoard[sSpotNew]};
   oBoard[sSpotNew] = BLANK;
   SetMarble(sSpotNew,oBoard[sSpotNew]);
   Count.innerText = 35 - iMovePos;

   //see if 35 moves. if so, you WIN!!!
   if (aMoves.length == 35) {
      Win();
   }
   
   //nullify selected position
   sPoSel = null;
}


/* 
   --------------------------------------------------------------------
   SetMarble
   --------------------------------------------------------------------
   Changes the Board Position to show Marble

   Parameters:
   sSpot - String
      Board Position ID
   sMarble - String
      Marble Name to Set

   Local Variables: NONE
   --------------------------------------------------------------------
*/
function SetMarble(sSpot,sMarble) {
   var sSpot, sMarble;
   self[sSpot].src = aMarbles[sMarble].src;
}


/* 
   --------------------------------------------------------------------
   Restart
   --------------------------------------------------------------------
   Restarts the game and resets all the variables. May actually want to 
   do a full rewind of the game instead.

   Local Variables: NONE
   --------------------------------------------------------------------
*/
function Restart() {
   window.onload();
}

/* 
   --------------------------------------------------------------------
   Win
   --------------------------------------------------------------------
   Do a Win and spell out congratulations or something.

   Local Variables: NONE
   --------------------------------------------------------------------
*/
function Win() {

}



/* 
   --------------------------------------------------------------------
   MarbleCheck
   --------------------------------------------------------------------
   Checks the board position to see if a marble hole exists. Used 
   solely during loading of the board.

   Parameters:
   row - the array row in question
   col - the array column in question

   Local Variables: NONE
   --------------------------------------------------------------------
*/
function MarbleCheck(row,col) {
   var row, col;
   //check to see if a marble exists
   switch (row) {
   case 1:
   case 7:
      switch (col) {
      case 1:
      case 2:
      case 6:
      case 7:
         return false;
      default:
         return true;
      } //switch col
      break;
   case 2:
   case 6:
      switch (col) {
      case 1:
      case 7:
         return false;
      default:
         return true;
      } //switch col
      break;
   default:
      return true;
   } //switch row
} //function MarbleCheck

/* 
   --------------------------------------------------------------------
   IDtoRC
   --------------------------------------------------------------------
   Returns the passed oBoard.id reference string changed to an object 
   specifying Row and Column

   Parameters:
   sID - the oBoard.id reference string (format: rXcY)

   Local Variables: NONE
   --------------------------------------------------------------------
*/
function IDtoRC(sID) {
   var sID;
   return {row:sID.substring(1,2),col:sID.substring(3,4)};
}

