var sbishop = [
        -2, -2, -2, -2, -2, -2, -2, -2, 0, 0, 0, 0, 0, 0, 0, 0, 
        -2,  8,  5,  5,  5,  5,  8, -2, 0, 0, 0, 0, 0, 0, 0, 0, 
        -2,  3,  3,  5,  5,  3,  3, -2, 0, 0, 0, 0, 0, 0, 0, 0, 
        -2,  2,  5,  4,  4,  5,  2, -2, 0, 0, 0, 0, 0, 0, 0, 0, 
        -2,  2,  5,  4,  4,  5,  2, -2, 0, 0, 0, 0, 0, 0, 0, 0, 
        -2,  3,  3,  5,  5,  3,  3, -2, 0, 0, 0, 0, 0, 0, 0, 0, 
        -2,  8,  5,  5,  5,  5,  8, -2, 0, 0, 0, 0, 0, 0, 0, 0, 
        -2, -2, -2, -2, -2, -2, -2, -2, 0, 0, 0, 0, 0, 0, 0, 0
];
var sknight = [
        -20, -10, -10, -10, -10, -10, -10, -20, 0, 0, 0, 0, 0, 0, 0, 0, 
        -10,   0,   0,   3,   3,   0,   0, -10, 0, 0, 0, 0, 0, 0, 0, 0, 
        -10,   0,   5,   5,   5,   5,   0, -10, 0, 0, 0, 0, 0, 0, 0, 0, 
        -10,   0,   5,  10,  10,   5,   0, -10, 0, 0, 0, 0, 0, 0, 0, 0, 
        -10,   0,   5,  10,  10,   5,   0, -10, 0, 0, 0, 0, 0, 0, 0, 0, 
        -10,   0,   5,   5,   5,   5,   0, -10, 0, 0, 0, 0, 0, 0, 0, 0, 
        -10,   0,   0,   3,   3,   0,   0, -10, 0, 0, 0, 0, 0, 0, 0, 0, 
        -20, -10, -10, -10, -10, -10, -10, -20, 0, 0, 0, 0, 0, 0, 0, 0
];
var swhite_pawn = [
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  
    1,  2,  3, 10, 10,  3,  2,  1,  0,  0,  0,  0,  0,  0,  0,  0,  
    2,  4,  6, 12, 12,  6,  4,  2,  0,  0,  0,  0,  0,  0,  0,  0,  
    3,  6,  9, 14, 14,  9,  6,  3,  0,  0,  0,  0,  0,  0,  0,  0,  
    4,  8, 12, 16, 16, 12,  8,  4,  0,  0,  0,  0,  0,  0,  0,  0,  
    5, 10, 15, 20, 20, 15, 10,  5,  0,  0,  0,  0,  0,  0,  0,  0,  
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0
];
var sblack_pawn = [
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  
    5, 10, 15, 20, 20, 15, 10,  5,  0,  0,  0,  0,  0,  0,  0,  0,  
    4,  8, 12, 16, 16, 12,  8,  4,  0,  0,  0,  0,  0,  0,  0,  0,  
    3,  6,  9, 14, 14,  9,  6,  3,  0,  0,  0,  0,  0,  0,  0,  0,  
    2,  4,  6, 12, 12,  6,  4,  2,  0,  0,  0,  0,  0,  0,  0,  0,  
    1,  2,  3, 10, 10,  3,  2,  1,  0,  0,  0,  0,  0,  0,  0,  0,  
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0
];

/* to be used during opening and middlegame for white king positioning: */
var  swhite_king = [
  2,  14,   0,   0,   0,   9,  14,   2, 0, 0, 0, 0, 0, 0, 0, 0, 
 -3,  -5,  -6,  -6,  -6,  -6,  -5,  -3, 0, 0, 0, 0, 0, 0, 0, 0, 
 -5,  -5,  -8,  -8,  -8,  -8,  -5,  -5, 0, 0, 0, 0, 0, 0, 0, 0, 
 -8,  -8, -13, -13, -13, -13,  -8,  -8, 0, 0, 0, 0, 0, 0, 0, 0, 
-13, -13, -21, -21, -21, -21, -13, -13, 0, 0, 0, 0, 0, 0, 0, 0, 
-21, -21, -34, -34, -34, -34, -21, -21, 0, 0, 0, 0, 0, 0, 0, 0, 
-34, -34, -55, -55, -55, -55, -34, -34, 0, 0, 0, 0, 0, 0, 0, 0, 
-55, -55, -89, -89, -89, -89, -55, -55, 0, 0, 0, 0, 0, 0, 0, 0
];

/* to be used during opening and middlegame for black king positioning: */
var  sblack_king = [
-55, -55, -89, -89, -89, -89, -55, -55, 0, 0, 0, 0, 0, 0, 0, 0, 
-34, -34, -55, -55, -55, -55, -34, -34, 0, 0, 0, 0, 0, 0, 0, 0, 
-21, -21, -34, -34, -34, -34, -21, -21, 0, 0, 0, 0, 0, 0, 0, 0, 
-13, -13, -21, -21, -21, -21, -13, -13, 0, 0, 0, 0, 0, 0, 0, 0, 
 -8,  -8, -13, -13, -13, -13,  -8,  -8, 0, 0, 0, 0, 0, 0, 0, 0, 
 -5,  -5,  -8,  -8,  -8,  -8,  -5,  -5, 0, 0, 0, 0, 0, 0, 0, 0, 
 -3,  -5,  -6,  -6,  -6,  -6,  -5,  -3, 0, 0, 0, 0, 0, 0, 0, 0, 
  2,  14,   0,   0,   0,   9,   14,  2, 0, 0, 0, 0, 0, 0, 0, 0
];

/* to be used for positioning of both kings during the endgame: */
var  send_king = [
-5, -3, -1,  0,  0, -1, -3, -5, 0, 0, 0, 0, 0, 0, 0, 0, 
-3, 10, 10, 10, 10, 10, 10, -3, 0, 0, 0, 0, 0, 0, 0, 0, 
-1, 10, 25, 25, 25, 25, 10, -1, 0, 0, 0, 0, 0, 0, 0, 0, 
 0, 10, 25, 30, 30, 25, 10,  0, 0, 0, 0, 0, 0, 0, 0, 0, 
 0, 10, 25, 30, 30, 25, 10,  0, 0, 0, 0, 0, 0, 0, 0, 0, 
-1, 10, 25, 25, 25, 25, 10, -1, 0, 0, 0, 0, 0, 0, 0, 0, 
-3, 10, 10, 10, 10, 10, 10, -3, 0, 0, 0, 0, 0, 0, 0, 0, 
-5, -3, -1,  0,  0, -1, -3, -5, 0, 0, 0, 0, 0, 0, 0, 0
];

