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)
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.
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 */
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 */
121 #define KNGPROTECT 25
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
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 };
249 static small_short *PC1, *PC2;
251 static small_short *fv1;
253 static long *atk1, *atk2;
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)
264 return(board[sq=csquare(side,square)]==piece && color[sq]==side);
267 inline static short on_column(short side,short piece,short c)
269 for (sq = c; sq < NO_SQUARES; sq+=9)
270 if (on_csquare(side,piece,sq))
275 #define empty_csquare(side,square)\
276 (board[csquare(side,square)]==no_piece)
278 inline static short on_left_side(short side,short piece)
281 if (on_column(side,piece,c))
286 inline static short on_right_side(short side,short piece)
288 for (c=5; c<NO_COLS; c++)
289 if (on_column(side,piece,c))
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
312 debug_svalue (FILE *D)
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]);
333 debug_table (FILE *D, small_short *table, char *s)
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]);
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;
369 register unsigned char far *ppos, *pdir;
371 short i, kd, piece, xside;
374 if ( MatchSignature(threats_signature[side]) ) {
375 /* data valid for current positional signature */
382 array_zero (a, NO_SQUARES * sizeof(a[0]));
384 PL = PieceList[side];
385 for (i = PieceCnt[side]; i >= 0; i--)
389 ptyp = ptype[side][piece];
392 u = first_direction(ptyp,&d,sq);
394 ppos = (*nextpos[ptyp])[sq];
395 pdir = (*nextdir[ptyp])[sq];
399 a[u] = ((a[u]+1) | c);
400 if ( (kd = Kdist[xside][u]) < 2 ) {
405 u = ((color[u] == neutral) ? next_position(ptyp,&d,sq,u)
406 : next_direction(ptyp,&d,sq));
408 u = ((color[u] == neutral) ? ppos[u] : pdir[u]);
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)
430 tsq = (side == black) ? nunmap[isq+id] : nunmap[isq-id];
432 target[xside = side^1]++;
433 if ( atak[side][tsq] )
434 starget[xside][tsq]++; /* protected target square */
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);
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);
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);
464 case bishop: /* vertically ahead */
465 add_target(sq,side,11);
467 case knight: /* vertically ahead if advanced */
468 if ( sq != 1 && sq != 7 && sq != 73 && sq != 79 )
469 add_target(sq,side,11);
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 */
484 c = 4 - ccolumn(c1,sq);
485 if ( c < 0 || (c == 0 && sq != kingP[c1]) ) {
486 s += (ds = -c - c - fv1[OPENWRONG]);
489 fprintf(debug_eval_file,"%d for king on right side (Static)\n",ds);
492 } else if ( GameType[c1] == RANGING_ROOK ) {
493 /* Malus for king on left side or fifth file */
495 c = 4 - ccolumn(c1,sq);
496 if ( c > 0 || (c == 0 && sq != kingP[c1]) ) {
497 s += (ds = -c - c - fv1[OPENWRONG]);
500 fprintf(debug_eval_file,"%d for king on left side (Ranging)\n",ds);
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]);
509 fprintf(debug_eval_file,"%d for king moved before rook switch (Ranging)\n",ds);
513 /* Malus for sitting king after rook switch */
514 if ( !on_csquare(c1,rook,16) ) {
515 s += (ds = -2 * fv1[OPENWRONG]);
518 fprintf(debug_eval_file,"%d for sitting king after rook switch (Ranging)\n",ds);
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]);
528 fprintf(debug_eval_file,"%d for defending general moved before king switch (Ranging)\n",ds);
539 ExamineSquares (void)
542 register short sq, side, piece, n;
544 if ( MatchSignature(squares_signature) ) {
545 /* data valid for current positional signature */
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] ) {
564 } else if ( InBlackCamp(sq) ) {
565 if ( !atak[black][sq] ) {
572 { /* occupied by "side" piece */
573 if ( !atak[side][sq] ) {
577 CheckTargetPiece(sq,side);
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);
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 ) {
611 fprintf(debug_eval_file,"%s captured=%d dcaptured=%d\n",
612 ColorStr[side],captured[side], dcaptured[side]);
617 /* Data valid for current positional signature */
618 CopySignature(squares_signature);
623 /* ............ POSITIONAL EVALUATION ROUTINES ............ */
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,
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;
667 s = -Pscore[ply - 1] + mtl[side] - mtl[xside] /* - INCscore */;
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 );
675 hung[black] = hung[white] = 0;
677 /* should we use the estimete or score the position */
680 (ply > Sdepth && s >= (alpha - 30) && s <= (beta + 30))
682 || (use_etable && CheckEETable (side))
686 /* score the position */
689 fprintf (debug_eval_file, "do NOT use the estimete\n");
691 array_zero (sseed, sizeof(sseed));
693 seed[0] = seed[1] = 0;
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);
700 *InChk = (board[sq=PieceList[side][0]] == king) ? Anyatak (xside, sq) : false;
708 s = ScorePosition (side);
713 /* use the estimate but look at check */
717 fprintf (debug_eval_file, "use the estimete\n");
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);
731 static short value_of_weakest_attacker (long a2)
733 register short piece;
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]) )
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.
763 register unsigned char far *ppos, *pdir;
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];
772 rvalue = (*value)[stage][piece];
773 ptyp = ptype[c1][upiece = unpromoted[piece]];
774 rvalue = (*value)[stage][upiece];
776 u = first_direction(ptyp,&d,sq);
778 ppos = (*nextpos[ptyp])[sq];
779 pdir = (*nextdir[ptyp])[sq];
782 pin = -1; /* start new direction */
786 s += (ds = fv1[CTRLK] * (2-Kd[u]));
789 fprintf(debug_eval_file,"%d for threatening square %d away from enemy king\n",
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]);
800 fprintf(debug_eval_file,"%d for threatening target square\n",ds);
804 if ( (ds = shole[u]) != 0 ) {
805 /* attacking or protecting a hole */
806 s += (ds = fv1[HOLES]);
809 fprintf(debug_eval_file,"%d for threatening a hole\n",ds);
811 } else if ( InPromotionZone(c1,u) ) {
812 /* attacking a square in promotion zone */
813 s += (ds = fv1[HOLES] / 2);
816 fprintf(debug_eval_file,"%d for threatening promotion zone\n",ds);
819 if (color[u] == neutral)
823 xu = next_position(ptyp,&d,sq,u);
824 if ( xu == next_direction(ptyp,&dd,sq) )
825 pin = -1; /* oops new direction */
827 if ((xu = ppos[u]) == pdir[u])
828 pin = -1; /* oops new direction */
834 { /* there is a piece in current direction */
836 { /* it's the first piece in the current direction */
839 fprintf(debug_eval_file,
840 "first piece on square %d is an %s piece\n",
841 u, (color[u]==c1) ? "own" : "enemy");
843 if ( color[u] == c1 ) {
844 /* own intercepting piece in xray attack */
845 if ( upiece == lance ) {
847 if ( board[u] == pawn ) {
848 s += (ds = 2*fv1[PROTECT]);
851 fprintf(debug_eval_file,"%d for lance protecting pawn\n",ds);
853 } else if ( in_opening_stage ) {
854 s += (ds = -2*fv1[PROTECT]);
857 fprintf(debug_eval_file,"%d for lance protecting non-pawn\n",ds);
861 /* bishop or rook xray */
862 if ( upiece == bishop && board[u] == pawn && GameType[c1] == STATIC_ROOK ) {
863 s += (ds = -2*fv1[HCLSD]);
866 fprintf(debug_eval_file,"%d for own pawn in bishops direction\n",ds);
868 } else if ( upiece == rook && board[u] == lance && GameType[c1] == STATIC_ROOK && column(u) == csq) {
869 s += (ds = fv1[XRAY]);
872 fprintf(debug_eval_file,"%d for lance supported by rook\n",ds);
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]);
884 fprintf(debug_eval_file,"%d for lance attacking pawn\n",ds);
886 } else if ( in_opening_stage ) {
887 s += (ds = 2*fv1[PROTECT]);
890 fprintf(debug_eval_file,"%d for lance attacking non-pawn\n",ds);
894 /* bishop or rook pin attack */
895 if ( board[u] == pawn ) {
896 s += (ds = -fv1[HCLSD]);
899 fprintf(debug_eval_file,"%d for enemy pawn in bishops direction\n",ds);
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 */
910 if ((xu = ppos[u]) != pdir[u])
911 pin = u; /* not on the edge and on to find a pin */
917 /* it's the second piece in the current direction */
920 fprintf(debug_eval_file,
921 "second piece on square %d is an %s piece\n",
922 u, (color[u]==c1) ? "own" : "enemy");
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]);
930 fprintf(debug_eval_file,"%d for own pawn in bishops (2) direction\n",ds);
934 /* second piece is an enemy piece */
935 if ( upiece == bishop && board[u] == pawn ) {
936 s += (ds = -fv1[HCLSD]/2);
939 fprintf(debug_eval_file,"%d for enemy pawn in bishops (2) direction\n",ds);
942 if ((*value)[stage][xupiece = unpromoted[board[u]]] > rvalue || atk2[u] == 0) {
945 fprintf(debug_eval_file,"enemy %s better than attacking %s\n",
946 PieceStr[upiece], PieceStr[xupiece]);
948 if (color[pin] == c2) {
949 if ( xupiece == king && in_endgame_stage ) {
950 s += (ds = 2*fv1[PINVAL]);
952 if ( debug_eval && ds )
953 fprintf(debug_eval_file,"%d for pin attack to king\n",ds);
956 s += (ds = fv1[PINVAL]);
958 if ( debug_eval && ds )
959 fprintf(debug_eval_file,"%d for pin attack\n",ds);
962 if (atk2[pin] == 0 || atk1[pin] > control[board[pin]] + 1) {
967 if ( upiece == lance ) {
968 s += (ds = fv1[XRAY]/2);
970 if ( debug_eval && ds )
971 fprintf(debug_eval_file,"lance xray attack: %d\n",ds);
974 s += (ds = fv1[XRAY]);
977 fprintf(debug_eval_file,"bishop/rook xray attack: %d\n",ds);
983 pin = -1; /* new direction */
985 u = next_direction(ptyp,&d,sq);
999 #define ctlSG (ctlS | ctlG | ctlPp | ctlLp | ctlNp | ctlSp)
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]
1017 #define ScoreThreat \
1018 { if (color[u] != c2)\
1019 if (atk1[u] == 0 || (atk2[u] & CNT_MASK) > 1) {\
1022 s += (ds = -fv1[CTRLK]);\
1024 fprintf(debug_eval_file,"%d for squares near king controlled by enemy %s\n",\
1031 #define ScoreThreat \
1032 { if (color[u] != c2)\
1033 if (atk1[u] == 0 || (atk2[u] & CNT_MASK) > 1) {\
1036 s += (ds = -fv1[CTRLK]);\
1048 register unsigned char far *ppos, *pdir;
1050 register short int s;
1051 register short u, ptyp;
1057 /* Penalties, if a king can be threatened by checks. */
1062 for ( p = pawn; p < king; p++ )
1063 if ( HasPiece[c2][p] || Captured[c2][p] )
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];
1072 u = first_direction(ptyp,&d,sq);
1074 ppos = (*nextpos[ptyp])[sq];
1075 pdir = (*nextdir[ptyp])[sq];
1080 /* If a p piece can reach (controls or can drop to)
1081 * square u, then score threat.
1083 if (atk2[u] & control[p])
1085 else if (Captured[c2][p] && color[u] == neutral)
1088 u = ((color[u] == neutral) ? next_position(ptyp,&d,sq,u)
1089 : next_direction(ptyp,&d,sq));
1091 u = ((color[u] == neutral) ? ppos[u] : pdir[u]);
1097 s += (ds = fv1[KSFTY] * KTHRT[cnt] / 16);
1100 if ( debug_eval && ds )
1101 fprintf(debug_eval_file,"%d for possible king threats\n",ds);
1104 /* Penalties, if squares near king are controlled by enemy. */
1108 ptyp = ptype[c1][king];
1110 u = first_direction(ptyp,&d,sq);
1112 pdir = (*nextpos[ptyp])[sq];
1117 if ( !ok && color[u] == c1 )
1119 short ptype_piece = ptype[black][board[u]];
1120 if ( ptype_piece == ptype_silver || ptype_piece == ptype_gold )
1123 if (atk2[u] > atk1[u])
1126 if (atk2[u] & ctlSG) {
1127 s += (ds = -fv1[KSFTY]/2);
1130 fprintf(debug_eval_file,"%d square controlled by near enemy silver or gold\n",ds);
1135 u = next_direction(ptyp,&d,sq);
1141 if ( !ok || cnt > 1) {
1143 s += (ds = -fv1[KSFTY]/2);
1145 s += (ds = -fv1[KSFTY]);
1149 fprintf(debug_eval_file,"%d for no general protect king\n",ds);
1151 fprintf(debug_eval_file,"%d for %d enemy generals dear king\n",cnt,ds);
1159 static short checked_trapped;
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;
1176 register unsigned char far *ppos, *pdir;
1178 register short int piece;
1182 rvalue = (*value)[stage][piece];
1183 ptyp = ptype[c1][piece];
1185 u = first_direction(ptyp,&d,sq);
1187 ppos = (*nextpos[ptyp])[sq];
1188 pdir = (*nextdir[ptyp])[sq];
1193 if (atk2[u] == 0 || (*value)[stage][board[u]] >= rvalue)
1196 u = ((color[u] == neutral) ? next_position(ptyp,&d,sq,u)
1197 : next_direction(ptyp,&d,sq));
1199 u = ((color[u] == neutral) ? ppos[u] : pdir[u]);
1204 fprintf(debug_eval_file,"piece is trapped\n");
1206 checked_trapped = true;
1213 static int AttackedPieceValue (register short int sq, short int side)
1219 ds += (ds = -fv1[HUNGP]);
1224 fprintf(debug_eval_file,"attacked: %d, hung[%s]++\n",
1234 fprintf(debug_eval_file,"trapped: hung[%s] += 2\n",
1245 OpenFileValue (register short sq, short hopn, short hopnx)
1249 if (PC1[fyle = column(sq)] == 0)
1253 if (debug_eval && hopn)
1254 fprintf(debug_eval_file,"adding %d for now own pawn on file\n",hopn);
1262 if (debug_eval && hopnx)
1263 fprintf(debug_eval_file,"%d for no opponents pawn on file\n",hopnx);
1271 /* Distance bonus */
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); \
1284 #define PromotionZoneDistanceValue(sq,dd)\
1285 if ( ds = fv1[PROMD] ) { \
1286 s += (ds = ds * PromotionZoneDistanceBonus[crow(c1,sq)] * dd);\
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); \
1303 #define OwnKingDistanceValue(sq,dd,maxd)\
1304 if ( (ds = fv1[KINGOD]) && ((ad = Kdist[c1][sq]) <= maxd) ) { \
1305 s += (ds = ds * OwnKingDistanceBonus[ad] * dd);\
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); \
1322 #define EnemyKingDistanceValue(sq,dd,maxd)\
1323 if ( (ds = fv1[KINGOD]) && ((ad = Kdist[c2][sq]) <= maxd) ) { \
1324 s += (ds = ds * EnemyKingDistanceBonus[ad] * dd);\
1333 PawnValue (register short int sq, short int side)
1335 * Calculate the positional value for a pawn on 'sq'.
1342 short ccol = ccolumn(c1,sq);
1344 PromotionZoneDistanceValue(sq,3);
1347 if ( color[(c1==black)?(sq+9):(sq-9)] == neutral ) {
1348 s += (ds = MBLTY[pawn]);
1350 if ( debug_eval && ds )
1351 fprintf(debug_eval_file,"%d for mobility\n", ds);
1355 if ( (a1 & ((ctlR | ctlRp) | ctlL)) ) {
1356 s += (ds = fv1[ATAKD]);
1358 if ( debug_eval && ds )
1359 fprintf(debug_eval_file,"%d for rook/lance-supported pawn\n",ds);
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)) */
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]);
1376 if ( debug_eval && ds )
1377 fprintf(debug_eval_file,"%d for opposing pawn pushed\n",ds);
1381 if ( GameType[c1] == STATIC_ROOK && sq == csquare(c1,43) )
1382 if ( (atk2[csquare(c1,52)] & CNT_MASK) < 2 )
1384 s += (ds = fv1[ATAKD]);
1387 fprintf(debug_eval_file,"%d for attacking pawn on 2nd col\n",ds);
1391 if ( GameType[c2] == STATIC_ROOK && ccol == 1 )
1393 if ( sq == csquare(c1,28) )
1395 s += (ds = -fv1[ATAKD]);
1398 fprintf(debug_eval_file,"%d for pushed pawn on 8th file\n",ds);
1401 if ( (atk1[csquare(c1,19)] & CNT_MASK) < 2 && (atk1[csquare(c1,28)] & CNT_MASK) < 2 )
1403 s += (ds = -2*fv1[ATAKD]);
1406 fprintf(debug_eval_file,"%d for weak pawn on 8th col\n",ds);
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]);
1437 fprintf(debug_eval_file,"%d for lance in danger\n",ds);
1442 s += (ds = -2*fv1[ATAKD]);
1445 fprintf(debug_eval_file,"%d for lance in danger\n",ds);
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 )
1471 s += (ds = -4*fv1[ATAKD]);
1474 fprintf(debug_eval_file,"%d for knight in danger\n",ds);
1479 s += (ds = -3*fv1[ATAKD]);
1481 if ( debug_eval && ds )
1482 fprintf(debug_eval_file,"%d for knight in danger\n",ds);
1487 if ( c == 0 || c == 8 ) {
1488 s += (ds = -fv1[ATAKD]);
1491 fprintf(debug_eval_file,"%d for knight on edge file\n",ds);
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]);
1513 fprintf(debug_eval_file,"%d for good cohesion\n",ds);
1517 if ( in_opening_stage ) {
1518 if ( GameType[c1] == STATIC_ROOK )
1519 if ( csquare(c1,sq) == 12 )
1522 if ( board[csq = csquare(c1,20)] == bishop && color[csq] == c1 )
1524 s += (ds = -2*fv1[OPENWRONG]);
1527 fprintf(debug_eval_file,"%d for wrong opening\n",ds);
1532 EnemyKingDistanceValue(sq,2,3);
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]);
1553 fprintf(debug_eval_file,"%d for good cohesion\n",ds);
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]);
1564 fprintf(debug_eval_file,"%d for wrong opening\n",ds);
1568 EnemyKingDistanceValue(sq,2,3);
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]);
1591 fprintf(debug_eval_file,"%d for open bishops diagonal\n",ds);
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]);
1603 fprintf(debug_eval_file,"%d for closed bishops diagonal\n",ds);
1605 } else if ( csquare(c1,sq) == 20 && !empty_csquare(c1,30) ) {
1606 s += (ds = -fv1[OPENWRONG]);
1609 fprintf(debug_eval_file,"%d for closed bishops diagonal\n",ds);
1614 EnemyKingDistanceValue(sq,1,3);
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 */
1641 fprintf(debug_eval_file,"%d for rook on 8th file\n",ds);
1644 /* Bonus for rook on right side, malus for rook on left side */
1647 s += (ds = c + c + OPOK);
1648 } else if ( c >= 0 ) {
1649 s += (ds = -c - c - WRONG);
1652 if ( debug_eval && ds )
1653 fprintf(debug_eval_file,"%d for king on correct/wrong side\n",ds);
1656 else if ( GameType[c1] == RANGING_ROOK )
1658 /* Bonus for rook on left side and bishops diagonal closed, malus otherwise. */
1660 c = 4 - ccolumn(c1,sq); ds = 0;
1662 /* Bishops diagonal should not be open */
1663 if ( on_csquare(c1,pawn,30) )
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;
1675 if ( debug_eval && ds )
1676 fprintf(debug_eval_file,"%d for bishops diagonal\n",ds);
1680 EnemyKingDistanceValue(sq,1,3);
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);
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);
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);
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);
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);
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]);
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 )
1783 if ( in_opening_stage )
1784 if ( GameType[c1] != UNKNOWN && ccolumn(c1,sq) == 4 ) {
1785 s += (ds = -fv1[OPENWRONG]/3);
1787 if ( debug_eval && ds )
1788 fprintf(debug_eval_file,"%d for center king\n",ds);
1790 } else if ( GameType[c1] == STATIC_ROOK && on_right_side(c1,sq) ) {
1791 s += (ds = -fv1[OPENWRONG]/2);
1793 if ( debug_eval && ds )
1794 fprintf(debug_eval_file,"%d for king on right side\n",ds);
1796 } else if ( GameType[c1] == RANGING_ROOK && on_left_side(c1,sq) ) {
1797 s += (ds = -fv1[OPENWRONG]/2);
1799 if ( debug_eval && ds )
1800 fprintf(debug_eval_file,"%d for king on left side\n",ds);
1804 if ( ds = fv1[HOPN] ) {
1805 s += OpenFileValue(sq,-2*ds,-4*ds);
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;
1825 if ( piece == no_piece )
1828 s = (*Mpiece[piece])[c1][sq];
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);
1836 checked_trapped = false;
1838 if ( sweep[piece] ) {
1839 /* pin/xray attack and mobility for sweeping pieces */
1840 s += (ds = BRLscan (sq, &mob));
1843 fprintf(debug_eval_file,"%d sum for sweeping piece\n", ds);
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);
1850 s += (ds = LMBLTY[mob] * fv1[MOBILITY] / 100);
1853 fprintf(debug_eval_file,"%d for mobility of sweeping piece\n", ds);
1856 /* mobility for non-sweeping pieces */
1863 { /* opponent attacks piece */
1865 { /* undefended piece */
1866 s += AttackedPieceValue (sq, side);
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]);
1882 fprintf(debug_eval_file,"exchange option: %d\n", ds);
1887 { /* piece is not defended by a pawn */
1888 s += (ds = -fv1[ATAKD]);
1891 fprintf(debug_eval_file,"not defended by pawn: %d\n", ds);
1898 if ( piece != king ) {
1901 /* piece is defended */
1902 s += (ds = (a1 & CNT_MASK)*fv1[PROTECT]);
1905 fprintf(debug_eval_file,"%d for protected piece\n", ds);
1910 s += (ds = fv1[SEED]);
1913 fprintf(debug_eval_file,"%d for seed piece\n", ds);
1918 s += (ds = -fv1[LOOSE]);
1921 fprintf(debug_eval_file,"%d for loose piece\n", ds);
1925 if ( starget[c1][sq] ) {
1926 if ( sweep[piece] ) {
1927 s -= (ds = -fv1[ATAKD]/2);
1930 fprintf(debug_eval_file,"%d for sweeping piece on own target square\n", ds);
1932 } else if ( piece == pawn ) {
1933 s += (ds = fv1[ATAKD]);
1936 fprintf(debug_eval_file,"%d for pawn on own target square\n", ds);
1941 if ( starget[c2][sq] ) {
1942 if ( piece != pawn ) {
1943 s -= (ds = -fv1[ATAKD]/3);
1946 fprintf(debug_eval_file,"%d for non-pawn on opponents target square\n", ds);
1949 s += (ds = fv1[ATAKD]);
1952 fprintf(debug_eval_file,"%d for pawn on opponents target square\n", ds);
1957 if ( Kdist[c1][sq] == 1 ) {
1958 s += (ds = fv1[KSFTY]);
1961 fprintf(debug_eval_file,"%d for piece near king\n", ds);
1969 s += PawnValue (sq, side);
1972 s += LanceValue (sq, side);
1975 s += KnightValue (sq, side);
1978 s += SilverValue (sq, side);
1981 s += GoldValue (sq, side);
1984 s += BishopValue (sq, side);
1987 s += RookValue (sq, side);
1990 s += KingValue (sq, side);
1993 s += PPawnValue (sq, side);
1996 s += PLanceValue (sq, side);
1999 s += PKnightValue (sq, side);
2002 s += PSilverValue (sq, side);
2005 s += PBishopValue (sq, side);
2008 s += PRookValue (sq, side);
2017 ScorePatternDistance (short c1)
2020 * Score distance to pattern regarding the game type which side plays.
2025 small_short *fv1 = fvalue[c1];
2031 fprintf(debug_eval_file,"scoring castle pattern distance for PCASTLE=%d\n",
2035 if ( MAXCDIST > 0 && fv1[PCASTLE] != 0 && ((os = castle_opening_sequence[c1]) >= 0) )
2037 ds = board_to_pattern_distance(c1,os,MAXCDIST,GameCnt);
2039 s += (ds *= fv1[PCASTLE]);
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);
2051 else if ( debug_eval && os<0 )
2052 fprintf(debug_eval_file,"no castle pattern for %s\n",ColorStr[c1]);
2057 fprintf(debug_eval_file,"scoring attack pattern distance for PATTACK=%d\n",
2061 if ( MAXADIST > 0 && fv1[PATTACK] != 0 && ((os = attack_opening_sequence[c1]) >= 0) )
2063 ds = board_to_pattern_distance(c1,os,MAXADIST,GameCnt);
2065 s += (ds *= fv1[PATTACK]);
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);
2077 else if ( debug_eval && os<0 )
2078 fprintf(debug_eval_file,"no attack pattern for %s\n",ColorStr[c1]);
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.
2097 short xside = side ^ 1;
2099 short i, j, k, n = 0;
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);
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");
2135 fprintf(debug_eval_file,"no castle pattern %s for %s\n",
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++;
2155 ShowPatternCount(side,n);
2158 if ( os!=END_OF_SEQUENCES ) update_advance_bonus (side,os);
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");
2176 fprintf(debug_eval_file,"no attak pattern %s for %s\n",
2194 for ( sq = 0; sq < NO_SQUARES; sq++ ) {
2196 for ( c1 = black, c2 = white; c1 <= white; c1++, c2-- ) {
2202 if ( InPromotionZone(c1,sq) ) {
2203 /* square in promotion zone */
2204 if ( a1 & control[pawn] ) {
2206 pscore[c1] += (ds = 2*fv1[DNGLPC]);
2209 fprintf(debug_eval_file,"%d for %s dangling pawn\n",ds,ColorStr[c1]);
2213 if ( a1 & (control[lance] | control[knight]) ) {
2214 /* dangling lance or dangling knight */
2215 pscore[c1] += (ds = fv1[DNGLPC]);
2218 fprintf(debug_eval_file,"%d for %s dangling knight/silver\n",ds,ColorStr[c1]);
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]);
2229 fprintf(debug_eval_file,"%d for %s protects own king\n",ds,ColorStr[c1]);
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]);
2240 fprintf(debug_eval_file,"%d for %s controls enemy king\n",ds,ColorStr[c1]);
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]);
2251 fprintf(debug_eval_file,"%d for %s attacks enemy's focal point\n",ds,ColorStr[c1]);
2258 if ( (c1 = color[sq]) == neutral ) {
2264 /* occupied square */
2272 if ( a2 && sloose[sq] ) {
2273 pscore[c2] += (ds = fv1[LSATTACK]);
2276 fprintf(debug_eval_file,"%d for %s attacks loose piece\n",ds,ColorStr[c2]);
2280 if ( a2 && !Captured[c2][unpromoted[board[sq]]] ) {
2281 pscore[c2] += (ds = fv1[NIHATTACK]);
2283 if ( debug_eval && ds ) {
2284 fprintf(debug_eval_file,"%d for %s attack piece not in hand\n",ds,ColorStr[c2]);
2298 ScoreCaptures (void)
2300 short ds, col, n, m, piece;
2302 if ( n = Captured[c1][pawn] ) {
2304 for ( col = 0; col < NO_COLS; col++ ) {
2310 pscore[c1] += (ds *= ((n > 2) ? 3 : n));
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);
2319 if ( m = seed[c1] ) {
2320 for ( piece = lance, n=0; piece <= rook; piece++ ) {
2321 if ( Captured[c1][piece] )
2324 pscore[c1] += (ds = m*fv1[DFFDROP]);
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);
2333 for ( piece = pawn, n = 0; piece <= rook; piece++ ) {
2334 if ( Captured[c1][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];
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]);
2348 if ( !Captured[c2][piece] )
2349 n += relative_value[piece];
2353 pscore[c1] += (ds = -n*fv1[OPPDROP]/2);
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]);
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;
2384 UpdateWeights (side);
2388 fprintf (debug_eval_file, "side = %s, stage = %d, in_opening = %d\n",
2389 ColorStr[side], stage, in_opening_stage );
2392 hung[black] = hung[white] = pscore[black] = pscore[white] = 0;
2394 array_zero(shung,sizeof(shung));
2398 if (debug_eval || !(use_etable && ProbeEETable (side, &s)))
2400 if (!(use_etable && ProbeEETable (side, &s)))
2404 for (c1 = black; c1 <= white; c1++)
2407 /* atk1 is array of atacks on squares by my side */
2409 /* atk2 is array of atacks on squares by other side */
2411 /* same for PC1 and PC2 */
2414 /* same for fv1 and fv2 */
2416 for (i = PieceCnt[c1]; i >= 0; i--)
2418 sq = PieceList[c1][i];
2419 #if defined SAVE_SVALUE
2420 pscore[c1] += PieceValue(sq,side);
2422 pscore[c1] += (svalue[sq] = PieceValue(sq,side));
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);
2439 sprintf(buffer,"%d Black and %d White HUNG PIECES",hung[black],hung[white]);
2440 debug_table (debug_eval_file,shung,buffer);
2443 for ( c1=black,c2=white; c1<=white; c1++,c2-- )
2449 /* Score fifth rank */
2450 for ( sq = 36, n=0; sq <= 44; sq++ )
2451 if ( color[sq] == c1 || atak[c1][sq] != 0 )
2455 pscore[c1] += (ds = n*fv1[CNTRL5TH]);
2458 fprintf(debug_eval_file,"%d for %s controls 5th rank with %d points\n",
2459 ds, ColorStr[c1], n);
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 )
2469 pscore[c1] += (ds = -n*fv1[HOLES]);
2471 if ( debug_eval && ds )
2472 fprintf(debug_eval_file,"%d for %s camp has %d holes\n",
2473 ds, ColorStr[c1], n);
2478 pscore[c1] += (ds = -fv1[HUNGX]);
2481 fprintf(debug_eval_file,"%d for %d hung pieces.\n",
2485 /* Score opening features and castle/attack pattern distances */
2487 if ( in_opening_stage ) {
2488 pscore[c1] += (ds = ScoreKingOpeningFeatures ());
2490 if ( debug_eval && ds)
2491 fprintf(debug_eval_file,"%d for %s opening features\n",
2494 pscore[c1] += (ds = ScorePatternDistance (c1));
2496 if ( debug_eval && ds )
2497 fprintf(debug_eval_file,"%d for %s pattern distance\n",
2503 score = mtl[side] - mtl[xside] + pscore[side] - pscore[xside] + 10;
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);
2517 gsrand (starttime + (unsigned int) hashbd);
2518 score += urand () % dither;
2523 if ( use_etable && PUTVAR )
2524 PutInEETable(side,score);
2528 fprintf (debug_eval_file, "score = %d\n", score);
2537 fprintf (debug_eval_file, "Score cached!\n" );
2543 fprintf (debug_eval_file, "s = %d\n", s);
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;
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;
2615 GameType[side] = UNKNOWN;
2620 #define StringOfGameType(side)\
2621 (GameType[side] == STATIC_ROOK ? "Static Rook" :\
2622 (GameType[side] == RANGING_ROOK ? "Ranging Rook" : "UNKNOWN"))
2625 fprintf(debug_eval_file,"guessing game type: %s vs. %s\n",
2626 StringOfGameType(black), StringOfGameType(white));
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
2639 if ( !on_csquare(side,pawn,25) ) {
2640 /* Play static rook if rook pawn has been pushed! */
2641 GameType[side] = STATIC_ROOK;
2643 unsigned int random = urand () % 100;
2644 short d = StaticRook[side] - RangingRook[side];
2645 switch ( GameType[side ^ 1] ) {
2647 if ( random < 35 + d ) GameType[side] = STATIC_ROOK;
2648 else if ( random < 95 ) GameType[side] = RANGING_ROOK;
2651 if ( random < 75 + d) GameType[side] = STATIC_ROOK;
2652 else if ( random < 95 ) GameType[side] = RANGING_ROOK;
2655 if ( random < 33 + d) GameType[side] = STATIC_ROOK;
2656 else if ( random < 66 ) GameType[side] = RANGING_ROOK;
2661 fprintf(debug_eval_file,"decide game type: %s vs. %s\n",
2662 StringOfGameType(black), StringOfGameType(white));
2672 #define StringOfGameType(side)\
2673 (GameType[side] == STATIC_ROOK ? "Static Rook" :\
2674 (GameType[side] == RANGING_ROOK ? "Ranging Rook" : "UNKNOWN"))
2681 DetermineGameType (short side_to_move)
2685 GuessGameType(side_to_move);
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);
2705 ShowPatternCount(black,-1);
2706 ShowPatternCount(white,-1);
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);
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]]];
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");
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 ) {
2784 else if ( GameCnt < 60 )
2786 else if ( GameCnt < 80 )
2790 } else if ( GameType[side] == RANGING_ROOK || GameType[xside] == RANGING_ROOK ) {
2793 else if ( GameCnt < 50 )
2795 else if ( GameCnt < 70 )
2802 else if ( GameCnt < 55 )
2804 else if ( GameCnt < 75 )
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]);
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);
2823 balance[side] += db1;
2824 } else if ( ds > 0 ) {
2825 balance[xside] += db1;
2827 stage += (ds = db1);
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]);
2837 for ( c1=black, c2=white; c1<=white; c1++, c2-- ) {
2839 if ( (ds = seed[c1]) > 2 ) {
2840 balance[c1] += (db1 = ds * 2);
2847 fprintf(debug_eval_file,"%d for seed pieces\n",ds);
2848 fprintf(debug_eval_file,"%d %s balance bonus for seed pieces\n",
2850 fprintf(debug_eval_file,"%d %s balance penalty for seed pieces\n",
2851 -db1, ColorStr[c2]);
2856 if ( (db1 = hung[c1]) > 2 ) {
2857 balance[c1] -= (db1 *= 2);
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",
2869 if ( (db1 = loose[c1]) > 4 ) {
2870 balance[c1] -= (db1 /= 2);
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",
2884 if ( (ds = hole[c1]) ) {
2885 balance[c1] -= (db1 = ds);
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",
2899 if ( (db1 = target[c1]) > 3 ) {
2900 balance[c1] += (db1 /= 3);
2902 stage += (ds = db1 / 4);
2905 fprintf(debug_eval_file,"%d stage bonus for targets\n",ds);
2906 fprintf(debug_eval_file,"%d %s balance bonus for targets\n",
2908 fprintf(debug_eval_file,"%d %s balance penalty for targets\n",
2909 -db1, ColorStr[c2]);
2914 stage += (ds = captured[c1]/2);
2916 if ( debug_eval && ds ) {
2917 fprintf(debug_eval_file,"%d stage bonus for captured pieces\n",ds);
2921 if ( (db1 = captured[c1]) > 4 ) {
2922 balance[c1] += (db1 /= 2);
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",
2933 if ( (db1 = dcaptured[c1]) > 3 ) {
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",
2945 if ( balance[c1] > 99 ) balance[c1] = 99;
2946 else if ( balance[c1] < 0 ) balance[c1] = 0;
2952 for ( c1 = black; c1 <= white; c1++ )
2953 fprintf(debug_eval_file,"balance[%s] = %d\n",ColorStr[c1],balance[c1]);
2956 if ( stage > 99 ) stage = 99;
2957 else if ( stage < 0 ) stage = 0;
2961 fprintf(debug_eval_file,"stage = %d\n",stage);
2968 /* Determine stage dependant weights */
2970 ADVNCM[pawn] = 1; /* advanced pawn bonus increment*/
2973 ADVNCM[silver] = 1; /* advanced silver bonus increment */
2974 ADVNCM[gold] = 1; /* advanced gold bonus increment */
2977 ADVNCM[king] = 1; /* advanced king bonus increment */
2979 MAXCDIST = (stage < 33 ) ? (33 - stage)/4 : 0;
2980 MAXADIST = (stage < 30 ) ? (30 - stage)/4 : 0;
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);
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);
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]);
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)
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;
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;
3097 debug_eval = ((debug_eval_file = fopen(EVALFILE,"w")) != NULL);
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);