Initial commit based on GNU Shogi 1.2 patchlevel 3.
[gnushogi.git] / src / eval.c
blob7d6a176c276bb451b1a6de57280bb1f56bca5e74
1 /*
2 * eval.c - C source for GNU SHOGI
4 * Copyright (c) 1993, 1994, 1995 Matthias Mutz
6 * GNU SHOGI is based on GNU CHESS
8 * Copyright (c) 1988,1989,1990 John Stanback
9 * Copyright (c) 1992 Free Software Foundation
11 * This file is part of GNU SHOGI.
13 * GNU Shogi is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 1, or (at your option)
16 * any later version.
18 * GNU Shogi is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with GNU Shogi; see the file COPYING. If not, write to
25 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
28 #include "gnushogi.h"
30 #include "pattern.h"
33 /* Hash table for preventing multiple scoring of the same position */
35 int EADD = 0; /* number of writes to the cache table */
36 int EGET = 0; /* number of hits to the cache table */
37 int PUTVAR = false; /* shall the current scoring be cached? */
40 /* Pieces and colors of initial board setup */
42 const small_short Stboard[NO_SQUARES] =
43 {lance,knight,silver,gold,king,gold,silver,knight,lance,
44 0, bishop, 0, 0, 0, 0, 0, rook, 0,
45 pawn, pawn, pawn, pawn, pawn, pawn, pawn, pawn, pawn,
46 0, 0, 0, 0, 0, 0, 0, 0, 0,
47 0, 0, 0, 0, 0, 0, 0, 0, 0,
48 0, 0, 0, 0, 0, 0, 0, 0, 0,
49 pawn, pawn, pawn, pawn, pawn, pawn, pawn, pawn, pawn,
50 0, rook, 0, 0, 0, 0, 0, bishop, 0,
51 lance,knight,silver,gold,king,gold,silver,knight,lance};
54 const small_short Stcolor[NO_SQUARES] =
55 {black, black, black, black, black, black, black, black, black,
56 neutral, black, neutral, neutral, neutral, neutral, neutral, black, neutral,
57 black, black, black, black, black, black, black, black, black,
58 neutral, neutral, neutral, neutral, neutral, neutral, neutral, neutral, neutral,
59 neutral, neutral, neutral, neutral, neutral, neutral, neutral, neutral, neutral,
60 neutral, neutral, neutral, neutral, neutral, neutral, neutral, neutral, neutral,
61 white, white, white, white, white, white, white, white, white,
62 neutral, white, neutral, neutral, neutral, neutral, neutral, white, neutral,
63 white, white, white, white, white, white, white, white, white};
66 /* Actual pieces and colors */
68 small_short board[NO_SQUARES], color[NO_SQUARES];
71 /* relative piece values at the beginning of main stages */
73 #define MAIN_STAGES 4
75 static small_short ispvalue[NO_PIECES][MAIN_STAGES] =
76 { 0, 35, 70, 99, /* main stage borders */
77 /* ------------------- */
78 7, 7, 8, 10, /* Pawn */
79 20, 35, 45, 60, /* Lance */
80 20, 35, 45, 60, /* Knight */
81 35, 40, 60, 80, /* Silver */
82 35, 50, 65, 80, /* Gold */
83 90, 90, 90, 90, /* Bishop */
84 95, 95, 95, 95, /* Rook */
85 15, 25, 40, 65, /* promoted Pawn */
86 25, 45, 55, 65, /* promoted Lance */
87 25, 45, 55, 65, /* promoted Knight */
88 35, 55, 75, 75, /* promoted Silver */
89 99, 99, 99, 99, /* promoted Bishop */
90 97, 97, 99, 99, /* promoted Rook */
91 100, 100, 100, 100, /* King */
94 /* Features and Weights */
96 #define ATAKD 0
97 #define HUNGP 1
98 #define HUNGX 2
99 #define CNTRL5TH 3
100 #define HOLES 4
101 #define PCASTLE 5
102 #define PATTACK 6
103 #define CTRLK 7
104 #define PROTECT 8
105 #define HCLSD 9
106 #define PINVAL 10
107 #define XRAY 11
108 #define OPENWRONG 12
109 #define SEED 13
110 #define LOOSE 14
111 #define MOBILITY 15
112 #define TARGET 16
113 #define KSFTY 17
114 #define HOPN 18
115 #define PROMD 19
116 #define KINGOD 20
117 #define PWNDROP 21
118 #define DFFDROP 22
119 #define FCLATTACK 23
120 #define KNGATTACK 24
121 #define KNGPROTECT 25
122 #define DNGLPC 26
123 #define LSATTACK 27
124 #define NIHATTACK 28
125 #define COHESION 29
126 #define OPPDROP 30
128 static small_short weight[NO_FEATURES+1][MAIN_STAGES+2] =
129 { 80, 100, 100, 40, 10, 15, /* ATAKD */
130 80, 100, 100, 50, 14, 10, /* HUNGP */
131 80, 100, 100, 50, 18, 12, /* HUNGX */
132 100, 50, 0, 0, 2, 1, /* CNTRL5TH */
133 100, 100, 60, 10, 4, 2, /* HOLES */
134 100, 50, 0, 0, 14, 7, /* PCASTLE */
135 100, 50, 0, 0, 6, 12, /* PATTACK */
136 10, 40, 70, 100, 10, 15, /* CTRLK */
137 100, 80, 50, 40, 2, 1, /* PROTECT */
138 40, 100, 40, 5, 4, 4, /* HCLSD */
139 80, 100, 80, 30, 10, 15, /* PINVAL */
140 80, 100, 60, 15, 6, 10, /* XRAY */
141 100, 50, 0, 0, 15, 15, /* OPENWRONG */
142 0, 40, 70, 100, 8, 12, /* SEED */
143 50, 100, 80, 20, 5, 3, /* LOOSE */
144 50, 100, 80, 50,100,100, /* MOBILITY (%) */
145 50, 100, 80, 50, 4, 8, /* TARGET */
146 50, 40, 100, 80, 8, 4, /* KSFTY */
147 80, 100, 60, 20, 5, 5, /* HOPN */
148 20, 40, 80, 100, 3, 6, /* PROMD */
149 20, 40, 80, 100, 4, 1, /* KINGOD */
150 5, 40, 100, 50, 0, 4, /* PWNDROP */
151 0, 20, 80, 100, 0, 4, /* DFFDROP */
152 20, 50, 100, 80, 0, 4, /* FCLATTACK */
153 0, 20, 80, 100, 0, 8, /* KNGATTACK */
154 40, 80, 100, 80, 6, 0, /* KNGPROTECT */
155 50, 100, 60, 10, 0, 8, /* DNGPC */
156 30, 100, 60, 5, 0, 6, /* LSATTACK */
157 0, 50, 80, 100, 0, 8, /* NIHATTACK */
158 50, 100, 80, 60, 8, 0, /* COHESION */
159 100, 100, 80, 60, 4, 4, /* OPPDROP */
161 short ADVNCM[NO_PIECES];
163 /* distance to enemy king */
164 static const EnemyKingDistanceBonus[10] =
165 {0, 6, 4, -1, -3, -4, -6, -8, -10, -12};
167 /* distance to own king */
168 static const OwnKingDistanceBonus[10] =
169 {0, 5, 2, 1, 0, -1, -2, -3, -4, -5};
171 /* distance to promotion zone */
172 static const PromotionZoneDistanceBonus[NO_ROWS] =
173 {0, 0, 0, 0, 2, 6, 6, 8, 8};
175 #define MAX_BMBLTY 20
176 #define MAX_RMBLTY 20
177 #define MAX_LMBLTY 8
179 /* Bishop mobility bonus indexed by # reachable squares */
180 static const short BMBLTY[MAX_BMBLTY] =
181 {0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 14, 14, 16, 16, 16, 16};
183 /* Rook mobility bonus indexed by # reachable squares */
184 static const short RMBLTY[MAX_RMBLTY] =
185 {0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 14, 14, 16, 16, 16, 16};
187 /* Lance mobility bonus indexed by # reachable squares */
188 static const short LMBLTY[MAX_LMBLTY] =
189 {0, 0, 0, 0, 4, 6, 8, 10};
191 static const short MBLTY[NO_PIECES] =
192 {0, 2, 1, 10, 5, 5, 1, 1, 5, 5, 5, 5, 1, 1, 4};
194 static const short KTHRT[36] =
195 {0, -8, -20, -36, -52, -68, -80, -80, -80, -80, -80, -80,
196 -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80,
197 -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80};
199 static small_short fvalue[2][NO_FEATURES];
201 long int atak[2][NO_SQUARES]; /* threats to squares */
202 small_short sseed[NO_SQUARES]; /* square occupied by a seed piece? */
204 struct signature threats_signature[2] = /* statistics valid for position ... */
205 {-1, -1, -1, -1}; /* atak and sseed available */
207 small_short starget[2][NO_SQUARES]; /* significance as a target for a side of a square */
208 small_short sloose[NO_SQUARES]; /* square occupied by a loose piece? */
209 small_short shole[NO_SQUARES]; /* empty square a hole? */
210 small_short shung[NO_SQUARES]; /* hung piece? */
212 struct signature squares_signature = /* statistics valid for position ... */
213 {0, 0}; /* starget, sloose, shole, shung available */
215 short target[2], seed[2], loose[2], hole[2];
217 short captured[2]; /* number of captured pieces */
218 short dcaptured[2]; /* different types of captured pieces */
220 small_short Kdist[2][NO_SQUARES]; /* distance to king */
222 short MAXADIST, MAXCDIST; /* maximum half move distance to pattern */
224 char GameType[2] = {UNKNOWN,UNKNOWN}; /* choosen game type of each side */
227 static short attack_opening_sequence[2]; /* current castle patterns */
228 static short castle_opening_sequence[2]; /* current attack formations */
230 static small_short Mpawn[2][NO_SQUARES];
231 static small_short Msilver[2][NO_SQUARES];
232 static small_short Mgold[2][NO_SQUARES];
233 static small_short Mking[2][NO_SQUARES];
234 static small_short Mlance[2][NO_SQUARES];
235 static small_short Mknight[2][NO_SQUARES];
236 static small_short Mbishop[2][NO_SQUARES];
237 static small_short Mrook[2][NO_SQUARES];
239 static Mpiece_array Mpawn, Mlance, Mknight, Msilver, Mgold,
240 Mbishop, Mrook, Mking;
242 Mpiece_array *Mpiece[NO_PIECES] =
243 { NULL, &Mpawn, &Mlance, &Mknight, &Msilver, &Mgold, &Mbishop, &Mrook,
244 &Mgold, &Mgold, &Mgold, &Mgold, &Mbishop, &Mrook, &Mking };
247 static short c1, c2;
249 static small_short *PC1, *PC2;
251 static small_short *fv1;
253 static long *atk1, *atk2;
255 static long a1, a2;
258 #define csquare(side,sq) ((side==black)?sq:(NO_SQUARES_1-sq))
259 #define crow(side,sq) row(csquare(side,sq))
260 #define ccolumn(side,sq) column(csquare(side,sq))
262 inline static short on_csquare(short side,short piece,short square)
263 { short sq;
264 return(board[sq=csquare(side,square)]==piece && color[sq]==side);
267 inline static short on_column(short side,short piece,short c)
268 { short sq;
269 for (sq = c; sq < NO_SQUARES; sq+=9)
270 if (on_csquare(side,piece,sq))
271 return(true);
272 return(false);
275 #define empty_csquare(side,square)\
276 (board[csquare(side,square)]==no_piece)
278 inline static short on_left_side(short side,short piece)
279 { short c;
280 for (c=0; c<4; c++)
281 if (on_column(side,piece,c))
282 return(true);
283 return(false);
286 inline static short on_right_side(short side,short piece)
287 { short c;
288 for (c=5; c<NO_COLS; c++)
289 if (on_column(side,piece,c))
290 return(true);
291 return(false);
296 short pscore[2]; /* piece score for each side */
300 #if defined DEBUG8 || defined DEBUG_EVAL
303 char *PieceStr[NO_PIECES] =
304 { "no piece", "Pawn", "Lance", "Knight", "Silver", "Gold", "Bishop", "Rook",
305 "promoted Pawn", "promoted Lance", "promoted Knight", "promoted Silver",
306 "promoted Bishop", "promoted Rook", "King" };
309 #if !defined SAVE_SVALUE
311 void
312 debug_svalue (FILE *D)
314 short r, c;
316 fprintf(D, "\nSVALUE\n");
317 for (r = (NO_ROWS-1); r >= 0; r--)
319 for (c = 0; c < NO_COLS; c++)
321 short sq = (r * NO_COLS) + c;
322 fprintf(D,"%5d",svalue[sq]);
324 fprintf (D, "\n");
326 fprintf (D, "\n");
329 #endif
332 void
333 debug_table (FILE *D, small_short *table, char *s)
335 short r, c;
337 fprintf (D, "\n%s\n", s);
338 for (r = (NO_ROWS-1); r >= 0; r--)
340 for (c = 0; c < NO_COLS; c++)
342 short sq = (r * NO_COLS) + c;
343 fprintf(D,"%5d",table[sq]);
345 fprintf (D, "\n");
347 fprintf (D, "\n");
351 #endif
354 void
355 threats (short int side)
357 * Fill array atak[side][] with info about ataks to a square. Bits 16-31 are set
358 * if the piece (king..pawn) ataks the square. Bits 0-15 contain a count of
359 * total ataks to the square.
360 * Fill array sseed[] with info about occupation by a seed piece.
363 register short u, sq;
364 long int c;
365 long int *a;
366 #ifdef SAVE_NEXTPOS
367 short d;
368 #else
369 register unsigned char far *ppos, *pdir;
370 #endif
371 short i, kd, piece, xside;
372 small_short *PL;
374 if ( MatchSignature(threats_signature[side]) ) {
375 /* data valid for current positional signature */
376 return;
379 a = atak[side];
380 xside = side ^ 1;
382 array_zero (a, NO_SQUARES * sizeof(a[0]));
384 PL = PieceList[side];
385 for (i = PieceCnt[side]; i >= 0; i--)
386 { short ptyp;
387 sq = PL[i];
388 piece = board[sq];
389 ptyp = ptype[side][piece];
390 c = control[piece];
391 #ifdef SAVE_NEXTPOS
392 u = first_direction(ptyp,&d,sq);
393 #else
394 ppos = (*nextpos[ptyp])[sq];
395 pdir = (*nextdir[ptyp])[sq];
396 u = ppos[sq];
397 #endif
398 do {
399 a[u] = ((a[u]+1) | c);
400 if ( (kd = Kdist[xside][u]) < 2 ) {
401 sseed[sq] += 2 - kd;
402 seed[side]++;
404 #ifdef SAVE_NEXTPOS
405 u = ((color[u] == neutral) ? next_position(ptyp,&d,sq,u)
406 : next_direction(ptyp,&d,sq));
407 #else
408 u = ((color[u] == neutral) ? ppos[u] : pdir[u]);
409 #endif
410 } while (u != sq);
413 /* data valid for current positional signature */
414 CopySignature(threats_signature[side]);
419 * Compute the board square with nunmap offset "id".
420 * If side==white, offset is negated.
421 * inunmap[sq] is the corresponding nunmap index isq.
422 * nunmap[isq+id] computes the board square. If negative,
423 * it is outside the board.
426 static void add_target (short sq, short side, short id)
428 short isq,tsq,xside;
429 isq = inunmap[sq];
430 tsq = (side == black) ? nunmap[isq+id] : nunmap[isq-id];
431 if ( tsq >= 0 ) {
432 target[xside = side^1]++;
433 if ( atak[side][tsq] )
434 starget[xside][tsq]++; /* protected target square */
435 else
436 starget[xside][tsq]+=2; /* unprotected target square */
442 * Target squares can be vertically ahead, diagonally ahead
443 * or diagonally behind.
446 static void CheckTargetPiece (short sq, short side)
448 switch ( board[sq] ) {
449 case pawn: /* vertically ahead if unprotected */
450 if ( !atak[side][sq] )
451 add_target(sq,side,11);
452 break;
453 case king: /* diagonally and vertically ahead */
454 add_target(sq,side,10);
455 add_target(sq,side,11);
456 add_target(sq,side,12);
457 break;
458 case rook: /* diagonally ahead and behind */
459 add_target(sq,side,10);
460 add_target(sq,side,12);
461 add_target(sq,side,-10);
462 add_target(sq,side,-12);
463 break;
464 case bishop: /* vertically ahead */
465 add_target(sq,side,11);
466 break;
467 case knight: /* vertically ahead if advanced */
468 if ( sq != 1 && sq != 7 && sq != 73 && sq != 79 )
469 add_target(sq,side,11);
470 break;
476 static
477 ScoreKingOpeningFeatures (void)
479 short s = 0, sq = OwnKing, ds;
481 if ( GameType[c1] == STATIC_ROOK ) {
482 /* Malus for king on right side or fifth file */
483 short c;
484 c = 4 - ccolumn(c1,sq);
485 if ( c < 0 || (c == 0 && sq != kingP[c1]) ) {
486 s += (ds = -c - c - fv1[OPENWRONG]);
487 #ifdef DEBUG_EVAL
488 if ( debug_eval )
489 fprintf(debug_eval_file,"%d for king on right side (Static)\n",ds);
490 #endif
492 } else if ( GameType[c1] == RANGING_ROOK ) {
493 /* Malus for king on left side or fifth file */
494 short c;
495 c = 4 - ccolumn(c1,sq);
496 if ( c > 0 || (c == 0 && sq != kingP[c1]) ) {
497 s += (ds = -c - c - fv1[OPENWRONG]);
498 #ifdef DEBUG_EVAL
499 if ( debug_eval )
500 fprintf(debug_eval_file,"%d for king on left side (Ranging)\n",ds);
501 #endif
503 /* Malus for king moved before rook switch */
504 if ( sq != kingP[c1] ) {
505 if ( on_csquare(c1,rook,16) ) {
506 s += (ds = -4 * fv1[OPENWRONG]);
507 #ifdef DEBUG_EVAL
508 if ( debug_eval )
509 fprintf(debug_eval_file,"%d for king moved before rook switch (Ranging)\n",ds);
510 #endif
512 } else {
513 /* Malus for sitting king after rook switch */
514 if ( !on_csquare(c1,rook,16) ) {
515 s += (ds = -2 * fv1[OPENWRONG]);
516 #ifdef DEBUG_EVAL
517 if ( debug_eval )
518 fprintf(debug_eval_file,"%d for sitting king after rook switch (Ranging)\n",ds);
519 #endif
522 /* Malus for defending general moved before king switch to right side */
523 if ( ccolumn(c1,sq) < 6 ) {
524 if ( Mvboard[csquare(c1,5)] || Mvboard[csquare(c1,6)] ) {
525 s += (ds = -2 * fv1[OPENWRONG]);
526 #ifdef DEBUG_EVAL
527 if ( debug_eval )
528 fprintf(debug_eval_file,"%d for defending general moved before king switch (Ranging)\n",ds);
529 #endif
533 return s;
537 inline
538 static
539 ExamineSquares (void)
542 register short sq, side, piece, n;
544 if ( MatchSignature(squares_signature) ) {
545 /* data valid for current positional signature */
546 return;
549 array_zero(shole,sizeof(shole));
550 array_zero(sloose,sizeof(sloose));
551 array_zero(starget,sizeof(starget));
553 hole[0] = hole[1] = loose[0] = loose[1] = target[0] = target[1] = 0;
555 for ( sq = 0; sq < NO_SQUARES; sq++ )
557 if ( (side = color[sq]) == neutral )
559 if ( InWhiteCamp(sq) ) {
560 if ( !atak[white][sq] ) {
561 shole[sq] = 1;
562 hole[white]++;
564 } else if ( InBlackCamp(sq) ) {
565 if ( !atak[black][sq] ) {
566 shole[sq] = 1;
567 hole[black]++;
571 else
572 { /* occupied by "side" piece */
573 if ( !atak[side][sq] ) {
574 sloose[sq] = 1;
575 loose[side]++;
577 CheckTargetPiece(sq,side);
581 #ifdef DEBUG_EVAL
582 if ( debug_eval ) {
583 char buffer[80];
584 debug_position (debug_eval_file);
585 debug_ataks (debug_eval_file, atak[black]);
586 debug_ataks (debug_eval_file, atak[white]);
587 sprintf(buffer,"%d Black and %d White SEED PIECES",seed[black],seed[white]);
588 debug_table (debug_eval_file,sseed,buffer);
589 sprintf(buffer,"%d Black TARGETS",target[black]);
590 debug_table (debug_eval_file,starget[black],buffer);
591 sprintf(buffer,"%d White TARGETS",target[white]);
592 debug_table (debug_eval_file,starget[white],buffer);
593 sprintf(buffer,"%d Black and %d White LOOSE PIECES",loose[black],loose[white]);
594 debug_table (debug_eval_file,sloose,buffer);
595 sprintf(buffer,"%d Black and %d White HOLES",hole[black], hole[white]);
596 debug_table (debug_eval_file,shole,buffer);
598 #endif
600 for ( side=black; side<=white; side++ ) {
601 captured[side] = dcaptured[side] = 0;
602 for ( piece = pawn; piece <= rook; piece++ ) {
603 if ( (n = Captured[side][piece]) != 0 ) {
604 if ( piece != pawn )
605 captured[side] += n;
606 dcaptured[side]++;
609 #ifdef DEBUG_EVAL
610 if ( debug_eval ) {
611 fprintf(debug_eval_file,"%s captured=%d dcaptured=%d\n",
612 ColorStr[side],captured[side], dcaptured[side]);
614 #endif
617 /* Data valid for current positional signature */
618 CopySignature(squares_signature);
623 /* ............ POSITIONAL EVALUATION ROUTINES ............ */
626 * Inputs are:
627 * mtl[side] - value of all material
628 * hung[side] - count of hung pieces
629 * Tscore[ply] - search tree score for ply ply
630 * Pscore[ply] - positional score for ply ply
631 * INCscore - bonus score or penalty for certain moves
632 * Sdepth - search goal depth
633 * xwndw - evaluation window about alpha/beta
634 * EWNDW - second evaluation window about alpha/beta
635 * ChkFlag[ply]- checking piece at level ply or 0 if no check
636 * TesujiFlag[ply]- 1 if tesuji move at level ply or 0 if no tesuji
637 * PC1[column] - # of my pawns in this column
638 * PC2[column] - # of opponents pawns in column
639 * PieceCnt[side] - just what it says
645 evaluate (register short int side,
646 register short int ply,
647 register short int alpha,
648 register short int beta,
649 short int INCscore,
650 short int *InChk, /* output Check flag */
651 short int *blockable) /* king threat blockable */
654 * Compute an estimate of the score by adding the positional score from the
655 * previous ply to the material difference. If this score falls inside a
656 * window which is 180 points wider than the alpha-beta window (or within a
657 * 50 point window during quiescence search) call ScorePosition() to
658 * determine a score, otherwise return the estimated score.
659 * "side" has to moved.
663 register short evflag, xside;
664 short s, sq;
666 xside = side ^ 1;
667 s = -Pscore[ply - 1] + mtl[side] - mtl[xside] /* - INCscore */;
669 #ifdef DEBUG_EVAL
670 if ( debug_eval )
671 fprintf (debug_eval_file, "estimated score at ply %d:%d, -%d+%d-%d-%d\n",
672 ply, s, Pscore[ply-1], mtl[side], mtl[xside], INCscore );
673 #endif
675 hung[black] = hung[white] = 0;
677 /* should we use the estimete or score the position */
678 if ( (ply == 1) ||
679 (ply == Sdepth) ||
680 (ply > Sdepth && s >= (alpha - 30) && s <= (beta + 30))
681 #ifdef CACHE
682 || (use_etable && CheckEETable (side))
683 #endif
685 { short sq;
686 /* score the position */
687 #ifdef DEBUG_EVAL
688 if ( debug_eval )
689 fprintf (debug_eval_file, "do NOT use the estimete\n");
690 #endif
691 array_zero (sseed, sizeof(sseed));
693 seed[0] = seed[1] = 0;
694 threats (side);
695 if (Anyatak (side, sq=PieceList[xside][0]) && board[sq] == king) {
696 *InChk = (board[sq=PieceList[side][0]] == king) ? SqAtakd (sq, xside, blockable) : false;
697 return ((SCORE_LIMIT+1001) - ply);
699 threats (xside);
700 *InChk = (board[sq=PieceList[side][0]] == king) ? Anyatak (xside, sq) : false;
701 *blockable = true;
702 #ifndef BAREBONES
703 EvalNodes++;
704 #endif
705 if ( ply > 4 )
706 PUTVAR=true;
707 ExamineSquares();
708 s = ScorePosition (side);
709 PUTVAR = false;
711 else
713 /* use the estimate but look at check */
714 short sq;
715 #ifdef DEBUG_EVAL
716 if ( debug_eval )
717 fprintf (debug_eval_file, "use the estimete\n");
718 #endif
719 *InChk = (board[sq=PieceList[side][0]] == king) ? SqAtakd (sq, xside, blockable) : false;
720 if ( board[sq=PieceList[xside][0]] == king && SqAtakd (sq, side, blockable) ) {
721 return ((SCORE_LIMIT+1001) - ply);
725 Pscore[ply] = s - mtl[side] + mtl[xside];
726 ChkFlag[ply - 1] = ((*InChk) ? Pindex[TOsquare] : 0);
727 return (s);
731 static short value_of_weakest_attacker (long a2)
733 register short piece;
734 short min_value, v;
735 min_value = SCORE_LIMIT;
736 for ( piece = pawn; piece <= king; piece++ )
737 if ( control[piece] & a2 )
739 if ( min_value > (v = (*value)[stage][piece]) )
740 min_value = v;
742 return min_value;
746 inline
748 BRLscan (register short int sq, short int *mob)
751 * Find (promoted) Bishop, (promoted) Rook, and Lance mobility, XRAY attacks, and pins.
752 * Let BRL be the bishop, rook, or lance.
753 * Let P be the first piece (no king and no pawn) in a direction and let Q be the second
754 * piece in the same direction. If Q is an unprotected opponent's piece with
755 * bigger relative value than BRL, there is a pin if P is an opponent's piece and
756 * there is an XRAY attack if P is an own piece.
757 * Increment the hung[] array if a pin is found.
760 #ifdef SAVE_NEXTPOS
761 short d, dd;
762 #else
763 register unsigned char far *ppos, *pdir;
764 #endif
765 register short s, mobx;
766 register short u, xu, pin, ptyp, csq = column(sq);
767 short piece, upiece, xupiece, rvalue, ds;
768 small_short *Kd = Kdist[c2];
769 mobx = s = 0;
770 piece = board[sq];
772 rvalue = (*value)[stage][piece];
773 ptyp = ptype[c1][upiece = unpromoted[piece]];
774 rvalue = (*value)[stage][upiece];
775 #ifdef SAVE_NEXTPOS
776 u = first_direction(ptyp,&d,sq);
777 #else
778 ppos = (*nextpos[ptyp])[sq];
779 pdir = (*nextdir[ptyp])[sq];
780 u = ppos[sq];
781 #endif
782 pin = -1; /* start new direction */
785 if ( Kd[u] < 2 ) {
786 s += (ds = fv1[CTRLK] * (2-Kd[u]));
787 #ifdef DEBUG_EVAL
788 if ( debug_eval )
789 fprintf(debug_eval_file,"%d for threatening square %d away from enemy king\n",
790 ds, Kd[u]);
791 #endif
793 if ( (ds = starget[c1][u]) != 0 ) {
794 /* threatening a target square */
795 if ( pin < 0 || /* direct threat */
796 color[pin] == c2 ) /* pin threat */ {
797 s += (ds *= fv1[TARGET]);
798 #ifdef DEBUG_EVAL
799 if ( debug_eval )
800 fprintf(debug_eval_file,"%d for threatening target square\n",ds);
801 #endif
804 if ( (ds = shole[u]) != 0 ) {
805 /* attacking or protecting a hole */
806 s += (ds = fv1[HOLES]);
807 #ifdef DEBUG_EVAL
808 if ( debug_eval )
809 fprintf(debug_eval_file,"%d for threatening a hole\n",ds);
810 #endif
811 } else if ( InPromotionZone(c1,u) ) {
812 /* attacking a square in promotion zone */
813 s += (ds = fv1[HOLES] / 2);
814 #ifdef DEBUG_EVAL
815 if ( debug_eval )
816 fprintf(debug_eval_file,"%d for threatening promotion zone\n",ds);
817 #endif
819 if (color[u] == neutral)
821 #ifdef SAVE_NEXTPOS
822 dd = d;
823 xu = next_position(ptyp,&d,sq,u);
824 if ( xu == next_direction(ptyp,&dd,sq) )
825 pin = -1; /* oops new direction */
826 #else
827 if ((xu = ppos[u]) == pdir[u])
828 pin = -1; /* oops new direction */
829 #endif
830 u = xu;
831 mobx++;
833 else
834 { /* there is a piece in current direction */
835 if (pin < 0)
836 { /* it's the first piece in the current direction */
837 #ifdef DEBUG_EVAL
838 if ( debug_eval )
839 fprintf(debug_eval_file,
840 "first piece on square %d is an %s piece\n",
841 u, (color[u]==c1) ? "own" : "enemy");
842 #endif
843 if ( color[u] == c1 ) {
844 /* own intercepting piece in xray attack */
845 if ( upiece == lance ) {
846 /* lance xray */
847 if ( board[u] == pawn ) {
848 s += (ds = 2*fv1[PROTECT]);
849 #ifdef DEBUG_EVAL
850 if ( debug_eval )
851 fprintf(debug_eval_file,"%d for lance protecting pawn\n",ds);
852 #endif
853 } else if ( in_opening_stage ) {
854 s += (ds = -2*fv1[PROTECT]);
855 #ifdef DEBUG_EVAL
856 if ( debug_eval )
857 fprintf(debug_eval_file,"%d for lance protecting non-pawn\n",ds);
858 #endif
860 } else {
861 /* bishop or rook xray */
862 if ( upiece == bishop && board[u] == pawn && GameType[c1] == STATIC_ROOK ) {
863 s += (ds = -2*fv1[HCLSD]);
864 #ifdef DEBUG_EVAL
865 if ( debug_eval )
866 fprintf(debug_eval_file,"%d for own pawn in bishops direction\n",ds);
867 #endif
868 } else if ( upiece == rook && board[u] == lance && GameType[c1] == STATIC_ROOK && column(u) == csq) {
869 s += (ds = fv1[XRAY]);
870 #ifdef DEBUG_EVAL
871 if ( debug_eval )
872 fprintf(debug_eval_file,"%d for lance supported by rook\n",ds);
873 #endif
876 } else {
877 /* enemy's intercepting piece in pin attack */
878 if ( upiece == lance ) {
879 /* lance pin attack */
880 if ( board[u] == pawn ) {
881 s += (ds = -2*fv1[PROTECT]);
882 #ifdef DEBUG_EVAL
883 if ( debug_eval )
884 fprintf(debug_eval_file,"%d for lance attacking pawn\n",ds);
885 #endif
886 } else if ( in_opening_stage ) {
887 s += (ds = 2*fv1[PROTECT]);
888 #ifdef DEBUG_EVAL
889 if ( debug_eval )
890 fprintf(debug_eval_file,"%d for lance attacking non-pawn\n",ds);
891 #endif
893 } else {
894 /* bishop or rook pin attack */
895 if ( board[u] == pawn ) {
896 s += (ds = -fv1[HCLSD]);
897 #ifdef DEBUG_EVAL
898 if ( debug_eval )
899 fprintf(debug_eval_file,"%d for enemy pawn in bishops direction\n",ds);
900 #endif
904 #ifdef SAVE_NEXTPOS
905 dd = d;
906 xu = next_position(ptyp,&d,sq,u);
907 if ( xu != next_direction(ptyp,&dd,sq) )
908 pin = u; /* not on the edge and on to find a pin */
909 #else
910 if ((xu = ppos[u]) != pdir[u])
911 pin = u; /* not on the edge and on to find a pin */
912 #endif
913 u = xu;
915 else
917 /* it's the second piece in the current direction */
918 #ifdef DEBUG_EVAL
919 if ( debug_eval )
920 fprintf(debug_eval_file,
921 "second piece on square %d is an %s piece\n",
922 u, (color[u]==c1) ? "own" : "enemy");
923 #endif
924 if ( color[u] == c1 ) {
925 /* second piece is an own piece */
926 if ( upiece == bishop && board[u] == pawn && GameType[c1] == STATIC_ROOK ) {
927 s += (ds = -fv1[HCLSD]);
928 #ifdef DEBUG_EVAL
929 if (debug_eval )
930 fprintf(debug_eval_file,"%d for own pawn in bishops (2) direction\n",ds);
931 #endif
933 } else {
934 /* second piece is an enemy piece */
935 if ( upiece == bishop && board[u] == pawn ) {
936 s += (ds = -fv1[HCLSD]/2);
937 #ifdef DEBUG_EVAL
938 if (debug_eval )
939 fprintf(debug_eval_file,"%d for enemy pawn in bishops (2) direction\n",ds);
940 #endif
942 if ((*value)[stage][xupiece = unpromoted[board[u]]] > rvalue || atk2[u] == 0) {
943 #ifdef DEBUG_EVAL
944 if ( debug_eval )
945 fprintf(debug_eval_file,"enemy %s better than attacking %s\n",
946 PieceStr[upiece], PieceStr[xupiece]);
947 #endif
948 if (color[pin] == c2) {
949 if ( xupiece == king && in_endgame_stage ) {
950 s += (ds = 2*fv1[PINVAL]);
951 #ifdef DEBUG_EVAL
952 if ( debug_eval && ds )
953 fprintf(debug_eval_file,"%d for pin attack to king\n",ds);
954 #endif
955 } else {
956 s += (ds = fv1[PINVAL]);
957 #ifdef DEBUG_EVAL
958 if ( debug_eval && ds )
959 fprintf(debug_eval_file,"%d for pin attack\n",ds);
960 #endif
962 if (atk2[pin] == 0 || atk1[pin] > control[board[pin]] + 1) {
963 hung[c2]++;
964 shung[u]++;
966 } else {
967 if ( upiece == lance ) {
968 s += (ds = fv1[XRAY]/2);
969 #ifdef DEBUG_EVAL
970 if ( debug_eval && ds )
971 fprintf(debug_eval_file,"lance xray attack: %d\n",ds);
972 #endif
973 } else {
974 s += (ds = fv1[XRAY]);
975 #ifdef DEBUG_EVAL
976 if ( debug_eval )
977 fprintf(debug_eval_file,"bishop/rook xray attack: %d\n",ds);
978 #endif
983 pin = -1; /* new direction */
984 #ifdef SAVE_NEXTPOS
985 u = next_direction(ptyp,&d,sq);
986 #else
987 u = pdir[u];
988 #endif
992 while (u != sq);
993 *mob = mobx;
994 return s;
999 #define ctlSG (ctlS | ctlG | ctlPp | ctlLp | ctlNp | ctlSp)
1002 inline
1003 short int
1004 KingScan (register short int sq)
1007 * Assign penalties if king can be threatened by checks, if squares near the
1008 * king are controlled by the enemy (especially by promoted pieces),
1009 * or if there are no own generals near the king.
1010 * The following must be true:
1011 * board[sq] == king, c1 == color[sq], c2 == otherside[c1]
1015 #ifdef DEBUG_EVAL
1017 #define ScoreThreat \
1018 { if (color[u] != c2)\
1019 if (atk1[u] == 0 || (atk2[u] & CNT_MASK) > 1) {\
1020 ++cnt;\
1021 } else {\
1022 s += (ds = -fv1[CTRLK]);\
1023 if ( debug_eval ) \
1024 fprintf(debug_eval_file,"%d for squares near king controlled by enemy %s\n",\
1025 ds, PieceStr[p]);\
1029 #else
1031 #define ScoreThreat \
1032 { if (color[u] != c2)\
1033 if (atk1[u] == 0 || (atk2[u] & CNT_MASK) > 1) {\
1034 ++cnt;\
1035 } else {\
1036 s += (ds = -fv1[CTRLK]);\
1040 #endif
1044 register short cnt;
1045 #ifdef SAVE_NEXTPOS
1046 short d;
1047 #else
1048 register unsigned char far *ppos, *pdir;
1049 #endif
1050 register short int s;
1051 register short u, ptyp;
1052 short int ok, ds;
1053 #ifdef DEBUG_EVAL
1054 short s0;
1055 #endif
1057 /* Penalties, if a king can be threatened by checks. */
1059 s = 0;
1060 cnt = 0;
1061 { short p;
1062 for ( p = pawn; p < king; p++ )
1063 if ( HasPiece[c2][p] || Captured[c2][p] )
1064 { short ptyp;
1065 /* if a c1 piece can reach u from sq,
1066 * then a c2 piece can reach sq from u.
1067 * That means, each u is a square, from which a
1068 * piece of type p and color c2 threats square sq.
1070 ptyp = ptype[c1][p];
1071 #ifdef SAVE_NEXTPOS
1072 u = first_direction(ptyp,&d,sq);
1073 #else
1074 ppos = (*nextpos[ptyp])[sq];
1075 pdir = (*nextdir[ptyp])[sq];
1076 u = ppos[sq];
1077 #endif
1080 /* If a p piece can reach (controls or can drop to)
1081 * square u, then score threat.
1083 if (atk2[u] & control[p])
1084 ScoreThreat
1085 else if (Captured[c2][p] && color[u] == neutral)
1086 ScoreThreat
1087 #ifdef SAVE_NEXTPOS
1088 u = ((color[u] == neutral) ? next_position(ptyp,&d,sq,u)
1089 : next_direction(ptyp,&d,sq));
1090 #else
1091 u = ((color[u] == neutral) ? ppos[u] : pdir[u]);
1092 #endif
1094 while (u != sq);
1097 s += (ds = fv1[KSFTY] * KTHRT[cnt] / 16);
1099 #ifdef DEBUG_EVAL
1100 if ( debug_eval && ds )
1101 fprintf(debug_eval_file,"%d for possible king threats\n",ds);
1102 #endif
1104 /* Penalties, if squares near king are controlled by enemy. */
1106 cnt = 0;
1107 ok = false;
1108 ptyp = ptype[c1][king];
1109 #ifdef SAVE_NEXTPOS
1110 u = first_direction(ptyp,&d,sq);
1111 #else
1112 pdir = (*nextpos[ptyp])[sq];
1113 u = pdir[sq];
1114 #endif
1117 if ( !ok && color[u] == c1 )
1119 short ptype_piece = ptype[black][board[u]];
1120 if ( ptype_piece == ptype_silver || ptype_piece == ptype_gold )
1121 ok = true;
1123 if (atk2[u] > atk1[u])
1125 ++cnt;
1126 if (atk2[u] & ctlSG) {
1127 s += (ds = -fv1[KSFTY]/2);
1128 #ifdef DEBUG_EVAL
1129 if (debug_eval )
1130 fprintf(debug_eval_file,"%d square controlled by near enemy silver or gold\n",ds);
1131 #endif
1134 #ifdef SAVE_NEXTPOS
1135 u = next_direction(ptyp,&d,sq);
1136 #else
1137 u = pdir[u];
1138 #endif
1140 while (u != sq);
1141 if ( !ok || cnt > 1) {
1142 if ( cnt > 1 )
1143 s += (ds = -fv1[KSFTY]/2);
1144 else
1145 s += (ds = -fv1[KSFTY]);
1146 #ifdef DEBUG_EVAL
1147 if (debug_eval )
1148 if ( !ok )
1149 fprintf(debug_eval_file,"%d for no general protect king\n",ds);
1150 else
1151 fprintf(debug_eval_file,"%d for %d enemy generals dear king\n",cnt,ds);
1152 #endif
1155 return (s);
1159 static short checked_trapped;
1162 inline
1164 trapped (register short int sq)
1167 * See if the attacked piece has unattacked squares to move to. The following
1168 * must be true: c1 == color[sq] c2 == otherside[c1]
1172 register short u, ptyp;
1173 #ifdef SAVE_NEXTPOS
1174 short d;
1175 #else
1176 register unsigned char far *ppos, *pdir;
1177 #endif
1178 register short int piece;
1179 short rvalue;
1181 piece = board[sq];
1182 rvalue = (*value)[stage][piece];
1183 ptyp = ptype[c1][piece];
1184 #ifdef SAVE_NEXTPOS
1185 u = first_direction(ptyp,&d,sq);
1186 #else
1187 ppos = (*nextpos[ptyp])[sq];
1188 pdir = (*nextdir[ptyp])[sq];
1189 u = ppos[sq];
1190 #endif
1191 do {
1192 if (color[u] != c1)
1193 if (atk2[u] == 0 || (*value)[stage][board[u]] >= rvalue)
1194 return (false);
1195 #ifdef SAVE_NEXTPOS
1196 u = ((color[u] == neutral) ? next_position(ptyp,&d,sq,u)
1197 : next_direction(ptyp,&d,sq));
1198 #else
1199 u = ((color[u] == neutral) ? ppos[u] : pdir[u]);
1200 #endif
1201 } while (u != sq);
1202 #ifdef DEBUG_EVAL
1203 if ( debug_eval )
1204 fprintf(debug_eval_file,"piece is trapped\n");
1205 #endif
1206 checked_trapped = true;
1208 return (true);
1213 static int AttackedPieceValue (register short int sq, short int side)
1215 short s, ds;
1217 s = 0;
1219 ds += (ds = -fv1[HUNGP]);
1220 hung[c1]++;
1221 shung[sq]++;
1222 #ifdef DEBUG_EVAL
1223 if ( debug_eval )
1224 fprintf(debug_eval_file,"attacked: %d, hung[%s]++\n",
1225 ds, ColorStr[c1]);
1226 #endif
1228 if (trapped (sq))
1230 hung[c1] += 2;
1231 shung[sq] += 2;
1232 #ifdef DEBUG_EVAL
1233 if ( debug_eval )
1234 fprintf(debug_eval_file,"trapped: hung[%s] += 2\n",
1235 ColorStr[c1]);
1236 #endif
1239 return s;
1244 static inline int
1245 OpenFileValue (register short sq, short hopn, short hopnx)
1247 short s=0, fyle;
1249 if (PC1[fyle = column(sq)] == 0)
1251 s += hopn;
1252 #ifdef DEBUG_EVAL
1253 if (debug_eval && hopn)
1254 fprintf(debug_eval_file,"adding %d for now own pawn on file\n",hopn);
1255 #endif
1258 if (PC2[fyle] == 0)
1260 s += hopnx;
1261 #ifdef DEBUG_EVAL
1262 if (debug_eval && hopnx)
1263 fprintf(debug_eval_file,"%d for no opponents pawn on file\n",hopnx);
1264 #endif
1267 return s;
1271 /* Distance bonus */
1273 #ifdef DEBUG_EVAL
1275 #define PromotionZoneDistanceValue(sq,dd)\
1276 if ( ds = fv1[PROMD] ) { \
1277 s += (ds = ds * PromotionZoneDistanceBonus[crow(c1,sq)] * dd);\
1278 if (debug_eval && ds) \
1279 fprintf(debug_eval_file,"%d for distance to promotion zone\n",ds); \
1282 #else
1284 #define PromotionZoneDistanceValue(sq,dd)\
1285 if ( ds = fv1[PROMD] ) { \
1286 s += (ds = ds * PromotionZoneDistanceBonus[crow(c1,sq)] * dd);\
1289 #endif
1292 #ifdef DEBUG_EVAL
1294 #define OwnKingDistanceValue(sq,dd,maxd)\
1295 if ( (ds = fv1[KINGOD]) && ((ad = Kdist[c1][sq]) <= maxd) ) { \
1296 s += (ds = ds * OwnKingDistanceBonus[ad] * dd);\
1297 if (debug_eval && ds) \
1298 fprintf(debug_eval_file,"%d for distance to own king\n",ds); \
1301 #else
1303 #define OwnKingDistanceValue(sq,dd,maxd)\
1304 if ( (ds = fv1[KINGOD]) && ((ad = Kdist[c1][sq]) <= maxd) ) { \
1305 s += (ds = ds * OwnKingDistanceBonus[ad] * dd);\
1308 #endif
1311 #ifdef DEBUG_EVAL
1313 #define EnemyKingDistanceValue(sq,dd,maxd)\
1314 if ( (ds = fv1[KINGOD]) && ((ad = Kdist[c2][sq]) <= maxd) ) { \
1315 s += (ds = ds * EnemyKingDistanceBonus[ad] * dd);\
1316 if (debug_eval && ds) \
1317 fprintf(debug_eval_file,"%d for distance to enemy king\n",ds); \
1320 #else
1322 #define EnemyKingDistanceValue(sq,dd,maxd)\
1323 if ( (ds = fv1[KINGOD]) && ((ad = Kdist[c2][sq]) <= maxd) ) { \
1324 s += (ds = ds * EnemyKingDistanceBonus[ad] * dd);\
1327 #endif
1332 static inline int
1333 PawnValue (register short int sq, short int side)
1335 * Calculate the positional value for a pawn on 'sq'.
1339 register short s=0;
1340 short ds;
1341 short n;
1342 short ccol = ccolumn(c1,sq);
1344 PromotionZoneDistanceValue(sq,3);
1346 /* pawn mobility */
1347 if ( color[(c1==black)?(sq+9):(sq-9)] == neutral ) {
1348 s += (ds = MBLTY[pawn]);
1349 #ifdef DEBUG_EVAL
1350 if ( debug_eval && ds )
1351 fprintf(debug_eval_file,"%d for mobility\n", ds);
1352 #endif
1355 if ( (a1 & ((ctlR | ctlRp) | ctlL)) ) {
1356 s += (ds = fv1[ATAKD]);
1357 #ifdef DEBUG_EVAL
1358 if ( debug_eval && ds )
1359 fprintf(debug_eval_file,"%d for rook/lance-supported pawn\n",ds);
1360 #endif
1363 if ( in_opening_stage ) {
1365 if ( crow(c1,sq) == 2 ) /* pawn on 3d rank */
1366 if ( board[(c1==black)?(sq+27):(sq-27)] == pawn )
1367 { /* opposing pawn has been moved (even column == (sq & 1)) */
1368 short m;
1369 switch ( ccol ) {
1370 case 0: case 8: m = ( side == c1 ) ? 3 : 5; break;
1371 case 4: m = ( side == c1 ) ? 2 : 3; break;
1372 default:m = ( side == c1 ) ? 1 : 2; break;
1374 s += (ds = -m*MBLTY[pawn]);
1375 #ifdef DEBUG_EVAL
1376 if ( debug_eval && ds )
1377 fprintf(debug_eval_file,"%d for opposing pawn pushed\n",ds);
1378 #endif
1381 if ( GameType[c1] == STATIC_ROOK && sq == csquare(c1,43) )
1382 if ( (atk2[csquare(c1,52)] & CNT_MASK) < 2 )
1384 s += (ds = fv1[ATAKD]);
1385 #ifdef DEBUG_EVAL
1386 if ( debug_eval )
1387 fprintf(debug_eval_file,"%d for attacking pawn on 2nd col\n",ds);
1388 #endif
1391 if ( GameType[c2] == STATIC_ROOK && ccol == 1 )
1393 if ( sq == csquare(c1,28) )
1395 s += (ds = -fv1[ATAKD]);
1396 #ifdef DEBUG_EVAL
1397 if ( debug_eval )
1398 fprintf(debug_eval_file,"%d for pushed pawn on 8th file\n",ds);
1399 #endif
1401 if ( (atk1[csquare(c1,19)] & CNT_MASK) < 2 && (atk1[csquare(c1,28)] & CNT_MASK) < 2 )
1403 s += (ds = -2*fv1[ATAKD]);
1404 #ifdef DEBUG_EVAL
1405 if ( debug_eval )
1406 fprintf(debug_eval_file,"%d for weak pawn on 8th col\n",ds);
1407 #endif
1413 return (s);
1417 static inline int
1418 LanceValue (register short int sq, short int side)
1420 * Calculate the positional value for a lance on 'sq'.
1424 register short s=0, ds, ad;
1426 OwnKingDistanceValue(sq,1,2);
1428 OpenFileValue (sq, -fv1[HOPN], fv1[HOPN]);
1430 if ( !checked_trapped && crow(c1,sq) > 2 )
1432 if (in_opening_stage || trapped (sq))
1434 s += (ds = -3*fv1[ATAKD]);
1435 #ifdef DEBUG_EVAL
1436 if ( debug_eval )
1437 fprintf(debug_eval_file,"%d for lance in danger\n",ds);
1438 #endif
1440 else
1442 s += (ds = -2*fv1[ATAKD]);
1443 #ifdef DEBUG_EVAL
1444 if ( debug_eval )
1445 fprintf(debug_eval_file,"%d for lance in danger\n",ds);
1446 #endif
1450 return (s);
1453 static inline int
1454 KnightValue (register short int sq, short int side)
1456 * Calculate the positional value for a knight on 'sq'.
1460 register short s = 0, ad;
1461 short ds, checked_trapped = false;
1462 short c = column(sq);
1464 PromotionZoneDistanceValue(sq,1);
1465 OwnKingDistanceValue(sq,1,2);
1467 if ( !checked_trapped && crow(c1,sq) > 2 )
1469 if (trapped (sq))
1471 s += (ds = -4*fv1[ATAKD]);
1472 #ifdef DEBUG_EVAL
1473 if ( debug_eval )
1474 fprintf(debug_eval_file,"%d for knight in danger\n",ds);
1475 #endif
1477 else
1479 s += (ds = -3*fv1[ATAKD]);
1480 #ifdef DEBUG_EVAL
1481 if ( debug_eval && ds )
1482 fprintf(debug_eval_file,"%d for knight in danger\n",ds);
1483 #endif
1487 if ( c == 0 || c == 8 ) {
1488 s += (ds = -fv1[ATAKD]);
1489 #ifdef DEBUG_EVAL
1490 if ( debug_eval )
1491 fprintf(debug_eval_file,"%d for knight on edge file\n",ds);
1492 #endif
1495 return (s);
1498 static inline int
1499 SilverValue (register short int sq, short int side)
1501 * Calculate the positional value for a silver on 'sq'.
1505 register short s= 0, ds, ad;
1507 OwnKingDistanceValue(sq,2,3);
1509 if ( Kdist[c1][sq] < 3 && (atk1[sq] & (control[gold] | control[silver])) ) {
1510 s += (ds = fv1[COHESION]);
1511 #ifdef DEBUG_EVAL
1512 if ( debug_eval )
1513 fprintf(debug_eval_file,"%d for good cohesion\n",ds);
1514 #endif
1517 if ( in_opening_stage ) {
1518 if ( GameType[c1] == STATIC_ROOK )
1519 if ( csquare(c1,sq) == 12 )
1521 short csq;
1522 if ( board[csq = csquare(c1,20)] == bishop && color[csq] == c1 )
1524 s += (ds = -2*fv1[OPENWRONG]);
1525 #ifdef DEBUG_EVAL
1526 if ( debug_eval )
1527 fprintf(debug_eval_file,"%d for wrong opening\n",ds);
1528 #endif
1531 } else {
1532 EnemyKingDistanceValue(sq,2,3);
1535 return (s);
1538 static inline int
1539 GoldValue (register short int sq, short int side)
1541 * Calculate the positional value for a gold on 'sq'.
1545 register short s=0, ds, ad;
1547 OwnKingDistanceValue(sq,2,3);
1549 if ( Kdist[c1][sq] < 3 && (atk1[sq] & (control[gold] | control[silver])) ) {
1550 s += (ds = fv1[COHESION]);
1551 #ifdef DEBUG_EVAL
1552 if ( debug_eval )
1553 fprintf(debug_eval_file,"%d for good cohesion\n",ds);
1554 #endif
1557 if ( in_opening_stage ) {
1558 if ( GameType[c1] == STATIC_ROOK && GameType[c2] != STATIC_ROOK )
1559 if ( Mvboard[csquare(c1,3)] )
1561 s += (ds = -2*fv1[OPENWRONG]);
1562 #ifdef DEBUG_EVAL
1563 if ( debug_eval )
1564 fprintf(debug_eval_file,"%d for wrong opening\n",ds);
1565 #endif
1567 } else {
1568 EnemyKingDistanceValue(sq,2,3);
1571 return (s);
1574 static inline int
1575 BishopValue (register short int sq, short int side)
1577 * Calculate the positional value for a bishop on 'sq'.
1581 register short s=0, ds, ad;
1583 if ( in_opening_stage ) {
1584 if ( GameType[c1] == RANGING_ROOK )
1586 /* Bishops diagonal should not be open */
1587 if ( !on_csquare(c1,pawn,30) ) {
1588 s += (ds = -fv1[OPENWRONG]);
1589 #ifdef DEBUG_EVAL
1590 if ( debug_eval )
1591 fprintf(debug_eval_file,"%d for open bishops diagonal\n",ds);
1592 #endif
1595 else if ( GameType[c2] == RANGING_ROOK )
1597 /* Bishops diagonal should be open */
1598 if ( csquare(c1,sq) == 10 &&
1599 (!empty_csquare(c1,20) || !empty_csquare(c1,30)) ) {
1600 s += (ds = -fv1[OPENWRONG]);
1601 #ifdef DEBUG_EVAL
1602 if ( debug_eval )
1603 fprintf(debug_eval_file,"%d for closed bishops diagonal\n",ds);
1604 #endif
1605 } else if ( csquare(c1,sq) == 20 && !empty_csquare(c1,30) ) {
1606 s += (ds = -fv1[OPENWRONG]);
1607 #ifdef DEBUG_EVAL
1608 if ( debug_eval )
1609 fprintf(debug_eval_file,"%d for closed bishops diagonal\n",ds);
1610 #endif
1613 } else {
1614 EnemyKingDistanceValue(sq,1,3);
1617 return (s);
1620 static inline int
1621 RookValue (register short int sq, short int side)
1623 * Calculate the positional value for a rook on 'sq'.
1627 register short s=0, ds, ad;
1629 OpenFileValue (sq, 2*fv1[HOPN], 4*fv1[HOPN]);
1631 if ( in_opening_stage ) {
1632 short WRONG = fv1[OPENWRONG], OPOK = WRONG/3;
1633 if ( GameType[c1] == STATIC_ROOK )
1635 short c = ccolumn(c1,sq);
1636 /* Bonus for rook on 8th file */
1637 if ( c == 7 ) {
1638 s += (ds = OPOK);
1639 #ifdef DEBUG_EVAL
1640 if ( debug_eval )
1641 fprintf(debug_eval_file,"%d for rook on 8th file\n",ds);
1642 #endif
1644 /* Bonus for rook on right side, malus for rook on left side */
1645 c = 4 - c; ds = 0;
1646 if ( c < 0 ) {
1647 s += (ds = c + c + OPOK);
1648 } else if ( c >= 0 ) {
1649 s += (ds = -c - c - WRONG);
1651 #ifdef DEBUG_EVAL
1652 if ( debug_eval && ds )
1653 fprintf(debug_eval_file,"%d for king on correct/wrong side\n",ds);
1654 #endif
1656 else if ( GameType[c1] == RANGING_ROOK )
1658 /* Bonus for rook on left side and bishops diagonal closed, malus otherwise. */
1659 short c;
1660 c = 4 - ccolumn(c1,sq); ds = 0;
1661 if ( c >= 0 ) {
1662 /* Bishops diagonal should not be open */
1663 if ( on_csquare(c1,pawn,30) )
1664 s += (ds = OPOK);
1665 else
1666 s += (ds = -c - c - WRONG);
1667 } else if ( c < 0 ) {
1668 s += (ds = -c - c - WRONG);
1669 /* Malus for king not on initial square */
1670 if ( !on_csquare(side,king,4) ) {
1671 s += -4*WRONG; ds += -4*WRONG;
1674 #ifdef DEBUG_EVAL
1675 if ( debug_eval && ds )
1676 fprintf(debug_eval_file,"%d for bishops diagonal\n",ds);
1677 #endif
1679 } else {
1680 EnemyKingDistanceValue(sq,1,3);
1683 return (s);
1686 static inline int
1687 PPawnValue (register short int sq, short int side)
1689 * Calculate the positional value for a promoted pawn on 'sq'.
1693 register short s = 0, ds, ad;
1695 EnemyKingDistanceValue(sq,3,10);
1697 return (s);
1700 static inline int
1701 PLanceValue (register short int sq, short int side)
1703 * Calculate the positional value for a promoted lance on 'sq'.
1707 register short s = 0, ds, ad;
1709 EnemyKingDistanceValue(sq,3,10);
1711 return (s);
1714 static inline int
1715 PKnightValue (register short int sq, short int side)
1717 * Calculate the positional value for a promoted knight on 'sq'.
1721 register short s = 0, ds, ad;
1723 EnemyKingDistanceValue(sq,3,10);
1725 return (s);
1728 static inline int
1729 PSilverValue (register short int sq, short int side)
1731 * Calculate the positional value for a promoted silver on 'sq'.
1735 register short s = 0, ds, ad;
1737 EnemyKingDistanceValue(sq,3,10);
1739 return (s);
1742 static inline int
1743 PBishopValue (register short int sq, short int side)
1745 * Calculate the positional value for a promoted bishop on 'sq'.
1749 register short s = 0, ds, ad;
1751 EnemyKingDistanceValue(sq,3,4);
1753 return (s);
1756 static inline int
1757 PRookValue (register short int sq, short int side)
1759 * Calculate the positional value for a promoted rook on 'sq'.
1763 register short s = 0, ds, ad;
1765 EnemyKingDistanceValue(sq,3,4);
1767 OpenFileValue (sq, 3*fv1[HOPN], 2*fv1[HOPN]);
1769 return (s);
1772 static inline int
1773 KingValue (register short int sq, short int side)
1775 * Calculate the positional value for a king on 'sq'.
1778 register short s = 0, ds;
1780 if ( fv1[KSFTY] != 0 )
1781 s += KingScan (sq);
1783 if ( in_opening_stage )
1784 if ( GameType[c1] != UNKNOWN && ccolumn(c1,sq) == 4 ) {
1785 s += (ds = -fv1[OPENWRONG]/3);
1786 #ifdef DEBUG_EVAL
1787 if ( debug_eval && ds )
1788 fprintf(debug_eval_file,"%d for center king\n",ds);
1789 #endif
1790 } else if ( GameType[c1] == STATIC_ROOK && on_right_side(c1,sq) ) {
1791 s += (ds = -fv1[OPENWRONG]/2);
1792 #ifdef DEBUG_EVAL
1793 if ( debug_eval && ds )
1794 fprintf(debug_eval_file,"%d for king on right side\n",ds);
1795 #endif
1796 } else if ( GameType[c1] == RANGING_ROOK && on_left_side(c1,sq) ) {
1797 s += (ds = -fv1[OPENWRONG]/2);
1798 #ifdef DEBUG_EVAL
1799 if ( debug_eval && ds )
1800 fprintf(debug_eval_file,"%d for king on left side\n",ds);
1801 #endif
1804 if ( ds = fv1[HOPN] ) {
1805 s += OpenFileValue(sq,-2*ds,-4*ds);
1808 return (s);
1813 static inline int
1814 PieceValue (register short int sq, short int side)
1816 * Calculate the positional value for a piece on 'sq'.
1820 register short s, piece, ds;
1821 short mob;
1823 piece = board[sq];
1825 if ( piece == no_piece )
1826 return 0;
1828 s = (*Mpiece[piece])[c1][sq];
1830 #ifdef DEBUG_EVAL
1831 if ( debug_eval )
1832 fprintf(debug_eval_file,"\ninital value for %s %s on %c%c: %d\n",
1833 ColorStr[c1], PieceStr[piece], cxx[column(sq)], rxx[row(sq)], s);
1834 #endif
1836 checked_trapped = false;
1838 if ( sweep[piece] ) {
1839 /* pin/xray attack and mobility for sweeping pieces */
1840 s += (ds = BRLscan (sq, &mob));
1841 #ifdef DEBUG_EVAL
1842 if ( debug_eval )
1843 fprintf(debug_eval_file,"%d sum for sweeping piece\n", ds);
1844 #endif
1845 if ( piece == bishop || piece == pbishop )
1846 s += (ds = BMBLTY[mob] * fv1[MOBILITY] / 100);
1847 else if ( piece == rook || piece == prook )
1848 s += (ds = RMBLTY[mob] * fv1[MOBILITY] / 100);
1849 else
1850 s += (ds = LMBLTY[mob] * fv1[MOBILITY] / 100);
1851 #ifdef DEBUG_EVAL
1852 if ( debug_eval )
1853 fprintf(debug_eval_file,"%d for mobility of sweeping piece\n", ds);
1854 #endif
1855 } else {
1856 /* mobility for non-sweeping pieces */
1859 a2 = atk2[sq];
1860 a1 = atk1[sq];
1862 if (a2 > 0)
1863 { /* opponent attacks piece */
1864 if (a1 == 0)
1865 { /* undefended piece */
1866 s += AttackedPieceValue (sq, side);
1868 else
1869 { /* defended piece */
1870 short attack_value = value_of_weakest_attacker(a2);
1871 short piece_value = (*value)[stage][piece];
1872 if ( attack_value < piece_value )
1873 { /* attacked by a weaker piece */
1874 s += AttackedPieceValue (sq, side) / 2;
1876 else if ( abs(attack_value - piece_value) < 10 )
1878 /* opponent has the option to exchange equal pieces */
1879 s += (ds = -fv1[ATAKD]);
1880 #ifdef DEBUG_EVAL
1881 if ( debug_eval )
1882 fprintf(debug_eval_file,"exchange option: %d\n", ds);
1883 #endif
1885 #ifdef notdef
1886 else if (a1 < ctlP)
1887 { /* piece is not defended by a pawn */
1888 s += (ds = -fv1[ATAKD]);
1889 #ifdef DEBUG_EVAL
1890 if ( debug_eval )
1891 fprintf(debug_eval_file,"not defended by pawn: %d\n", ds);
1892 #endif
1894 #endif
1898 if ( piece != king ) {
1900 if ( a1 > 0 ) {
1901 /* piece is defended */
1902 s += (ds = (a1 & CNT_MASK)*fv1[PROTECT]);
1903 #ifdef DEBUG_EVAL
1904 if ( debug_eval )
1905 fprintf(debug_eval_file,"%d for protected piece\n", ds);
1906 #endif
1909 if ( sseed[sq] ) {
1910 s += (ds = fv1[SEED]);
1911 #ifdef DEBUG_EVAL
1912 if ( debug_eval )
1913 fprintf(debug_eval_file,"%d for seed piece\n", ds);
1914 #endif
1917 if ( sloose[sq] ) {
1918 s += (ds = -fv1[LOOSE]);
1919 #ifdef DEBUG_EVAL
1920 if ( debug_eval )
1921 fprintf(debug_eval_file,"%d for loose piece\n", ds);
1922 #endif
1925 if ( starget[c1][sq] ) {
1926 if ( sweep[piece] ) {
1927 s -= (ds = -fv1[ATAKD]/2);
1928 #ifdef DEBUG_EVAL
1929 if ( debug_eval )
1930 fprintf(debug_eval_file,"%d for sweeping piece on own target square\n", ds);
1931 #endif
1932 } else if ( piece == pawn ) {
1933 s += (ds = fv1[ATAKD]);
1934 #ifdef DEBUG_EVAL
1935 if ( debug_eval )
1936 fprintf(debug_eval_file,"%d for pawn on own target square\n", ds);
1937 #endif
1941 if ( starget[c2][sq] ) {
1942 if ( piece != pawn ) {
1943 s -= (ds = -fv1[ATAKD]/3);
1944 #ifdef DEBUG_EVAL
1945 if ( debug_eval )
1946 fprintf(debug_eval_file,"%d for non-pawn on opponents target square\n", ds);
1947 #endif
1948 } else {
1949 s += (ds = fv1[ATAKD]);
1950 #ifdef DEBUG_EVAL
1951 if ( debug_eval )
1952 fprintf(debug_eval_file,"%d for pawn on opponents target square\n", ds);
1953 #endif
1957 if ( Kdist[c1][sq] == 1 ) {
1958 s += (ds = fv1[KSFTY]);
1959 #ifdef DEBUG_EVAL
1960 if ( debug_eval )
1961 fprintf(debug_eval_file,"%d for piece near king\n", ds);
1962 #endif
1967 switch ( piece ) {
1968 case pawn:
1969 s += PawnValue (sq, side);
1970 break;
1971 case lance:
1972 s += LanceValue (sq, side);
1973 break;
1974 case knight:
1975 s += KnightValue (sq, side);
1976 break;
1977 case silver:
1978 s += SilverValue (sq, side);
1979 break;
1980 case gold:
1981 s += GoldValue (sq, side);
1982 break;
1983 case bishop:
1984 s += BishopValue (sq, side);
1985 break;
1986 case rook:
1987 s += RookValue (sq, side);
1988 break;
1989 case king:
1990 s += KingValue (sq, side);
1991 break;
1992 case ppawn:
1993 s += PPawnValue (sq, side);
1994 break;
1995 case plance:
1996 s += PLanceValue (sq, side);
1997 break;
1998 case pknight:
1999 s += PKnightValue (sq, side);
2000 break;
2001 case psilver:
2002 s += PSilverValue (sq, side);
2003 break;
2004 case pbishop:
2005 s += PBishopValue (sq, side);
2006 break;
2007 case prook:
2008 s += PRookValue (sq, side);
2009 break;
2012 return (s);
2016 short
2017 ScorePatternDistance (short c1)
2020 * Score distance to pattern regarding the game type which side plays.
2024 short ds, s = 0;
2025 small_short *fv1 = fvalue[c1];
2026 short os = 0;
2028 #ifdef DEBUG_EVAL
2029 char name[16];
2030 if ( debug_eval )
2031 fprintf(debug_eval_file,"scoring castle pattern distance for PCASTLE=%d\n",
2032 fv1[PCASTLE]);
2033 #endif
2035 if ( MAXCDIST > 0 && fv1[PCASTLE] != 0 && ((os = castle_opening_sequence[c1]) >= 0) )
2037 ds = board_to_pattern_distance(c1,os,MAXCDIST,GameCnt);
2038 if ( ds != 0) {
2039 s += (ds *= fv1[PCASTLE]);
2040 #ifdef DEBUG_EVAL
2041 if ( debug_eval && ds != 0 ) {
2042 NameOfOpeningValue(OpeningSequence[os].opening_type,name);
2043 fprintf(debug_eval_file,
2044 "add %d for max gain of %s to reachable castle patterns %s\n",
2045 ds, ColorStr[c1], name);
2047 #endif
2050 #ifdef DEBUG_EVAL
2051 else if ( debug_eval && os<0 )
2052 fprintf(debug_eval_file,"no castle pattern for %s\n",ColorStr[c1]);
2053 #endif
2055 #ifdef DEBUG_EVAL
2056 if ( debug_eval )
2057 fprintf(debug_eval_file,"scoring attack pattern distance for PATTACK=%d\n",
2058 fv1[PATTACK]);
2059 #endif
2061 if ( MAXADIST > 0 && fv1[PATTACK] != 0 && ((os = attack_opening_sequence[c1]) >= 0) )
2063 ds = board_to_pattern_distance(c1,os,MAXADIST,GameCnt);
2064 if ( ds != 0 ) {
2065 s += (ds *= fv1[PATTACK]);
2066 #ifdef DEBUG_EVAL
2067 if ( debug_eval && ds != 0 ) {
2068 NameOfOpeningValue(OpeningSequence[os].opening_type,name);
2069 fprintf(debug_eval_file,
2070 "add %d for max gain of %s to reachable attack patterns %s\n",
2071 ds, ColorStr[c1], name);
2073 #endif
2076 #ifdef DEBUG_EVAL
2077 else if ( debug_eval && os<0 )
2078 fprintf(debug_eval_file,"no attack pattern for %s\n",ColorStr[c1]);
2079 #endif
2081 return(s);
2086 static
2087 void
2088 UpdatePatterns (short int side, short int GameCnt)
2091 * Determine castle and attack pattern which should be reached next.
2092 * Only patterns are considered, which have not been reached yet.
2096 char s[12];
2097 short xside = side ^ 1;
2098 short os;
2099 short i, j, k, n = 0;
2100 #ifdef DEBUG_EVAL
2101 char name[16];
2102 #endif
2104 strcpy(s,"CASTLE_?_?");
2105 s[7] = GameType[side];
2106 s[9] = GameType[xside];
2107 castle_opening_sequence[side] = os = locate_opening_sequence(side,s,GameCnt);
2109 if ( flag.post && os!=END_OF_SEQUENCES )
2111 for (j=0; j<MAX_SEQUENCE; j++) {
2112 for (k=OpeningSequence[os].first_pattern[j]; k!=END_OF_PATTERNS; k=Pattern[k].next_pattern)
2113 if ( Pattern[k].distance[side] >= 0 ) n++;
2117 if ( os!=END_OF_SEQUENCES ) update_advance_bonus (side,os);
2119 #ifdef DEBUG_EVAL
2120 if ( debug_eval )
2121 if (os!=END_OF_SEQUENCES )
2123 NameOfOpeningValue(OpeningSequence[os].opening_type,name);
2124 fprintf(debug_eval_file,"castle pattern of %s is %s\n",
2125 ColorStr[side], name);
2126 fprintf(debug_eval_file,"reachable patterns: ");
2127 for (j=0; j<MAX_SEQUENCE; j++)
2128 for (i=0,k=OpeningSequence[os].first_pattern[j]; k!=END_OF_PATTERNS; i++,k=Pattern[k].next_pattern)
2129 if ( Pattern[k].distance[side] >= 0 )
2130 fprintf(debug_eval_file,"%d(%d) ",i,j);
2131 fprintf(debug_eval_file,"\n");
2133 else
2135 fprintf(debug_eval_file,"no castle pattern %s for %s\n",
2136 s, ColorStr[side]);
2138 #endif
2140 strcpy(s,"ATTACK_?_?");
2141 s[7] = GameType[side];
2142 s[9] = GameType[xside];
2143 attack_opening_sequence[side] = os = locate_opening_sequence(side,s,GameCnt);
2145 if ( flag.post && os!=END_OF_SEQUENCES )
2147 for (j=0; j<MAX_SEQUENCE; j++) {
2148 for (k=OpeningSequence[os].first_pattern[j]; k!=END_OF_PATTERNS; k=Pattern[k].next_pattern)
2149 if ( Pattern[k].distance[side] >= 0 ) n++;
2153 if ( flag.post )
2155 ShowPatternCount(side,n);
2158 if ( os!=END_OF_SEQUENCES ) update_advance_bonus (side,os);
2160 #ifdef DEBUG_EVAL
2161 if ( debug_eval )
2162 if ( os!=END_OF_SEQUENCES )
2164 NameOfOpeningValue(OpeningSequence[os].opening_type,name);
2165 fprintf(debug_eval_file,"attak pattern of %s is %s\n",
2166 ColorStr[side], name);
2167 fprintf(debug_eval_file,"reachable patterns: ");
2168 for (j=0; j<MAX_SEQUENCE; j++)
2169 for (i=0,k=OpeningSequence[os].first_pattern[j]; k!=END_OF_PATTERNS; k=Pattern[k].next_pattern)
2170 if ( Pattern[k].distance[side] >= 0 )
2171 fprintf(debug_eval_file,"%d(%d) ",i,j);
2172 fprintf(debug_eval_file,"\n");
2174 else
2176 fprintf(debug_eval_file,"no attak pattern %s for %s\n",
2177 s, ColorStr[side]);
2179 #endif
2187 static
2188 void
2189 ScoreSquares (void)
2191 register short sq;
2192 short ds, n, m;
2194 for ( sq = 0; sq < NO_SQUARES; sq++ ) {
2196 for ( c1 = black, c2 = white; c1 <= white; c1++, c2-- ) {
2198 a1 = atak[c1][sq];
2199 a2 = atak[c2][sq];
2200 fv1 = fvalue[c1];
2202 if ( InPromotionZone(c1,sq) ) {
2203 /* square in promotion zone */
2204 if ( a1 & control[pawn] ) {
2205 /* dangling pawn */
2206 pscore[c1] += (ds = 2*fv1[DNGLPC]);
2207 #ifdef DEBUG_EVAL
2208 if ( debug_eval ) {
2209 fprintf(debug_eval_file,"%d for %s dangling pawn\n",ds,ColorStr[c1]);
2211 #endif
2213 if ( a1 & (control[lance] | control[knight]) ) {
2214 /* dangling lance or dangling knight */
2215 pscore[c1] += (ds = fv1[DNGLPC]);
2216 #ifdef DEBUG_EVAL
2217 if ( debug_eval ) {
2218 fprintf(debug_eval_file,"%d for %s dangling knight/silver\n",ds,ColorStr[c1]);
2220 #endif
2223 if ( a1 & control[king] ) {
2224 /* square controlled by own king */
2225 if ( (n = a1 & CNT_MASK) > 1 ) {
2226 pscore[c1] += (ds = (n-1)*fv1[KNGPROTECT]);
2227 #ifdef DEBUG_EVAL
2228 if ( debug_eval ) {
2229 fprintf(debug_eval_file,"%d for %s protects own king\n",ds,ColorStr[c1]);
2231 #endif
2234 if ( a2 & control[king] ) {
2235 /* square controlled by enemy king */
2236 if ( (n = a1 & CNT_MASK) > 0 ) {
2237 pscore[c1] += (ds = n*fv1[KNGATTACK]);
2238 #ifdef DEBUG_EVAL
2239 if ( debug_eval ) {
2240 fprintf(debug_eval_file,"%d for %s controls enemy king\n",ds,ColorStr[c1]);
2242 #endif
2245 if ( (a2 & CNT_MASK) > 1 ) {
2246 /* enemy's focal point */
2247 if ( (n = a1 & CNT_MASK) > 0 ) {
2248 pscore[c1] += (ds = n*fv1[FCLATTACK]);
2249 #ifdef DEBUG_EVAL
2250 if ( debug_eval ) {
2251 fprintf(debug_eval_file,"%d for %s attacks enemy's focal point\n",ds,ColorStr[c1]);
2253 #endif
2258 if ( (c1 = color[sq]) == neutral ) {
2260 /* empty square */
2262 } else {
2264 /* occupied square */
2266 c2 = c1 ^ 1;
2268 a1 = atak[c1][sq];
2269 a2 = atak[c2][sq];
2270 fv1 = fvalue[c1];
2272 if ( a2 && sloose[sq] ) {
2273 pscore[c2] += (ds = fv1[LSATTACK]);
2274 #ifdef DEBUG_EVAL
2275 if ( debug_eval ) {
2276 fprintf(debug_eval_file,"%d for %s attacks loose piece\n",ds,ColorStr[c2]);
2278 #endif
2280 if ( a2 && !Captured[c2][unpromoted[board[sq]]] ) {
2281 pscore[c2] += (ds = fv1[NIHATTACK]);
2282 #ifdef DEBUG_EVAL
2283 if ( debug_eval && ds ) {
2284 fprintf(debug_eval_file,"%d for %s attack piece not in hand\n",ds,ColorStr[c2]);
2286 #endif
2296 static
2297 void
2298 ScoreCaptures (void)
2300 short ds, col, n, m, piece;
2302 if ( n = Captured[c1][pawn] ) {
2303 ds = m = 0;
2304 for ( col = 0; col < NO_COLS; col++ ) {
2305 if ( !PC1[col] ) {
2306 m++;
2307 ds += fv1[PWNDROP];
2310 pscore[c1] += (ds *= ((n > 2) ? 3 : n));
2311 #ifdef DEBUG_EVAL
2312 if ( debug_eval && ds ) {
2313 fprintf(debug_eval_file,"%d for %s %d captured pawns dropable to %d cols\n",
2314 ds,ColorStr[c2],n,m);
2316 #endif
2319 if ( m = seed[c1] ) {
2320 for ( piece = lance, n=0; piece <= rook; piece++ ) {
2321 if ( Captured[c1][piece] )
2322 n++;
2324 pscore[c1] += (ds = m*fv1[DFFDROP]);
2325 #ifdef DEBUG_EVAL
2326 if ( debug_eval && ds ) {
2327 fprintf(debug_eval_file,"%d for %s %d diff captures supported by %d seed pieces\n",
2328 ds,ColorStr[c2],n,m);
2330 #endif
2333 for ( piece = pawn, n = 0; piece <= rook; piece++ ) {
2334 if ( Captured[c1][piece] ) {
2335 switch ( piece ) {
2336 case bishop: ds = BMBLTY[MAX_BMBLTY-1]; break;
2337 case rook : ds = RMBLTY[MAX_RMBLTY-1]; break;
2338 case lance : ds = LMBLTY[MAX_LMBLTY-1]; break;
2339 default : ds = MBLTY[piece];
2341 pscore[c1] += ds;
2342 #ifdef DEBUG_EVAL
2343 if ( debug_eval && ds ) {
2344 fprintf(debug_eval_file,"%d for %s's piece %s in hand mobility\n",
2345 ds,ColorStr[c2],PieceStr[piece]);
2347 #endif
2348 if ( !Captured[c2][piece] )
2349 n += relative_value[piece];
2352 if ( n ) {
2353 pscore[c1] += (ds = -n*fv1[OPPDROP]/2);
2354 #ifdef DEBUG_EVAL
2355 if ( debug_eval && ds ) {
2356 fprintf(debug_eval_file,"%d for %s's captured pieces not in %s's hand\n",
2357 ds,ColorStr[c2],ColorStr[c1]);
2359 #endif
2367 short int
2368 ScorePosition (register short int side)
2371 * Perform normal static evaluation of board position. A score is generated
2372 * for each piece and these are summed to get a score for each side.
2376 register short int score;
2377 register short sq, i, xside;
2378 short int s;
2379 short int escore;
2380 short int ds;
2382 xside = side ^ 1;
2384 UpdateWeights (side);
2386 #ifdef DEBUG_EVAL
2387 if ( debug_eval )
2388 fprintf (debug_eval_file, "side = %s, stage = %d, in_opening = %d\n",
2389 ColorStr[side], stage, in_opening_stage );
2390 #endif
2392 hung[black] = hung[white] = pscore[black] = pscore[white] = 0;
2394 array_zero(shung,sizeof(shung));
2396 #ifdef CACHE
2397 #ifdef DEBUG_EVAL
2398 if (debug_eval || !(use_etable && ProbeEETable (side, &s)))
2399 #else
2400 if (!(use_etable && ProbeEETable (side, &s)))
2401 #endif
2403 #endif
2404 for (c1 = black; c1 <= white; c1++)
2406 c2 = c1 ^ 1;
2407 /* atk1 is array of atacks on squares by my side */
2408 atk1 = atak[c1];
2409 /* atk2 is array of atacks on squares by other side */
2410 atk2 = atak[c2];
2411 /* same for PC1 and PC2 */
2412 PC1 = PawnCnt[c1];
2413 PC2 = PawnCnt[c2];
2414 /* same for fv1 and fv2 */
2415 fv1 = fvalue[c1];
2416 for (i = PieceCnt[c1]; i >= 0; i--)
2418 sq = PieceList[c1][i];
2419 #if defined SAVE_SVALUE
2420 pscore[c1] += PieceValue(sq,side);
2421 #else
2422 pscore[c1] += (svalue[sq] = PieceValue(sq,side));
2423 #endif
2425 ScoreCaptures();
2427 #ifdef DEBUG_EVAL
2428 if ( debug_eval ) {
2429 fprintf(debug_eval_file,"pscore[%s] = %d, pscore[%s] = %d\n",
2430 ColorStr[side], pscore[side], ColorStr[xside], pscore[xside]);
2431 #if !defined SAVE_SVALUE
2432 debug_svalue(debug_eval_file);
2433 #endif
2435 #endif
2436 #ifdef DEBUG_EVAL
2437 if ( debug_eval ) {
2438 char buffer[80];
2439 sprintf(buffer,"%d Black and %d White HUNG PIECES",hung[black],hung[white]);
2440 debug_table (debug_eval_file,shung,buffer);
2442 #endif
2443 for ( c1=black,c2=white; c1<=white; c1++,c2-- )
2445 short n;
2447 fv1 = fvalue[c1];
2449 /* Score fifth rank */
2450 for ( sq = 36, n=0; sq <= 44; sq++ )
2451 if ( color[sq] == c1 || atak[c1][sq] != 0 )
2452 n++;
2454 if ( n != 0 ) {
2455 pscore[c1] += (ds = n*fv1[CNTRL5TH]);
2456 #ifdef DEBUG_EVAL
2457 if ( debug_eval )
2458 fprintf(debug_eval_file,"%d for %s controls 5th rank with %d points\n",
2459 ds, ColorStr[c1], n);
2460 #endif
2463 /* Score holes */
2464 for ( sq = ((c1==black)?0:54), n=0; sq<=((c1==black)?26:80); sq++ )
2465 if ( board[sq] == no_piece && atak[c1][sq] == 0 )
2466 n++;
2468 if ( n != 0 ) {
2469 pscore[c1] += (ds = -n*fv1[HOLES]);
2470 #ifdef DEBUG_EVAL
2471 if ( debug_eval && ds )
2472 fprintf(debug_eval_file,"%d for %s camp has %d holes\n",
2473 ds, ColorStr[c1], n);
2474 #endif
2477 if (hung[c1] > 1) {
2478 pscore[c1] += (ds = -fv1[HUNGX]);
2479 #ifdef DEBUG_EVAL
2480 if ( debug_eval )
2481 fprintf(debug_eval_file,"%d for %d hung pieces.\n",
2482 ds, hung[c1]);
2483 #endif
2485 /* Score opening features and castle/attack pattern distances */
2487 if ( in_opening_stage ) {
2488 pscore[c1] += (ds = ScoreKingOpeningFeatures ());
2489 #ifdef DEBUG_EVAL
2490 if ( debug_eval && ds)
2491 fprintf(debug_eval_file,"%d for %s opening features\n",
2492 ds, ColorStr[c1]);
2493 #endif
2494 pscore[c1] += (ds = ScorePatternDistance (c1));
2495 #ifdef DEBUG_EVAL
2496 if ( debug_eval && ds )
2497 fprintf(debug_eval_file,"%d for %s pattern distance\n",
2498 ds, ColorStr[c1]);
2499 #endif
2503 score = mtl[side] - mtl[xside] + pscore[side] - pscore[xside] + 10;
2505 #ifdef DEBUG_EVAL
2506 if ( debug_eval ) {
2507 fprintf(debug_eval_file,"side=%s xside=%s %d - %d + %d - %d + 10 = %d\n",
2508 ColorStr[side], ColorStr[xside],
2509 mtl[side], mtl[xside], pscore[side], pscore[xside], score);
2511 #endif
2513 #ifdef notdef
2514 if (dither)
2516 if (flag.hash)
2517 gsrand (starttime + (unsigned int) hashbd);
2518 score += urand () % dither;
2520 #endif
2522 #ifdef CACHE
2523 if ( use_etable && PUTVAR )
2524 PutInEETable(side,score);
2525 #endif
2526 #ifdef DEBUG_EVAL
2527 if ( debug_eval )
2528 fprintf (debug_eval_file, "score = %d\n", score);
2529 #endif
2530 return(score);
2531 #ifdef CACHE
2533 #ifdef DEBUG_EVAL
2534 else
2536 if ( debug_eval )
2537 fprintf (debug_eval_file, "Score cached!\n" );
2539 #endif
2541 #ifdef DEBUG_EVAL
2542 if ( debug_eval )
2543 fprintf (debug_eval_file, "s = %d\n", s);
2544 #endif
2545 return (s);
2546 #endif
2552 inline static void
2553 GuessGameType (short side_to_move)
2556 * Try to determine the game type of "side".
2559 short side, sq, gt, StaticRook[2] = {0,0}, RangingRook[2] = {0,0};
2561 for ( side=black; side<=white; side++ ) {
2563 /* computer should not change its mind */
2565 extern int bookflag;
2567 gt = GameType[side];
2569 if ( !bookflag && side == side_to_move )
2570 if ( gt == STATIC_ROOK )
2571 StaticRook[side] += 4;
2572 else if ( gt == RANGING_ROOK )
2573 RangingRook[side] += 4;
2575 /* static rook conditions */
2577 if ( on_column(side,rook,7) )
2578 StaticRook[side] += 3;
2579 if ( on_csquare(side,pawn,34) )
2580 StaticRook[side] += 6;
2581 else if ( on_csquare(side,pawn,43) )
2582 StaticRook[side] += 4;
2583 else if ( !on_column(side,pawn,7) )
2584 StaticRook[side] += 5;
2585 if ( empty_csquare(side,5) || empty_csquare(side,6) )
2586 StaticRook[side] += 2;
2587 if ( on_left_side(side,king) )
2588 StaticRook[side] += 2;
2590 /* ranging rook conditions */
2592 if ( on_left_side(side,rook) )
2593 RangingRook[side] += 5;
2594 else if ( !on_column(side,rook,7) )
2595 RangingRook[side] += 3;
2596 if ( on_csquare(side,pawn,25) )
2597 RangingRook[side] += 1;
2598 if ( on_csquare(side,pawn,30) )
2599 RangingRook[side] += 1;
2600 else
2601 RangingRook[side] -= 2;
2602 if ( !on_right_side(side,rook) )
2603 RangingRook[side] += 4;
2604 if ( on_right_side(side,king) )
2605 RangingRook[side] += 4;
2606 if ( on_csquare(side,bishop,20) )
2607 if ( on_csquare(side,silver,11) || on_csquare(side,silver,12) ||
2608 on_csquare(side,silver,21) )
2609 RangingRook[side] += 3;
2611 if ( StaticRook[side] > 5 || RangingRook[side] > 5 )
2612 GameType[side] = (StaticRook[side] > RangingRook[side])
2613 ? STATIC_ROOK : RANGING_ROOK;
2614 else
2615 GameType[side] = UNKNOWN;
2619 #ifdef DEBUG_EVAL
2620 #define StringOfGameType(side)\
2621 (GameType[side] == STATIC_ROOK ? "Static Rook" :\
2622 (GameType[side] == RANGING_ROOK ? "Ranging Rook" : "UNKNOWN"))
2624 if ( debug_eval )
2625 fprintf(debug_eval_file,"guessing game type: %s vs. %s\n",
2626 StringOfGameType(black), StringOfGameType(white));
2627 #endif
2629 if ( GameType[black] == UNKNOWN || GameType[white] == UNKNOWN )
2631 for (side = black; side <= white; side++)
2632 if ( side == computer && GameType[side] == UNKNOWN ) {
2634 * Game type is UNKNOWN.
2635 * Make a decision what type of game to play.
2636 * To make computer games more interesting, make a
2637 * random decision.
2639 if ( !on_csquare(side,pawn,25) ) {
2640 /* Play static rook if rook pawn has been pushed! */
2641 GameType[side] = STATIC_ROOK;
2642 } else {
2643 unsigned int random = urand () % 100;
2644 short d = StaticRook[side] - RangingRook[side];
2645 switch ( GameType[side ^ 1] ) {
2646 case STATIC_ROOK:
2647 if ( random < 35 + d ) GameType[side] = STATIC_ROOK;
2648 else if ( random < 95 ) GameType[side] = RANGING_ROOK;
2649 break;
2650 case RANGING_ROOK:
2651 if ( random < 75 + d) GameType[side] = STATIC_ROOK;
2652 else if ( random < 95 ) GameType[side] = RANGING_ROOK;
2653 break;
2654 default:
2655 if ( random < 33 + d) GameType[side] = STATIC_ROOK;
2656 else if ( random < 66 ) GameType[side] = RANGING_ROOK;
2659 #ifdef DEBUG_EVAL
2660 if ( debug_eval )
2661 fprintf(debug_eval_file,"decide game type: %s vs. %s\n",
2662 StringOfGameType(black), StringOfGameType(white));
2663 #endif
2670 #ifdef DEBUG_EVAL
2672 #define StringOfGameType(side)\
2673 (GameType[side] == STATIC_ROOK ? "Static Rook" :\
2674 (GameType[side] == RANGING_ROOK ? "Ranging Rook" : "UNKNOWN"))
2676 #endif
2679 static
2680 void
2681 DetermineGameType (short side_to_move)
2683 short int side;
2685 GuessGameType(side_to_move);
2687 #if !defined XSHOGI
2688 if ( flag.post )
2689 ShowGameType();
2690 #endif
2692 array_zero (Mpawn, sizeof(Mpawn));
2693 array_zero (Mlance, sizeof(Mlance));
2694 array_zero (Mknight, sizeof(Mknight));
2695 array_zero (Msilver, sizeof(Msilver));
2696 array_zero (Mgold, sizeof(Mgold));
2697 array_zero (Mbishop, sizeof(Mbishop));
2698 array_zero (Mrook, sizeof(Mrook));
2699 array_zero (Mking, sizeof(Mking));
2701 if ( in_opening_stage ) {
2702 for (side = black; side <= white; side++)
2703 UpdatePatterns (side, GameCnt);
2704 } else {
2705 ShowPatternCount(black,-1);
2706 ShowPatternCount(white,-1);
2711 void
2712 ExaminePosition (short side)
2715 * This is done one time before the search is started. Set up arrays Mwpawn,
2716 * Mbpawn, Mknight, Mbishop, Mking which are used in the SqValue() function
2717 * to determine the positional value of each piece.
2721 register short c1, piece, sq, i, bsq, wsq;
2723 /* Build enemy king distance tables. */
2725 for (sq = 0, bsq = BlackKing, wsq = WhiteKing; sq < NO_SQUARES; sq++)
2727 Kdist[black][sq] = distance(sq,bsq);
2728 Kdist[white][sq] = distance(sq,wsq);
2731 threats (black);
2732 threats (white);
2734 ExamineSquares();
2736 DetermineGameType(side);
2737 DetermineStage(side);
2739 UpdateWeights(side);
2741 array_zero (HasPiece, sizeof(HasPiece));
2743 for (c1 = black; c1 <= white; c1++)
2744 for (i = PieceCnt[c1]; i >= 0; i--)
2746 ++HasPiece[c1][piece=board[sq=PieceList[c1][i]]];
2749 #ifdef DEBUG_EVAL
2750 if ( debug_eval )
2751 for (c1=black; c1<=white; c1++)
2753 fprintf(debug_eval_file,"%s's tables\n\n",ColorStr[c1]);
2754 debug_table(debug_eval_file,Mpawn[c1],"pawn");
2755 debug_table(debug_eval_file,Mlance[c1],"lance");
2756 debug_table(debug_eval_file,Mknight[c1],"knight");
2757 debug_table(debug_eval_file,Msilver[c1],"silver");
2758 debug_table(debug_eval_file,Mgold[c1],"gold");
2759 debug_table(debug_eval_file,Mbishop[c1],"bishop");
2760 debug_table(debug_eval_file,Mrook[c1],"rook");
2761 debug_table(debug_eval_file,Mking[c1],"king");
2762 debug_table(debug_eval_file,Kdist[c1],"distance to king");
2764 #endif
2771 void
2772 DetermineStage (short side)
2775 short xside = side ^ 1, ds, db1, db2, c1,c2, feature;
2777 /* Determine initial stage */
2779 balance[side] = balance[xside] = 50;
2781 if ( GameType[side] == STATIC_ROOK && GameType[xside] == STATIC_ROOK ) {
2782 if ( GameCnt < 40 )
2783 stage = 0;
2784 else if ( GameCnt < 60 )
2785 stage = 15;
2786 else if ( GameCnt < 80 )
2787 stage = 25;
2788 else
2789 stage = 30;
2790 } else if ( GameType[side] == RANGING_ROOK || GameType[xside] == RANGING_ROOK ) {
2791 if ( GameCnt < 30 )
2792 stage = 0;
2793 else if ( GameCnt < 50 )
2794 stage = 15;
2795 else if ( GameCnt < 70 )
2796 stage = 25;
2797 else
2798 stage = 30;
2799 } else {
2800 if ( GameCnt < 35 )
2801 stage = 0;
2802 else if ( GameCnt < 55 )
2803 stage = 15;
2804 else if ( GameCnt < 75 )
2805 stage = 25;
2806 else
2807 stage = 30;
2810 #ifdef DEBUG_EVAL
2811 if ( debug_eval ) {
2812 fprintf(debug_eval_file,"initial stage value = %d\n",stage);
2813 fprintf(debug_eval_file,"initial balance values = %d,%d\n",
2814 balance[0], balance[1]);
2816 #endif
2818 /* Update stage depending on board features and attack balance value */
2820 if ( abs(ds = (mtl[side] - mtl[xside])) > (db1 = (*value)[stage][lance]) ) {
2821 db1 = abs(4 * ds / db1);
2822 if ( ds < 0 ) {
2823 balance[side] += db1;
2824 } else if ( ds > 0 ) {
2825 balance[xside] += db1;
2827 stage += (ds = db1);
2828 #ifdef DEBUG_EVAL
2829 if ( debug_eval ) {
2830 fprintf(debug_eval_file,"%d stage bonus for material balance\n",ds);
2831 fprintf(debug_eval_file,"%d %s balance bonus for material balance\n",
2832 db1, ColorStr[side]);
2834 #endif
2837 for ( c1=black, c2=white; c1<=white; c1++, c2-- ) {
2839 if ( (ds = seed[c1]) > 2 ) {
2840 balance[c1] += (db1 = ds * 2);
2841 balance[c2] -= db1;
2842 if ( stage < 30 )
2843 stage = 30;
2844 stage += ds;
2845 #ifdef DEBUG_EVAL
2846 if ( debug_eval ) {
2847 fprintf(debug_eval_file,"%d for seed pieces\n",ds);
2848 fprintf(debug_eval_file,"%d %s balance bonus for seed pieces\n",
2849 db1, ColorStr[c1]);
2850 fprintf(debug_eval_file,"%d %s balance penalty for seed pieces\n",
2851 -db1, ColorStr[c2]);
2853 #endif
2856 if ( (db1 = hung[c1]) > 2 ) {
2857 balance[c1] -= (db1 *= 2);
2858 balance[c2] += db1;
2859 #ifdef DEBUG_EVAL
2860 if ( debug_eval ) {
2861 fprintf(debug_eval_file,"%d %s balance penalty for hung pieces\n",
2862 -db1, ColorStr[c1]);
2863 fprintf(debug_eval_file,"%d %s balance bonus for hung pieces\n",
2864 db1, ColorStr[c2]);
2866 #endif
2869 if ( (db1 = loose[c1]) > 4 ) {
2870 balance[c1] -= (db1 /= 2);
2871 balance[c2] += db1;
2872 stage += (ds = 1);
2873 #ifdef DEBUG_EVAL
2874 if ( debug_eval ) {
2875 fprintf(debug_eval_file,"%d stage bonus for loose piece\n",ds);
2876 fprintf(debug_eval_file,"%d %s balance penalty for loose pieces\n",
2877 -db1, ColorStr[c1]);
2878 fprintf(debug_eval_file,"%d %s balance bonus for loose pieces\n",
2879 db1, ColorStr[c2]);
2881 #endif
2884 if ( (ds = hole[c1]) ) {
2885 balance[c1] -= (db1 = ds);
2886 balance[c2] += db1;
2887 stage += (ds /= 2);
2888 #ifdef DEBUG_EVAL
2889 if ( debug_eval ) {
2890 fprintf(debug_eval_file,"%d stage bonus for holes\n",ds);
2891 fprintf(debug_eval_file,"%d %s balance penalty for holes\n",
2892 -db1, ColorStr[c1]);
2893 fprintf(debug_eval_file,"%d %s balance bonus for holes\n",
2894 db1, ColorStr[c2]);
2896 #endif
2899 if ( (db1 = target[c1]) > 3 ) {
2900 balance[c1] += (db1 /= 3);
2901 balance[c2] -= db1;
2902 stage += (ds = db1 / 4);
2903 #ifdef DEBUG_EVAL
2904 if ( debug_eval ) {
2905 fprintf(debug_eval_file,"%d stage bonus for targets\n",ds);
2906 fprintf(debug_eval_file,"%d %s balance bonus for targets\n",
2907 db1, ColorStr[c1]);
2908 fprintf(debug_eval_file,"%d %s balance penalty for targets\n",
2909 -db1, ColorStr[c2]);
2911 #endif
2914 stage += (ds = captured[c1]/2);
2915 #ifdef DEBUG_EVAL
2916 if ( debug_eval && ds ) {
2917 fprintf(debug_eval_file,"%d stage bonus for captured pieces\n",ds);
2919 #endif
2921 if ( (db1 = captured[c1]) > 4 ) {
2922 balance[c1] += (db1 /= 2);
2923 stage += (ds = 3);
2924 #ifdef DEBUG_EVAL
2925 if ( debug_eval ) {
2926 fprintf(debug_eval_file,"%d stage bonus for pieces in hand\n",ds);
2927 fprintf(debug_eval_file,"%d %s balance bonus for pieces in hand\n",
2928 db1, ColorStr[c1]);
2930 #endif
2933 if ( (db1 = dcaptured[c1]) > 3 ) {
2934 balance[c1] += db1;
2935 stage += (ds = 3);
2936 #ifdef DEBUG_EVAL
2937 if ( debug_eval ) {
2938 fprintf(debug_eval_file,"%d stage bonus for different piece types in hand\n",ds);
2939 fprintf(debug_eval_file,"%d %s balance bonus for different piece types in hand\n",
2940 db1, ColorStr[c1]);
2942 #endif
2945 if ( balance[c1] > 99 ) balance[c1] = 99;
2946 else if ( balance[c1] < 0 ) balance[c1] = 0;
2950 #ifdef DEBUG_EVAL
2951 if ( debug_eval )
2952 for ( c1 = black; c1 <= white; c1++ )
2953 fprintf(debug_eval_file,"balance[%s] = %d\n",ColorStr[c1],balance[c1]);
2954 #endif
2956 if ( stage > 99 ) stage = 99;
2957 else if ( stage < 0 ) stage = 0;
2959 #ifdef DEBUG_EVAL
2960 if ( debug_eval )
2961 fprintf(debug_eval_file,"stage = %d\n",stage);
2963 #endif
2965 if ( flag.post )
2966 ShowStage ();
2968 /* Determine stage dependant weights */
2970 ADVNCM[pawn] = 1; /* advanced pawn bonus increment*/
2971 ADVNCM[lance] = 1;
2972 ADVNCM[knight] = 1;
2973 ADVNCM[silver] = 1; /* advanced silver bonus increment */
2974 ADVNCM[gold] = 1; /* advanced gold bonus increment */
2975 ADVNCM[bishop] = 1;
2976 ADVNCM[rook] = 1;
2977 ADVNCM[king] = 1; /* advanced king bonus increment */
2979 MAXCDIST = (stage < 33 ) ? (33 - stage)/4 : 0;
2980 MAXADIST = (stage < 30 ) ? (30 - stage)/4 : 0;
2982 #ifdef DEBUG_EVAL
2983 if ( debug_eval ) {
2984 fprintf(debug_eval_file,"maximum distance to castle pattern: %d\n",MAXCDIST);
2985 fprintf(debug_eval_file,"maximum distance to attack pattern: %d\n",MAXADIST);
2987 #endif
2989 for ( c1 = black; c1 <= white; c1++ ) {
2990 for ( feature = 0; feature < NO_FEATURES; feature++ ) {
2991 fvalue[c1][feature] =
2992 ((((*fscore)[stage][feature][0] * (99 - balance[c1])) + 50) / 100)
2993 + ((((*fscore)[stage][feature][1] * balance[c1]) + 50) / 100);
2997 #ifdef DEBUG_EVAL
2998 if ( debug_eval ) {
2999 fprintf(debug_eval_file,"weighted and balanced feature values\n");
3000 fprintf(debug_eval_file," Black White\n");
3001 for ( feature = 0; feature < NO_FEATURES; feature++ ) {
3002 fprintf(debug_eval_file,"%3d %5d %5d\n",
3003 feature,fvalue[0][feature],fvalue[1][feature]);
3006 #endif
3010 void
3011 UpdateWeights (short stage)
3017 * Compute stage dependent relative material values assuming
3018 * linearity between the main stages:
3020 * minstage < stage < maxstage =>
3021 * stage - minstage value - minvalue
3022 * ------------------- = -------------------
3023 * maxstage - minstage maxvalue - minvalue
3027 static short linear_piece_value (short piece, short stage, short i, short j)
3029 short minvalue, maxvalue, minstage, maxstage;
3030 minstage = ispvalue[0][i];
3031 maxstage = ispvalue[0][j];
3032 minvalue = ispvalue[piece][i];
3033 maxvalue = ispvalue[piece][j];
3034 return ((stage-minstage)*(maxvalue-minvalue)/(maxstage-minstage))+minvalue;
3037 static short linear_feature_value (short feature, short stage, short i, short j)
3039 short minvalue, maxvalue, minstage, maxstage;
3040 minstage = ispvalue[0][i];
3041 maxstage = ispvalue[0][j];
3042 minvalue = weight[feature][i];
3043 maxvalue = weight[feature][j];
3044 return ((stage-minstage)*(maxvalue-minvalue)/(maxstage-minstage))+minvalue;
3049 * matweight = percentage_of_max_value * max_value(stage) / 100
3050 * max_value(0) = MAX_VALUE; max_value(100) = MIN_VALUE
3051 * => max_value(stage) = a*stage+b; b=MAX_VALUE, a=(MIN_VALUE-MAX_VALUE)/100
3054 #define MIN_VALUE 300
3055 #define MAX_VALUE 1000
3057 #define max_value(stage) ((long)(MIN_VALUE - MAX_VALUE) * stage + (long)100 * MAX_VALUE)
3058 #define matweight(value,stage) ((long)max_value(stage) * value / 10000)
3061 void
3062 Initialize_eval (void)
3064 register short stage, piece, feature, i;
3066 for ( stage = 0; stage < NO_STAGES; stage++ ) {
3067 for ( i = 0; i < MAIN_STAGES; i++ ) {
3068 if ( stage == ispvalue[0][i] ) {
3069 for ( piece = 0; piece < NO_PIECES; piece++ )
3070 (*value)[stage][piece] =
3071 matweight(ispvalue[piece][i],stage);
3072 for ( feature = 0; feature < NO_FEATURES; feature++ ) {
3073 (*fscore)[stage][feature][0] =
3074 (weight[feature][i] * weight[feature][MAIN_STAGES] + 50) / 100;
3075 (*fscore)[stage][feature][1] =
3076 (weight[feature][i] * weight[feature][MAIN_STAGES+1] + 50) / 100;
3078 break;
3079 } if ( stage < ispvalue[0][i+1] ) {
3080 for ( piece = 0; piece < NO_PIECES; piece++ )
3081 (*value)[stage][piece] =
3082 matweight(linear_piece_value(piece,stage,i,i+1),stage);
3083 for ( feature = 0; feature < NO_FEATURES; feature++ ) {
3084 (*fscore)[stage][feature][0] =
3085 (linear_feature_value(feature,stage,i,i+1)
3086 * weight[feature][MAIN_STAGES] + 50) /100;
3087 (*fscore)[stage][feature][1] =
3088 (linear_feature_value(feature,stage,i,i+1)
3089 * weight[feature][MAIN_STAGES+1] + 50) /100;
3091 break;
3096 #ifdef DEBUG_EVAL
3097 debug_eval = ((debug_eval_file = fopen(EVALFILE,"w")) != NULL);
3098 if ( debug_eval ) {
3099 fprintf(debug_eval_file,"stage dependent absolute material values\n\n");
3100 fprintf(debug_eval_file," # - P L N S G B R +P +L +N +S +B +R K\n");
3101 for ( stage = 0; stage < NO_STAGES; stage++ ) {
3102 fprintf(debug_eval_file,"%3d:",stage);
3103 for ( piece = 0; piece < NO_PIECES; piece++ ) {
3104 fprintf(debug_eval_file,"%4d",(*value)[stage][piece]);
3106 fprintf(debug_eval_file,"\n");
3108 fprintf(debug_eval_file,"\n");
3109 fprintf(debug_eval_file,"stage dependent absolute feature scores\n\n");
3110 fprintf(debug_eval_file," # ");
3111 for ( feature = 0; feature < NO_FEATURES; feature++ )
3112 fprintf(debug_eval_file,"%5d ",feature);
3113 fprintf(debug_eval_file,"\n");
3114 for ( stage = 0; stage < NO_STAGES; stage++ ) {
3115 fprintf(debug_eval_file,"%3d:",stage);
3116 for ( feature = 0; feature < NO_FEATURES; feature++ ) {
3117 fprintf(debug_eval_file," %3d,%3d",
3118 (*fscore)[stage][feature][0], (*fscore)[stage][feature][1]);
3120 fprintf(debug_eval_file,"\n");
3122 fprintf(debug_eval_file,"\n");
3123 fclose(debug_eval_file);
3124 debug_eval = false;
3126 #endif