/* utility array to reverse rank: */
 var srev_rank = [0, 8, 7, 6, 5, 4, 3, 2, 1];

 var std_p_tropism = [ 9999, 15, 10, 7, 2, 0, 0, 0, 9999];

 var std_r_tropism = [ 9999, 10, 6, 4, 2, 0, 0, 0, 9999];

 var std_n_tropism = [ 9999, 14, 9, 6, 1, 0, 0, 0, 9999];

 var std_q_tropism = [ 9999, 16, 12, 7, 2, 0, 0, 0, 9999];

 var std_b_tropism = [ 9999, 12, 7, 5, 0, 0, 0, 0, 9999];

qengine.prototype.check_phase = function() {
    var num_pieces = 0, phase = 0;
    var j, i;
    var BOARD = this.BOARD, cast = this.castle;
    for (i = 0; i < 120; i++)
        if(!(i & 0x88)) {
            j = BOARD[i];
            if(j > 3)
                num_pieces++;
        }
    if ((num_pieces >= 12) && cast) {
	/* not both have castled */
//	&& (!white_castled || !black_castled) 
	/* no both lost castling priveledges */
//	&& (board[30] == wking || board[114] == bking)) 
	phase = 1; // Opening;
    }
    else if (num_pieces <= 6) {
	phase = 3; // Endgame;
    }
    else 
	phase = 2; // Middlegame;
    return phase;
};

qengine.prototype.std_eval = function() {

    /* select the appropriate eval() routine: */
    var phase = this.check_phase();

    if(phase == 1) {
	return (this.opn_eval ());
    }
    else if(phase == 3) {
	return (this.end_eval ());
    }
    else {
	return (this.mid_eval ());
    }
}


qengine.prototype.bishop_mobility = function(square) {
    var board = this.BOARD, sq, dir, m = 0;
    for(dir = 0; dir < 4; dir++) {
        var step = offs_b[dir];
        sq = square + step;
        while(!(sq & 0x88)) {
            if(board[sq]) break;
            m++;
            sq += step;
        }
    }
    return m;
};

