#include "evaluate.h"
/*
 *
 * 	1st Order Terms are 'rule based' and handled by search
 *
 * 		Mates and Draws
 *
 * 	2nd Order Terms ( >= 100 )
 *
 * 		Material:
 * 			Raw
 * 			imbalances
 *
 * 		Near Promotion [Passers on 6th & 7th]
 *
 * 		Trapped Piece:
 * 			Rook
 * 			Bishop
 * 			Knight
 *		Menace:
 *			marauder
 *			outpost
 *
 * 		King safety:
 * 			Tropism
 * 			Defenders
 * 			Majors on open files by King
 * 			Storm
 * 			Shield
 * 			Location - should automatically change all above
 *
 * 	3rd Order Terms ( < 100 )
 *
 *		weak pawns
 *		mobility:
 *			king & knight PST
 *			bishop lines?
 *			rook open files? 
 */
//const int shield[8] = {0, 24, 12, 6, 3, 1, 1, 0};
const int shield[8] = {0, 32, 16, 8, 2, 1, 1, 0};
//const int storm[8] = {6, 0, 4, 8, 10, 10, 10, 10};
const int storm[8] = {6, 1, 2, 4, 8, 16, 16, 16};


//2Qx3=6 + 2Rx2=4 + 4Mx1=4
//				  m  R  Q  2  Q   Q
//				  	   R  R   R
//				  	   	  m
const int attacks_scale[16] = {0, 1, 2, 3, 4, 5,  6, 10, 15, 20, 25, 30, 35, 40, 45, 50};
const int kdanger[32] = {0, 0, 0, 10, 20, 30, 30, 30, 30, 40, 40, 50, 60, 85,100, 125, 150, 175, 200, 250, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300};


//marauder=7 q=4 ropen=3 hopen=2 outpost=(1-4)*1-2.5) pawn 2
const int menace[64] = {0, 4,  8, 12, 16, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 75, 85,
	95, 105, 115, 125, 135, 145, 155, 165, 175, 185, 195, 205, 215, 225, 235, 245,
	250, 255, 260, 265, 270, 275, 280, 285, 290, 300, 305, 310, 315, 320, 325, 330,
	335, 340, 345, 350, 355, 360, 365, 370, 375, 380, 385, 390, 395, 400, 405};
//inactive Q+R=1, minor={1-4} but knight ought be worse, as bishop has 'immobility' blocked pawn=1
const int inactive[32] = {0, 10, 20, 30, 45, 60, 75, 90, 95, 100,105,110,115,120,130,140,
	150,160,170,180,190,200,210,220,230,240,250,260,270,280,290,300};

const int kingpawn[8] = {0, 2, 6, 6, 2, 0, 0, 0};

int best = 0;

