1 /**
2 ***   STATIC EVALUATION
3 **/
4 
5 #include "phalanx.h"
6 
7 /**
8 ***   command `score' shows detailed information about static
9 ***   evaluation of actual position. If you want this to work,
10 ***   SCORING must be defined. Then, static evaluation function
11 ***   is somewhat slower.
12 **/
13 #undef SCORING
14 int Scoring;
15 
16 /**
17 ***   If the material value is between ENDMATERIAL and MIDMATERIAL,
18 ***   Phalanx computes both endgame and middlegame evaluation.
19 ***   The evaluation is proportionally computed from these two values.
20 **/
21 #define ENDMATERIAL 3000 /* minimum is 0 */
22 #define MIDMATERIAL 6000 /* maximum is 8600 */
23 
24 tknow Wknow, Bknow;
25 
26 
27 /* isolated pawn penalty by rank */
28 static const int isofile[10] =
29 { 0, -4, -6, -8, -10, -10, -8, -6, -4, 0 };
30 /***  A   B   C    D    E   F   G   H  ***/
31 
32 /*** Square color ***/
33 signed char sqcolor_[80] =
34 {
35   0, 2, 1, 2, 1, 2, 1, 2, 1, 0,
36   0, 1, 2, 1, 2, 1, 2, 1, 2, 0,
37   0, 2, 1, 2, 1, 2, 1, 2, 1, 0,
38   0, 1, 2, 1, 2, 1, 2, 1, 2, 0,
39   0, 2, 1, 2, 1, 2, 1, 2, 1, 0,
40   0, 1, 2, 1, 2, 1, 2, 1, 2, 0,
41   0, 2, 1, 2, 1, 2, 1, 2, 1, 0,
42   0, 1, 2, 1, 2, 1, 2, 1, 2, 0
43 }; signed char * sqcolor = sqcolor_-20;
44 
45 /*** Pawn in middlegame ***/
46 int pmpb_[80] =
47 {
48   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
49   0,  2,  3,  4,  6,  6,  4,  3,  2,  0,
50   0,  0,  1,  5,  8,  8,  5,  1,  0,  0,
51   0,  0,  1,  6, 16, 12,  6,  1,  0,  0,
52   0,  1,  5,  7, 16, 12,  7,  5,  1,  0,
53   0,  5,  8, 10, 16, 12, 10,  8,  5,  0,
54   0,  5,  5,  5,  6,  6,  5,  5,  5,  0,
55   0,  0,  0,  0,  0,  0,  0,  0,  0,  0
56 }; const int * pmpb = pmpb_-20;
57 
58 /*** queenside pawn attack ***/
59 int qstormtable_[80] =
60 {
61   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
62   0,-12,-12,-12,  0,  0, 10, 10, 10,  0,
63   0, -9,-10, -9,  0,  6,  8,  8,  8,  0,
64   0, -6, -6, -6,  6, 10,  4,  4,  4,  0,
65   0, -3, -3, -3, 10,  4,  0,  0,  0,  0,
66   0,  0,  0,  5,  0,  0,  0,  0,  0,  0,
67   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
68   0,  0,  0,  0,  0,  0,  0,  0,  0,  0
69 }; const int * qstormtable = qstormtable_-20;
70 
71 /*** kingside pawn attack ***/
72 int kstormtable_[80] =
73 {
74   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
75   0, 10, 10, 10,  0,  0,-12,-12,-12,  0,
76   0,  8,  8,  8,  6,  0, -9,-10, -9,  0,
77   0,  4,  4,  4, 10,  6, -6, -6, -6,  0,
78   0,  0,  0,  0,  4, 10, -3, -3, -3,  0,
79   0,  0,  0,  0,  0,  0,  5,  0,  0,  0,
80   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
81   0,  0,  0,  0,  0,  0,  0,  0,  0,  0
82 }; const int * kstormtable = kstormtable_-20;
83 
84 /*** knight in middlegame ***/
85 int nmpb_[80] =
86 {
87   0,-16,-10, -8, -8, -8, -8,-10,-16,  0,
88   0,-10, -3,  1,  3,  3,  1, -3,-10,  0,
89   0, -8,  1,  5,  5,  5,  5,  1, -8,  0,
90   0, -8,  2,  5,  8,  8,  5,  2, -8,  0,
91   0, -8,  4,  6, 10, 10,  6,  4, -8,  0,
92   0, -8,  4,  7,  8,  8,  7,  4, -8,  0,
93   0,-10,  0,  3,  4,  4,  3,  0,-10,  0,
94   0,-16,-10, -8, -8, -8, -8,-10,-16,  0
95 }; const int * nmpb = nmpb_-20;
96 
97 /*** knight in endgame ***/
98 int nepb_[80] =
99 {
100   0,-16,-10, -6, -2, -2, -6,-10,-16,  0,
101   0, -9, -3,  1,  4,  4,  1, -3, -9,  0,
102   0, -4,  1,  5,  8,  8,  5,  1, -4,  0,
103   0,  0,  4,  8, 12, 12,  8,  4,  0,  0,
104   0,  1,  5,  9, 13, 13,  9,  5,  1,  0,
105   0, -2,  2,  6,  9,  9,  6,  2, -2,  0,
106   0, -6, -1,  2,  5,  5,  2, -1, -6,  0,
107   0, -9, -6, -3,  0,  0, -3, -6, -9,  0
108 }; int *nepb = nepb_-20;
109 
110 /*** bishop in middlegame ***/
111 int bmpb_[80] =
112 {
113   0,  10,  8,  6,  4,  4,  6,  8, 10,  0,
114   0,   8, 12,  8,  9,  9,  8, 12,  8,  0,
115   0,  10, 10, 11, 11, 11, 11, 10, 10,  0,
116   0,  11, 12, 13, 14, 14, 13, 12, 11,  0,
117   0,  12, 13, 15, 17, 17, 15, 14, 12,  0,
118   0,  13, 14, 16, 16, 16, 16, 14, 13,  0,
119   0,  11, 14, 12, 12, 12, 12, 14, 11,  0,
120   0,  13, 10, 10, 10, 10, 10, 10, 13,  0
121 }; const int * bmpb = bmpb_-20;
122 
123 /*** bishop in endgame ***/
124 int bepb_[80] =
125 {
126   0, 24, 21, 18, 15, 15, 18, 21, 24,  0,
127   0, 21, 24, 21, 18, 18, 21, 24, 21,  0,
128   0, 18, 21, 24, 24, 24, 24, 21, 18,  0,
129   0, 15, 18, 24, 30, 30, 24, 18, 15,  0,
130   0, 15, 18, 24, 30, 30, 24, 18, 15,  0,
131   0, 18, 21, 24, 24, 24, 24, 21, 18,  0,
132   0, 21, 24, 21, 18, 18, 21, 24, 21,  0,
133   0, 24, 21, 18, 15, 15, 18, 21, 24,  0
134 }; const int * bepb = bepb_-20;
135 
136 /*** rook in middlegame ***/
137 int rmpb_[80] =
138 {
139   0,  0,  1,  2,  3,  3,  2,  1,  0,  0,
140   0,  0,  1,  2,  3,  3,  2,  1,  0,  0,
141   0,  0,  1,  2,  3,  3,  2,  1,  0,  0,
142   0,  0,  1,  2,  3,  3,  2,  1,  0,  0,
143   0,  0,  1,  2,  3,  3,  2,  1,  0,  0,
144   0,  7,  8,  9, 10, 10,  9,  8,  7,  0,
145   0, 10, 11, 12, 13, 13, 12, 11, 10,  0,
146   0, 10, 11, 12, 13, 13, 12, 11, 10,  0
147 }; const int * rmpb = rmpb_-20;
148 
149 /*** queen in middlegame ***/
150 int qmpb_[80] =
151 {
152   0,  0,  1,  2,  3,  3,  2,  1,  0,  0,
153   0,  4,  5,  6,  7,  7,  6,  5,  4,  0,
154   0,  5,  6,  7,  8,  8,  7,  6,  5,  0,
155   0,  6,  7,  8,  9,  9,  8,  7,  6,  0,
156   0,  8,  9, 10, 11, 11, 10,  9,  8,  0,
157   0, 10, 11, 12, 13, 13, 12, 11, 10,  0,
158   0,  8, 10, 11, 12, 12, 11, 10,  8,  0,
159   0,  5,  6,  7,  8,  8,  7,  6,  5,  0
160 }; const int * qmpb = qmpb_-20;
161 
162 /*** king in middlegame ***/
163 int kmpb_[80] =
164 {
165   0,  0,  0, -3, -6, -6, -3,  0,  0,  0,
166   0, -2, -4, -8,-12,-12, -8, -4, -2,  0,
167   0, -6,-12,-20,-25,-25,-20,-12, -6,  0,
168   0,-15,-20,-30,-40,-40,-30,-20,-15,  0,
169   0,-30,-40,-50,-60,-60,-50,-40,-30,  0,
170   0,-35,-45,-55,-65,-65,-55,-45,-35,  0,
171   0,-30,-40,-50,-60,-60,-50,-40,-30,  0,
172   0,-20,-30,-40,-50,-50,-40,-30,-20,  0
173 }; const int * kmpb = kmpb_-20;
174 
175 /*** king in endgame ***/
176 int kepb_[80] =
177 {
178   0, -5,  5, 10, 15, 15, 10,  5, -5,  0,
179   0,  6, 11, 16, 21, 21, 16, 11,  6,  0,
180   0, 12, 17, 22, 27, 27, 22, 17, 12,  0,
181   0, 18, 24, 30, 34, 34, 28, 24, 18,  0,
182   0, 20, 27, 33, 48, 48, 33, 27, 20,  0,
183   0, 16, 25, 34, 40, 40, 34, 25, 16,  0,
184   0,  9, 20, 28, 35, 35, 28, 20,  9,  0,
185   0,  3, 10, 17, 24, 24, 17, 10,  3,  0,
186 }; const int * kepb = kepb_-20;
187 
188 int outpost_[80] =
189 {
190   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
191   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
192   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
193   0, 0, 0, 0, 1, 1, 0, 0, 0, 0,
194   0, 0, 0, 1, 2, 2, 1, 0, 0, 0,
195   0, 0, 1, 2, 3, 3, 2, 1, 0, 0,
196   0, 0, 0, 0, 1, 1, 0, 0, 0, 0,
197   0, 0, 0, 0, 0, 0, 0, 0, 0, 0
198 }; const int *outpost = outpost_-20;
199 
200 /* Mobility bonuses are extremely non-linear, a piece that has a very small
201  * number of moves gets a large penalty. The rook mobility bonus/penalty is
202  * tripled in endgame. */
203 int B_mobi[20] =
204  { -36, -28, -20, -14, -6, -2, 1, 2, 3, 4, 5, 6, 7, 8, 8, 8, 8, 8, 8, 8 };
205 int N_mobi[10] =
206  { -50, -25, -15, -10, -5, 0, 5, 10, 15, 20 };
207 int R_mobi[16] =
208  { -20, -15, -10, -7, -4, -2, 0, 2, 4, 6, 8, 9, 10, 10, 10, 10 };
209 
210 /* power table */
211 unsigned P[120];
212 
213 int *pf, *xpf, wpf[10], bpf[10]; /* # of w&b pawns on a file */
214 
215 
score_position(void)216 int score_position(void)
217 {
218 
219 int i;
220 
221 /**
222 ***  We always compute both 'endgame' value and 'middlegame' position
223 ***  value.  After they are computed, they are balanced by total material.
224 ***  This prevents evaluation to do big jumps when searching a position
225 ***  on the edge of middlegame and endgame.
226 ***
227 ***  Evaluation is done in two passes:
228 ***  1) Extract knowledge (see typedef tknow), prepare mirrored board.
229 ***  2) Use knowledge.  Thanks to mirroring board in first pass, we dont
230 ***     have to write evaluation of specific things twice (for white and
231 ***     black separately).  This might also make better use of internal
232 ***     cache on small machines.
233 **/
234 
235 int midresult, endresult, result, mtrl_diff;
236 
237 int whp, bhp; /* sum of hung pieces. >=2 means troubles -> big penalty. */
238 
239 int kp, xkp; /* this side and other side king position */
240 
241 tknow * know, * xknow;
242 
243 static int *l, wl[34], bl[34];   /* w&b piece list. Indexes to B[] (mB[]) */
244 static int n, wn, bn;
245 
246 static int pin[32];
247 int npin;
248 
249 /* mirrored board */
250 static tsquare mB[120] =
251 { 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
252   3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
253   3, 0, 0, 0, 0, 0, 0, 0, 0, 3,
254   3, 0, 0, 0, 0, 0, 0, 0, 0, 3,
255   3, 0, 0, 0, 0, 0, 0, 0, 0, 3,
256   3, 0, 0, 0, 0, 0, 0, 0, 0, 3,
257   3, 0, 0, 0, 0, 0, 0, 0, 0, 3,
258   3, 0, 0, 0, 0, 0, 0, 0, 0, 3,
259   3, 0, 0, 0, 0, 0, 0, 0, 0, 3,
260   3, 0, 0, 0, 0, 0, 0, 0, 0, 3,
261   3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
262   3, 3, 3, 3, 3, 3, 3, 3, 3, 3 };
263 
264 static tsquare mBinit[80] =
265 { 3, 0, 0, 0, 0, 0, 0, 0, 0, 3,
266   3, 0, 0, 0, 0, 0, 0, 0, 0, 3,
267   3, 0, 0, 0, 0, 0, 0, 0, 0, 3,
268   3, 0, 0, 0, 0, 0, 0, 0, 0, 3,
269   3, 0, 0, 0, 0, 0, 0, 0, 0, 3,
270   3, 0, 0, 0, 0, 0, 0, 0, 0, 3,
271   3, 0, 0, 0, 0, 0, 0, 0, 0, 3,
272   3, 0, 0, 0, 0, 0, 0, 0, 0, 3 };
273 
274 tsquare *b;
275 
276 /***************************************************************/
277 
278 if( Totmat <= (R_VALUE+R_VALUE+P_VALUE) )
279 {
280 	/* if there are no pieces, return special pawn endgame evaluation */
281 	/* [moved, computed later] */
282 
283 	/* Now, check some special endgame positions that are known to be
284 	 * hopeless draw (this might also cause pruning of the search). */
285 	switch(Totmat)
286 	{
287 	case (B_VALUE+P_VALUE): /* minor piece and pawn */
288 		{	int r = e_mp();
289 			if( r ) return DRAW+r;
290 		}
291 	break;
292 	case (N_VALUE+N_VALUE): /* minor against minor or two knights */
293 		if( G[Counter].mtrl == N_VALUE ) /* minor:minor */
294 		if( G[Counter].m.in2 == 0 ) return DRAW;
295 		{ int nn=0;
296 		  for( i=L[WKP].next; i!=0; i=L[i].next )
297 		  if( B[i] == WN ) nn++;
298 		  if( nn == 1 ) return e_nb(WHITE);
299 		  if( nn == 2 ) return
300 			Color==WHITE ?
301 				  DRAW-(N_VALUE+N_VALUE)
302 				: DRAW+(N_VALUE+N_VALUE);
303 		  if( nn == 0 )
304 		  {
305 		  for( i=L[BKP].next; i!=0; i=L[i].next )
306 		  if( B[i] == BN ) nn++;
307 		  if( nn == 1 ) return e_nb(BLACK);
308 		  if( nn == 2 ) return
309 			Color==WHITE ?
310 				  DRAW+(N_VALUE+N_VALUE)
311 				: DRAW-(N_VALUE+N_VALUE);
312 		  }
313 		}
314 	break;
315 	case (R_VALUE+R_VALUE+P_VALUE):  /* RPr */
316 		if( abs(G[Counter].mtrl-G[Counter].xmtrl) == P_VALUE )
317 		{
318 			int i; int np=0;
319 			for( i=L[WKP].next; i!=0; i=L[i].next ) np++;
320 			for( i=L[BKP].next; i!=0; i=L[i].next ) np++;
321 			if( np == 3 ) return e_rpr();
322 		}
323 	break;
324 	}
325 }
326 
327 result = midresult = endresult = whp = bhp = npin = 0;
328 
329 memcpy( mB+20, mBinit, 80*sizeof(tsquare) );
330 
331 wn = bn = 1; /* King ... at least */
332 for(i=0;i!=10;i++) wpf[i]=bpf[i]=0;
333 
334 memset( &Wknow, 0, sizeof(tknow) );
335 memset( &Bknow, 0, sizeof(tknow) );
336 memset( P+20, 0, 80*sizeof(unsigned) );
337 
338 Wknow.kp = WKP; Wknow.worsebm = 100;
339 Wknow.lpf = 9;
340 Bknow.kp = BKP; Bknow.worsebm = 100;
341 Bknow.lpf = 9;
342 
343 /************************************************/
344 
345 i=WKP; mB[ Th[i] ] = BK; wl[0] = i;
346 for( i=L[i].next; i!=0; i=L[i].next )
347 {
348 	int j; int mobi;
349 	switch( B[i] )
350 	{
351 	case WP: mB[ Th[i] ] = BP; wl[wn] = i; wn++;
352 		wpf[i%10]++;
353 		if(i%10<Wknow.lpf) Wknow.lpf=i%10;
354 		if(i%10>Wknow.rpf) Wknow.rpf=i%10;
355 		Wknow.p++;
356 		for( j=i+9; j<=i+11; j+=2 ) { P[j] |= WPM; P[j] += WWW; }
357 		if( i>=A6 && B[i+10]==0 ) /* Passed pawn */
358 		{ Bknow.hung+=4;
359 		  if(B[i+20]==0||B[i+20]==3) Bknow.hung+=16;
360 		}
361 	break;
362 	case WN: mB[ Th[i] ] = BN; wl[wn] = i; wn++;
363 		Wknow.n++;
364 		mobi = 0;
365 		for( j=0; j!=8; j++ )
366 		{
367 			int d = i+N_moves[j]; P[d] |= WNM; P[d] += WWW;
368 			/* knight mobility below, note that this is not just
369 			 * the number of pseudo-legal moves. We don't count
370 			 * squares with friendly pawns and squares attacked
371 			 * by enemy pawns. We do count moves targeting other
372 			 * friendly and enemy pieces - search should handle. */
373 			if( B[d]!=3 && B[d]!=WP && B[d+9]!=BP && B[d+11]!=BP)
374 				mobi++;
375 		}
376 		result += N_mobi[mobi];
377 	break;
378 	case WB: mB[ Th[i] ] = BB; wl[wn] = i; wn++;
379 		Wknow.b++;
380 		Wknow.bishopcolor  |= sqcolor[i];
381 		Bknow.xbishopcolor |= 3-sqcolor[i];
382 		mobi = 4;
383 		for( j=4; j!=8; j++ )
384 		{ int step = RB_dirs[j]; int d = i;
385 		  do { d+=step; mobi++; P[d] |= WBM; P[d] += WWW; }
386 		  while( B[d] == 0 );
387 		  if( B[d] & WHITE ) /* edge or friendly piece */
388 		  {
389 			mobi--;
390 			if( B[d]==3 || ( B[d]==WP && B[d+10] ) ) mobi--;
391 		  }
392 		  else
393 		  if( B[d]==BN || B[d]==BR || B[d]==BQ )
394 		  { pin[npin]=d;
395 		    do d+=step; while( B[d]==0 );
396 		    if( B[d]==BQ || B[d]==BK ) npin++;
397 		  }
398 		}
399 		result += B_mobi[mobi];
400 		if( mobi < Wknow.worsebm ) Wknow.worsebm = mobi;
401 	break;
402 	case WR: mB[ Th[i] ] = BR; wl[wn] = i; wn++;
403 		if( i>=A7 && i<=H7 ) Wknow.r7r+=2;
404 		Wknow.r++;
405 		mobi = 0;
406 		for( j=0; j!=4; j++ )
407 		{ int step = RB_dirs[j]; int d = i;
408 		  do { d += step; mobi++; P[d] |= WRM; P[d] += WWW; }
409 		  while( B[d] == 0 );
410 		  if( B[d] & WHITE ) mobi--;
411 		  else
412 		  if( B[d]==BN || B[d]==BB || B[d]==BQ )
413 		  { pin[npin]=d;
414 		    do d+=step; while( B[d]==0 );
415 		    if( B[d]==BQ || B[d]==BK ) npin++;
416 		  }
417 		}
418 		result += R_mobi[mobi];
419 		endresult += 2 * R_mobi[mobi];
420 	break;
421 	case WQ: mB[ Th[i] ] = BQ; wl[wn] = i; wn++;
422 		if( i>=A6 ) Wknow.r7r++;
423 		Wknow.q++;
424 		for( j=0; j!=8; j++ )
425 		{ int step = RB_dirs[j]; int d = i;
426 		  do { d += step; P[d] |= WQM; P[d] += WWW; }
427 		  while( B[d] == 0 );
428 
429 		  if( B[d]==BN || ( B[d]==BB && j<4 ) || ( B[d]==BR && j>=4 ) )
430 		  { pin[npin]=d;
431 		    do d+=step; while( B[d]==0 );
432 		    if( B[d]==BK ) npin++;
433 		  }
434 		}
435 	break;
436 	}
437 }
438 
439 i=BKP; mB[ Th[i] ] = WK; bl[0] = Th[i];
440 for( i=L[i].next; i!=0; i=L[i].next )
441 {
442 	int j;
443 	int mobi;
444 	switch( B[i] )
445 	{
446 	case BP: mB[ Th[i] ] = WP; bl[bn] = Th[i]; bn++;
447 		bpf[i%10]++;
448 		if(i%10<Bknow.lpf) Bknow.lpf=i%10;
449 		if(i%10>Bknow.rpf) Bknow.rpf=i%10;
450 		Bknow.p++;
451 		for( j=i-11; j<=i-9; j+=2 ) { P[j] |= BPM; P[j] += BBB; }
452 		if( i<=H3 && B[i-10]==0 )
453 		{ Wknow.hung+=4;
454 		  if(B[i-20]==0||B[i-20]==3) Wknow.hung+=16;
455 		}
456 	break;
457 	case BN: mB[ Th[i] ] = WN; bl[bn] = Th[i]; bn++;
458 		Bknow.n++;
459 		mobi = 0;
460 		for( j=0; j!=8; j++ )
461 		{
462 			int d = i+N_moves[j]; P[d] |= BNM; P[d] += BBB;
463 			if( B[d]!=3 && B[d]!=BP && B[d-9]!=WP && B[d-11]!=WP)
464 				mobi++;
465 		}
466 		result -= N_mobi[mobi];
467 	break;
468 	case BB: mB[ Th[i] ] = WB; bl[bn] = Th[i]; bn++;
469 		Bknow.b++;
470 		Bknow.bishopcolor  |= 3-sqcolor[i];
471 		Wknow.xbishopcolor |= sqcolor[i];
472 		mobi = 4;
473 		for( j=4; j!=8; j++ )
474 		{ int step = RB_dirs[j]; int d = i;
475 		  do { d += step; mobi++; P[d] |= BBM; P[d] += BBB; }
476 		  while( B[d] == 0 );
477 		  if( B[d] & BLACK )
478 		  {
479 			mobi--;
480 			if( B[d]==3 || ( B[d]==BP && B[d-10] ) ) mobi--;
481 		  }
482 		  else
483 		  if( B[d]==WN || B[d]==WR || B[d]==WQ )
484 		  { pin[npin]=d;
485 		    do d+=step; while( B[d]==0 );
486 		    if( B[d]==WQ || B[d]==WK ) npin++;
487 		  }
488 		}
489 		result -= B_mobi[mobi];
490 		if( mobi < Bknow.worsebm ) Bknow.worsebm = mobi;
491 	break;
492 	case BR: mB[ Th[i] ] = WR; bl[bn] = Th[i]; bn++;
493 		if( i>=A2 && i<=H2 ) Bknow.r7r+=2;
494 		Bknow.r++;
495 		mobi = 0;
496 		for( j=0; j!=4; j++ )
497 		{ int step = RB_dirs[j]; int d = i;
498 		  do { d += step; mobi++; P[d] |= BRM; P[d] += BBB; }
499 		  while( B[d] == 0 );
500 		  if( B[d] & BLACK ) mobi--;
501 		  else
502 		  if( B[d]==WN || B[d]==WB || B[d]==WQ )
503 		  { pin[npin]=d;
504 		    do d+=step; while( B[d]==0 );
505 		    if( B[d]==WQ || B[d]==WK ) npin++;
506 		  }
507 		}
508 		result -= R_mobi[mobi];
509 		endresult -= 2 * R_mobi[mobi];
510 	break;
511 	case BQ: mB[ Th[i] ] = WQ; bl[bn] = Th[i]; bn++;
512 		if( i<=H3 ) Bknow.r7r++;
513 		Bknow.q++;
514 		for( j=0; j!=8; j++ )
515 		{ int step = RB_dirs[j]; int d = i;
516 		  do { d += step; P[d] += BBB; P[d] |= BQM; }
517 		  while( B[d] == 0 );
518 		  if( B[d]==WN || ( B[d]==WB && j<4 ) || ( B[d]==WR && j>=4 ) )
519 		  { pin[npin]=d;
520 		    do d+=step; while( B[d]==0 );
521 		    if( B[d]==WK ) npin++;
522 		  }
523 		}
524 	break;
525 	}
526 }
527 
528 if( Totmat == P_VALUE*(Wknow.p+Bknow.p) )
529 { /* only pawns */ return pawns(); }
530 
531 #undef debug
532 #ifdef debug
533 { int i,j; puts("");
534   for(i=110;i>=0;i-=10) { for(j=0;j!=10;j++)
535                           printf(" %04X",P[i+j]);puts(""); } }
536 #endif
537 
538 #ifdef SCORING
539 if( Scoring ) printf(" (w/b) mobility = %i\n",result);
540 #endif
541 
542 /**
543 ***   Scan pinned pieces
544 **/
545 { int pini;
546 for( i=0; i!=npin; i++ )
547 switch( B[ pini = pin[i] ] )
548 {
549 case WQ: result -= 50; Wknow.hung += 20;
550 break;
551 case BQ: result += 50; Bknow.hung += 20;
552 break;
553 case WN: case WB: case WR:
554 	if( (P[pini] & WPM) == 0 ) /* not pawn-protected */
555 	{ Wknow.hung += 6; result += -15*(P[pini]>>13); }
556 	else result += -6*(P[pini]>>13);
557 	if( P[pini] & BPM ) { Wknow.hung += 5; result -= 15; }
558 break;
559 case BN: case BB: case BR:
560 	if( (P[pini] & BPM) == 0 )
561 	{ Bknow.hung += 6; result +=  15*((0x00F0&P[pini])>>5); }
562 	else result +=  6*((0x00F0&P[pini])>>5);
563 	if( P[pini] & WPM ) { Bknow.hung += 5; result += 15; }
564 break;
565 }
566 }
567 
568 /**
569 ***   Look for hung pieces & weak pawns
570 **/
571 {
572 	static unsigned m[112] =
573 	{ 0,   0,   0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0,
574 	  0, 0x0, 0x0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0,
575 	  0, 0x1, 0x1, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0,
576 	  0, 0x1, 0x1, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0,
577 	  0, 0x7, 0x7, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0,
578 	  0, 0xF, 0xF, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0,
579 	  0, 0xF, 0xF, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0 };
580 
581 	for( i=L[WKP].next; i!=0; i=L[i].next )
582 	if(P[i]&0xFF00) /* Black attacks the square 'i' */
583 	{
584 		if( (P[i]&0x00FF)==0 /* undefended */
585 		 || ( m[B[i]] & (P[i]>>8) ) /* attacked by less valuable */ )
586 			switch(B[i])
587 		{ case WP: Wknow.hung += 8; break;
588 		  case WN:
589 		  case WB: whp++; Wknow.hung+=12; break;
590 		  case WR: whp++; Wknow.hung+=14; break;
591 		  case WQ: whp++; Wknow.hung+=16;
592 		}
593 		else if( (P[i]&WPM) == 0 ) /* not pawn-protected */
594 		{
595 		  if(B[i]==WP) result -= (P[i]>>13)*5;
596 		  else Wknow.hung += 6;
597 		}
598 	}
599 
600 	for( i=L[BKP].next; i!=0; i=L[i].next )
601 	if(P[i]&0x00FF) /* white attacks this square */
602 	{
603 		if( (P[i]&0xFF00)==0 || ( m[B[i]] & P[i] ) )
604 			switch(B[i])
605 		{ case BP: Bknow.hung += 8; break;
606 		  case BN:
607 		  case BB: bhp++; Bknow.hung+=12; break;
608 		  case BR: bhp++; Bknow.hung+=14; break;
609 		  case BQ: bhp++; Bknow.hung+=16;
610 		}
611 		else if( (P[i]&BPM) == 0 ) /* not pawn-protected */
612 		{
613 		  if(B[i]==BP) result += ((P[i]>>5)&0x7)*5;
614 		  else Bknow.hung += 6;
615 		}
616 	}
617 
618 	if( whp>1 ) Wknow.hung += 8*whp;
619 	if( bhp>1 ) Bknow.hung += 8*bhp;
620 }
621 
622 /*** King safety ***/
623 for(i=0;i!=8;i++)
624 {
625 	int direction = K_moves[i];
626 	int d=Wknow.kp+direction;
627 	if(B[d]!=3)
628 	{
629 		int ataks = (P[d]>>13) & 0x7;
630 		if(ataks)
631 		{
632 			int defs = (P[d]>>5) & 0x7;
633 			Wknow.khung += ataks;
634 			if( defs == 0 )
635 			{
636 				Wknow.khung ++;
637 				if( ataks>1 && (P[d]&BQM) )
638 				Wknow.khung += 2;
639 			}
640 		}
641 
642 		/*** Add number of safe checks available ***/
643 		if( B[d]==0 )
644 		{
645 			d += direction;
646 			while( (B[d]&BLACK) == 0 )
647 			{
648 				if( ( P[d] & 0xE0 ) == 0 )
649 				{
650 					if( i<4 )
651 					{ if( P[d] & (BQM|BRM) )
652 					  { Wknow.khung +=2; break; } }
653 					else
654 					{ if( P[d] & (BQM|BBM) )
655 					  { Wknow.khung +=2; break; } }
656 				}
657 				if( B[d] ) break;
658 				d += direction;
659 			}
660 		}
661 		d = Wknow.kp+N_moves[i];
662 		if( (P[d]&BNM) && (B[d]&BLACK) == 0 && ( P[d] & 0xE0 ) == 0 )
663 		Wknow.khung += 2;
664 	}
665 
666 	d=Bknow.kp+direction;
667 	if(B[d]!=3)
668 	{
669 		int ataks = (P[d]>>5) & 0x7;
670 		if(ataks)
671 		{
672 			int defs = (P[d]>>13) & 0x7;
673 			Bknow.khung += ataks;
674 			if( defs == 0 )
675 			{
676 				Bknow.khung ++;
677 				if( ataks>1 && (P[d]&WQM) )
678 				Bknow.khung += 2;
679 			}
680 		}
681 
682 		/*** Add number of safe checks available ***/
683 		if( B[d]==0 )
684 		{
685 			d += direction;
686 			while( (B[d]&WHITE) == 0 )
687 			{
688 				if( ( P[d] & 0xE000 ) == 0 )
689 				{
690 					if( i<4 )
691 					{ if( P[d] & (WQM|WRM) )
692 					  { Bknow.khung +=2; break; } }
693 					else
694 					{ if( P[d] & (WQM|WBM) )
695 					  { Bknow.khung +=2; break; } }
696 				}
697 				if( B[d] ) break;
698 				d += direction;
699 			}
700 		}
701 		d = Bknow.kp+N_moves[i];
702 		if( (P[d]&WNM) && (B[d]&WHITE) == 0 && ( P[d] & 0xE000 ) == 0 )
703 		{ Bknow.khung += 2; }
704 	}
705 }
706 
707 if( Totmat >= ENDMATERIAL+Q_VALUE )
708 {
709 	if( Wknow.kp%10 < FILE_E && Bknow.kp%10 > FILE_E )
710 	{
711 		Wknow.kstorm = 1; Bknow.qstorm = 1;
712 	}
713 	else
714 	if( Wknow.kp%10 > FILE_E && Bknow.kp%10 < FILE_E )
715 	{
716 		Wknow.qstorm = 1; Bknow.kstorm = 1;
717 	}
718 }
719 
720 if( Wknow.hung || Bknow.hung )
721 {
722 	int hresult = Bknow.hung - Wknow.hung;
723 	midresult += hresult;
724 	endresult += hresult;
725 #ifdef SCORING
726 	if( Scoring ) printf(" (w/b) hung pieces = %i\n",hresult);
727 #endif
728 }
729 
730 Wknow.castling = ( G[Counter].castling & 3 );
731 Bknow.castling = ( G[Counter].castling >> 2 );
732 
733 if( (P[G1]|P[F1]) & 0xFF00 ) Wknow.castling |= WSHORT;
734 if( (P[C1]|P[D1]) & 0xFF00 ) Wknow.castling |= WLONG;
735 
736 if( (P[G8]|P[F8]) & 0x00FF ) Bknow.castling |= WSHORT; /* WSHORT is correct! */
737 if( (P[C8]|P[D8]) & 0x00FF ) Bknow.castling |= WLONG;  /* We're mirroring */
738 
739 /**
740 ***   PASS 2
741 **/
742 
743 n = wn; l = wl; b = B;
744 pf = wpf; xpf = bpf;
745 know = &Wknow; xknow = &Bknow;
746 kp = Wknow.kp; xkp = Bknow.kp;
747 
748 mtrl_diff = G[Counter].mtrl-G[Counter].xmtrl;
749 if( Color == BLACK ) mtrl_diff = -mtrl_diff;
750 
751 for(;;)
752 {
753 	tdist *kdist = dist+120*kp;
754 	tdist *xkdist = dist+120*xkp;
755 
756 	int j;
757 	int mr = 0, er = 0;
758 
759 	/* bishop pair */
760 	if( know->bishopcolor == 3 )
761 	{
762 		int bb = 18 + 2*know->worsebm;
763 		mr += bb;
764 		er += bb*2;
765 #ifdef SCORING
766 		if( Scoring )
767 		{
768 		  if(l==wl) printf(" (whi) bishop pair bonus = %i\n",bb);
769 		  else      printf(" (bla) bishop pair bonus = %i\n",bb);
770 		}
771 #endif
772 	}
773 
774 	/* rooks on 7th row */
775 	/* r7r: 2 pts for rook, 1 pt for queen on 6-8th row */
776 	if( know->r7r > 1 )
777 	{
778 		if( xkp >= A8 )
779 		{ er += 12 * know->r7r; mr += 5 * know->r7r; }
780 		mr += 10 * know->r7r; er += 4 * know->r7r;
781 		if( know->r7r > 2 ) mr += know->r7r * know->r7r + 4;
782 	}
783 
784 	if( Totmat >= ENDMATERIAL )
785 	{
786 		int d = 0;
787 
788 		/*** play Pc2-c4 (black Pc7-c5) in closed games ***/
789 		if( b[D5]==BP )
790 		{
791 			if( b[C4]==WP )
792 			{	mr+=10;
793 				if( b[E6]==BP && B[D4]==WP ) mr+=10;
794 				/*** defender in stonewall must keep pressure
795 				 *** to opponent's d-pawn ****/
796 				if( b[F5]==BP ) mr+=15;
797 			}
798 			if( b[C2]==WP )
799 			{
800 				if( b[C3]!=0 ) mr -= 7;
801 				else           mr -= 3;
802 				if( b[E2]==WP || b[E3]==WP ) mr -= 5;
803 				if( b[E6]==BP || b[C6]==BP ) mr -= 4;
804 			}
805 		}
806 
807 		/*** development ***/
808 		if( b[A1] == WR && pf[FILE_A] != 0 ) d+=2;
809 		if( b[B1] == WN ) d+=5;
810 		if( b[C1] == WB ) { d+=3; if( b[B2] && b[D2] ) d+=4; }
811 		if( b[D1] == WQ ) d++;
812 		if( b[F1] == WB ) { d+=3; if( b[E2] && b[G2] ) d+=4; }
813 		if( b[G1] == WN ) d+=5;
814 		if( b[H1] == WR && pf[FILE_H] != 0 ) d+=2;
815 
816 		know->devel = d; /* maximum is 29, <10 is okay */
817 
818 		/*** central pawns ***/
819 		if( b[D4]==WP && b[E4]==WP )
820 		{
821 			if( b[E5]!=BP && b[D5]!=BP ) d = 12; else d = 6;
822 			if( b[C4]==WP || b[F4]==WP ) d += 4;
823 
824 			mr += d;
825 
826 #ifdef SCORING
827 			if( Scoring )
828 			{
829 				if(l==wl)
830 				printf( " (whi) pawn center = %i\n", d );
831 				else
832 				printf( " (bla) pawn center = %i\n", d );
833 			}
834 #endif
835 		}
836 
837 		{
838 		/*** castling ***/
839 		int cneed;
840 		d = 0;
841 		if( kp%10 < FILE_D || kp%10 > FILE_E ) cneed=0;
842 		else
843 		{
844 			cneed = 4;
845 			if( !  pf[FILE_E] ) cneed += 3;
846 			if( ! xpf[FILE_E] ) cneed += 5;
847 		}
848 
849 		switch( know->castling )
850 		{
851 		case 0:               /* both castlings possible */
852 			if( b[F1] ) d -= 2*cneed;
853 			if( b[G1] ) d -= 2*cneed;
854 			if( b[B1] ) d -= cneed;
855 			if( b[C1] ) d -= cneed;
856 			if( b[D1] ) d -= cneed;
857 		break;
858 		case WSHORT:          /* only long castling possible */
859 			d-=20;
860 			if( b[B1] ) d -= cneed;
861 			if( b[C1] ) d -= cneed;
862 			if( b[D1] ) d -= cneed;
863 		break;
864 		case WLONG:           /* only short castling possible */
865 			d-=8;
866 			if( b[F1] ) d -= 2*cneed;
867 			if( b[G1] ) d -= 2*cneed;
868 		break;
869 		case (WSHORT|WLONG):  /* castling impossible */
870 			if( kp%10 > FILE_E )
871 			{
872 			   if( b[G2]!=WP && b[G3]!=WP ) d -= 10;
873 			   if( b[H2]!=WP && b[H3]!=WP ) d -= 8;
874 			}
875 			else if( kp%10 < FILE_D )
876 			{
877 			    d -= 15;
878 			    if( b[B2]!=WP && b[B3]!=WP ) d -= 10;
879 			    if( b[A2]!=WP && b[A3]!=WP ) d -= 8;
880 			}
881 			else
882 			{ d -= 5*cneed; }
883 		break;
884 		}
885 
886 		if( Totmat < 5000 ) d /= 2;
887 
888 		mr += d;
889 
890 		}
891 
892 #ifdef SCORING
893 		if( Scoring && d!=0 )
894 		{
895 			if(l==wl)
896 			printf( " (whi) castling = %i\n", d );
897 			else
898 			printf( " (bla) castling = %i\n", d );
899 		}
900 #endif
901 	}
902 
903 	if( mtrl_diff > 0 )
904 	{
905 		int mtrl_weight = 100; /* 100% */
906 
907 		if( know->p == 0 )
908 		{
909 			/* Winning without pawns is difficult. We try
910 			 * to reduce the distance of kings. Then, if
911 			 * we are ahead a minor piece or less
912 			 * we just reduce the advantage. We ignore
913 			 * enemy pawns here - a rook against
914 			 * 3 non-advanced pawns should still win. */
915 
916 			er += 10 - 2*dist[kp*120+xkp].max;
917 
918 			if( mtrl_diff + P_VALUE*xknow->p <= N_VALUE )
919 				mtrl_weight /= 10;
920 		}
921 		else
922 		if( know->p == 1 && mtrl_diff == P_VALUE )
923 		{
924 			if( know->q || know->r ) mtrl_weight /= 2;
925 			else mtrl_weight /= 4;
926 		}
927 		else
928 		{
929 			/* trade down bonus:
930 			 * if ahead in material, trade pieces but not pawns */
931 
932 			static int pp[12] =
933 			{ 0, 1, 4, 6, 7, 8, 9, 9, 9, 9, 9, 9 };
934 
935 			int tbonus =
936 			 ( pp[know->p]
937 			 - 3*xknow->q - 2*xknow->r
938 			 - xknow->n - xknow->b ) /* -11 .. 9 */
939 			 * ( min(mtrl_diff,N_VALUE)/50 + 2 ); /* 2..9 */
940 
941 			er += tbonus; mr += tbonus;
942 		}
943 
944 		/* Opposite colored bishops in endgame lead to draw
945 		 * This also covers positions with other pieces,
946 		 * e.g. RBPP-RBP, in these cases, the material
947 		 * rebalancing is much lower. */
948 		if(   know->b == 1 && xknow->b == 1
949 		   && mtrl_diff == (know->p - xknow->p) * P_VALUE
950 		   && know->bishopcolor != know->xbishopcolor )
951 		mtrl_weight -=
952 			100 * mtrl_weight
953 			/ (    max(P_VALUE,mtrl_diff)
954 			       + 20*know->p
955 			       + 250*know->r + 400*know->n + 400*know->q );
956 
957 		mtrl_weight = 100-mtrl_weight;
958 		mr -= mtrl_diff * mtrl_weight / 100;
959 		er -= mtrl_diff * mtrl_weight / 100;
960 
961 	}
962 
963 	/*** pawn structure ***/
964 	for( i=1; i!=9; i++ ) if( pf[i] )
965 	{
966 		if( pf[i] > 1 ) /* doubled */ { mr-=5; er-=10; }
967 
968 		if( pf[i-1]==0 && pf[i+1]==0 ) /* isolated */
969 		{
970 			/* knights are strong against an isolated pawn
971 			 * since they can block it. */
972 			int pen = isofile[i]
973 			          + (2+isofile[i]) * xknow->n
974 			          + 4*know->b;
975 
976 			/* rooks are strong against an isolated pawn on
977 			 * open file */
978 			if( xpf[i]==0 && xknow->r )
979 			{
980 				int j;
981 				static const int rfip[10] =
982 				{ 0, -2, -3, -4, -5, -5, -4, -3, -2, 0 };
983 				for( j=i+20; j<H9; j+=10 ) if( b[j]==BR )
984 					pen += rfip[i];
985 				pen += (rfip[i]-2)*xknow->r;
986 			}
987 
988 			if( pf[i] > 1 ) pen = pen*pf[i] + 2*isofile[i];
989 
990 			mr += pen; er += pen;
991 #ifdef SCORING
992 			if( Scoring )
993 			{
994 				if(l==wl)
995 				printf( " (whi) isolated pawn = %i\n", pen );
996 				else
997 				printf( " (bla) isolated pawn = %i\n", pen );
998 			}
999 #endif
1000 		}
1001 	}
1002 
1003 	for( i=0; i!=n; i++ ) /* scan pieces */
1004 	{
1005 	static int sq;
1006 	sq = l[i];
1007 	switch( b[ sq ] )
1008 	{
1009 	case WP:
1010 		/* is it passed? */
1011 		for( j=sq+10; j<A8; j+=10 )
1012 		if( b[j-1]==BP || b[j]==BP || b[j+1]==BP ) goto not_passed;
1013 
1014 		{ /* yes, the pawn is passed */
1015 
1016 	/* passed pawn advancement bonus */
1017 	static const int P_advance[12] =
1018 	       {  0,  0,  0, 10, 15, 25, 40, 60, 95,  0,  0,  0 };
1019 	/* ROW:   -   -   1   2   3   4   5   6   7   8   -   -   */
1020 
1021 			int row = sq/10;
1022 			int abonus = P_advance[row];
1023 			int ppeval = abonus;
1024 
1025 			if( b[sq+10]==0 )
1026 			{
1027 				if( row==8 )
1028 				{
1029 					if(see(b,sq,sq+10)>=0)
1030 					{ ppeval+=80; abonus /= 2; }
1031 				}
1032 				else
1033 				if( row==7 && b[sq+20]==0 )
1034 				{
1035 					if( see(b,sq,sq+10)>=0
1036 					 && see(b,sq,sq+20)>=0 )
1037 					{ ppeval+=50; abonus /= 2; }
1038 				}
1039 			}
1040 			else /* blocked */
1041 			if( color(b[sq+10]) == BLACK )
1042 			{ ppeval /= 2; }
1043 			else /* blocked - reserve blocking square */
1044 			if( color(b[sq+20]) == BLACK )
1045 			{ ppeval -= ppeval/4; }
1046 
1047 			/* covered or a member of a phalanx */
1048 			if( b[sq-9]==WP || b[sq-11]==WP
1049 			 || b[sq-1]==WP || b[sq+1]==WP )
1050 			{ ppeval += abonus; }
1051 
1052 			/* rook behind - support or brake */
1053 			for( j=sq-10;
1054 			     b[j]==0 || b[j]==WR || b[j]==BR
1055 			             || b[j]==BQ || b[j]==WQ;
1056 			     j-=10 )
1057 				if( b[j] == WR )
1058 				{ ppeval += abonus/2 + 4; }
1059 				else if( b[j] == BR )
1060 				{ ppeval -= abonus/2 + 9; }
1061 
1062 			if( Totmat < ENDMATERIAL )
1063 			{
1064 				/* distance from enemy king */
1065 				int difdis
1066 				= 2*xkdist[sq+10].max - ( 9 - row );
1067 				if( difdis >= 0 ) ppeval += 8+4*difdis;
1068 
1069 				/* king supports the pawn */
1070 				if( kdist[sq+10].max < 2 ) ppeval += abonus;
1071 			}
1072 
1073 			er += ppeval;
1074 			mr += ppeval/2;
1075 
1076 #ifdef SCORING
1077 			if( Scoring && ppeval != 0 )
1078 			{
1079 				if(l==wl) printf(" (whi) ");
1080 				else printf(" (bla) ");
1081 				printf("passed pawn = %i ... %i\n",
1082 				ppeval/2, ppeval );
1083 			}
1084 #endif
1085 		}
1086 
1087 		not_passed:;
1088 
1089 		/* backward */
1090 		if(     sq <= H3
1091 		     && ( b[sq+19]==BP || b[sq+21]==BP )
1092 		     && b[sq+10] != BP
1093 		     && b[sq-1]  != WP
1094 		     && b[sq+1]  != WP
1095 		     && b[sq-9]  != WP
1096 		     && b[sq-11] != WP    )
1097 		{
1098 			int pen = 0;
1099 
1100 /*
1101 printboard(); printf("%02i",sq); getchar();
1102 */
1103 			if( xpf[sq%10]==0 && xknow->r )
1104 			{
1105 				int j;
1106 				for( j=sq%10+20; j<H9; j+=10 ) if( b[j]==BR )
1107 					pen += -2 + isofile[sq%10]/2;
1108 				pen += isofile[sq%10]*xknow->r;
1109 			}
1110 
1111 			mr += isofile[ sq%10 ] + pen/2;
1112 			er += -15 + pen;
1113 #ifdef SCORING
1114 			if( Scoring && pen != 0 )
1115 			{
1116 				if(l==wl) printf(" (whi) ");
1117 				else printf(" (bla) ");
1118 				printf("backward pawn = %i ... %i\n",
1119 				isofile[ sq%10 ] + pen/2, -15 + pen );
1120 			}
1121 #endif
1122 		}
1123 
1124 		/* cannot move */
1125 		{
1126 			int cannotmove = 0;
1127 
1128 			if( b[ sq + 10 ] != 0 )
1129 			{
1130 				mr -= (12-sq/10); er -= (12-sq/10);
1131 				if( sq == E2 || sq == D2 )
1132 				{ mr -= 10; er -= 8; }
1133 
1134 				if( b[ sq + 10 ] )
1135 				{	/* blocked pawn is an attack brake */
1136 					if( know->kstorm && sq%10 > FILE_E )
1137 						mr -= 12;
1138 					else
1139 					if( know->qstorm && sq%10 < FILE_D )
1140 						mr -= 12;
1141 
1142 					if( b[sq+10]==BP
1143 					 && pf[sq%10-1]==0
1144 					 && pf[sq%10+1]==0 )
1145 					/* this pawn was already penalized
1146 					 * as isolated. But this is a pawn
1147 					 * ram - blocked by enemy pawn
1148 					 * face to face. It is not so
1149 					 * critical; take back a small part
1150 					 * of the penalty. *********/
1151 					{ mr+=5; er+=8; }
1152 				}
1153 
1154 				cannotmove = 1;
1155 			}
1156 			else
1157 			{
1158 				int ata=0;
1159 				if( b[ sq - 1 ] == WP ) ata++;
1160 				if( b[ sq + 1 ] == WP ) ata++;
1161 				if( b[ sq + 9 ] == BP ) ata--;
1162 				if( b[ sq +11 ] == BP ) ata--;
1163 
1164 				if( ata < 1 )
1165 				{
1166 					mr += -4+ata; er += -8+2*ata;
1167 					cannotmove = 1;
1168 				}
1169 			}
1170 
1171 			if( cannotmove )
1172 			{
1173 				int p = 1 + (b[sq+10]==BP);
1174 
1175 				if( Totmat < 1500 ) er -= 6*p;
1176 
1177 				/* penalize friendly bishop that stands
1178 				 * on a square of this color */
1179 				if( sqcolor[sq] & know->bishopcolor )
1180 				{
1181 					if(    sq==E4 || sq==D4
1182 					    || sq==E3 || sq==D3   )
1183 					{ er-=7*p; mr-=5*p; }
1184 					else
1185 					{ er-=5*p; mr-=4*p; }
1186 				}
1187 			}
1188 		}
1189 
1190 		/* pawn phalanx or chain, both midgame & endgame */
1191 		if( b[sq-1]==WP || b[sq-9]==WP || b[sq-11]==WP )
1192 		{
1193 			if( sq >= A4 )
1194 			{ mr += 6; er += 4; }
1195 			else
1196 			{ mr += 2; er += 2; }
1197 		}
1198 
1199 		if( Totmat >= ENDMATERIAL )
1200 		{
1201 			/*** outpost "spacemaker" pawn in midgame */
1202 			if( outpost[sq] )
1203 			{
1204 				int o = outpost[sq] + (sq==D4);
1205 				if( b[sq-1]==WP ) mr += 2*o;
1206 				if( b[sq+1]==WP ) mr += 2*o;
1207 				if( b[sq-9]==WP || b[sq-11]==WP ) mr += 3*o;
1208 				if( b[sq+9]==BP || b[sq+11]==BP ) mr -= 3*o;
1209 				if(b==B) mr += (P[sq]&0x00FF)/0x0020 *  5*o;
1210 				else     mr += (P[sq]>>8)    /0x0020 *  5*o;
1211 			}
1212 
1213 			/*** storm */
1214 			if( know->qstorm ) mr += qstormtable[sq];
1215 			else if( know->kstorm ) mr += kstormtable[sq];
1216 
1217 			/*** `table' bonus */
1218 			mr += pmpb[sq];
1219 
1220 			/*** don't play a4/b4/g4/h4 in opening */
1221 			if( sq >= A4 )
1222 			{
1223 			  if( know->castling == (WSHORT|WLONG) )
1224 			  {
1225 			    if( kp%10 > FILE_E )
1226 			    {
1227 				    if( sq%10 > FILE_F )
1228 					    mr -= 10;
1229 			    }
1230 			    else
1231 			    {
1232 				    if( kp%10 < FILE_D && sq%10 < FILE_C )
1233 				      mr -= 8;
1234 			    }
1235 			  }
1236 			  else
1237 			  {
1238                             if( sq%10 < 3 )
1239 				    mr -= know->devel;
1240                             else if( sq%10 > 6 ) mr -= 4+know->devel;
1241 			  }
1242 			}
1243 		}
1244 
1245 	break;
1246 	case WK:
1247 		er += kepb[sq];
1248 
1249 		if( Totmat >= ENDMATERIAL )
1250 		{
1251 			mr += kmpb[sq];
1252 			/* SHELTER */
1253 
1254 			switch( b[sq-1] )
1255 			{ case WP: mr += 3; know->kshield++; break;
1256 		  	  case WB: mr += 2; know->kshield++;
1257 			           if( b[sq+9]==WP ) mr += 2; }
1258 
1259 			switch( b[sq+1] )
1260 			{ case WP: mr += 3; know->kshield++; break;
1261 		  	  case WB: mr += 2; know->kshield++;
1262 			           if( b[sq+11]==WP ) mr += 2; }
1263 
1264 			switch( b[sq+10] )
1265 			{ case WP: mr += 6; know->kshield+=2;
1266 				if( b[sq+9]==WP || b[sq+11]==WP )
1267 				{ mr += 3; know->kshield+=2; }
1268 		  	  break;
1269 		  	  case WB: mr += 2; know->kshield++;
1270 				if( b[sq+9]==WP || b[sq+11]==WP )
1271 				{
1272 				  know->kshield++;
1273 				  if( b[sq+20]==WP )
1274 				  { mr += 2; know->kshield++; }
1275 				}
1276 			}
1277 
1278 			if( b[sq+20]==WP )
1279 			{ know->kshield++;
1280 			  if( b[sq+19]==WP || b[sq+21]==WP )
1281 			    know->kshield++;
1282 			}
1283 
1284 			if( b[sq+9]==WP ) { know->kshield++; mr += 4; }
1285 
1286 			if( b[sq+11]==WP ) { know->kshield++; mr += 4; }
1287 
1288 			if( xknow->q || xknow->r >= 2 )
1289 			{	int file = sq%10;
1290 			  	if( pf[file] == 0 ) mr -= 6;
1291 				if( pf[file-1] == 0 ) mr -= 3;
1292 				if( pf[file+1] == 0 ) mr -= 3;
1293 
1294 				if( file > FILE_C && file < FILE_F )
1295 				{ /* open center makes us cry */
1296 					if( xpf[file] == 0 )
1297 					{
1298 					  if(pf[file]==0) mr -= 8;
1299 					  else            mr -= 5;
1300 					}
1301 				}
1302 			}
1303 		}
1304 
1305 	break;
1306 	case WR:
1307 	{
1308 		int j;
1309 		int r;
1310 		int mrr = 0; int err = 0;
1311 		static int frb[12] =
1312 			{ 0, 0, -5, -5, -2, 0, 2, 4, 8, 10, 10, 10 };
1313 
1314 		for( j = sq+10; b[j]==0 || b[j]>=ROOK; j += 10 ) {};
1315 
1316 		r=j/10;		/* 2...10 */
1317 
1318 		if( b[j]==WP && b[j+10] ) r--;
1319 
1320 		mrr = err = frb[r];
1321 
1322 		if( xpf[sq%10] != 0 ) mrr -= 5;
1323 
1324 		if( pf[sq%10] != 0 )
1325 		{
1326 		  mrr -= 5;
1327 		  if( b[j]==WP )
1328 		  {
1329 			/* avoid pseudocastling, that's moving king
1330 			 * e1-f1-g1, satisfying king safety but blocking
1331 			 * the rook undeveloped */
1332 			if( sq==H1 || sq==H2 || sq==G1 )
1333 			if( kp==F1 || kp==G1 )
1334 			{ mrr -= 33; err -= 33; }
1335 		  }
1336 		}
1337 
1338 		mrr += rmpb[sq];
1339 
1340 		mr += mrr; er += err;
1341 #ifdef SCORING
1342 		if( Scoring )
1343 		{
1344 			if(l==wl)
1345 			printf( " (whi) rook = %i,%i\n", mrr, err );
1346 			else
1347 			printf( " (bla) rook = %i,%i\n", mrr, err );
1348 		}
1349 #endif
1350 	}
1351 	break;
1352 	case WB:
1353 		if(    b[sq+10]==BP
1354 		    || (    outpost[sq]
1355 		         && ( b[sq-9]==WP || b[sq-11]==WP )
1356 		       )
1357 		  )
1358 		{
1359 			int j;
1360 			int bonus;
1361 
1362 			for( j=sq+9; j<A8; j+=10 )
1363 			if( b[j]==BP || b[j+2]==BP ) goto no_bishop_outpost;
1364 
1365 				bonus = 0;
1366 				if( b[sq+10]==BP ) bonus += 12*xpf[sq%10];
1367 				if( b[sq+20]==BP ) bonus += 8;
1368 				if( outpost[sq] ) bonus += 10 + 4*outpost[sq];
1369 				if( b[sq-9]==WP ) bonus += 10;
1370 				if( b[sq-11]==WP ) bonus += 10;
1371 
1372 			mr += bonus; er += bonus/2;
1373 
1374 #ifdef SCORING
1375 			if( Scoring )
1376 			{
1377 				if(l==wl)
1378 				printf( " (whi) strong bishop = %i\n", bonus );
1379 				else
1380 				printf( " (bla) strong bishop = %i\n", bonus );
1381 			}
1382 #endif
1383 
1384 			no_bishop_outpost:;
1385 		}
1386 
1387 		/*** trapped bishop - it's not worth the pawn ***/
1388 		if( sq==A7 )
1389 		{
1390 			if( b[B6] == BP && see(b,A7,B6) < -200 )
1391 			{ mr -= 140; er -= 140; }
1392 		}
1393 		else
1394 		if( sq==H7 )
1395 		{
1396 			if( b[G6] == BP && see(b,H7,G6) < -200 )
1397 			{ mr -= 140; er -= 140; }
1398 		}
1399 
1400 		if( know->qstorm || know->kstorm )
1401 		{
1402 			static int bon[16] =
1403 			{ 8,  8,  8,  7,  5,  3,  1,  0,
1404 			 -1, -2, -3, -4, -5, -6, -7, -8 };
1405 			mr += bon[ xkdist[sq].diag ];
1406 		}
1407 
1408 		mr += bmpb[sq]; er += bepb[sq];
1409 	break;
1410 	case WN:
1411 		if(    b[sq+10]==BP
1412 		    || (    outpost[sq]
1413 		         && ( b[sq-9]==WP || b[sq-11]==WP )
1414 		       )
1415 		  )
1416 		{
1417 			int j;
1418 			int bonus;
1419 
1420 			for( j=sq+9; j<A8; j+=10 )
1421 			if( b[j]==BP || b[j+2]==BP ) goto no_knight_outpost;
1422 
1423 				bonus = 0;
1424 				if( b[sq+10]==BP ) bonus += 15*xpf[sq%10];
1425 				if( outpost[sq] ) bonus += 8 + 5*outpost[sq];
1426 				if( b[sq-9]==WP ) bonus += 10;
1427 				if( b[sq-11]==WP ) bonus += 10;
1428 
1429 				/*** Look at opponent's minor pieces:
1430 				 *** is it possible to attack the knight
1431 				 *** with a minor piece? ******************/
1432 				if( sq>=A4 && sq%10>=FILE_B && sq%10<=FILE_G
1433 				 && xknow->n == 0
1434 				 && ( know->xbishopcolor & sqcolor[sq] ) == 0
1435 				 && ( b[sq-9]==WP || b[sq-11]==WP )
1436 				  )
1437 				{ mr+=8+2*outpost[sq]; er+=15+4*outpost[sq]; }
1438 
1439 			mr += bonus; er += bonus/2;
1440 
1441 #ifdef SCORING
1442 			if( Scoring )
1443 			{
1444 				if(l==wl)
1445 				printf( " (whi) strong knight = %i\n", bonus );
1446 				else
1447 				printf( " (bla) strong knight = %i\n", bonus );
1448 			}
1449 #endif
1450 
1451 			no_knight_outpost:;
1452 		}
1453 
1454 		/*** trapped knight ***/
1455 		if( sq==A8 )
1456 		{
1457 			if( b[A7] == BP && see(b,A8,C7) < -200 )
1458 			{ mr -= 140; er -= 140; }
1459 		}
1460 		else if( sq==H8 )
1461 		{
1462 			if( b[H7] == BP && see(b,H8,F7) < -200 )
1463 			{ mr -= 140; er -= 140; }
1464 		}
1465 		else if( sq==A7 )
1466 		{
1467 			if( b[B7]==BP )
1468 			if( b[A6]==BP || b[C6]==BP )
1469 			{ mr -= 45; er -= 45; }
1470 		}
1471 		else if( sq==H7 )
1472 		{
1473 			if( b[G7]==BP )
1474 			if( b[H6]==BP || b[F6]==BP )
1475 			{ mr -= 45; er -= 45; }
1476 		}
1477 
1478 		mr += nmpb[sq];
1479 
1480 		if( know->qstorm || know->kstorm )
1481 		{
1482 			static int bon[8] =
1483 				{ 8, /* 1-st entry is never used */
1484 				     8, 8, 5, 2, -1, -4, -7 };
1485 			mr += bon[ xkdist[sq].max ];
1486 		}
1487 
1488 		if( Totmat < ENDMATERIAL )
1489 		{
1490 			/* look at the leftmost and righmost pawn file -
1491 			 * large distance between these files is bad
1492 			 * for knight in endgame */
1493 			int d =
1494 			max(Wknow.rpf,Bknow.rpf)-min(Wknow.lpf,Bknow.lpf);
1495 			if(d>3)  /* look at nonpawn material */
1496 			{ if( Totmat-P_VALUE*(Wknow.p+Bknow.p)
1497 			      <= N_VALUE+B_VALUE ) er-=5*d;
1498 			  else                     er-=3*d;
1499 			}
1500 		}
1501 
1502 		er += nepb[sq];
1503 	break;
1504 	case WQ:
1505 		/* penalize early queen activity, */
1506 		/* 10 to 31 pts., depending on development */
1507 		if( know->devel >= 8 )
1508 		if( sq >= A3 ) mr -= (2+know->devel);
1509 
1510 		/* let's play aggressively - */
1511 		/* penalize for distance from enemy king */
1512 		/* active queen is very strong; especially in endgame */
1513 		{
1514 			static int bon[16] =
1515 			{ 10, 10, 10,  9,  7,  5,  3,  0,
1516 			  -2, -4, -8, -8, -8, -8, -8, -8 };
1517 			int qb;
1518 
1519 			if( !( B==b ? (P[sq]>>8) : (P[Th[sq]]&0x00FF) ) )
1520 				qb = bon[ xkdist[sq].taxi ];
1521 			else	qb = -8;
1522 
1523 			if( know->qstorm || know->kstorm ) mr += 2*qb;
1524 			else mr += qb;
1525 			er += 3*qb;
1526 		}
1527 
1528 		mr += qmpb[sq];
1529 
1530 	break;
1531 	}
1532 	}
1533 
1534 	if( l == wl )
1535 	{
1536 		midresult += mr; endresult += er;
1537 		l = bl; n = bn; b = mB;
1538 		pf = bpf; xpf = wpf;
1539 		know = &Bknow; xknow = &Wknow;
1540 		kp = Th[Bknow.kp]; xkp = Th[Wknow.kp];
1541 		mtrl_diff = -mtrl_diff;
1542 	}
1543 	else
1544 	{
1545 		midresult -= mr; endresult -= er;
1546 		break;
1547 	}
1548 }
1549 
1550 
1551 /*********** Development */
1552 
1553 if( Totmat >= ENDMATERIAL )
1554 {
1555 
1556 if( Color == WHITE ) { if( Wknow.devel>1 && Wknow.hung<10 ) Wknow.devel-=2; }
1557 else                 { if( Bknow.devel>1 && Bknow.hung<10 ) Bknow.devel-=2; }
1558 
1559 {
1560 	int d = Bknow.devel-Wknow.devel;
1561 	d = 4*d + d*max(Wknow.devel,Bknow.devel)/8;
1562 
1563 	midresult += d;
1564 
1565 #ifdef SCORING
1566 	if( Scoring )
1567 	{
1568 		printf(" (   ) %i %i\n", Bknow.devel, Wknow.devel );
1569 		if( d!=0 ) printf( " (w/b) development = %i\n", d );
1570 	}
1571 #endif
1572 }
1573 
1574 }
1575 else  /* outside passed pawn */
1576 {
1577 	int whas=0, bhas=0;
1578 
1579 	extern int Oppb[];  /* outside passed pawn bonus, see endgame.c */
1580 
1581 	/* white/black left/right -most pawn file (0-10) */
1582 	int wrm = Wknow.rpf;
1583 	int wlm = Wknow.lpf;
1584 	int brm = Bknow.rpf;
1585 	int blm = Bknow.lpf;
1586 
1587 	/*** look at leftmost pawn ***/
1588 	if( wlm+1<blm && wrm>wlm+3 ) whas=blm-wlm;
1589 	else
1590 	if( blm+1<wlm && brm>blm+3 ) bhas=wlm-blm;
1591 
1592 	/*** look at rightmost pawn ***/
1593 	if( wrm-1>brm && wrm>wlm+3 ) whas+=wrm-brm;
1594 	else
1595 	if( brm-1>wrm && brm>blm+3 ) bhas+=brm-wrm;
1596 
1597 	endresult +=
1598 		(Oppb[whas]-Oppb[bhas]) * Q_VALUE
1599 		/ (Q_VALUE+Totmat-P_VALUE*(Wknow.p+Bknow.p));
1600 }
1601 
1602 midresult += (Bknow.khung-Wknow.khung) * 2;
1603 
1604 /*********** King danger */
1605 Wknow.khung -= Wknow.kshield/3;
1606 Bknow.khung -= Bknow.kshield/3;
1607 
1608 #define KSAFETY 1
1609 if( Wknow.khung > 1 )
1610 {
1611 	midresult -= Wknow.khung * Wknow.khung * KSAFETY;
1612 #ifdef SCORING
1613 	if( Scoring )
1614 	printf( " (whi) king safety = %i\n", Wknow.khung * Wknow.khung * -KSAFETY );
1615 #endif
1616 }
1617 
1618 if( Bknow.khung > 1 )
1619 {
1620 	midresult += Bknow.khung * Bknow.khung * KSAFETY;
1621 #ifdef SCORING
1622 	if( Scoring )
1623 	printf( " (bla) king safety = %i\n", Bknow.khung * Bknow.khung * -KSAFETY );
1624 #endif
1625 }
1626 
1627 Wknow.prune = ( Wknow.hung < 10 && Wknow.khung < 2 );
1628 Bknow.prune = ( Bknow.hung < 10 && Bknow.khung < 2 );
1629 
1630 if( Totmat < ENDMATERIAL ) result += endresult;
1631 else if( Totmat > MIDMATERIAL ) result += midresult;
1632 else result += (Totmat-ENDMATERIAL) * midresult / (MIDMATERIAL-ENDMATERIAL)
1633             + (MIDMATERIAL-Totmat) * endresult / (MIDMATERIAL-ENDMATERIAL);
1634 
1635 #define TEMPO 4
1636 
1637 if( Color == WHITE ) return result+TEMPO;
1638 else return -result+TEMPO;
1639 
1640 }
1641 
1642