qengine.prototype.end_eval = function() {
    /* return a score for the current endgame position: */

    var score = 0, i, pawn_file, srank, j, isolated, backwards;
    var pawns = [[0,0,0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0,0,0]]; 
    var white_back_pawn = [7,7,7,7,7,7,7,7,7,7], black_back_pawn = [2,2,2,2,2,2,2,2,2,2];
    var wp = 0, bp = 0, wn = 0, bn = 0, wb = 0, bb = 0,	wq = 0, bq = 0, wr = 0, br = 0;
    var fwrook, fbrook, rwrook, rbrook;
    var wpotential = 0, bpotential = 0, tmp;
    
    //var in_cache = 0;
    //checkECache(&score, &in_cache);
    // if(in_cache)
    //     {
    //         if (white_to_move == 1) return score;
    //         return -score;
    //     }

    var ocsq = [], BOARD = this.BOARD, to_move = this.to_move, wking_loc = this.sq_king[0], bking_loc = this.sq_king[1];
    for (i = 0; i < 120; i++) if(!(i & 0x88) && BOARD[i]) ocsq.push(i);

    /* initialize the pawns array, (files offset by one to use dummy files in
       order to easier determine isolated status) and also initialize the
       arrays keeping track of the rank of the most backward pawn: */
    for(i = 0, np = ocsq.length; i < np; i++) {
        var sq = ocsq[i]; var p = BOARD[sq];
        if(p == 2 || p == 3) {
            pawn_file = (sq & 7) + 1; srank = (sq >> 4) + 1;
            if(p == 2) {
	        pawns[1][pawn_file]++;
	        if (srank < white_back_pawn[pawn_file]) {
		    white_back_pawn[pawn_file] = srank;
	        }
	    }
	    else {
	        pawns[0][pawn_file]++;
	        if (srank > black_back_pawn[pawn_file]) {
		    black_back_pawn[pawn_file] = srank;
	        }
	    }
        }
    }
    
    /* loop through the board, adding material value, as well as positional
       bonuses for all pieces encountered: */
    for(i = 0, np = ocsq.length; i < np; i++) {
        var sq = ocsq[i]; var p = BOARD[sq];
        pawn_file = (sq & 7) + 1; srank = (sq >> 4) + 1;
        switch(p) {
        case 2:
	    isolated = backwards = false;
	    score += 100;
	    score += swhite_pawn[sq];
	    wp++;

	    /* in general, bonuses/penalties in the endgame evaluation will be
	       higher, since pawn structure becomes more important for the
	       creation of passed pawns */

	    /* check for backwards pawns: */
	    if((white_back_pawn[pawn_file+1] > srank) && (white_back_pawn[pawn_file-1] > srank)) {
		score -= 8; backwards = true;
		/* check to see if it is furthermore isolated: */
		if (!pawns[1][pawn_file+1] && !pawns[1][pawn_file-1]) {
		    score -= 5; isolated = true;
		}
	    }

	    /* give weak, exposed pawns a penalty (not as much as in the midgame,
	       since there may be no pieces to take advantage of it): */
	    if(!pawns[0][pawn_file]) {
		if (backwards) score -= 3;
		if (isolated) score -= 5;
	    }

	    /* give doubled, trippled, etc.. pawns a penalty (bigger in the
	       endgame, since they will become big targets): */
	    if(pawns[1][pawn_file] > 1)
		score -= 3 * (pawns[1][pawn_file]-1);

	    /* give bonuses for passed pawns (bigger in the endgame since passed
	       pawns are what wins the endgame): */
	    if(!pawns[0][pawn_file] && (srank >= black_back_pawn[pawn_file-1]) && (srank >= black_back_pawn[pawn_file+1])) {
		score += 30 + 3 * swhite_pawn[sq];
		/* check queening race; tmp = queening square */
		tmp = 0x6F + pawn_file; // A8 = 0x70
                var qrace = to_move ?
                    Math.max( Math.abs((bking_loc & 7)-(tmp & 7)), Math.abs((bking_loc >> 4)-(tmp >> 4))-1) :
                    Math.max( Math.abs((bking_loc & 7)-(tmp & 7)), Math.abs((bking_loc >> 4)-(tmp >> 4)));
                if(qrace > Math.abs((tmp >> 4) - srank - 1))
		    wpotential += 800;
                
		/* outside passer ? */
		if(pawn_file == 1 || pawn_file == 8)
		    score += 12 + 2 * swhite_pawn[sq];
	    
		/* give an extra bonus if a connected, passed pawn: */
		if(!isolated) {
		    score += 12;
                    
		    /* check whether supporter is passed */
		    if(pawns[1][pawn_file+1]) {
			if(!pawns[0][pawn_file+1] && (white_back_pawn[pawn_file+1] >= black_back_pawn[pawn_file+2])) {
			    score += 7 * (srank - 1);

			    /* connected on seventh ? */
			    if ((srank == 8) && (white_back_pawn[pawn_file+1] >= 6))
				score += 50;
			}
		    }
		    if(pawns[1][pawn_file-1]) {
			if(!pawns[0][pawn_file-1] && (white_back_pawn[pawn_file+1] >= black_back_pawn[pawn_file-2])) {
			    score += 7 * (srank - 1);

			    /* connected on seventh ? */
			    if(srank == 7 && white_back_pawn[pawn_file-1] >= 6)
				score += 50;
			}
		    }
		}
	    }

	    if (!pawns[1][pawn_file-1])
		score -= 7;
	
	    break;

        case 3:
	    isolated = backwards = false;
	    score -= 100;
	    score -= sblack_pawn[sq];
	    bp++;

	    /* in general, bonuses/penalties in the endgame evaluation will be
	       higher, since pawn structure becomes more important for the
	       creation of passed pawns */

	    /* check for backwards pawns: */
	    if((black_back_pawn[pawn_file+1] < srank) && (black_back_pawn[pawn_file-1] < srank)) {
		score += 8; backwards = true;
		/* check to see if it is furthermore isolated: */
		if (!pawns[0][pawn_file+1] && !pawns[0][pawn_file-1]) {
		    score += 5; isolated = true;
		}
	    }

	    /* give weak, exposed pawns a penalty (not as much as in the midgame,
	       since there may be no pieces to take advantage of it): */
	    if(!pawns[1][pawn_file]) {
		if (backwards) score += 3;
		if (isolated) score += 5;
	    }

	    /* give doubled, trippled, etc.. pawns a penalty (bigger in the
	       endgame, since they will become big targets): */
	    if(pawns[0][pawn_file] > 1)
		score += 3 * (pawns[0][pawn_file]-1);

	    /* give bonuses for passed pawns (bigger in the endgame since passed
	       pawns are what wins the endgame): */
	    if(!pawns[1][pawn_file] && (srank <= white_back_pawn[pawn_file-1]) && (srank <= white_back_pawn[pawn_file+1])) {
		score -= 30 + 3 * sblack_pawn[sq];
		/* check queening race; tmp = queening square */
		tmp = pawn_file - 1; // A1 = 0x00
                var qrace = to_move ?
                    Math.max( Math.abs((wking_loc & 7)-(tmp & 7)), Math.abs((wking_loc >> 4)-(tmp >> 4))-1) :
                    Math.max( Math.abs((wking_loc & 7)-(tmp & 7)), Math.abs((wking_loc >> 4)-(tmp >> 4)));
                if(qrace > Math.abs((tmp >> 4) - srank - 1))
		    bpotential -= 800;
                
		/* outside passer ? */
		if(pawn_file == 1 || pawn_file == 8)
		    score -= 12 + 2 * sblack_pawn[sq];
	    
		/* give an extra bonus if a connected, passed pawn: */
		if(!isolated) {
		    score -= 12;
                    
		    /* check whether supporter is passed */
		    if(pawns[0][pawn_file+1]) {
			if(!pawns[1][pawn_file+1] && (black_back_pawn[pawn_file+1] <= white_back_pawn[pawn_file+2])) {
			    score -= 7 * (8 - srank);

			    /* connected on seventh ? */
			    if ((srank == 2) && (black_back_pawn[pawn_file+1] <= 3))
				score -= 50;
			}
		    }
		    if(pawns[0][pawn_file-1]) {
			if(!pawns[1][pawn_file-1] && (black_back_pawn[pawn_file+1] <= white_back_pawn[pawn_file-2])) {
			    score -= 7 * (8 - srank);

			    /* connected on seventh ? */
			    if(srank == 2 && black_back_pawn[pawn_file-1] <= 3)
				score -= 50;
			}
		    }
		}
	    }

	    if (!pawns[0][pawn_file-1])
		score += 7;
	
	    break;

        case 10:
	    score += 500;
	    wr++;

	    if(wr == 1) {
	        fwrook = pawn_file;
	        rwrook = srank;
	    }
	    
	    /* bonus for being on the 7th (a bit bigger bonus in the endgame, b/c
	     a rook on the 7th can be a killer in the endgame): */
	    if(srank == 7) {
		score += 12;
		
		if (wr == 2 && 6 == rwrook) 
		    score += 10;
	    }

	    /* give bonuses depending on how open the rook's file is: */
	    if(!pawns[1][pawn_file]) {
		/* half open file */
		score += 5;

		if (wr == 2 && pawn_file == fwrook) /* connected on file */
		    score += 10;

		if (!pawns[0][pawn_file])  /* open file */
		    score += 3;
	    }

	    break;

	case 11:
	    score -= 500;
	    br++;

	    if(br == 1) {
	        fbrook = pawn_file;
	        rbrook = srank;
	    }

	    /* bonus for being on the 7th (a bit bigger bonus in the endgame, b/c
	     a rook on the 7th can be a killer in the endgame): */
	    if(srank == 2) {
		score -= 12;
		
		if(br == 2 && 2 == rbrook) 
		    score -= 10;
	    }

	    /* give bonuses depending on how open the rook's file is: */
	    if (!pawns[0][pawn_file]) {
		/* half open file */
		score -= 5;
	        
		if (br == 2 && pawn_file == fbrook) /* connected on file */
		    score -= 10;

		if (!pawns[1][pawn_file]) /* open file */
		    score -= 3;
	    }

	    break;

	case 8:
	    score += 325;
	    score += sbishop[sq];
	    score += (this.bishop_mobility(sq) << 1) - 15;
	    wb++;
	    break;

	case 9:
	    score -= 325;
	    score -= sbishop[sq];
	    score -= (this.bishop_mobility(sq) << 1) - 15;
	    bb++;
	    break;

	case 4:
	    score += 310;
	    score += sknight[sq];
	    wn++;
	    break;

	case 5:
	    score -= 310;
	    score -= sknight[sq];
	    bn++;
	    break;

	case 12:
	    score += 900;
	    wq++;
	    break;

	case 13:
	    score -= 900;
	    bq++;
	    break;
	}
    }
            
    /* some static knowledge about drawn endgames */
 
    /* pawn ending detection */
    if (!wr && !wq && !wb && !wn)
	score += bpotential;
 
    if (!br && !bq && !bb && !bn)
	score += wpotential;
 
    /* no more pawns */
    if (!wp && !bp) {
	/* nor heavies */
	if (!wr && !br && !wq && !bq) {
	    if (!bb && !wb) {
		/* only knights */
		/* it pretty safe to say this is a draw */
		if (wn < 3 && bn < 3)
		    score = 0;
	    }
	    else if (!wn && !bn) {
		/* only bishops */
		/* not a draw if one side two other side zero
		 else its always a draw                     */
		if (Math.abs(wb - bb) < 2)
		    score = 0;
	    }
	    else if ((wn < 3 && !wb) || (wb == 1 && !wn)) {
		/* we cant win, but can black? */
		if ((bn < 3 && !bb) || (bb == 1 && !bn))
		    /* guess not */
		    score = 0;
	    }
	}
	else if (!wq && !bq) {
	    if (wr == 1 && br == 1) {
		/* rooks equal */
		if ((wn + wb) < 2 && (bn + bb) < 2) 
		    /* one minor difference max */
		    /* a draw too usually */
		    score = 0;
	    }
	    else if (wr == 1 && !br) {
		/* one rook */
		/* draw if no minors to support AND
		 minors to defend  */
		if ((wn + wb == 0) && (((bn + bb) == 1) || ((bn + bb) == 2)))
		    score = 0;
	    }
	    else if (br == 1 && !wr) {
		/* one rook */
		/* draw if no minors to support AND
		 minors to defend  */
		if ((bn + bb == 0) && (((wn + wb) == 1) || ((wn + wb) == 2)))
				    score = 0;
	    }
	}
    }
    else {
	/* bad trade code, largely based on Crafty's */
	/* minors are not equal */
	if ((wn + wb) != (bn + bb)) {
	    /* majors are equal */
	    if ((wq + wr) == (bq + br)) {
		if ((wn + wb) > (bn + bb))
		    /* white is a piece up */
		    score += 120;
		else
		    /* black is a piece up */
		    score -= 120;
	    }
	    else if (Math.abs((wr + wq) - (br + bq)) == 1) {
		/* one major difference */
	      
		if ((wb + wn) > (bb + bn + 1)) {
		    /* two minors for one major */
		    score += 120;
		}
		else if ((bb + bn) > (wb + wn + 1)) {
		    score -= 120;
		}
	    }
	    else if (Math.abs((wr + wq) - (br + bq)) == 2) {	
		/* two majors difference */
	      
		if ((wb + wn) > (bb + bn + 2)) {
		    /* three minors for two majors */
		    score += 120;
		}
		else if ((bb + bn) > (wb + wn + 2)) {
		    score -= 120;
		}
	      
	    }
	}
	else if ((wq + wr) == (bq + br)) {
	    if (wq && !bq) {
		score += 120;
	    }
	    else if (!wq && bq)	{
		score -= 120;
	    }
	}
    }
  
    /* the king is safe to come out in the endgame, so we don't check for
       king safety anymore, and encourage centralization of the king */
    score += send_king[wking_loc];
  
    /* the king is safe to come out in the endgame, so we don't check for
       king safety anymore, and encourage centralization of the king */
    score -= send_king[bking_loc];
  
    /* the e/d pawn blockage is not relevant in the endgame, and we don't need
       to check for king safety due to pawn storms / heavy piece infiltration */
  
    // storeECache(score);

    /* adjust for color: */
    return  to_move? -score : score;

};

