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
);