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