qengine.prototype.mid_eval = function() {
    /* return a score for the current middlegame position: */

    var score = 0, i, pawn_file, srank, j, isolated, backwards, wking_pawn_file, bking_pawn_file;
    var pawns = [[0,0,0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0,0,0]]; 
    var white_back_pawn = [7,7,7,7,7,7,7,7,7,7], black_back_pawn = [2,2,2,2,2,2,2,2,2,2];
    var wp = 0, bp = 0, wn = 0, bn = 0, wb = 0, bb = 0,	wq = 0, bq = 0, wr = 0, br = 0;
    var fwrook, fbrook, rwrook, rbrook;
    
    //var in_cache = 0;
    //checkECache(&score, &in_cache);
    // if(in_cache)
    //     {
    //         if (white_to_move == 1) return score;
    //         return -score;
    //     }

    var ocsq = [], BOARD = this.BOARD, to_move = this.to_move, wking_loc = this.sq_king[0], bking_loc = this.sq_king[1];
    for (i = 0; i < 120; i++) if(!(i & 0x88) && BOARD[i]) ocsq.push(i);

    /* initialize the pawns array, (files offset by one to use dummy files in
       order to easier determine isolated status) and also initialize the
       arrays keeping track of the rank of the most backward pawn: */
    for(i = 0, np = ocsq.length; i < np; i++) {
        var sq = ocsq[i]; var p = BOARD[sq];
        if(p == 2 || p == 3) {
            pawn_file = (sq & 7) + 1; srank = (sq >> 4) + 1;
            if(p == 2) {
	        pawns[1][pawn_file]++;
	        if (srank < white_back_pawn[pawn_file]) {
		    white_back_pawn[pawn_file] = srank;
	        }
	    }
	    else {
	        pawns[0][pawn_file]++;
	        if (srank > black_back_pawn[pawn_file]) {
		    black_back_pawn[pawn_file] = srank;
	        }
	    }
        }
    }
    
    /* loop through the board, adding material value, as well as positional
       bonuses for all pieces encountered: */
    for(i = 0, np = ocsq.length; i < np; i++) {
        var sq = ocsq[i]; var p = BOARD[sq];
        pawn_file = (sq & 7) + 1; srank = (sq >> 4) + 1;
        switch(p) {
        case 2:
	    isolated = backwards = false;
	    score += 100;
	    score += swhite_pawn[sq];
	    wp++;

	    /* in general, bonuses/penalties in the endgame evaluation will be
	       higher, since pawn structure becomes more important for the
	       creation of passed pawns */

	    /* check for backwards pawns: */
	    if((white_back_pawn[pawn_file+1] > srank) && (white_back_pawn[pawn_file-1] > srank)) {
		score -= 5; backwards = true;
		/* check to see if it is furthermore isolated: */
		if (!pawns[1][pawn_file+1] && !pawns[1][pawn_file-1]) {
		    score -= 3; isolated = true;
		}
	    }

	    score += std_p_tropism[Math.max(Math.abs(srank - 1 - (bking_loc >> 4)), 
				       Math.abs(pawn_file - 1 - (bking_loc & 7)))];

	    /* give weak, exposed pawns a penalty:  */
	    if(!pawns[0][pawn_file]) {
		if (backwards) score -= 4;
		if (isolated) score -= 8;
	    }

	    /* give doubled, trippled, etc.. pawns a penalty: */
	    if(pawns[1][pawn_file] > 1)
		score -= 2 * (pawns[1][pawn_file]-1);

	    /* give bonuses for passed pawns: */
	    if(!pawns[0][pawn_file] && (srank >= black_back_pawn[pawn_file-1]) && (srank >= black_back_pawn[pawn_file+1])) {
		score += 20 + 2 * swhite_pawn[sq];
	    
		/* give an extra bonus if a connected, passed pawn: */
		if(!isolated) {
		    score += 10;
                    
		    /* check whether supporter is passed */
		    if(pawns[1][pawn_file+1]) {
			if(!pawns[0][pawn_file+1] && (white_back_pawn[pawn_file+1] >= black_back_pawn[pawn_file+2])) {
			    score += 7 * (srank - 1);

			    /* connected on seventh ? */
			    if ((srank == 8) && (white_back_pawn[pawn_file+1] >= 6))
				score += 50;
			}
		    }
		    if(pawns[1][pawn_file-1]) {
			if(!pawns[0][pawn_file-1] && (white_back_pawn[pawn_file+1] >= black_back_pawn[pawn_file-2])) {
			    score += 7 * (srank - 1);

			    /* connected on seventh ? */
			    if(srank == 7 && white_back_pawn[pawn_file-1] >= 6)
				score += 50;
			}
		    }
		}
	    }

	    if (!pawns[1][pawn_file-1])
		score -= 5;
	
	    break;

        case 3:
	    isolated = backwards = false;
	    score -= 100;
	    score -= sblack_pawn[sq];
	    bp++;

	    /* check for backwards pawns: */
	    if((black_back_pawn[pawn_file+1] < srank) && (black_back_pawn[pawn_file-1] < srank)) {
		score += 5; backwards = true;
		/* check to see if it is furthermore isolated: */
		if (!pawns[0][pawn_file+1] && !pawns[0][pawn_file-1]) {
		    score += 3; isolated = true;
		}
	    }

	    score -= std_p_tropism[Math.max(Math.abs(srank - 1 - (wking_loc >> 4)), 
				       Math.abs(pawn_file - 1 - (wking_loc & 7)))];

	    /* give weak, exposed pawns a penalty: */
	    if(!pawns[1][pawn_file]) {
		if (backwards) score += 4;
		if (isolated) score += 8;
	    }

	    /* give doubled, trippled, etc.. pawns a penalty: */
	    if(pawns[0][pawn_file] > 1)
		score += 2 * (pawns[0][pawn_file]-1);

	    /* give bonuses for passed pawns: */
	    if(!pawns[1][pawn_file] && (srank <= white_back_pawn[pawn_file-1]) && (srank <= white_back_pawn[pawn_file+1])) {
		score -= 20 + 2 * sblack_pawn[sq];
	    
		/* give an extra bonus if a connected, passed pawn: */
		if(!isolated) {
		    score -= 10;
                    
		    /* check whether supporter is passed */
		    if(pawns[0][pawn_file+1]) {
			if(!pawns[1][pawn_file+1] && (black_back_pawn[pawn_file+1] <= white_back_pawn[pawn_file+2])) {
			    score -= 7 * (8 - srank);

			    /* connected on seventh ? */
			    if ((srank == 2) && (black_back_pawn[pawn_file+1] <= 3))
				score -= 50;
			}
		    }
		    if(pawns[0][pawn_file-1]) {
			if(!pawns[1][pawn_file-1] && (black_back_pawn[pawn_file+1] <= white_back_pawn[pawn_file-2])) {
			    score -= 7 * (8 - srank);

			    /* connected on seventh ? */
			    if(srank == 2 && black_back_pawn[pawn_file-1] <= 3)
				score -= 50;
			}
		    }
		}
	    }

	    if (!pawns[0][pawn_file-1])
		score += 5;
	
	    break;

        case 10:
	    score += 500;
	    wr++;

	    if(wr == 1) {
	        fwrook = pawn_file;
	        rwrook = srank;
	    }
	    
	    score += std_r_tropism[Math.max(Math.abs(srank - 1 - (bking_loc >> 4)), 
				       Math.abs(pawn_file - 1 - (bking_loc & 7)))];
	    /* bonus for being on the 7th: */
	    if(srank == 7) {
		score += 8;
		
		if (wr == 2 && 6 == rwrook) 
		    score += 10;
	    }

	    /* give bonuses depending on how open the rook's file is: */
	    if(!pawns[1][pawn_file]) {
		/* half open file */
		score += 5;

		if (wr == 2 && pawn_file == fwrook) /* connected on file */
		    score += 12;

		if (!pawns[0][pawn_file])  /* open file */
		    score += 3;
	    }

	    break;

	case 11:
	    score -= 500;
	    br++;

	    if(br == 1) {
	        fbrook = pawn_file;
	        rbrook = srank;
	    }

	    score -= std_r_tropism[Math.max(Math.abs(srank - 1 - (wking_loc >> 4)), 
				       Math.abs(pawn_file - 1 - (wking_loc & 7)))];

	    /* bonus for being on the 7th: */
	    if(srank == 2) {
		score -= 8;
		
		if(br == 2 && 2 == rbrook) 
		    score -= 10;
	    }

	    /* give bonuses depending on how open the rook's file is: */
	    if (!pawns[0][pawn_file]) {
		/* half open file */
		score -= 5;
	        
		if (br == 2 && pawn_file == fbrook) /* connected on file */
		    score -= 12;

		if (!pawns[1][pawn_file]) /* open file */
		    score -= 3;
	    }

	    break;

	case 8:
	    score += 325;
	    score += sbishop[sq];
	    score += (this.bishop_mobility(sq) << 1) - 15;
	    wb++;
	    score += std_b_tropism[Math.max(Math.abs(srank - 1 - (bking_loc >> 4)), 
				       Math.abs(pawn_file - 1 - (bking_loc & 7)))];
	    score += this.bishop_mobility(sq);
            break;

	case 9:
	    score -= 325;
	    score -= sbishop[sq];
	    score -= (this.bishop_mobility(sq) << 1) - 15;
	    bb++;
	    score -= std_b_tropism[Math.max(Math.abs(srank - 1 - (wking_loc >> 4)), 
				       Math.abs(pawn_file - 1 - (wking_loc & 7)))];
	    score -= this.bishop_mobility(sq);
	    break;

	case 4:
	    score += 310;
	    score += sknight[sq];
	    wn++;
	    score += std_n_tropism[Math.max(Math.abs(srank - 1 - (bking_loc >> 4)), 
				       Math.abs(pawn_file - 1 - (bking_loc & 7)))];
	    break;

	case 5:
	    score -= 310;
	    score -= sknight[sq];
	    bn++;
	    score -= std_n_tropism[Math.max(Math.abs(srank - 1 - (wking_loc >> 4)), 
				       Math.abs(pawn_file - 1 - (wking_loc & 7)))];
	    break;

	case 12:
	    score += 900;
	    wq++;
	    score += std_q_tropism[Math.max(Math.abs(srank - 1 - (bking_loc >> 4)), 
				       Math.abs(pawn_file - 1 - (bking_loc & 7)))];
	    break;

	case 13:
	    score -= 900;
	    bq++;
	    score -= std_q_tropism[Math.max(Math.abs(srank - 1 - (wking_loc >> 4)), 
				       Math.abs(pawn_file - 1 - (wking_loc & 7)))];
	    break;

	case 6:
	    score += swhite_king[sq];

	    /* encourage castling, and give a penalty for moving the king without castling */
	    // if(white_castled == wcq)
	    //     score += 15;
	    // else if (white_castled == wck)
	    // score += 25;
	    if((this.castle & 3) && (BOARD[4] != 6)) {
		score -= 10;
		/* make the penalty bigger if the king is open, leaving the other
		 side a chance to gain tempo with files along the file, as well
		 as building an attack: */
		if(!pawns[1][pawn_file])
		    score -= 15;
	    }

	    /* if the king is behind some pawn cover, give penalties for the pawn
	     cover being far from the king, else give a penalty for the king
	     not having any pawn cover: */
	    var fik = wking_loc & 7;
            if((fik != 3) && (fik != 4)) {
		if (srank < white_back_pawn[pawn_file] && pawns[1][pawn_file])
		    score -= 9 * (white_back_pawn[pawn_file]-srank-1);
		else
		    score -= 22;
		if (srank < white_back_pawn[pawn_file+1] && pawns[1][pawn_file+1])
		    score -= 8 * (white_back_pawn[pawn_file+1]-srank-1);
		else
		    score -= 16;
		if (srank < white_back_pawn[pawn_file-1] && pawns[1][pawn_file-1])
		    score -= 8 * (white_back_pawn[pawn_file-1]-srank-1);
		else
		    score -= 16;	  
	    } else {
	        /* being in center isnt great either, so correct */
	        score -= 10;
            }

	    break;

	case 7:
	    score -= sblack_king[i];

	    /* encourage castling, and give a penalty for moving the king without castling */
	    // if (black_castled == bcq)
	    //     score -= 15;
	    // else if (black_castled == bck)
	    // score -= 25;
	    if((this.castle & 0x0C) && (BOARD[0x74] != 7))  {
		score += 10;
		/* make the penalty bigger if the king is open, leaving the other
		 side a chance to gain tempo with files along the file, as well
		 as building an attack: */
		if (!pawns[0][pawn_file])
		    score += 15;
	    }

	    /* if the king is behind some pawn cover, give penalties for the pawn
	     cover being far from the king, else give a penalty for the king
	     not having any pawn cover: */
	    var fik = bking_loc & 7;
	    if ((fik != 3) && (fik != 4)) {
		if (srank > black_back_pawn[pawn_file] && pawns[0][pawn_file])
		    score += 9 * (srev_rank[srank-black_back_pawn[pawn_file]-1]);
		else
		    score += 22;
		if (srank > black_back_pawn[pawn_file+1] && pawns[0][pawn_file+1])
		    score += 8 * (srev_rank[srank-black_back_pawn[pawn_file+1]-1]);
		else
		    score += 16;
		if (srank > black_back_pawn[pawn_file-1] && pawns[0][pawn_file-1])
		    score += 8 * (srev_rank[srank-black_back_pawn[pawn_file-1]-1]);
		else
		    score += 16;
	    } else {
	        score += 10;
	    }

	    break;
	}
    }

    /* give penalties for blocking the e/d pawns: */
    if((BOARD[0x13] == 2) && BOARD[0x23])
	score -= 5;
    if((BOARD[0x14] == 2) && BOARD[0x24])
	score -= 5;
    if((BOARD[0x63] == 3) && BOARD[0x53])
	score += 5;
    if((BOARD[0x64] == 3) && BOARD[0x54])
	score += 5;

    /* to be used for pawn storm code: */
    wking_pawn_file = (wking_loc & 7)+1;
    bking_pawn_file = (bking_loc & 7)+1;

    /* if the kings are on opposite wings, or far apart, check for pawn
     storms, and open lines for heavy pieces: */
    if(Math.abs(wking_pawn_file - bking_pawn_file) > 2) {
	/* black pawn storms: */
	score -= 3 * (srev_rank[black_back_pawn[wking_pawn_file]] - 2);
	score -= 3 * (srev_rank[black_back_pawn[wking_pawn_file+1]] - 2);
	score -= 3 * (srev_rank[black_back_pawn[wking_pawn_file-1]] - 2);
        
	/* white pawn storms: */
	/* this has side effects on no pawns, but I guess it wont hurt - GCP */
	score += 3 * (white_back_pawn[bking_pawn_file] - 2);
	score += 3 * (white_back_pawn[bking_pawn_file+1] - 2);
	score += 3 * (white_back_pawn[bking_pawn_file-1] - 2);

	/* black opening up lines: */
	if(!pawns[0][wking_pawn_file])
	    score -= 8;
	if(!pawns[0][wking_pawn_file+1])
	    score -= 6;
	if(!pawns[0][wking_pawn_file-1])
	    score -= 6;
        
	/* white opening up lines: */
	if(!pawns[1][bking_pawn_file])
	    score += 8;
	if(!pawns[1][bking_pawn_file+1])
	    score += 6;
	if(!pawns[1][bking_pawn_file-1])
	    score += 6;
    }

    /* bad trade code, largely based on Crafty's */

    /* minors are not equal */
    if((wn + wb) != (bn + bb)) {
	/* majors are equal */
	if((wq + wr) == (bq + br)) {
	    if((wn + wb) > (bn + bb)) {
		/* white is a piece up */
		score += 120;
	    } else {
		/* black is a piece up */
		score -= 120;
	    }
	}
	else if(Math.abs((wr + wq) - (br + bq)) == 1) {
	    /* one major difference */
	  
	    if((wb + wn) > (bb + bn + 1)) {
		/* two minors for one major */
		score += 120;
	    }
	    else if((bb + bn) > (wb + wn + 1)) {
		score -= 120;
	    }
	}
	else if(Math.abs((wr + wq) - (br + bq)) == 2) {	
	    /* two majors difference */
	    
	    if((wb + wn) > (bb + bn + 2)) {
		/* three minors for two majors */
		score += 120;
	    }
	    else if((bb + bn) > (wb + wn + 2)) {
		score -= 120;
	    }
	}
    }
    else if((wq + wr) == (bq + br)) {
	if(wq && !bq) {
	    score += 120;
	}
	else if(!wq && bq) {
	    score -= 120;
	}
    }

    // storeECache(score);

    /* adjust for color: */
    return  to_move? -score : score;

};