int evaluate ()
{
	int sq, i, p, f, r;
	
	int lap[2][10] = {{7, 7, 7, 7, 7, 7, 7, 7, 7, 7}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}; /* black default=7 white
																						* default=0 */
	int lar[2][10] = {{7, 7, 7, 7, 7, 7, 7, 7, 7, 7}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
	int map[2][10] = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {7, 7, 7, 7, 7, 7, 7, 7, 7, 7}};
	int passedb[10] = {0};
	int passedw[10] = {0};
	int bishopb[] = {0, 0};
	int bishopw[] = {0, 0};
	int obstaclesb = 0;
	int obstaclesw = 0;
	/*
	 int spacew = 0;
	 int spaceb = 0;
	 */
	int weakb = 0;
	int weakw = 0;
	int passerb = 0;
	int passerw = 0;
	int inactiveb = 0;
	int inactivew = 0;
	int rooksb = 0;
	int rooksw = 0;
	int bishopmb = 0;
	int bishopmw = 0;
	int safetyb = 0;
	int safetyw = 0;
	int offenseb = 0;
	int offensew = 0;
	int menaceb = 0;
	int menacew = 0;
	int tropismb = 0;
	int tropismw = 0;
	int attacksb = 0;
	int attacksw = 0;
	int pstw = 0;
	int pstb = 0;
	int pushw = 0;
	int pushb = 0;
	int homer = 0; /* pawn on home row. black=bit0,
					* white bit1 */
	int t = 1;
	int x;
	int s;
	int pw = 0;
	int pb = 0;
	int db = 0;
	int dw = 0;
	
//	assert(checkboard() == 0);
	
#ifdef EHASH
	
	sEHASHENTRY *ehash;
	
	if ((ehash = eprobe ())) {
		return stm? ehash->score : -ehash->score;
	}
	
#endif
	
	s = material (&t);
	
	//return (stm)? s : -s;
	
	if((t&136) == 136) {
		s = (stm) ? (s / ((s>0) ? 1<<dw : 1<<db)) : (-s / ((-s>0) ? 1<<db : 1<<dw));
		return s;
	}
	
	db = (t & 15);
	dw = (t >> 4);
	
	++evals;
	
	/* Pass 1 */
	/* BLACK */
	for (i = 0; i < 16; ++i) {
		sq = pieces[BLACK][i];
		if (sq) {
			p = board[sq];
			f = FILE (sq);
			r = RANK (sq);
			if (p == BP) {
				if (r < lap[BLACK][f + 1])
					lap[BLACK][f + 1] = r;
				if (r > map[BLACK][f + 1])
					map[BLACK][f + 1] = r;
				homer |= (r == 1);
				pstb += pst[p][sq];
				pushb += (r-1);
			} else if (p == BB  && r < 3  )
				++bishopb[sq_color[sq]];
			else if (p == BR) {
				if (r < lar[BLACK][f + 1])
					lar[BLACK][f + 1] = r;
			}
		}
	}
	/* WHITE */
	for (i = 0; i < 16; ++i) {
		sq = pieces[WHITE][i];
		if (sq) {
			p = board[sq];
			f = FILE (sq);
			r = RANK (sq);
			if (p == WP) {
				
				if (r > lap[WHITE][f + 1])
					lap[WHITE][f + 1] = r;
				if (r < map[WHITE][f + 1])
					map[WHITE][f + 1] = r;
				homer |= ((r == 6) << 1);
				pstw += pst[p][sq];
				pushw += (7-r-1);
			} else if (p == WB  && r > 4  )
				++bishopw[sq_color[sq]];
			else if (p == WR) {
				if (r > lar[WHITE][f + 1])
					lar[WHITE][f + 1] = r;
			}
		}
	}
	
	//*
	if((force[WHITE] + force[BLACK]) == 6 && (types[WB] + types[BB]) == 2 && (bishopw[0] == bishopb[1] || bishopw[1] == bishopb[0])) {
		dw |= 1;
		db |= 1;
	}
	//*/
	
	/* gradually replace space&center control w/ advance */
	pstw = pstw * f_curve[force[BLACK]] / MF;
	pstb = pstb * f_curve[force[WHITE]] / MF;
	
	pstw += pushw * 3 * (MF-f_curve[force[BLACK]]) / MF;
	pstb += pushb * 3 * (MF-f_curve[force[WHITE]]) / MF; 
	
	/* Pass 2 */
	/* BLACK */
	for (i = 0; i < 16; ++i) {
		sq = pieces[BLACK][i];
		if (sq) {
			p = board[sq];
			
			switch (p) {
				case BP:
					f = FILE (sq);
					r = RANK (sq);
					t = (r != map[BLACK][f + 1]); /* doubled */
					weakb += 5 * t;
					if (t == 0 && r >= lap[WHITE][f + 1 - 1] && r >= lap[WHITE][f + 1 + 1] && r > lap[WHITE][f + 1]) {
						passerb += 10 * (force[WHITE] == 0 && passerb > 0); /* multiple passer bonus */
						passerb += 10 * (force[WHITE] == 0 && types[BP]-1); /* passer is at least a decoy */
						passerb += 2 * r * ((7-r) < (distance[128 + (A8+f) - kingsq[WHITE]])) << (force[BLACK]==0);
						passerb += passed_pawn[r]; /* base value */
						passerb += supported_passer[r] * (board[sq - 1] == BP || board[sq + 1] == BP || board[sq - 17] == BP || board[sq - 15] == BP);
						passedb[f+1] = r;
						passerb -= blocked_passer[r] * (IS_WHITE (board[sq + 16])); /* malis: blocked */
						passerb += (8 + 2 * r) * (lar[BLACK][f + 1] < r); /* bonus: rook behind */
						passerb += escorted_passer[r] * (distance[128 + sq + 16 - kingsq[BLACK]] < 2) << (force[WHITE]==0); /* bonus: king escort */
						passerb -= escorted_passer[r] * (distance[128 + sq + 16 - kingsq[WHITE]] < 2) << (force[BLACK]==0); /* malis: nme king */
					}
					weakb += (8>>t) * (r < lap[BLACK][f + 1 - 1] && r < lap[BLACK][f + 1 + 1]);
					inactiveb += (f > 2 && f < 5 && r == 1 && board[sq + 16] != MT);
					menaceb += (f > 1 && f < 6 && r > 3) * 2 >> (r==4);
					obstaclesb += bishopb[sq_color[sq]] * middle[sq];
					offenseb += kingpawn[distance[128 + sq + 16 - kingsq[BLACK]]];
					break;
				case BN:
					f = FILE (sq);
					r = RANK (sq);
					if ((t=outposts[BLACK][sq]/4)) {
						menaceb += t/2;
						if ( lap[WHITE][f + 1 - 1] <= r && lap[WHITE][f + 1 + 1] <= r) {
							menaceb += t;
							if (board[sq - 17] == BP || board[sq - 15] == BP) {
								menaceb += t/2;
							}
						}
					}
					inactiveb += TRAPPEDN * (r > 5 && (t=ntrap[sq]) && board[t]==WP && board[sq-16]==WP);
					inactiveb += border[sq] + (r == 0);
					pstb += pst[p][sq];
					t =  tropism_n[128 + sq - kingsq[WHITE]];
					tropismb += t;
					attacksb += (t>0);
					break;
				case BB:
					f = FILE (sq);
					r = RANK (sq);
					if ((t=outposts[BLACK][sq]/4)) {
						menaceb += t/2;
						if (lap[WHITE][f + 1 - 1] <= r && lap[WHITE][f + 1 + 1] <= r) {
							menaceb += t;
							
							if (board[sq - 17] == BP || board[sq - 15] == BP) {
								menaceb += t/2;
							}
						}
					}
					inactiveb += TRAPPEDB * (r > 4 && (t=btrap[sq]) && board[t]==WP && ((f<2 && board[t+17] == WP) || (f>5 && board[t+15]==WP)));
					inactiveb +=  /* border[sq] + */ (r == 0);
					pstb += pst[p][sq];
					t = tropism_b[128 + sq - kingsq[WHITE]];
					tropismb += t;
					attacksb += (t>0);
					
					//*
					t = (min(f, r) + min(7-f, r))/2;
					x = sq;
					while((board[x+=17]&14) != BP && board[x] != OB) ++t;
					x = sq;
					while((board[x+=15]&14) != BP && board[x] != OB) ++t;
					inactiveb += (t<1) + (t<2) + (t<3);
					bishopmb += 3 * t;// + min(f, r) + min(7-f, r);
					//*/
					break;
				case BR:
					f = FILE (sq);
					r = RANK (sq);
					if(r > 5 && ((homer & 2) == 2 || RANK (kingsq[WHITE]) > 5)) {
						menaceb += 7;
						rooksb += 10;
						t = max(1, tropism_r[128 + sq - kingsq[WHITE]]);
						tropismb += t;
						attacksb += 2;
					}
					else if (lap[BLACK][f + 1] > 3) {
						if (lap[BLACK][f + 1] > 5) { /* lap: black default=7
													  * white default=0 */
							if (r >= lap[WHITE][f + 1]) {
								rooksb += 15;
								//menaceb += (abs (f - FILE (kingsq[WHITE])) < 2) * 3;
								t = max(3*(abs (f - FILE (kingsq[WHITE])) < 2), tropism_r[128 + sq - kingsq[WHITE]]);
								tropismb += t;
								attacksb += (t>0)*2;
							} 
							else {
								rooksb += 10;
								//menaceb += (abs (f - FILE (kingsq[WHITE])) < 2) * 2;
								t = max(1*(abs (f - FILE (kingsq[WHITE])) < 2), tropism_r[128 + sq - kingsq[WHITE]]);
								tropismb += t;
								attacksb += (t>0)*2;
							}
						}
						else {
							++inactiveb; // but never trapped ?
							t = tropism_r[128 + sq - kingsq[WHITE]];
							tropismb += t;
							attacksb += (t>0)*2;
						}
						
					} else if (r >= map[BLACK][f + 1]) { /* map: black default=0
														  * white default=7 */
						if (r >= lap[WHITE][f + 1]) {
							rooksb += 10;
							//menaceb += (abs (f - FILE (kingsq[WHITE])) < 2) * 3;
							t = max(3*(abs (f - FILE (kingsq[WHITE])) < 2), tropism_r[128 + sq - kingsq[WHITE]]);
							tropismb += t;
							attacksb += (t>0)*2;
						} 
						else {
							rooksb += 5;
							//menaceb += (abs (f - FILE (kingsq[WHITE])) < 2) * 2;
							t = max(1*(abs (f - FILE (kingsq[WHITE])) < 2), tropism_r[128 + sq - kingsq[WHITE]]);
							tropismb += t;
							attacksb += (t>0)*2;
						}
					} else {
						++inactiveb;
						if (RANK (kingsq[BLACK]) == 0 && (castle & 3) == 0 && r < 2) {
							inactiveb += TRAPPEDR * (FILE (kingsq[BLACK]) > 3 && f > FILE (kingsq[BLACK]));
							inactiveb += TRAPPEDR * (FILE (kingsq[BLACK]) < 4 && f < FILE (kingsq[BLACK]));
						}
						else {
							t = tropism_r[128 + sq - kingsq[WHITE]];
							tropismb += t;
							attacksb += (t>0)*2;
						}

					}
					//menaceb += 7 * (r > 5 && ((homer & 2) == 2 || RANK (kingsq[WHITE]) > 5));
					pstb += pst[p][sq];
					//t = tropism_r[128 + sq - kingsq[WHITE]];
					//tropismb += t;
					//attacksb += (t>0)*2;
					break;
				case BQ:
					f = FILE (sq);
					r = RANK (sq);
					if (r > 5 && ((homer & 2) == 2 || RANK (kingsq[WHITE]) > 5)) {
						menaceb += 4;
						t = max(1, tropism_q[128 + sq - kingsq[WHITE]]);
						tropismb += t;
						attacksb += 3;
					}
					else if (lap[BLACK][f + 1] > 6) {
						if (r >= lap[WHITE][f + 1]) {
							//menaceb += (abs (f - FILE (kingsq[WHITE])) < 2) * 3;
							t = max(2*(abs (f - FILE (kingsq[WHITE])) < 2), tropism_q[128 + sq - kingsq[WHITE]]);
							tropismb += t;
							attacksb += (t>0)*3;
						} 
						else {
							//menaceb += (abs (f - FILE (kingsq[WHITE])) < 2) * 2;
							t = max((abs (f - FILE (kingsq[WHITE])) < 2), tropism_q[128 + sq - kingsq[WHITE]]);
							tropismb += t;
							attacksb += (t>0)*3;
						}
					} 
					else if (r >= map[BLACK][f + 1]) { /* map: black default=0
														* white default=7 */
						if (r >= lap[WHITE][f + 1]) {
							//menaceb += (abs (f - FILE (kingsq[WHITE])) < 2) * 3;
							t = max(2*(abs (f - FILE (kingsq[WHITE])) < 2), tropism_q[128 + sq - kingsq[WHITE]]);
							tropismb += t;
							attacksb += (t>0)*3;
						} 
						else {
							//menaceb += (abs (f - FILE (kingsq[WHITE])) < 2) * 2;
							t = max((abs (f - FILE (kingsq[WHITE])) < 2), tropism_q[128 + sq - kingsq[WHITE]]);
							tropismb += t;
							attacksb += (t>0)*3;
						}
					}
					else {
						t = tropism_q[128 + sq - kingsq[WHITE]];
						tropismb += t;
						attacksb += (t>0)*3;
					}

					inactiveb += (r < 1);
					pstb += pst[p][sq];
					
					break;
				default:
					break;
			}
			
		}
	}
	/* WHITE */
	for (i = 0; i < 16; ++i) {
		sq = pieces[WHITE][i];
		if (sq) {
			p = board[sq];
			
			switch (p) {
				case WP:
					f = FILE (sq);
					r = RANK (sq);
					t = (r != map[WHITE][f + 1]); /* doubled */
					
					weakw += 5 * t;
					
					if (t == 0 && r <= lap[BLACK][f + 1 - 1] && r <= lap[BLACK][f + 1 + 1] && r < lap[BLACK][f + 1]) {
						passerw += 10 * (force[BLACK] == 0 && passerw > 0); /* multiple passer bonus */
						passerw += 10 * (force[BLACK] == 0 && types[WP]-1); /* Decoy */
						passerw += 2 * (7-r) * ((r) < (distance[128 + (A1+f) - kingsq[BLACK]])) << (force[WHITE]==0);
						passerw += passed_pawn[7 - r]; /* base value */
						passerw += supported_passer[7 - r] * (board[sq - 1] == WP || board[sq + 1] == WP || board[sq + 15] == WP || board[sq + 17] == WP);
						passedw[f+1] = 7-r;
						passerw -= blocked_passer[7 - r] * (IS_BLACK (board[sq - 16])); /* malis: blocked */
						passerw += (8 + 2 * (7 - r)) * (lar[WHITE][f + 1] > r); /* bonus: rook behind */
						passerw += escorted_passer[7 - r] * (distance[128 + sq - 16 - kingsq[WHITE]] < 2) << (force[BLACK]==0); /* bonus: king escort */
						passerw -= escorted_passer[7 - r] * (distance[128 + sq - 16 - kingsq[BLACK]] < 2) << (force[WHITE]==0); /* malis: nme king */
					}
					weakw += (8>>t) * (r > lap[WHITE][f + 1 - 1] && r > lap[WHITE][f + 1 + 1]);
					inactivew += (f > 2 && f < 5 && r == 6 && board[sq - 16] != MT);
					menacew += (f > 1 && f < 6 && r < 4) * 2 >> (r==3);
					/* spacew += 3 * (7-r); */
					obstaclesw += bishopw[sq_color[sq]] * middle[sq];
					offensew += kingpawn[distance[128 + sq - 16 - kingsq[WHITE]]];
					break;
				case WN:
					f = FILE (sq);
					r = RANK (sq);
					if ((t=outposts[WHITE][sq]/4)) {
						menacew += t/2;
						if (lap[BLACK][f + 1 - 1] >= r && lap[BLACK][f + 1 + 1] >= r) {
							menacew += t;
							if (board[sq + 17] == WP || board[sq + 15] == WP) {
								menacew += t/2;
							}
						}
					}
					inactivew += TRAPPEDN * (r < 2 && (t=ntrap[sq]) && board[t]==BP && board[sq+16]==BP);
					inactivew +=  border[sq] + (r == 7);
					pstw += pst[p][sq];
					t = tropism_n[128 + sq - kingsq[BLACK]];
					tropismw += t;
					attacksw += (t>0);
					break;
				case WB:
					f = FILE (sq);
					r = RANK (sq);
					if ((t=outposts[WHITE][sq]/4)) {
						menacew += t/2;
						if (lap[BLACK][f + 1 - 1] >= r && lap[BLACK][f + 1 + 1] >= r) {
							menacew += t;
							
							if (board[sq + 17] == WP || board[sq + 15] == WP) {
								menacew += t/2;
							}
						}
					}
					inactivew += TRAPPEDB * (r < 3 && (t=btrap[sq]) && board[t]==BP && ((f<2 && board[t-15] == BP) || (f>5 && board[t-17]==BP)));
					inactivew += /* border[sq] + */ (r == 7);
					pstw += pst[p][sq];
					t = tropism_b[128 + sq - kingsq[BLACK]];
					tropismw += t;
					attacksw += (t>0);
					
					//*
					t = (min(f, 7-r) + min(7-f, 7-r))/2;
					x = sq;
					while((board[x-=17]&14) != BP && board[x] != OB) ++t;
					x = sq;
					while((board[x-=15]&14) != BP && board[x] != OB) ++t;
					inactivew += (t<1) + (t<2) + (t<3);
					bishopmw += 3 * t;// + min(f, 7-r) + min(7-f, 7-r);
					//*/
					break;
				case WR:
					f = FILE (sq);
					r = RANK (sq);
					if (r < 2 && ((homer & 1) == 1 || RANK (kingsq[BLACK]) < 2)) {
						menacew += 7;
						rooksw += 10;
						t = max(1, tropism_r[128 + sq - kingsq[BLACK]]);
						tropismw += t;
						attacksw += 2;
					}
					else if (lap[WHITE][f + 1] < 4) {
						if (lap[WHITE][f + 1] < 2) { /* lap: black default=7
													  * white default=0 */
							if (r <= lap[BLACK][f + 1]) {
								rooksw += 15;
								//menacew += (abs (f - FILE (kingsq[BLACK])) < 2) * 3;
								t = max(3*(abs (f - FILE (kingsq[BLACK])) < 2), tropism_r[128 + sq - kingsq[BLACK]]);
								tropismw += t;
								attacksw += (t>0)*2;
							} 
							else {
								rooksw += 10;
								//menacew += (abs (f - FILE (kingsq[BLACK])) < 2) * 2;
								t = max(1*(abs (f - FILE (kingsq[BLACK])) < 2), tropism_r[128 + sq - kingsq[BLACK]]);
								tropismw += t;
								attacksw += (t>0)*2;
							}
						}
						else {
							++inactivew; // but never trapped ?
							t = tropism_r[128 + sq - kingsq[BLACK]];
							tropismw += t;
							attacksw += (t>0)*2;
						}
						
					} else if (r <= map[WHITE][f + 1]) { /* map: black default=0
														  * white default=7 */
						if (r <= lap[BLACK][f + 1]) {
							rooksw += 10; 
							//menacew += (abs (f - FILE (kingsq[BLACK])) < 2) * 3;
							t = max(3*(abs (f - FILE (kingsq[BLACK])) < 2), tropism_r[128 + sq - kingsq[BLACK]]);
							tropismw += t;
							attacksw += (t>0)*2;
						} 
						else {
							rooksw += 5;
							//menacew += (abs (f - FILE (kingsq[BLACK])) < 2) * 2;
							t = max(1*(abs (f - FILE (kingsq[BLACK])) < 2), tropism_r[128 + sq - kingsq[BLACK]]);
							tropismw += t;
							attacksw += (t>0)*2;
						}
					} else {
						++inactivew;
						if (RANK (kingsq[WHITE]) == 7 && (castle & 12) == 0 && r > 5) {
							inactivew += TRAPPEDR * (FILE (kingsq[WHITE]) > 3 && f > FILE (kingsq[WHITE]));
							inactivew += TRAPPEDR * (FILE (kingsq[WHITE]) < 4 && f < FILE (kingsq[WHITE]));
						}
						else {
							t = tropism_r[128 + sq - kingsq[BLACK]];
							tropismw += t;
							attacksw += (t>0)*2;
						}

					}
					//menacew += 7 * (r < 2 && ((homer & 1) == 1 || RANK (kingsq[BLACK]) < 2));
					pstw += pst[p][sq];
					//t = tropism_r[128 + sq - kingsq[BLACK]];
					//tropismw += t;
					//attacksw += (t>0)*2;
					break;
				case WQ:
					f = FILE (sq);
					r = RANK (sq);
					if (r < 2 && ((homer & 1) == 1 || RANK (kingsq[BLACK]) < 2)) {
						menacew += 4;
						t = max(1, tropism_q[128 + sq - kingsq[BLACK]]);
						tropismw += t;
						attacksw += 3;
					}
					else if (lap[WHITE][f + 1] < 2) {
						if (r <= lap[BLACK][f + 1]) {
							//menacew += (abs (f - FILE (kingsq[BLACK])) < 2) * 3;
							t = max(2*(abs (f - FILE (kingsq[BLACK])) < 2), tropism_q[128 + sq - kingsq[BLACK]]);
							tropismw += t;
							attacksw += (t>0)*3;
						} 
						else {
							//menacew += (abs (f - FILE (kingsq[BLACK])) < 2) * 2;
							t = max((abs (f - FILE (kingsq[BLACK])) < 2), tropism_q[128 + sq - kingsq[BLACK]]);
							tropismw += t;
							attacksw += (t>0)*3;
						}
					} 
					else if (r <= map[WHITE][f + 1]) { /* map: black default=0
														* white default=7 */
						if (r <= lap[BLACK][f + 1]) {
							//menacew += (abs (f - FILE (kingsq[BLACK])) < 2) * 3;
							t = max(2*(abs (f - FILE (kingsq[BLACK])) < 2), tropism_q[128 + sq - kingsq[BLACK]]);
							tropismw += t;
							attacksw += (t>0)*3;
						} 
						else {
							//menacew += (abs (f - FILE (kingsq[BLACK])) < 2) * 2;
							t = max((abs (f - FILE (kingsq[BLACK])) < 2), tropism_q[128 + sq - kingsq[BLACK]]);
							tropismw += t;
							attacksw += (t>0)*3;
						}
					}
					else {
						t = tropism_q[128 + sq - kingsq[BLACK]];
						tropismw += t;
						attacksw += (t>0)*3;
					}

					inactivew += (r > 6);
					pstw += pst[p][sq];
					
					break;
				default:
					break;
			}
		}
	}
	
	/* Pass 3 [for connected passers] */
	if( passerb || passerw) {
		for (i=2; i<9; ++i) {
			passerb += connected_passer[max(passedb[i], passedb[i-1])] * (passedb[i] && passedb[i-1] && abs(passedb[i]-passedb[i-1]) <= 1);// << (passedb[i] == passedb[i-1]);
			passerw += connected_passer[max(passedw[i], passedw[i-1])] * (passedw[i] && passedw[i-1] && abs(passedw[i]-passedw[i-1]) <= 1);// << (passedw[i] == passedw[i-1]);
		}
	}
	//*/
	
	/*
	 NOTES about p_curve & f_curve:
	 
	 f_curve scales potential_threat to material. Greatest with ALL pieces and near zero with <= 'bare' mating material.
	 p_curve scales passer_value to material. Least [1X] in beginning up to full [2X] in end
	 
	 King Activity is inversely related to f_curve.
	 Pawn weaknesses are: important in open, because they 'require' resources and later because they are key in endgame
	 
	 */
	
	/* KING SAFETY */
	/* BLACK */
	f = FILE (kingsq[BLACK]);
	r = RANK (kingsq[BLACK]);
	
	f = f + (f == 0) - (f == 7) + (f == 5) - (f == 2);
	safetyb += shield[lap[BLACK][f + 1 - 1]]; /* no pawn == 7 */
	safetyb += shield[lap[BLACK][f + 1 - 0]];
	safetyb += shield[lap[BLACK][f + 1 + 1]];
	
	safetyb -= 16 * (safetyb == 96);
	safetyb >>= (safetyb < 33);
	
	feature[BLACK][SHIELD] = safetyb * f_curve[force[WHITE]] / MF;
	
	safetyb -= storm[7 - map[WHITE][f + 1 - 1]]; /* map[W] = 7 for no
												  * pawn and rank1-6 */
	safetyb -= storm[7 - map[WHITE][f + 1]];
	safetyb -= storm[7 - map[WHITE][f + 1 + 1]];
	
	safetyb -= bk_defect[kingsq[BLACK]];
	
	/* WHITE */
	f = FILE (kingsq[WHITE]);
	r = RANK (kingsq[WHITE]);
	
	f = f + (f == 0) - (f == 7) + (f == 5) - (f == 2);
	safetyw += shield[7 - lap[WHITE][f + 1 - 1]]; /* no pawn == 0 */
	safetyw += shield[7 - lap[WHITE][f + 1 - 0]];
	safetyw += shield[7 - lap[WHITE][f + 1 + 1]];
	
	safetyw -= 16 * (safetyw == 96);
	safetyw >>= (safetyw < 33);
	
	feature[WHITE][SHIELD] = safetyw * f_curve[force[BLACK]] / MF;
	
	safetyw -= storm[map[BLACK][f + 1 - 1]]; /* map[B] = 0 for no
											  * pawn and rank1-6 */
	safetyw -= storm[map[BLACK][f + 1]];
	safetyw -= storm[map[BLACK][f + 1 + 1]];
	
	safetyw -= wk_defect[kingsq[WHITE]];
	
	pw = safetyw * f_curve[force[BLACK]] / MF;
	pb = safetyb * f_curve[force[WHITE]] / MF;
	
	feature[WHITE][SAFETY] = safetyw * f_curve[force[BLACK]] / MF;
	feature[BLACK][SAFETY] = safetyb * f_curve[force[WHITE]] / MF;
	
	/* Tropism */
	pw -= tropismb * attacks_scale[attacksb] * (51-p_curve[force[BLACK]]) / MF; //attacksb; // 
	pb -= tropismw * attacks_scale[attacksw] * (51-p_curve[force[WHITE]]) / MF; //attacksw; //
	
	feature[WHITE][TROPISM] = -tropismb * attacks_scale[attacksb] * (51-p_curve[force[BLACK]]) / MF;
	feature[BLACK][TROPISM] = -tropismw * attacks_scale[attacksw] * (51-p_curve[force[WHITE]]) / MF;
	
	/* PASSERS */
	pw += passerw * p_curve[force[BLACK]] / 14;//(MF / 2);
	pb += passerb * p_curve[force[WHITE]] / 14;//(MF / 2);
	
	feature[WHITE][PASSERS] = passerw * p_curve[force[BLACK]] / 14;//(MF / 2);
	feature[BLACK][PASSERS] = passerb * p_curve[force[WHITE]] / 14;//(MF / 2);
	
	/* PAWN WEAKNESS */
	pw += weakb * p_curve[force[BLACK]] / (MF / 2);
	pb += weakw * p_curve[force[WHITE]] / (MF / 2);
	
	feature[WHITE][WEAKNESS] = weakw * p_curve[force[WHITE]] / (MF / 2);
	feature[BLACK][WEAKNESS] = weakb * p_curve[force[BLACK]] / (MF / 2);
	
	
	/* ACTIVITY */
	/* Kings */
	offenseb += pst[BK][kingsq[BLACK]];
	offensew += pst[WK][kingsq[WHITE]];
	
	pw += offensew * (MF - f_curve[force[BLACK]]) / MF;
	pb += offenseb * (MF - f_curve[force[WHITE]]) / MF;
	
	feature[WHITE][OFFENSE] = offensew * (MF - f_curve[force[BLACK]]) / MF;
	feature[BLACK][OFFENSE] = offenseb * (MF - f_curve[force[WHITE]]) / MF;
	
	/* Rooks & minors*/
	pw += bishopmw;
	pb += bishopmb;
	
	pw += rooksw * (51-p_curve[force[WHITE]]) / MF;
	pb += rooksb * (51-p_curve[force[BLACK]]) / MF;
	
	pw += inactive[inactiveb];
	pb += inactive[inactivew];
	
	pw += 3 * obstaclesb;
	pb += 3 * obstaclesw;
	
	/* pawn PST (center control) is scaled earlier */
	pw += pstw;// * f_curve[force[WHITE]] / MF;
	pb += pstb;// * f_curve[force[BLACK]] / MF;
	
	feature[WHITE][PIECESQUARE] = pstw;
	feature[BLACK][PIECESQUARE] = pstb;
	
	feature[WHITE][ACTIVITY] = bishopmw + rooksw - 3*obstaclesw - inactive[inactivew];
	feature[BLACK][ACTIVITY] = bishopmb + rooksb - 3*obstaclesb - inactive[inactiveb];
	
	/* MENACING */
	
	pw += menace[menacew] * (51-p_curve[force[WHITE]]) / MF;
	pb += menace[menaceb] * (51-p_curve[force[BLACK]]) / MF;
	
	feature[WHITE][MENACE] = menace[menacew] * (51-p_curve[force[WHITE]]) / MF;
	feature[BLACK][MENACE] = menace[menaceb] * (51-p_curve[force[BLACK]]) / MF;
	
	s += (pw - pb);
	//s += stm? STM_BONUS : -STM_BONUS;
	s /= ((s>0)? 1<<dw : 1<<db);
	
	
	//s = (stm) ? ((s + pw-pb) / ((s+pw-pb>0) ? 1<<dw : 1<<db)) : ((-s + pb-pw) / ((-s+pb-pw>0) ? 1<<db : 1<<dw));
	
	//s &= ~(GRAINS-1);
	
#ifdef EHASH
	estore (s);
#endif
	
	return stm? s : -s;
}