qengine.prototype.opn_eval = function() {
    /* return a score for the current opening position: */

    var score = 0, i, pawn_file, srank, j, isolated, backwards, wking_pawn_file, bking_pawn_file;
    var pawns = [[0,0,0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0,0,0]]; 
    var white_back_pawn = [7,7,7,7,7,7,7,7,7,7], black_back_pawn = [2,2,2,2,2,2,2,2,2,2];
    var fwrook, fbrook;
    
    //var in_cache = 0;
    //checkECache(&score, &in_cache);
    // if(in_cache)
    //     {
    //         if (white_to_move == 1) return score;
    //         return -score;
    //     }

    var ocsq = [], BOARD = this.BOARD, to_move = this.to_move, wking_loc = this.sq_king[0], bking_loc = this.sq_king[1];
    for (i = 0; i < 120; i++) if(!(i & 0x88) && BOARD[i]) ocsq.push(i);

    /* initialize the pawns array, (files offset by one to use dummy files in
       order to easier determine isolated status) and also initialize the
       arrays keeping track of the rank of the most backward pawn: */
    for(i = 0, np = ocsq.length; i < np; i++) {
        var sq = ocsq[i]; var p = BOARD[sq];
        if(p == 2 || p == 3) {
            pawn_file = (sq & 7) + 1; srank = (sq >> 4) + 1;
            if(p == 2) {
	        pawns[1][pawn_file]++;
	        if (srank < white_back_pawn[pawn_file]) {
		    white_back_pawn[pawn_file] = srank;
	        }
	    }
	    else {
	        pawns[0][pawn_file]++;
	        if (srank > black_back_pawn[pawn_file]) {
		    black_back_pawn[pawn_file] = srank;
	        }
	    }
        }
    }
    
    /* loop through the board, adding material value, as well as positional
       bonuses for all pieces encountered: */
    for(i = 0, np = ocsq.length; i < np; i++) {
        var sq = ocsq[i]; var p = BOARD[sq];
        pawn_file = (sq & 7) + 1; srank = (sq >> 4) + 1;
        switch(p) {
        case 2:
	    isolated = backwards = false;
	    score += 100;
	    score += swhite_pawn[sq];

	    /* penalties / bonuses will be in general smaller in the opening,
	       in order to put an emphasis on piece development */

	    /* check for backwards pawns: */
	    if((white_back_pawn[pawn_file+1] > srank) && (white_back_pawn[pawn_file-1] > srank)) {
		/* no penalty in the opening for having a backwards pawn that hasn't
		   moved yet! */
		if(srank !=2)
                    score -= 3; 
                backwards = true;
		/* check to see if it is furthermore isolated: */
		if (!pawns[1][pawn_file+1] && !pawns[1][pawn_file-1]) {
		    score -= 2; isolated = true;
		}
	    }

	    /* give weak, exposed pawns a penalty:  */
	    if(!pawns[0][pawn_file]) {
		if(backwards) score -= 3;
		if(isolated) score -= 5;
	    }

	    /* give doubled, trippled, etc.. pawns a penalty: */
	    if(pawns[1][pawn_file] > 1)
		score -= 2 * (pawns[1][pawn_file]-1);
            
	    /* give bonuses for passed pawns: */
	    if(!pawns[0][pawn_file] && (srank >= black_back_pawn[pawn_file-1]) && (srank >= black_back_pawn[pawn_file+1])) {
		score += 5 + 2 * swhite_pawn[sq];
		/* give an extra bonus if a connected, passed pawn: */
		if(!isolated) 
		    score += 10;
	    }

	    break;

        case 3:
	    isolated = backwards = false;
	    score -= 100;
	    score -= sblack_pawn[sq];
            
	    /* penalties / bonuses will be in general smaller in the opening,
	       in order to put an emphasis on piece development */

	    /* check for backwards pawns: */
	    if((black_back_pawn[pawn_file+1] < srank) && (black_back_pawn[pawn_file-1] < srank)) {
		/* no penalty in the opening for having a backwards pawn that hasn't
		   moved yet! */
		if(srank != 2)
                    score += 3; 
                backwards = true;
		/* check to see if it is furthermore isolated: */
		if (!pawns[0][pawn_file+1] && !pawns[0][pawn_file-1]) {
		    score += 2; isolated = true;
		}
	    }

	    /* give weak, exposed pawns a penalty: */
	    if(!pawns[1][pawn_file]) {
		if (backwards) score += 3;
		if (isolated) score += 5;
	    }

	    /* give doubled, trippled, etc.. pawns a penalty: */
	    if(pawns[0][pawn_file] > 1)
		score += 2 * (pawns[0][pawn_file]-1);

	    /* give bonuses for passed pawns: */
	    if(!pawns[1][pawn_file] && (srank <= white_back_pawn[pawn_file-1]) && (srank <= white_back_pawn[pawn_file+1])) {
		score -= 5 + 2 * sblack_pawn[sq];
	    
		/* give an extra bonus if a connected, passed pawn: */
		if(!isolated) 
		    score -= 10;
	    }

	    break;

        case 10:
	    score += 500;

	    if(!fwrook) fwrook = pawn_file;
	    else if(pawn_file == fwrook) {
		/* two rooks, file at least halfopen */
		if (!pawns[1][pawn_file])
		    score += 10;
	    }

	    /* bonus for being on the 7th: */
	    if(srank == 7) 
		score += 8;

	    /* give bonuses depending on how open the rook's file is: */
	    if(!pawns[1][pawn_file]) {
		/* half open file */
		score += 5;
		if (!pawns[0][pawn_file])  /* open file */
		    score += 3;
	    }

	    break;

	case 11:
	    score -= 500;

	    if(!fbrook) fbrook = pawn_file;
	    else if(pawn_file == fbrook) {
		/* two rooks, file at least halfopen */
		if(!pawns[0][pawn_file])
		    score -= 10;
	    }

	    /* bonus for being on the 7th: */
	    if(srank == 2) 
		score -= 8;

	    /* give bonuses depending on how open the rook's file is: */
	    if (!pawns[0][pawn_file]) {
		/* half open file */
		score -= 5;

		if (!pawns[1][pawn_file]) /* open file */
		    score -= 3;
	    }

	    break;

	case 8:
	    score += 325;
	    score += sbishop[sq];
	    score += std_b_tropism[Math.max(Math.abs(srank - 1 - (bking_loc >> 4)), 
				       Math.abs(pawn_file - 1 - (bking_loc & 7)))];
	    score += this.bishop_mobility(sq);
            break;

	case 9:
	    score -= 325;
	    score -= sbishop[sq];
	    score -= std_b_tropism[Math.max(Math.abs(srank - 1 - (wking_loc >> 4)), 
				       Math.abs(pawn_file - 1 - (wking_loc & 7)))];
	    score -= this.bishop_mobility(sq);
	    break;

	case 4:
	    score += 310;
	    score += sknight[sq];
	    score += std_n_tropism[Math.max(Math.abs(srank - 1 - (bking_loc >> 4)), 
				       Math.abs(pawn_file - 1 - (bking_loc & 7)))];
	    break;

	case 5:
	    score -= 310;
	    score -= sknight[sq];
	    score -= std_n_tropism[Math.max(Math.abs(srank - 1 - (wking_loc >> 4)), 
				       Math.abs(pawn_file - 1 - (wking_loc & 7)))];
	    break;

	case 12:
	    score += 900;
	    score += std_q_tropism[Math.max(Math.abs(srank - 1 - (bking_loc >> 4)), 
				       Math.abs(pawn_file - 1 - (bking_loc & 7)))];
	    /* a small penalty to discourage moving the queen in the opening
	       before the other minors: */
	    if(sq != 3)
		if((BOARD[1]==4) || (BOARD[2]==8) || (BOARD[6]==4) || (BOARD[5]==8))
		    score -= 10;

	    break;

	case 13:
	    score -= 900;
	    score -= std_q_tropism[Math.max(Math.abs(srank - 1 - (wking_loc >> 4)), 
				       Math.abs(pawn_file - 1 - (wking_loc & 7)))];
	    /* a small penalty to discourage moving the queen in the opening
	       before the other minors: */
	    if(sq != 0x73)
		if((BOARD[0x71]==5) || (BOARD[0x72]==9) || (BOARD[0x76]==5) || (BOARD[0x75]==9))
		    score += 10;
	    break;

	case 6:
	    score += swhite_king[sq];

	    /* encourage castling, and give a penalty for moving the king without castling */
	    // if(white_castled == wcq)
	    //     score += 15;
	    // else if (white_castled == wck)
	    // score += 25;
	    if((this.castle & 3) && (BOARD[4] != 6)) {
		score -= 15;
		/* make the penalty bigger if the king is open, leaving the other
		 side a chance to gain tempo with files along the file, as well
		 as building an attack: */
		if(!pawns[1][pawn_file])
		    score -= 10;
	    }
            
	    /* in general, in the opening, don't worry quite so much about pawn
	       cover, because sometimes it isn't good for the king to castle */

	    /* if the king is behind some pawn cover, give penalties for the pawn
	     cover being far from the king, else give a penalty for the king
	     not having any pawn cover: */
	    /* only worry about cover when castled */
	    var fik = wking_loc & 7;
            if((fik != 3) && (fik != 4)) {
		if (srank < white_back_pawn[pawn_file] && pawns[1][pawn_file])
		    score -= 7 * (white_back_pawn[pawn_file]-srank-1);
		else
		    score -= 14;
		if (srank < white_back_pawn[pawn_file+1] && pawns[1][pawn_file+1])
		    score -= 4 * (white_back_pawn[pawn_file+1]-srank-1);
		else
		    score -= 8;
		if (srank < white_back_pawn[pawn_file-1] && pawns[1][pawn_file-1])
		    score -= 4 * (white_back_pawn[pawn_file-1]-srank-1);
		else
		    score -= 8;	  
	    } else {
	        /* being in center isnt great either, so correct */
	        score -= 7;
            }

	    break;

	case 7:
	    score -= sblack_king[i];

	    /* encourage castling, and give a penalty for moving the king without castling */
	    // if (black_castled == bcq)
	    //     score -= 12;
	    // else if (black_castled == bck)
	    // score -= 20;
	    if((this.castle & 0x0C) && (BOARD[0x74] != 7))  {
		score += 15;
		/* make the penalty bigger if the king is open, leaving the other
		 side a chance to gain tempo with files along the file, as well
		 as building an attack: */
		if (!pawns[0][pawn_file])
		    score += 10;
	    }
	    /* in general, in the opening, don't worry quite so much about pawn
	       cover, because sometimes it isn't good for the king to castle */

	    /* if the king is behind some pawn cover, give penalties for the pawn
	     cover being far from the king, else give a penalty for the king
	     not having any pawn cover: */
	    var fik = bking_loc & 7;
	    if ((fik != 3) && (fik != 4)) {
		if (srank > black_back_pawn[pawn_file] && pawns[0][pawn_file])
		    score += 7 * (srev_rank[srank-black_back_pawn[pawn_file]-1]);
		else
		    score += 14;
		if (srank > black_back_pawn[pawn_file+1] && pawns[0][pawn_file+1])
		    score += 4 * (srev_rank[srank-black_back_pawn[pawn_file+1]-1]);
		else
		    score += 8;
		if (srank > black_back_pawn[pawn_file-1] && pawns[0][pawn_file-1])
		    score += 4 * (srev_rank[srank-black_back_pawn[pawn_file-1]-1]);
		else
		    score += 8;
	    } else {
	        score += 7;
	    }

	    break;
	}
    }

    /* give bigger penalties for blocking the e/d pawns in the opening, as
       we want to develop quickly: */
    if((BOARD[0x13] == 2) && BOARD[0x23])
	score -= 7;
    if((BOARD[0x14] == 2) && BOARD[0x24])
	score -= 7;
    if((BOARD[0x63] == 3) && BOARD[0x53])
	score += 7;
    if((BOARD[0x64] == 3) && BOARD[0x54])
	score += 7;

    /* to be used for pawn storm code: */
    wking_pawn_file = (wking_loc & 7)+1;
    bking_pawn_file = (bking_loc & 7)+1;

    /* if the kings are on opposite wings, or far apart, check for pawn
       storms, and open lines for heavy pieces (bonuses/penalties brought
       down a bit in the opening, as it isn't a good idea to start pawn
       storming when the position is still fluid): */
    if(Math.abs(wking_pawn_file - bking_pawn_file) > 2) {
	/* black pawn storms: */
	score -= srev_rank[black_back_pawn[wking_pawn_file]] - 2;
	score -= srev_rank[black_back_pawn[wking_pawn_file+1]] - 2;
	score -= srev_rank[black_back_pawn[wking_pawn_file-1]] - 2;
        
	/* white pawn storms: */
	score += white_back_pawn[bking_pawn_file] - 2;
	score += white_back_pawn[bking_pawn_file+1] - 2;
	score += white_back_pawn[bking_pawn_file-1] - 2;

	/* black opening up lines: */
	if(!pawns[0][wking_pawn_file])
	    score -= 6;
	if(!pawns[0][wking_pawn_file+1])
	    score -= 4;
	if(!pawns[0][wking_pawn_file-1])
	    score -= 4;
        
	/* white opening up lines: */
	if(!pawns[1][bking_pawn_file])
	    score += 6;
	if(!pawns[1][bking_pawn_file+1])
	    score += 4;
	if(!pawns[1][bking_pawn_file-1])
	    score += 4;
    }

    // storeECache(score);

    /* adjust for color: */
    return  to_move? -score : score;
};

