Fix another hardcored 9x9-board hardcoded value.
[gnushogi.git] / gnushogi / eval.c
1 /*
2  * FILE: eval.c
3  *
4  * ----------------------------------------------------------------------
5  *
6  * Copyright (c) 2012 Free Software Foundation
7  *
8  * GNU SHOGI is based on GNU CHESS
9  *
10  * This file is part of GNU SHOGI.
11  *
12  * GNU Shogi is free software; you can redistribute it and/or modify it
13  * under the terms of the GNU General Public License as published by the
14  * Free Software Foundation; either version 3 of the License,
15  * or (at your option) any later version.
16  *
17  * GNU Shogi is distributed in the hope that it will be useful, but WITHOUT
18  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
19  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
20  * for more details.
21  *
22  * You should have received a copy of the GNU General Public License along
23  * with GNU Shogi; see the file COPYING. If not, see
24  * <http://www.gnu.org/licenses/>.
25  * ----------------------------------------------------------------------
26  *
27  */
28
29 #include "gnushogi.h"
30 #include "pattern.h"
31
32 extern void
33 ShowStage(void);
34
35 /* Hash table for preventing multiple scoring of the same position */
36
37 int EADD = 0;       /* number of writes to the cache table */
38 int EGET = 0;       /* number of hits to the cache table */
39 int PUTVAR = false; /* shall the current scoring be cached? */
40
41
42 /* Pieces and colors of initial board setup */
43
44 const small_short Stboard[NO_SQUARES] =
45 {
46     lance, knight, silver,   gold,   king,   gold, silver, knight,  lance,
47     0, bishop,      0,      0,      0,      0,      0,   rook,      0,
48     pawn,   pawn,   pawn,   pawn,   pawn,   pawn,   pawn,   pawn,   pawn,
49     0,      0,      0,      0,      0,      0,      0,      0,      0,
50     0,      0,      0,      0,      0,      0,      0,      0,      0,
51     0,      0,      0,      0,      0,      0,      0,      0,      0,
52     pawn,   pawn,   pawn,   pawn,   pawn,   pawn,   pawn,   pawn,   pawn,
53     0,   rook,      0,      0,      0,      0,      0, bishop,      0,
54     lance, knight, silver,   gold,   king,   gold, silver, knight,  lance
55 };
56
57
58 const small_short Stcolor[NO_SQUARES] =
59 {
60     black,   black,   black,   black,
61     black,   black,   black,   black,   black,
62     neutral, black, neutral, neutral,
63     neutral, neutral, neutral,   black, neutral,
64     black,   black,   black,   black,
65     black,   black,   black,   black,   black,
66     neutral, neutral, neutral, neutral,
67     neutral, neutral, neutral, neutral, neutral,
68     neutral, neutral, neutral, neutral,
69     neutral, neutral, neutral, neutral, neutral,
70     neutral, neutral, neutral, neutral,
71     neutral, neutral, neutral, neutral, neutral,
72     white,   white,   white,   white,
73     white,   white,   white, white, white,
74     neutral, white, neutral, neutral,
75     neutral, neutral, neutral, white, neutral,
76     white,   white,   white,   white,
77     white,   white,   white, white, white
78 };
79
80
81 /* Actual pieces and colors */
82
83 small_short board[NO_SQUARES], color[NO_SQUARES];
84
85
86 /* relative piece values at the beginning of main stages */
87
88 #define MAIN_STAGES 4
89
90 static small_short ispvalue[NO_PIECES][MAIN_STAGES] =
91 {
92     {   0,  35,  70,  99 }, /* main stage borders */
93     /* ------------------------------------------ */
94     {   7,   7,   8,  10 }, /* Pawn               */
95     {  20,  35,  45,  60 }, /* Lance              */
96     {  20,  35,  45,  60 }, /* Knight             */
97     {  35,  40,  60,  80 }, /* Silver             */
98     {  35,  50,  65,  80 }, /* Gold               */
99     {  90,  90,  90,  90 }, /* Bishop             */
100     {  95,  95,  95,  95 }, /* Rook               */
101     {  15,  25,  40,  65 }, /* promoted Pawn      */
102     {  25,  45,  55,  65 }, /* promoted Lance     */
103     {  25,  45,  55,  65 }, /* promoted Knight    */
104     {  35,  55,  75,  75 }, /* promoted Silver    */
105     {  99,  99,  99,  99 }, /* promoted Bishop    */
106     {  97,  97,  99,  99 }, /* promoted Rook      */
107     { 100, 100, 100, 100 }, /* King               */
108 };
109
110 /* Features and Weights */
111
112 #define ATTACKED    0
113 #define HUNGP       1
114 #define HUNGX       2
115 #define CNTRL5TH    3
116 #define HOLES       4
117 #define PCASTLE     5
118 #define PATTACK     6
119 #define CTRLK       7
120 #define PROTECT     8
121 #define HCLSD       9
122 #define PINVAL     10
123 #define XRAY       11
124 #define OPENWRONG  12
125 #define SEED       13
126 #define LOOSE      14
127 #define MOBILITY   15
128 #define TARGET     16
129 #define KSFTY      17
130 #define HOPN       18
131 #define PROMD      19
132 #define KINGOD     20
133 #define PWNDROP    21
134 #define DFFDROP    22
135 #define FCLATTACK  23
136 #define KNGATTACK  24
137 #define KNGPROTECT 25
138 #define DNGLPC     26
139 #define LSATTACK   27
140 #define NIHATTACK  28
141 #define COHESION   29
142 #define OPPDROP    30
143
144
145 static small_short weight[NO_FEATURES + 1][MAIN_STAGES + 2] =
146 {
147     {  80, 100, 100,  40,  10,  15 },    /* ATTACKED      */
148     {  80, 100, 100,  50,  14,  10 },    /* HUNGP         */
149     {  80, 100, 100,  50,  18,  12 },    /* HUNGX         */
150     { 100,  50,   0,   0,   2,   1 },    /* CNTRL5TH      */
151     { 100, 100,  60,  10,   4,   2 },    /* HOLES         */
152     { 100,  50,   0,   0,  14,   7 },    /* PCASTLE       */
153     { 100,  50,   0,   0,   6,  12 },    /* PATTACK       */
154     {  10,  40,  70, 100,  10,  15 },    /* CTRLK         */
155     { 100,  80,  50,  40,   2,   1 },    /* PROTECT       */
156     {  40, 100,  40,   5,   4,   4 },    /* HCLSD         */
157     {  80, 100,  80,  30,  10,  15 },    /* PINVAL        */
158     {  80, 100,  60,  15,   6,  10 },    /* XRAY          */
159     { 100,  50,   0,   0,  15,  15 },    /* OPENWRONG     */
160     {   0,  40,  70, 100,   8,  12 },    /* SEED          */
161     {  50, 100,  80,  20,   5,   3 },    /* LOOSE         */
162     {  50, 100,  80,  50, 100, 100 },    /* MOBILITY (%)  */
163     {  50, 100,  80,  50,   4,   8 },    /* TARGET        */
164     {  50,  40, 100,  80,   8,   4 },    /* KSFTY         */
165     {  80, 100,  60,  20,   5,   5 },    /* HOPN          */
166     {  20,  40,  80, 100,   3,   6 },    /* PROMD         */
167     {  20,  40,  80, 100,   4,   1 },    /* KINGOD        */
168     {   5,  40, 100,  50,   0,   4 },    /* PWNDROP       */
169     {   0,  20,  80, 100,   0,   4 },    /* DFFDROP       */
170     {  20,  50, 100,  80,   0,   4 },    /* FCLATTACK     */
171     {   0,  20,  80, 100,   0,   8 },    /* KNGATTACK     */
172     {  40,  80, 100,  80,   6,   0 },    /* KNGPROTECT    */
173     {  50, 100,  60,  10,   0,   8 },    /* DNGPC         */
174     {  30, 100,  60,   5,   0,   6 },    /* LSATTACK      */
175     {   0,  50,  80, 100,   0,   8 },    /* NIHATTACK     */
176     {  50, 100,  80,  60,   8,   0 },    /* COHESION      */
177     { 100, 100,  80,  60,   4,   4 },    /* OPPDROP       */
178 };
179
180
181 short ADVNCM[NO_PIECES];
182
183 /* distance to enemy king */
184 static const short EnemyKingDistanceBonus[10] =
185 { 0, 6, 4, -1, -3, -4, -6, -8, -10, -12 };
186
187 /* distance to own king */
188 static const short OwnKingDistanceBonus[10] =
189 { 0, 5, 2, 1, 0, -1, -2, -3, -4, -5 };
190
191 /* distance to promotion zone */
192 static const int PromotionZoneDistanceBonus[NO_ROWS] =
193 { 0, 0, 0, 0, 2, 6, 6, 8, 8 };
194
195 #define MAX_BMBLTY 20
196 #define MAX_RMBLTY 20
197 #define MAX_LMBLTY 8
198
199 /* Bishop mobility bonus indexed by # reachable squares */
200 static const short BMBLTY[MAX_BMBLTY] =
201 { 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 14, 14, 16, 16, 16, 16 };
202
203 /* Rook mobility bonus indexed by # reachable squares */
204 static const short RMBLTY[MAX_RMBLTY] =
205 { 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 14, 14, 16, 16, 16, 16 };
206
207 /* Lance mobility bonus indexed by # reachable squares */
208 static const short LMBLTY[MAX_LMBLTY] =
209 { 0, 0, 0, 0, 4, 6, 8, 10 };
210
211 static const short MBLTY[NO_PIECES] =
212 { 0, 2, 1, 10, 5, 5, 1, 1, 5, 5, 5, 5, 1, 1, 4 };
213
214 static const short KTHRT[36] =
215 {   0,  -8, -20, -36, -52, -68, -80, -80, -80, -80, -80, -80,
216     -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80,
217     -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80 };
218
219 static small_short fvalue[2][NO_FEATURES];
220
221 long attack[2][NO_SQUARES];         /* threats to squares */
222 small_short sseed[NO_SQUARES];      /* square occupied by a seed piece? */
223
224 struct signature threats_signature[2] = /* statistics valid for position.. */
225 { { -1, -1 }, { -1, -1 } };             /* attack and sseed available */
226
227 small_short starget[2][NO_SQUARES]; /* significance as a target for a
228                                      * side of a square */
229 small_short sloose[NO_SQUARES];     /* square occupied by a loose piece? */
230 small_short shole[NO_SQUARES];      /* empty square a hole? */
231 small_short shung[NO_SQUARES];      /* hung piece? */
232
233 struct signature squares_signature =  /* statistics valid for position ... */
234 { 0, 0 };                /* starget, sloose, shole, shung available */
235
236 short target[2], seed[2], loose[2], hole[2];
237
238 short captured[2];  /* number of captured pieces */
239 short dcaptured[2]; /* different types of captured pieces */
240
241 small_short Kdist[2][NO_SQUARES];    /* distance to king */
242
243 short MAXADIST, MAXCDIST; /* maximum half move distance to pattern */
244
245 char GameType[2] = { UNKNOWN, UNKNOWN }; /* chosen game type of each side */
246
247
248 static short attack_opening_sequence[2];    /* current castle patterns */
249 static short castle_opening_sequence[2];    /* current attack formations */
250
251 static small_short Mpawn  [2][NO_SQUARES];
252 static small_short Msilver[2][NO_SQUARES];
253 static small_short Mgold  [2][NO_SQUARES];
254 static small_short Mking  [2][NO_SQUARES];
255 static small_short Mlance [2][NO_SQUARES];
256 static small_short Mknight[2][NO_SQUARES];
257 static small_short Mbishop[2][NO_SQUARES];
258 static small_short Mrook  [2][NO_SQUARES];
259
260 static Mpiece_array Mpawn, Mlance, Mknight, Msilver, Mgold,
261     Mbishop, Mrook, Mking;
262
263 Mpiece_array *Mpiece[NO_PIECES] =
264 { NULL, &Mpawn, &Mlance, &Mknight, &Msilver, &Mgold, &Mbishop, &Mrook,
265   &Mgold, &Mgold, &Mgold, &Mgold, &Mbishop, &Mrook, &Mking };
266
267
268 static short c1, c2;
269 static small_short *PC1, *PC2;
270 static small_short *fv1;
271 static long *atk1, *atk2;
272 static long  a1, a2;
273
274 #define csquare(side, sq) ((side == black) ? sq : (NO_SQUARES - 1 - sq))
275 #define crow(side, sq)    row(csquare(side, sq))
276 #define ccolumn(side, sq) column(csquare(side, sq))
277
278
279 inline static short
280 on_csquare(short side, short piece, short square)
281 {
282     short sq;
283     /* FIXME: un-obfuscate this! */
284     return ((board[sq = csquare(side, square)] == piece)
285             && (color[sq] == side));
286 }
287
288
289 inline static short
290 on_column(short side, short piece, short c)
291 {
292     short sq;
293
294     for (sq = c; sq < NO_SQUARES; sq += NO_COLS)
295     {
296         if (on_csquare(side, piece, sq))
297             return true;
298     }
299
300     return false;
301 }
302
303
304 #define empty_csquare(side, square) \
305   (board[csquare(side, square)] == no_piece)
306
307 inline static short
308 on_left_side(short side, short piece)
309 {
310     short c;
311
312     for (c = 0; c < 4; c++)
313     {
314         if (on_column(side, piece, c))
315             return true;
316     }
317
318     return false;
319 }
320
321
322 inline static short
323 on_right_side(short side, short piece)
324 {
325     short c;
326
327     for (c = 5; c < NO_COLS; c++)
328     {
329         if (on_column(side, piece, c))
330             return true;
331     }
332
333     return false;
334 }
335
336
337 short pscore[2];  /* piece score for each side */
338
339
340
341
342 /*
343  * Fill array attack[side][] with info about attacks to a square.  Bits
344  * 16-31 are set if the piece (king .. pawn) attacks the square.  Bits 0-15
345  * contain a count of total attacks to the square.  Fill array sseed[] with
346  * info about occupation by a seed piece.
347  */
348
349 void
350 threats(short side)
351 {
352     short  u, sq;
353     long   c;
354     long  *a;
355 #ifdef SAVE_NEXTPOS
356     short d;
357 #else
358     unsigned char  *ppos, *pdir;
359 #endif
360     short i, kd, piece, xside;
361     small_short *PL;
362
363     if (MatchSignature(threats_signature[side]))
364     {
365         /* data valid for current positional signature */
366         return;
367     }
368
369     a = attack[side];
370     xside = side ^ 1;
371
372     array_zero(a, NO_SQUARES * sizeof(a[0]));
373
374     PL = PieceList[side];
375
376     for (i = PieceCnt[side]; i >= 0; i--)
377     {
378         short ptyp;
379
380         sq = PL[i];
381         piece = board[sq];
382         ptyp = ptype[side][piece];
383         c = control[piece];
384 #ifdef SAVE_NEXTPOS
385         u = first_direction(ptyp, &d, sq);
386 #else
387         ppos = (*nextpos[ptyp])[sq];
388         pdir = (*nextdir[ptyp])[sq];
389         u = ppos[sq];
390 #endif
391
392         do
393         {
394             a[u] = ((a[u] + 1) | c);
395
396             if ((kd = Kdist[xside][u]) < 2)
397             {
398                 sseed[sq] += 2 - kd;
399                 seed[side]++;
400             }
401
402 #ifdef SAVE_NEXTPOS
403             u = ((color[u] == neutral)
404                  ? next_position(ptyp, &d, sq, u)
405                  : next_direction(ptyp, &d, sq));
406 #else
407             u = ((color[u] == neutral) ? ppos[u] : pdir[u]);
408 #endif
409         }
410         while (u != sq);
411     }
412
413     /* data valid for current positional signature */
414     CopySignature(threats_signature[side]);
415 }
416
417
418
419 /*
420  * Compute the board square with nunmap offset "id".  If side == white,
421  * offset is negated.  inunmap[sq] is the corresponding nunmap index isq.
422  * nunmap[isq + id] computes the board square. If negative, it is outside
423  * the board.
424  */
425
426 static void
427 add_target(short sq, short side, short id)
428 {
429     short isq, tsq, xside;
430     isq = inunmap[sq];
431     tsq = (side == black) ? nunmap[isq + id] : nunmap[isq - id];
432
433     if (tsq >= 0)
434     {
435         target[xside = side^1]++;
436
437         if (attack[side][tsq])
438             starget[xside][tsq]++;  /* protected target square */
439         else
440             starget[xside][tsq] += 2; /* unprotected target square */
441     }
442 }
443
444
445
446 /*
447  * Target squares can be vertically ahead, diagonally ahead
448  * or diagonally behind.
449  */
450
451 static void
452 CheckTargetPiece(short sq, short side)
453 {
454     switch (board[sq])
455     {
456     case pawn: /* vertically ahead if unprotected */
457         if (!attack[side][sq])
458             add_target(sq, side, 11);
459         break;
460
461     case king: /* diagonally and vertically ahead */
462         add_target(sq, side, 10);
463         add_target(sq, side, 11);
464         add_target(sq, side, 12);
465         break;
466
467     case rook: /* diagonally ahead and behind */
468         add_target(sq, side, 10);
469         add_target(sq, side, 12);
470         add_target(sq, side, -10);
471         add_target(sq, side, -12);
472         break;
473
474     case bishop: /* vertically ahead */
475         add_target(sq, side, 11);
476         break;
477
478     case knight: /* vertically ahead if advanced */
479         /* FIXME: gotta love them magic numbers... */
480         if ((sq != 1) && (sq != 7) && (sq != 73) && (sq != 79))
481             add_target(sq, side, 11);
482         break;
483     }
484 }
485
486
487
488 static short
489 ScoreKingOpeningFeatures(void)
490 {
491     short s = 0, sq = OwnKing, ds;
492
493     if (GameType[c1] == STATIC_ROOK)
494     {
495         /* Penalty for king on right side or fifth file */
496         short c;
497         c = 4 - ccolumn(c1, sq);
498
499         if ((c < 0) || ((c == 0) && (sq != kingP[c1])))
500             s += (ds = -c - c - fv1[OPENWRONG]);
501     }
502     else if (GameType[c1] == RANGING_ROOK)
503     {
504         /* Penalty for king on left side or fifth file */
505         short c;
506         c = 4 - ccolumn(c1, sq);
507
508         if ((c > 0) || ((c == 0) && (sq != kingP[c1])))
509         {
510             s += (ds = -c - c - fv1[OPENWRONG]);
511         }
512
513         /* Penalty for king moved before rook switch */
514         if (sq != kingP[c1])
515         {
516             if (on_csquare(c1, rook, 16))
517             {
518                 s += (ds = -4 * fv1[OPENWRONG]);
519             }
520         }
521         else
522         {
523             /* Penalty for sitting king after rook switch */
524             if (!on_csquare(c1, rook, 16))
525             {
526                 s += (ds = -2 * fv1[OPENWRONG]);
527             }
528         }
529
530         /* Penalty for defending general moved
531          * before king switch to right side */
532         if (ccolumn(c1, sq) < 6)
533         {
534             if (Mvboard[csquare(c1, 5)] || Mvboard[csquare(c1, 6)])
535             {
536                 s += (ds = -2 * fv1[OPENWRONG]);
537             }
538         }
539     }
540
541     return s;
542 }
543
544
545
546
547 inline static void
548 ExamineSquares(void)
549 {
550     short sq, side, piece, n;
551
552     if (MatchSignature(squares_signature))
553     {
554         /* data valid for current positional signature */
555         return;
556     }
557
558     array_zero(shole,   sizeof(shole));
559     array_zero(sloose,  sizeof(sloose));
560     array_zero(starget, sizeof(starget));
561
562     hole[0] = hole[1] = loose[0] = loose[1]
563         = target[0] = target[1] = 0;
564
565     for (sq = 0; sq < NO_SQUARES; sq++)
566     {
567         if ((side = color[sq]) == neutral)
568         {
569             if (InWhiteCamp(sq))
570             {
571                 if (!attack[white][sq])
572                 {
573                     shole[sq] = 1;
574                     hole[white]++;
575                 }
576             }
577             else if (InBlackCamp(sq))
578             {
579                 if (!attack[black][sq])
580                 {
581                     shole[sq] = 1;
582                     hole[black]++;
583                 }
584             }
585         }
586         else
587         {
588             /* occupied by "side" piece */
589             if (!attack[side][sq])
590             {
591                 sloose[sq] = 1;
592                 loose[side]++;
593             }
594
595             CheckTargetPiece(sq, side);
596         }
597     }
598
599     for (side = black; side <= white; side++)
600     {
601         captured[side] = dcaptured[side] = 0;
602
603         for (piece = pawn; piece <= rook; piece++)
604         {
605             if ((n = Captured[side][piece]) != 0)
606             {
607                 if (piece != pawn)
608                     captured[side] += n;
609
610                 dcaptured[side]++;
611             }
612         }
613     }
614
615     /* Data valid for current positional signature */
616     CopySignature(squares_signature);
617 }
618
619
620
621 /* ............    POSITIONAL EVALUATION ROUTINES    ............ */
622
623 /*
624  * Inputs are:
625  * mtl[side]       - value of all material
626  * hung[side]      - count of hung pieces
627  * Tscore[ply]     - search tree score for ply ply
628  * Pscore[ply]     - positional score for ply ply
629  * INCscore        - bonus score or penalty for certain moves
630  * Sdepth          - search goal depth
631  * xwndw           - evaluation window about alpha/beta
632  * EWNDW           - second evaluation window about alpha/beta
633  * ChkFlag[ply]    - checking piece at level ply or 0 if no check
634  * TesujiFlag[ply] - 1 if tesuji move at level ply or 0 if no tesuji
635  * PC1[column]     - # of my pawns in this column
636  * PC2[column]     - # of opponents pawns in column
637  * PieceCnt[side]  - just what it says
638  */
639
640
641
642
643 /*
644  * Compute an estimate of the score by adding the positional score from the
645  * previous ply to the material difference. If this score falls inside a
646  * window which is 180 points wider than the alpha-beta window (or within a
647  * 50 point window during quiescence search) call ScorePosition() to
648  * determine a score, otherwise return the estimated score.  "side" is the
649  * side which has to move.
650  */
651
652 int
653 evaluate(short side,
654          short ply,
655          short alpha,
656          short beta,
657          short INCscore,
658          short *InChk,     /* output Check flag     */
659          short *blockable) /* king threat blockable */
660 {
661     short xside;
662     short s;
663
664     xside = side ^ 1;
665     s = -Pscore[ply - 1] + mtl[side] - mtl[xside] /* - INCscore */;
666     hung[black] = hung[white] = 0;
667
668     /* should we use the estimete or score the position */
669     if ((ply == 1)
670         || (ply == Sdepth)
671         || (ply > Sdepth && s >= (alpha - 30) && s <= (beta + 30))
672 #ifdef CACHE
673         || (use_etable && CheckEETable(side))
674 #endif
675         )
676     {
677         short sq;
678
679         /* score the position */
680         array_zero(sseed, sizeof(sseed));
681
682         seed[0] = seed[1] = 0;
683         threats(side);
684
685         if (Anyattack(side, sq = PieceList[xside][0]) && (board[sq] == king))
686         {
687             *InChk = (board[sq = PieceList[side][0]] == king)
688                 ? SqAttacked(sq, xside, blockable)
689                 : false;
690
691             return ((SCORE_LIMIT + 1001) - ply);
692         }
693
694         threats(xside);
695         *InChk = (board[sq = PieceList[side][0]] == king)
696             ? Anyattack(xside, sq)
697             : false;
698         *blockable = true;
699         EvalNodes++;
700
701         if (ply > 4)
702             PUTVAR = true;
703
704         ExamineSquares();
705         s = ScorePosition(side);
706         PUTVAR = false;
707     }
708     else
709     {
710         /* use the estimate but look at check */
711         short sq;
712
713         *InChk = (board[sq = PieceList[side][0]] == king)
714             ? SqAttacked(sq, xside, blockable)
715             : false;
716
717         if ((board[sq = PieceList[xside][0]] == king)
718             && SqAttacked(sq, side, blockable))
719         {
720             return ((SCORE_LIMIT + 1001) - ply);
721         }
722     }
723
724     Pscore[ply] = s - mtl[side] + mtl[xside];
725     ChkFlag[ply - 1] = ((*InChk) ? Pindex[TOsquare] : 0);
726
727     return s;
728 }
729
730
731
732 static short
733 value_of_weakest_attacker(long a2)
734 {
735     short piece;
736     short min_value, v;
737     min_value = SCORE_LIMIT;
738
739     for (piece = pawn; piece <= king; piece++)
740     {
741         if (control[piece] & a2)
742         {
743             if (min_value > (v = (*value)[stage][piece]))
744                 min_value = v;
745         }
746     }
747
748     return min_value;
749 }
750
751
752
753
754 /*
755  * Find (promoted) Bishop, (promoted) Rook, and Lance mobility, x-ray
756  * attacks, and pins.  Let BRL be the bishop, rook, or lance.  Let P be the
757  * first piece (not a king or a pawn) in a direction and let Q be the
758  * second piece in the same direction.  If Q is an unprotected opponent's
759  * piece with bigger relative value than BRL, there is a pin if P is an
760  * opponent's piece and there is an x-ray attack if P belongs to this side.
761  * Increment the hung[] array if a pin is found.
762  */
763
764 inline int
765 BRLscan(short sq, short *mob)
766 {
767 #ifdef SAVE_NEXTPOS
768     short d, dd;
769 #else
770     unsigned char  *ppos, *pdir;
771 #endif
772
773     short s, mobx;
774     short u, xu, pin, ptyp, csq = column(sq);
775     short piece, upiece, xupiece, rvalue, ds;
776     small_short *Kd = Kdist[c2];
777
778     mobx = s = 0;
779     piece = board[sq];
780
781     rvalue = (*value)[stage][piece];
782     ptyp = ptype[c1][upiece = unpromoted[piece]];
783     rvalue = (*value)[stage][upiece];
784
785 #ifdef SAVE_NEXTPOS
786     u = first_direction(ptyp, &d, sq);
787 #else
788     ppos = (*nextpos[ptyp])[sq];
789     pdir = (*nextdir[ptyp])[sq];
790     u = ppos[sq];
791 #endif
792
793     pin = -1;           /* start new direction */
794
795     do
796     {
797         if (Kd[u] < 2)
798         {
799             s += (ds = fv1[CTRLK] * (2 - Kd[u]));
800         }
801
802         if ((ds = starget[c1][u]) != 0)
803         {
804             /* threatening a target square */
805             if ((pin < 0)               /* direct threat */
806                 || (color[pin] == c2))  /* pin threat    */
807             {
808                 s += (ds *= fv1[TARGET]);
809             }
810         }
811
812         if ((ds = shole[u]) != 0)
813         {
814             /* attacking or protecting a hole */
815             s += (ds = fv1[HOLES]);
816         }
817         else if (InPromotionZone(c1, u))
818         {
819             /* attacking a square in promotion zone */
820             s += (ds = fv1[HOLES] / 2);
821         }
822
823         if (color[u] == neutral)
824         {
825 #ifdef SAVE_NEXTPOS
826             dd = d;
827             xu = next_position(ptyp, &d, sq, u);
828
829             if (xu == next_direction(ptyp, &dd, sq))
830                 pin = -1;   /* oops new direction */
831 #else
832
833             if ((xu = ppos[u]) == pdir[u])
834                 pin = -1;   /* oops new direction */
835 #endif
836             u = xu;
837             mobx++;
838         }
839         else
840         {
841             /* there is a piece in current direction */
842             if (pin < 0)
843             {
844                 /* it's the first piece in the current direction */
845                 if (color[u] == c1)
846                 {
847                     /* own intercepting piece in x-ray attack */
848                     if (upiece == lance)
849                     {
850                         /* lance x-ray */
851                         if (board[u] == pawn)
852                         {
853                             s += (ds = 2*fv1[PROTECT]);
854                         }
855                         else if (in_opening_stage)
856                         {
857                             s += (ds = -2*fv1[PROTECT]);
858                         }
859                     }
860                     else
861                     {
862                         /* bishop or rook x-ray */
863                         if ((upiece == bishop) && (board[u] == pawn)
864                             && (GameType[c1] == STATIC_ROOK))
865                         {
866                             s += (ds = -2*fv1[HCLSD]);
867                         }
868                         else if ((upiece == rook) && (board[u] == lance)
869                                  && (GameType[c1] == STATIC_ROOK)
870                                  && (column(u) == csq))
871                         {
872                             s += (ds = fv1[XRAY]);
873                         }
874                     }
875                 }
876                 else
877                 {
878                     /* enemy's intercepting piece in pin attack */
879                     if (upiece == lance)
880                     {
881                         /* lance pin attack */
882                         if (board[u] == pawn)
883                         {
884                             s += (ds = -2*fv1[PROTECT]);
885                         }
886                         else if (in_opening_stage)
887                         {
888                             s += (ds = 2 * fv1[PROTECT]);
889                         }
890                     }
891                     else
892                     {
893                         /* bishop or rook pin attack */
894                         if (board[u] == pawn)
895                         {
896                             s += (ds = -fv1[HCLSD]);
897                         }
898                     }
899                 }
900
901 #ifdef SAVE_NEXTPOS
902                 dd = d;
903                 xu = next_position(ptyp, &d, sq, u);
904
905                 if (xu != next_direction(ptyp, &dd, sq))
906                     pin = u;    /* not on the edge and on to find a pin */
907 #else
908                 if ((xu = ppos[u]) != pdir[u])
909                     pin = u;    /* not on the edge and on to find a pin */
910 #endif
911                 u = xu;
912             }
913             else
914             {
915                 /* it's the second piece in the current direction */
916
917                 if (color[u] == c1)
918                 {
919                     /* second piece is an own piece */
920                     if ((upiece == bishop) && (board[u] == pawn)
921                         && (GameType[c1] == STATIC_ROOK))
922                     {
923                         s += (ds = -fv1[HCLSD]);
924                     }
925                 }
926                 else
927                 {
928                     /* second piece is an enemy piece */
929                     if (upiece == bishop && board[u] == pawn)
930                     {
931                         s += (ds = -fv1[HCLSD]/2);
932                     }
933
934                     if (((*value)[stage][xupiece = unpromoted[board[u]]]
935                          > rvalue)
936                         || (atk2[u] == 0))
937                     {
938                         if (color[pin] == c2)
939                         {
940                             if ((xupiece == king) && (in_endgame_stage))
941                             {
942                                 s += (ds = 2 * fv1[PINVAL]);
943                             }
944                             else
945                             {
946                                 s += (ds = fv1[PINVAL]);
947                             }
948
949                             if ((atk2[pin] == 0)
950                                 || (atk1[pin] > control[board[pin]] + 1))
951                             {
952                                 hung[c2]++;
953                                 shung[u]++;
954                             }
955                         }
956                         else
957                         {
958                             if (upiece == lance)
959                             {
960                                 s += (ds = fv1[XRAY] / 2);
961                             }
962                             else
963                             {
964                                 s += (ds = fv1[XRAY]);
965                             }
966                         }
967                     }
968                 }
969
970                 pin = -1;   /* new direction */
971
972 #ifdef SAVE_NEXTPOS
973                 u = next_direction(ptyp, &d, sq);
974 #else
975                 u = pdir[u];
976 #endif
977             }
978         }
979     }
980     while (u != sq);
981
982     *mob = mobx;
983
984     return s;
985 }
986
987
988 #define ctlSG (ctlS | ctlG | ctlPp | ctlLp | ctlNp | ctlSp)
989
990
991
992 /*
993  * Assign penalties if king can be threatened by checks, if squares near
994  * the king are controlled by the enemy (especially by promoted pieces), or
995  * if there are no own generals near the king.
996  *
997  * The following must be true:
998  * board[sq] == king, c1 == color[sq], c2 == otherside[c1]
999  */
1000
1001 #define SCORETHREAT \
1002 { \
1003     if (color[u] != c2) \
1004     { \
1005         if ((atk1[u] == 0) || ((atk2[u] & CNT_MASK) != 0)) \
1006         { \
1007             ++cnt; \
1008         } \
1009         else \
1010         { \
1011             s += (ds = -fv1[CTRLK]); \
1012         } \
1013     } \
1014 }
1015
1016
1017
1018
1019 inline short
1020 KingScan(short sq)
1021 {
1022     short cnt;
1023
1024 #ifdef SAVE_NEXTPOS
1025     short d;
1026 #else
1027     unsigned char  *ppos, *pdir;
1028 #endif
1029
1030     short s;
1031     short u, ptyp;
1032     short ok, ds;
1033
1034     /* Penalties, if a king can be threatened by checks. */
1035
1036     s = 0;
1037     cnt = 0;
1038
1039     {
1040         short p;
1041
1042         for (p = pawn; p < king; p++)
1043         {
1044             if (HasPiece[c2][p] || Captured[c2][p])
1045             {
1046                 short ptyp;
1047
1048                 /* if a c1 piece can reach u from sq,
1049                  * then a c2 piece can reach sq from u.
1050                  * That means, each u is a square, from which a
1051                  * piece of type p and color c2 threats square sq.
1052                  */
1053                 ptyp = ptype[c1][p];
1054
1055 #ifdef SAVE_NEXTPOS
1056                 u = first_direction(ptyp, &d, sq);
1057 #else
1058                 ppos = (*nextpos[ptyp])[sq];
1059                 pdir = (*nextdir[ptyp])[sq];
1060                 u = ppos[sq];
1061 #endif
1062
1063                 do
1064                 {
1065                     /* If a p piece can reach (controls or can drop to)
1066                      * square u, then score threat.
1067                      */
1068
1069                     if (atk2[u] & control[p])
1070                         SCORETHREAT
1071                     else if ((Captured[c2][p] && color[u]) == neutral)
1072                         SCORETHREAT
1073
1074 #ifdef SAVE_NEXTPOS
1075                     u = ((color[u] == neutral)
1076                          ? next_position(ptyp, &d, sq, u)
1077                          : next_direction(ptyp, &d, sq));
1078 #else
1079                     u = ((color[u] == neutral) ? ppos[u] : pdir[u]);
1080 #endif
1081                 }
1082                 while (u != sq);
1083             }
1084         }
1085     }
1086
1087     s += (ds = fv1[KSFTY] * KTHRT[cnt] / 16);
1088
1089     /* Penalties, if squares near king are controlled by enemy. */
1090
1091     cnt = 0;
1092     ok = false;
1093     ptyp = ptype[c1][king];
1094
1095 #ifdef SAVE_NEXTPOS
1096     u = first_direction(ptyp, &d, sq);
1097 #else
1098     pdir = (*nextpos[ptyp])[sq];
1099     u = pdir[sq];
1100 #endif
1101
1102     do
1103     {
1104         if (!ok && color[u] == c1)
1105         {
1106             short ptype_piece = ptype[black][board[u]];
1107
1108             if ((ptype_piece == ptype_silver) || (ptype_piece == ptype_gold))
1109                 ok = true;
1110         }
1111
1112         if (atk2[u] > atk1[u])
1113         {
1114             ++cnt;
1115
1116             if (atk2[u] & ctlSG)
1117             {
1118                 s += (ds = -fv1[KSFTY] / 2);
1119             }
1120         }
1121
1122 #ifdef SAVE_NEXTPOS
1123         u = next_direction(ptyp, &d, sq);
1124 #else
1125         u = pdir[u];
1126 #endif
1127     }
1128     while (u != sq);
1129
1130     if (!ok || (cnt > 1))
1131     {
1132         if (cnt > 1)
1133             s += (ds = -fv1[KSFTY]/2);
1134         else
1135             s += (ds = -fv1[KSFTY]);
1136     }
1137
1138     return s;
1139 }
1140
1141
1142 static short checked_trapped;
1143
1144
1145 /*
1146  * See if the attacked piece has unattacked squares to move to. The following
1147  * must be true: c1 == color[sq] c2 == otherside[c1]
1148  */
1149
1150 inline int
1151 trapped(short sq)
1152 {
1153     short u, ptyp;
1154 #ifdef SAVE_NEXTPOS
1155     short d;
1156 #else
1157     unsigned char *ppos, *pdir;
1158 #endif
1159     short piece;
1160     short rvalue;
1161
1162     piece  = board[sq];
1163     rvalue = (*value)[stage][piece];
1164     ptyp   = ptype[c1][piece];
1165
1166 #ifdef SAVE_NEXTPOS
1167     u = first_direction(ptyp, &d, sq);
1168 #else
1169     ppos = (*nextpos[ptyp])[sq];
1170     pdir = (*nextdir[ptyp])[sq];
1171     u = ppos[sq];
1172 #endif
1173
1174     do
1175     {
1176         if (color[u] != c1)
1177         {
1178             if ((atk2[u] == 0) || ((*value)[stage][board[u]] >= rvalue))
1179                 return false;
1180         }
1181
1182 #ifdef SAVE_NEXTPOS
1183         u = ((color[u] == neutral)
1184              ? next_position(ptyp, &d, sq, u)
1185              : next_direction(ptyp, &d, sq));
1186 #else
1187         u = ((color[u] == neutral) ? ppos[u] : pdir[u]);
1188 #endif
1189     }
1190     while (u != sq);
1191
1192     checked_trapped = true;
1193
1194     return true;
1195 }
1196
1197
1198
1199 static int
1200 AttackedPieceValue(short sq, short side)
1201 {
1202     short s, ds;
1203
1204     s = 0;
1205
1206         ds = -fv1[HUNGP] * 2;
1207     hung[c1]++;
1208     shung[sq]++;
1209
1210     if (trapped(sq))
1211     {
1212         hung[c1]  += 2;
1213         shung[sq] += 2;
1214     }
1215
1216     return s;
1217 }
1218
1219
1220
1221 static inline int
1222 OpenFileValue(short sq, short hopn, short hopnx)
1223 {
1224     short s = 0, fyle;
1225
1226     if (PC1[fyle = column(sq)] == 0)
1227     {
1228         s += hopn;
1229     }
1230
1231     if (PC2[fyle] == 0)
1232     {
1233         s += hopnx;
1234     }
1235
1236     return s;
1237 }
1238
1239
1240
1241
1242 /* Distance bonus */
1243
1244 #define PromotionZoneDistanceValue(sq, dd) \
1245 if ((ds = fv1[PROMD])) \
1246 { \
1247     s += (ds = ds * PromotionZoneDistanceBonus[crow(c1, sq)] * dd); \
1248 }
1249
1250 #define OwnKingDistanceValue(sq, dd, maxd) \
1251 if ((ds = fv1[KINGOD]) && ((ad = Kdist[c1][sq]) <= maxd)) \
1252 { \
1253     s += (ds = ds * OwnKingDistanceBonus[ad] * dd); \
1254 }
1255
1256 #define EnemyKingDistanceValue(sq, dd, maxd) \
1257 if ((ds = fv1[KINGOD]) && ((ad = Kdist[c2][sq]) <= maxd)) \
1258 { \
1259     s += (ds = ds * EnemyKingDistanceBonus[ad] * dd); \
1260 }
1261
1262
1263
1264
1265
1266 /*
1267  * Calculate the positional value for a pawn on 'sq'.
1268  */
1269
1270 static inline int
1271 PawnValue(short sq, short side)
1272 {
1273     short s = 0;
1274     short ds;
1275     short ccol = ccolumn(c1, sq);
1276
1277     PromotionZoneDistanceValue(sq, 3);
1278
1279     /* pawn mobility */
1280     if (color[(c1 == black) ? (sq + NO_COLS) : (sq - NO_COLS)] == neutral)
1281     {
1282         s += (ds = MBLTY[pawn]);
1283     }
1284
1285     if ((a1 & ((ctlR | ctlRp) | ctlL)))
1286     {
1287         s += (ds = fv1[ATTACKED]);
1288     }
1289
1290     if (in_opening_stage)
1291     {
1292         if (crow(c1, sq) == 2) /* pawn on 3d rank */
1293         {
1294             if (board[(c1 == black) ?
1295                       (sq + 3*NO_COLS) : (sq - 3*NO_COLS)] == pawn)
1296             {
1297                 /* opposing pawn has been moved (even column == (sq & 1)) */
1298
1299                 short m;
1300
1301                 switch (ccol)
1302                 {
1303                 case 0:
1304                 case 8:
1305                     m = (side == c1) ? 3 : 5;
1306                     break;
1307
1308                 case 4:
1309                     m = (side == c1) ? 2 : 3;
1310                     break;
1311
1312                 default:
1313                     m = (side == c1) ? 1 : 2;
1314                     break;
1315                 }
1316
1317                 s += (ds = -m * MBLTY[pawn]);
1318             }
1319         }
1320
1321         if ((GameType[c1] == STATIC_ROOK) && (sq == csquare(c1, 43)))
1322         {
1323             if ((atk2[csquare(c1, 52)] & CNT_MASK) < 2)
1324             {
1325                 s += (ds = fv1[ATTACKED]);
1326             }
1327         }
1328
1329         if ((GameType[c2] == STATIC_ROOK) && (ccol == 1))
1330         {
1331             if (sq == csquare(c1, 28))
1332             {
1333                 s += (ds = -fv1[ATTACKED]);
1334             }
1335
1336             if (((atk1[csquare(c1, 19)] & CNT_MASK) < 2)
1337                 && ((atk1[csquare(c1, 28)] & CNT_MASK) < 2))
1338             {
1339                 s += (ds = -2 * fv1[ATTACKED]);
1340             }
1341         }
1342     }
1343
1344     return s;
1345 }
1346
1347
1348
1349 /*
1350  * Calculate the positional value for a lance on 'sq'.
1351  */
1352
1353 static inline int
1354 LanceValue(short sq, short side)
1355 {
1356     short s = 0, ds, ad;
1357
1358     OwnKingDistanceValue(sq, 1, 2);
1359
1360     OpenFileValue(sq, -fv1[HOPN], fv1[HOPN]);
1361
1362     if (!checked_trapped && (crow(c1, sq) > 2))
1363     {
1364         if (in_opening_stage || trapped(sq))
1365         {
1366             s += (ds = -3 * fv1[ATTACKED]);
1367         }
1368         else
1369         {
1370             s += (ds = -2 * fv1[ATTACKED]);
1371         }
1372     }
1373
1374     return s;
1375 }
1376
1377
1378
1379 /*
1380  * Calculate the positional value for a knight on 'sq'.
1381  */
1382
1383 static inline int
1384 KnightValue(short sq, short side)
1385 {
1386     short s = 0, ad;
1387     short ds, checked_trapped = false;
1388     short c = column(sq);
1389
1390     PromotionZoneDistanceValue(sq, 1);
1391     OwnKingDistanceValue(sq, 1, 2);
1392
1393     if (!checked_trapped && (crow(c1, sq) > 2))
1394     {
1395         if (trapped(sq))
1396         {
1397             s += (ds = -4 * fv1[ATTACKED]);
1398         }
1399         else
1400         {
1401             s += (ds = -3 * fv1[ATTACKED]);
1402         }
1403     }
1404
1405     if ((c == 0) || (c == 8))
1406     {
1407         s += (ds = -fv1[ATTACKED]);
1408     }
1409
1410     return s;
1411 }
1412
1413
1414
1415 /*
1416  * Calculate the positional value for a silver on 'sq'.
1417  */
1418
1419 static inline int
1420 SilverValue(short sq, short side)
1421 {
1422     short s= 0, ds, ad;
1423
1424     OwnKingDistanceValue(sq, 2, 3);
1425
1426     if ((Kdist[c1][sq] < 3)
1427         && (atk1[sq] & (control[gold] | control[silver])))
1428     {
1429         s += (ds = fv1[COHESION]);
1430     }
1431
1432     if (in_opening_stage)
1433     {
1434         if (GameType[c1] == STATIC_ROOK)
1435         {
1436             if (csquare(c1, sq) == 12)
1437             {
1438                 short csq;
1439
1440                 if ((board[csq = csquare(c1, 20)] == bishop)
1441                     && (color[csq] == c1))
1442                 {
1443                     s += (ds = -2 * fv1[OPENWRONG]);
1444                 }
1445             }
1446         }
1447     }
1448     else
1449     {
1450         EnemyKingDistanceValue(sq, 2, 3);
1451     }
1452
1453     return s;
1454 }
1455
1456
1457
1458 /*
1459  * Calculate the positional value for a gold on 'sq'.
1460  */
1461
1462 static inline int
1463 GoldValue(short sq, short side)
1464 {
1465     short s = 0, ds, ad;
1466
1467     OwnKingDistanceValue(sq, 2, 3);
1468
1469     if ((Kdist[c1][sq] < 3)
1470         && (atk1[sq] & (control[gold] | control[silver])))
1471     {
1472         s += (ds = fv1[COHESION]);
1473     }
1474
1475     if (in_opening_stage)
1476     {
1477         if ((GameType[c1] == STATIC_ROOK) && (GameType[c2] != STATIC_ROOK))
1478         {
1479             if (Mvboard[csquare(c1, 3)])
1480             {
1481                 s += (ds = -2 * fv1[OPENWRONG]);
1482             }
1483         }
1484     }
1485     else
1486     {
1487         EnemyKingDistanceValue(sq, 2, 3);
1488     }
1489
1490     return s;
1491 }
1492
1493
1494
1495 /*
1496  * Calculate the positional value for a bishop on 'sq'.
1497  */
1498
1499 static inline int
1500 BishopValue(short sq, short side)
1501 {
1502     short s = 0, ds, ad;
1503
1504     if (in_opening_stage)
1505     {
1506         if (GameType[c1] == RANGING_ROOK)
1507         {
1508             /* Bishops diagonal should not be open */
1509             if (!on_csquare(c1, pawn, 30))
1510             {
1511                 s += (ds = -fv1[OPENWRONG]);
1512             }
1513         }
1514         else if (GameType[c2] == RANGING_ROOK)
1515         {
1516             /* Bishops diagonal should be open */
1517             if ((csquare(c1, sq) == 10)
1518                 && (!empty_csquare(c1, 20) || !empty_csquare(c1, 30)))
1519             {
1520                 s += (ds = -fv1[OPENWRONG]);
1521             }
1522             else if ((csquare(c1, sq) == 20) && !empty_csquare(c1, 30))
1523             {
1524                 s += (ds = -fv1[OPENWRONG]);
1525             }
1526         }
1527     }
1528     else
1529     {
1530         EnemyKingDistanceValue(sq, 1, 3);
1531     }
1532
1533     return s;
1534 }
1535
1536
1537
1538 /*
1539  * Calculate the positional value for a rook on 'sq'.
1540  */
1541
1542 static inline int
1543 RookValue(short sq, short side)
1544 {
1545     short s = 0, ds, ad;
1546
1547     OpenFileValue(sq, 2 * fv1[HOPN], 4*fv1[HOPN]);
1548
1549     if (in_opening_stage)
1550     {
1551         short WRONG = fv1[OPENWRONG], OPOK = WRONG / 3;
1552
1553         if (GameType[c1] == STATIC_ROOK)
1554         {
1555             short c = ccolumn(c1, sq);
1556
1557             /* Bonus for rook on 8th file */
1558             if (c == 7)
1559             {
1560                  s += (ds = OPOK);
1561             }
1562
1563             /*
1564              * Bonus for rook on right side,
1565              * penalty for rook on left side
1566              */
1567
1568             c = 4 - c;
1569             ds = 0;
1570
1571             if (c < 0)
1572             {
1573                 s += (ds = c + c + OPOK);
1574             }
1575             else if (c >= 0)
1576             {
1577                 s += (ds = -c - c - WRONG);
1578             }
1579         }
1580         else if (GameType[c1] == RANGING_ROOK)
1581         {
1582             /* Bonus for rook on left side and
1583              * bishops diagonal closed, penalty otherwise. */
1584
1585             short c;
1586             c = 4 - ccolumn(c1, sq);
1587             ds = 0;
1588
1589             if (c >= 0)
1590             {
1591                 /* Bishops diagonal should not be open. */
1592                 if (on_csquare(c1, pawn, 30))
1593                     s += (ds = OPOK);
1594                 else
1595                     s += (ds = -c - c - WRONG);
1596             }
1597             else if (c < 0)
1598             {
1599                 s += (ds = -c - c - WRONG);
1600
1601                 /* Penalty for king not on initial square. */
1602                 if (!on_csquare(side, king, 4))
1603                 {
1604                     s  += -4 * WRONG;
1605                     ds += -4 * WRONG;
1606                 }
1607             }
1608         }
1609     }
1610     else
1611     {
1612         EnemyKingDistanceValue(sq, 1, 3);
1613     }
1614
1615     return s;
1616 }
1617
1618
1619
1620 /*
1621  * Calculate the positional value for a promoted pawn on 'sq'.
1622  */
1623
1624 static inline int
1625 PPawnValue(short sq, short side)
1626 {
1627     short s = 0, ds, ad;
1628
1629     EnemyKingDistanceValue(sq, 3, 10);
1630
1631     return s;
1632 }
1633
1634
1635
1636 /*
1637  * Calculate the positional value for a promoted lance on 'sq'.
1638  */
1639
1640 static inline int
1641 PLanceValue(short sq, short side)
1642 {
1643     short s = 0, ds, ad;
1644
1645     EnemyKingDistanceValue(sq, 3, 10);
1646
1647     return s;
1648 }
1649
1650
1651
1652 /*
1653  * Calculate the positional value for a promoted knight on 'sq'.
1654  */
1655
1656 static inline int
1657 PKnightValue(short sq, short side)
1658 {
1659     short s = 0, ds, ad;
1660
1661     EnemyKingDistanceValue(sq, 3, 10);
1662
1663     return s;
1664 }
1665
1666
1667
1668 /*
1669  * Calculate the positional value for a promoted silver on 'sq'.
1670  */
1671
1672 static inline int
1673 PSilverValue(short sq, short side)
1674 {
1675     short s = 0, ds, ad;
1676
1677     EnemyKingDistanceValue(sq, 3, 10);
1678
1679     return s;
1680 }
1681
1682
1683
1684 /*
1685  * Calculate the positional value for a promoted bishop on 'sq'.
1686  */
1687
1688 static inline int
1689 PBishopValue(short sq, short side)
1690 {
1691     short s = 0, ds, ad;
1692
1693     EnemyKingDistanceValue(sq, 3, 4);
1694
1695     return s;
1696 }
1697
1698
1699
1700 /*
1701  * Calculate the positional value for a promoted rook on 'sq'.
1702  */
1703
1704 static inline int
1705 PRookValue(short sq, short side)
1706 {
1707     short s = 0, ds, ad;
1708
1709     EnemyKingDistanceValue(sq, 3, 4);
1710
1711     OpenFileValue(sq, 3 * fv1[HOPN], 2 * fv1[HOPN]);
1712
1713     return s;
1714 }
1715
1716
1717
1718 /*
1719  * Calculate the positional value for a king on 'sq'.
1720  */
1721
1722 static inline int
1723 KingValue(short sq, short side)
1724 {
1725     short s = 0, ds;
1726
1727     if (fv1[KSFTY] != 0)
1728         s += KingScan(sq);
1729
1730     if (in_opening_stage)
1731     {
1732         if ((GameType[c1] != UNKNOWN) && (ccolumn(c1, sq) == 4))
1733         {
1734             s += (ds = -fv1[OPENWRONG] / 3);
1735         }
1736         else if ((GameType[c1] == STATIC_ROOK) && on_right_side(c1, sq))
1737         {
1738             s += (ds = -fv1[OPENWRONG] / 2);
1739         }
1740         else if ((GameType[c1] == RANGING_ROOK) && on_left_side(c1, sq))
1741         {
1742             s += (ds = -fv1[OPENWRONG] / 2);
1743         }
1744     }
1745
1746     /* CHECKME: is this correct? */
1747     if ((ds = fv1[HOPN]))
1748     {
1749         s += OpenFileValue(sq, -2 * ds, -4 * ds);
1750     }
1751
1752     return s;
1753 }
1754
1755
1756
1757 /*
1758  * Calculate the positional value for a piece on 'sq'.
1759  */
1760
1761 static inline int
1762 PieceValue(short sq, short side)
1763 {
1764     short s, piece, ds;
1765     short mob;
1766
1767     piece = board[sq];
1768
1769     if (piece == no_piece)
1770         return 0;
1771
1772     s = (*Mpiece[piece])[c1][sq];
1773
1774     checked_trapped = false;
1775
1776     if (sweep[piece])
1777     {
1778         /* pin/x-ray attack and mobility for sweeping pieces */
1779         s += (ds = BRLscan(sq, &mob));
1780
1781         if ((piece == bishop) || (piece == pbishop))
1782             s += (ds = BMBLTY[mob] * fv1[MOBILITY] / 100);
1783         else if ((piece == rook) || (piece == prook))
1784             s += (ds = RMBLTY[mob] * fv1[MOBILITY] / 100);
1785         else
1786             s += (ds = LMBLTY[mob] * fv1[MOBILITY] / 100);
1787     }
1788     else
1789     {
1790         /* mobility for non-sweeping pieces */
1791     }
1792
1793     a2 = atk2[sq];
1794     a1 = atk1[sq];
1795
1796     if (a2 > 0)
1797     {
1798         /* opponent attacks piece */
1799         if (a1 == 0)
1800         {
1801             /* undefended piece */
1802             s += AttackedPieceValue(sq, side);
1803         }
1804         else
1805         {
1806             /* defended piece */
1807             short attack_value = value_of_weakest_attacker(a2);
1808             short piece_value = (*value)[stage][piece];
1809
1810             if (attack_value < piece_value)
1811             {
1812                 /* attacked by a weaker piece */
1813                 s += AttackedPieceValue(sq, side) / 2;
1814             }
1815             else if (abs(attack_value - piece_value) < 10)
1816             {
1817                 /* opponent has the option to exchange equal pieces */
1818                 s += (ds = -fv1[ATTACKED]);
1819             }
1820         }
1821     }
1822
1823     if (piece != king)
1824     {
1825
1826         if (a1 > 0)
1827         {
1828             /* piece is defended */
1829             s += (ds = (a1 & CNT_MASK) * fv1[PROTECT]);
1830         }
1831
1832         if (sseed[sq])
1833         {
1834             s += (ds = fv1[SEED]);
1835         }
1836
1837         if (sloose[sq])
1838         {
1839             s += (ds = -fv1[LOOSE]);
1840         }
1841
1842         if (starget[c1][sq])
1843         {
1844             if (sweep[piece])
1845             {
1846                 s -= (ds = -fv1[ATTACKED]/2);
1847             }
1848             else if (piece == pawn)
1849             {
1850                 s += (ds = fv1[ATTACKED]);
1851             }
1852         }
1853
1854         if (starget[c2][sq])
1855         {
1856             if (piece != pawn)
1857             {
1858                 s -= (ds = -fv1[ATTACKED] / 3);
1859             }
1860             else
1861             {
1862                 s += (ds = fv1[ATTACKED]);
1863             }
1864         }
1865
1866         if (Kdist[c1][sq] == 1)
1867         {
1868             s += (ds = fv1[KSFTY]);
1869         }
1870     }
1871
1872     switch (piece)
1873     {
1874     case pawn:
1875         s += PawnValue(sq, side);
1876         break;
1877
1878     case lance:
1879         s += LanceValue(sq, side);
1880         break;
1881
1882     case knight:
1883         s += KnightValue(sq, side);
1884         break;
1885
1886     case silver:
1887         s += SilverValue(sq, side);
1888         break;
1889
1890     case gold:
1891         s += GoldValue(sq, side);
1892         break;
1893
1894     case bishop:
1895         s += BishopValue(sq, side);
1896         break;
1897
1898     case rook:
1899         s += RookValue(sq, side);
1900         break;
1901
1902     case king:
1903         s += KingValue(sq, side);
1904         break;
1905
1906     case ppawn:
1907         s += PPawnValue(sq, side);
1908         break;
1909
1910     case plance:
1911         s += PLanceValue(sq, side);
1912         break;
1913
1914     case pknight:
1915         s += PKnightValue(sq, side);
1916         break;
1917
1918     case psilver:
1919         s += PSilverValue(sq, side);
1920         break;
1921
1922     case pbishop:
1923         s += PBishopValue(sq, side);
1924         break;
1925
1926     case prook:
1927         s += PRookValue(sq, side);
1928         break;
1929     }
1930
1931     return s;
1932 }
1933
1934
1935
1936 /*
1937  * Score distance to pattern regarding the game type which side plays.
1938  */
1939
1940 short
1941 ScorePatternDistance(short c1)
1942 {
1943     short ds, s = 0;
1944     small_short *fv1 = fvalue[c1];
1945     short os = 0;
1946
1947     if ((MAXCDIST > 0) && (fv1[PCASTLE] != 0)
1948         && ((os = castle_opening_sequence[c1]) >= 0))
1949     {
1950         ds = board_to_pattern_distance(c1, os, MAXCDIST, GameCnt);
1951
1952         if (ds != 0)
1953         {
1954             s += (ds *= fv1[PCASTLE]);
1955         }
1956     }
1957
1958     if ((MAXADIST > 0) && (fv1[PATTACK] != 0)
1959         && ((os = attack_opening_sequence[c1]) >= 0))
1960     {
1961         ds = board_to_pattern_distance(c1, os, MAXADIST, GameCnt);
1962
1963         if (ds != 0)
1964         {
1965             s += (ds *= fv1[PATTACK]);
1966         }
1967     }
1968
1969     return s;
1970 }
1971
1972
1973
1974
1975 /*
1976  * Determine castle and attack pattern which should be reached next.
1977  * Only patterns are considered, which have not been reached yet.
1978  */
1979
1980 static void
1981 UpdatePatterns(short side, short GameCnt)
1982 {
1983     char s[12];
1984     short xside = side ^ 1;
1985     short os;
1986     short j, k, n = 0;
1987
1988     strcpy(s, "CASTLE_?_?");
1989     s[7] = GameType[side];
1990     s[9] = GameType[xside];
1991     castle_opening_sequence[side] = os
1992         = locate_opening_sequence(side, s, GameCnt);
1993
1994     if (flag.post && (os != END_OF_SEQUENCES))
1995     {
1996         for (j = 0; j < MAX_SEQUENCE; j++)
1997         {
1998             for (k = OpeningSequence[os].first_pattern[j];
1999                  k != END_OF_PATTERNS;
2000                  k = Pattern[k].next_pattern)
2001             {
2002                 if (Pattern[k].distance[side] >= 0)
2003                     n++;
2004             }
2005         }
2006     }
2007
2008     if (os != END_OF_SEQUENCES)
2009         update_advance_bonus(side, os);
2010
2011     strcpy(s, "ATTACK_?_?");
2012     s[7] = GameType[side];
2013     s[9] = GameType[xside];
2014     attack_opening_sequence[side] = os
2015         = locate_opening_sequence(side, s, GameCnt);
2016
2017     if (flag.post && (os != END_OF_SEQUENCES))
2018     {
2019         for (j = 0; j < MAX_SEQUENCE; j++)
2020         {
2021             for (k = OpeningSequence[os].first_pattern[j];
2022                  k != END_OF_PATTERNS;
2023                  k = Pattern[k].next_pattern)
2024             {
2025                 if (Pattern[k].distance[side] >= 0)
2026                     n++;
2027             }
2028         }
2029     }
2030
2031     if (flag.post)
2032         ShowPatternCount(side, n);
2033
2034     if (os != END_OF_SEQUENCES)
2035         update_advance_bonus(side, os);
2036 }
2037
2038
2039
2040 static void
2041 ScoreCaptures(void)
2042 {
2043     short ds, col, n, m, piece;
2044
2045     if ((n = Captured[c1][pawn]))
2046     {
2047         ds = m = 0;
2048
2049         for (col = 0; col < NO_COLS; col++)
2050         {
2051             if (!PC1[col])
2052             {
2053                 m++;
2054                 ds += fv1[PWNDROP];
2055             }
2056         }
2057
2058         /* FIXME! another great obfuscated line... */
2059         pscore[c1] += (ds *= ((n > 2) ? 3 : n));
2060     }
2061
2062     if ((m = seed[c1]))
2063     {
2064         for (piece = lance, n = 0; piece <= rook; piece++)
2065         {
2066             if (Captured[c1][piece])
2067                 n++;
2068         }
2069
2070         pscore[c1] += (ds = m * fv1[DFFDROP]);
2071     }
2072
2073     for (piece = pawn, n = 0; piece <= rook; piece++)
2074     {
2075         if (Captured[c1][piece])
2076         {
2077             switch (piece)
2078             {
2079             case bishop:
2080                 ds = BMBLTY[MAX_BMBLTY - 1];
2081                 break;
2082
2083             case rook:
2084                 ds = RMBLTY[MAX_RMBLTY - 1];
2085                 break;
2086
2087             case lance:
2088                 ds = LMBLTY[MAX_LMBLTY - 1];
2089                 break;
2090
2091             default:
2092                 ds = MBLTY[piece];
2093             }
2094
2095             pscore[c1] += ds;
2096
2097             if (!Captured[c2][piece])
2098                 n += relative_value[piece];
2099         }
2100     }
2101
2102     if (n)
2103     {
2104         pscore[c1] += (ds = -n * fv1[OPPDROP] / 2);
2105     }
2106 }
2107
2108
2109
2110
2111
2112 /*
2113  * Perform normal static evaluation of board position. A score is generated
2114  * for each piece and these are summed to get a score for each side.
2115  */
2116
2117 short
2118 ScorePosition(short side)
2119 {
2120     short score;
2121     short sq, i, xside;
2122     short s;
2123     short ds;
2124
2125     xside = side ^ 1;
2126
2127     UpdateWeights(side);
2128
2129     hung[black] = hung[white] = pscore[black] = pscore[white] = 0;
2130
2131     array_zero(shung, sizeof(shung));
2132
2133 #ifdef CACHE
2134     if (!(use_etable && ProbeEETable(side, &s)))
2135     {
2136 #endif
2137         for (c1 = black; c1 <= white; c1++)
2138         {
2139             c2 = c1 ^ 1;
2140
2141             /* atk1 is array of attacks on squares by my side */
2142             atk1 = attack[c1];
2143
2144             /* atk2 is array of attacks on squares by other side */
2145             atk2 = attack[c2];
2146
2147             /* same for PC1 and PC2 */
2148             PC1 = PawnCnt[c1];
2149             PC2 = PawnCnt[c2];
2150
2151             /* same for fv1 and fv2 */
2152             fv1 = fvalue[c1];
2153
2154             for (i = PieceCnt[c1]; i >= 0; i--)
2155             {
2156                 sq = PieceList[c1][i];
2157
2158 #if defined SAVE_SVALUE
2159                 pscore[c1] += PieceValue(sq, side);
2160 #else
2161                 pscore[c1] += (svalue[sq] = PieceValue(sq, side));
2162 #endif
2163             }
2164
2165             ScoreCaptures();
2166         }
2167
2168         for (c1 = black, c2 = white; c1 <= white; c1++, c2--)
2169         {
2170             short n;
2171
2172             fv1 = fvalue[c1];
2173
2174             /* Score fifth rank */
2175             for (sq = 36, n = 0; sq <= 44; sq++)
2176             {
2177                 if ((color[sq] == c1) || (attack[c1][sq] != 0))
2178                     n++;
2179             }
2180
2181             if (n != 0)
2182             {
2183                 pscore[c1] += (ds = n * fv1[CNTRL5TH]);
2184             }
2185
2186             /* Score holes */
2187             for (sq = ((c1 == black) ? 0 : 54), n = 0;
2188                  sq <= ((c1 == black) ? 26 : 80);
2189                  sq++)
2190             {
2191                 if (board[sq] == no_piece && attack[c1][sq] == 0)
2192                     n++;
2193             }
2194
2195             if (n != 0)
2196             {
2197                 pscore[c1] += (ds = -n * fv1[HOLES]);
2198             }
2199
2200             if (hung[c1] > 1)
2201             {
2202                 pscore[c1] += (ds = -fv1[HUNGX]);
2203             }
2204
2205             /* Score opening features and
2206              * castle/attack pattern distances */
2207
2208             if (in_opening_stage)
2209             {
2210                 pscore[c1] += (ds = ScoreKingOpeningFeatures());
2211                 pscore[c1] += (ds = ScorePatternDistance(c1));
2212             }
2213         }
2214
2215         score = mtl[side] - mtl[xside]
2216             + pscore[side] - pscore[xside] + 10;
2217
2218 #ifdef CACHE
2219         if (use_etable && PUTVAR)
2220             PutInEETable(side, score);
2221 #endif
2222
2223         return score;
2224 #ifdef CACHE /* CHECKME: this looks bad */
2225     }
2226
2227     return s;
2228 #endif
2229 }
2230
2231
2232
2233 /*
2234  * Try to determine the game type of "side".
2235  */
2236
2237 inline static void
2238 GuessGameType(short side_to_move)
2239 {
2240     short side, gt;
2241     short StaticRook[2]  = { 0, 0 };
2242     short RangingRook[2] = { 0, 0 };
2243
2244     for (side = black; side <= white; side++)
2245     {
2246         /* computer should not change its mind */
2247
2248         extern int bookflag;
2249
2250         gt = GameType[side];
2251
2252         if (!bookflag && (side == side_to_move))
2253         {
2254             if (gt == STATIC_ROOK)
2255                 StaticRook[side] += 4;
2256             else if (gt == RANGING_ROOK)
2257                 RangingRook[side] += 4;
2258         }
2259
2260         /* static rook conditions */
2261
2262         if (on_column(side, rook, 7))
2263             StaticRook[side] += 3;
2264
2265         if (on_csquare(side, pawn, 34))
2266             StaticRook[side] += 6;
2267         else if (on_csquare(side, pawn, 43))
2268             StaticRook[side] += 4;
2269         else if (!on_column(side, pawn, 7))
2270             StaticRook[side] += 5;
2271
2272         if (empty_csquare(side, 5) || empty_csquare(side, 6))
2273             StaticRook[side] += 2;
2274
2275         if (on_left_side(side, king))
2276             StaticRook[side] += 2;
2277
2278         /* ranging rook conditions */
2279
2280         if (on_left_side(side, rook))
2281             RangingRook[side] += 5;
2282         else if (!on_column(side, rook, 7))
2283             RangingRook[side] += 3;
2284
2285         if (on_csquare(side, pawn, 25))
2286             RangingRook[side] += 1;
2287
2288         if (on_csquare(side, pawn, 30))
2289             RangingRook[side] += 1;
2290         else
2291             RangingRook[side] -= 2;
2292
2293         if (!on_right_side(side, rook))
2294             RangingRook[side] += 4;
2295
2296         if (on_right_side(side, king))
2297             RangingRook[side] += 4;
2298
2299         if (on_csquare(side, bishop, 20))
2300         {
2301             if (on_csquare(side, silver, 11)
2302                 || on_csquare(side, silver, 12)
2303                 || on_csquare(side, silver, 21))
2304             {
2305                 RangingRook[side] += 3;
2306             }
2307         }
2308
2309         if ((StaticRook[side] > 5) || (RangingRook[side] > 5))
2310         {
2311             GameType[side] = (StaticRook[side] > RangingRook[side])
2312                 ? STATIC_ROOK : RANGING_ROOK;
2313         }
2314         else
2315         {
2316             GameType[side] = UNKNOWN;
2317         }
2318     }
2319
2320     if ((GameType[black] == UNKNOWN) || (GameType[white] == UNKNOWN))
2321     {
2322         for (side = black; side <= white; side++)
2323         {
2324             if ((side == computer) && (GameType[side] == UNKNOWN))
2325             {
2326                 /*
2327                  * Game type is UNKNOWN.
2328                  * Make a decision what type of game to play.
2329                  * To make computer games more interesting, make a
2330                  * random decision.
2331                  */
2332
2333                 if (!on_csquare(side, pawn, 25))
2334                 {
2335                     /* Play static rook if rook pawn has been pushed! */
2336                     GameType[side] = STATIC_ROOK;
2337                 }
2338                 else
2339                 {
2340                     unsigned int random = urand() % 100;
2341                     short d = StaticRook[side] - RangingRook[side];
2342
2343                     switch (GameType[side ^ 1])
2344                     {
2345                     case STATIC_ROOK:
2346                         if (random < 35 + d)
2347                             GameType[side] = STATIC_ROOK;
2348                         else if (random < 95)
2349                             GameType[side] = RANGING_ROOK;
2350                         break;
2351
2352                     case RANGING_ROOK:
2353                         if (random < 75 + d)
2354                             GameType[side] = STATIC_ROOK;
2355                         else if (random < 95)
2356                             GameType[side] = RANGING_ROOK;
2357                         break;
2358
2359                     default:
2360                         if (random < 33 + d)
2361                             GameType[side] = STATIC_ROOK;
2362                         else if (random < 66)
2363                             GameType[side] = RANGING_ROOK;
2364                     }
2365                 }
2366             }
2367         }
2368     }
2369 }
2370
2371
2372
2373
2374 static void
2375 DetermineGameType(short side_to_move)
2376 {
2377     short side;
2378
2379     GuessGameType(side_to_move);
2380
2381     array_zero(Mpawn,   sizeof(Mpawn));
2382     array_zero(Mlance,  sizeof(Mlance));
2383     array_zero(Mknight, sizeof(Mknight));
2384     array_zero(Msilver, sizeof(Msilver));
2385     array_zero(Mgold,   sizeof(Mgold));
2386     array_zero(Mbishop, sizeof(Mbishop));
2387     array_zero(Mrook,   sizeof(Mrook));
2388     array_zero(Mking,   sizeof(Mking));
2389
2390     if (in_opening_stage)
2391     {
2392         for (side = black; side <= white; side++)
2393             UpdatePatterns(side, GameCnt);
2394     }
2395     else
2396     {
2397         ShowPatternCount(black, -1);
2398         ShowPatternCount(white, -1);
2399     }
2400 }
2401
2402
2403
2404 /*
2405  * This is done one time before the search is started. Set up arrays
2406  * Mwpawn, Mbpawn, Mknight, Mbishop, Mking which are used in the SqValue()
2407  * function to determine the positional value of each piece.
2408  */
2409
2410 void
2411 ExaminePosition(short side)
2412 {
2413     short c1, piece, sq, i, bsq, wsq;
2414
2415     /* Build enemy king distance tables. */
2416
2417     for (sq = 0, bsq = BlackKing, wsq = WhiteKing; sq < NO_SQUARES; sq++)
2418     {
2419         Kdist[black][sq] = distance(sq, bsq);
2420         Kdist[white][sq] = distance(sq, wsq);
2421     }
2422
2423     threats(black);
2424     threats(white);
2425
2426     ExamineSquares();
2427
2428     DetermineGameType(side);
2429     DetermineStage(side);
2430
2431     UpdateWeights(side);
2432
2433     array_zero(HasPiece, sizeof(HasPiece));
2434
2435     for (c1 = black; c1 <= white; c1++)
2436     {
2437         for (i = PieceCnt[c1]; i >= 0; i--)
2438         {
2439             ++HasPiece[c1][piece = board[sq = PieceList[c1][i]]];
2440         }
2441     }
2442 }
2443
2444
2445
2446 void
2447 DetermineStage(short side)
2448 {
2449     short xside = side ^ 1, ds, db1, c1, c2, feature;
2450
2451     /* Determine initial stage */
2452
2453     balance[side] = balance[xside] = 50;
2454
2455     if ((GameType[side] == STATIC_ROOK)
2456         && (GameType[xside] == STATIC_ROOK))
2457     {
2458         if (GameCnt < 40)
2459             stage = 0;
2460         else if (GameCnt < 60)
2461             stage = 15;
2462         else if (GameCnt < 80)
2463             stage = 25;
2464         else
2465             stage = 30;
2466     }
2467     else if ((GameType[side] == RANGING_ROOK)
2468              || (GameType[xside] == RANGING_ROOK))
2469     {
2470         if (GameCnt < 30)
2471             stage = 0;
2472         else if (GameCnt < 50)
2473             stage = 15;
2474         else if (GameCnt < 70)
2475             stage = 25;
2476         else
2477             stage = 30;
2478     }
2479     else
2480     {
2481         if (GameCnt < 35)
2482             stage = 0;
2483         else if (GameCnt < 55)
2484             stage = 15;
2485         else if (GameCnt < 75)
2486             stage = 25;
2487         else
2488             stage = 30;
2489     }
2490
2491     /* Update stage depending on board features and attack balance value */
2492
2493     if (abs(ds = (mtl[side] - mtl[xside]))
2494         > (db1 = (*value)[stage][lance]))
2495     {
2496         db1 = abs(4 * ds / db1);
2497
2498         if (ds < 0)
2499             balance[side] += db1;
2500         else if (ds > 0)
2501             balance[xside] += db1;
2502
2503         stage += (ds = db1);
2504     }
2505
2506     for (c1 = black, c2 = white; c1 <= white; c1++, c2--)
2507     {
2508         if ((ds = seed[c1]) > 2)
2509         {
2510             balance[c1] += (db1 = ds * 2);
2511             balance[c2] -= db1;
2512
2513             if (stage < 30)
2514                 stage = 30;
2515
2516             stage += ds;
2517         }
2518
2519         if ((db1 = hung[c1]) > 2)
2520         {
2521             balance[c1] -= (db1 *= 2);
2522             balance[c2] += db1;
2523         }
2524
2525         if ((db1 = loose[c1]) > 4)
2526         {
2527             balance[c1] -= (db1 /= 2);
2528             balance[c2] += db1;
2529             stage += (ds = 1);
2530         }
2531
2532         if ((ds = hole[c1]))
2533         {
2534             balance[c1] -= (db1 = ds);
2535             balance[c2] += db1;
2536             stage += (ds /= 2);
2537         }
2538
2539         if ((db1 = target[c1]) > 3)
2540         {
2541             balance[c1] += (db1 /= 3);
2542             balance[c2] -= db1;
2543             stage += (ds = db1 / 4);
2544         }
2545
2546         stage += (ds = captured[c1] / 2);
2547
2548         if ((db1 = captured[c1]) > 4)
2549         {
2550             balance[c1] += (db1 /= 2);
2551             stage += (ds = 3);
2552         }
2553
2554         if ((db1 = dcaptured[c1]) > 3)
2555         {
2556             balance[c1] += db1;
2557             stage += (ds = 3);
2558         }
2559
2560         if (balance[c1] > 99)
2561             balance[c1] = 99;
2562         else if (balance[c1] < 0)
2563             balance[c1] = 0;
2564     }
2565
2566     if (stage > 99)
2567         stage = 99;
2568     else if (stage < 0)
2569         stage = 0;
2570
2571     if (flag.post)
2572         ShowStage();
2573
2574     /* Determine stage dependant weights */
2575
2576     ADVNCM[pawn]   = 1; /* advanced pawn bonus increment   */
2577     ADVNCM[lance]  = 1;
2578     ADVNCM[knight] = 1;
2579     ADVNCM[silver] = 1; /* advanced silver bonus increment */
2580     ADVNCM[gold]   = 1; /* advanced gold bonus increment   */
2581     ADVNCM[bishop] = 1;
2582     ADVNCM[rook]   = 1;
2583     ADVNCM[king]   = 1; /* advanced king bonus increment   */
2584
2585     MAXCDIST = (stage < 33) ? (33 - stage) / 4 : 0;
2586     MAXADIST = (stage < 30) ? (30 - stage) / 4 : 0;
2587
2588     for (c1 = black; c1 <= white; c1++)
2589     {
2590         for (feature = 0; feature < NO_FEATURES; feature++)
2591         {
2592             fvalue[c1][feature] =
2593                 ((((*fscore)[stage][feature][0] * (99 - balance[c1])) + 50)
2594                  / 100)
2595                 + ((((*fscore)[stage][feature][1] * balance[c1]) + 50)
2596                    / 100);
2597         }
2598     }
2599 }
2600
2601
2602
2603 void
2604 UpdateWeights(short stage)
2605 {
2606 }
2607
2608
2609
2610 /*
2611  * Compute stage dependent relative material values assuming
2612  * linearity between the main stages:
2613  *
2614  *   minstage < stage < maxstage =>
2615  *          stage - minstage        value - minvalue
2616  *         -------------------  =  -------------------
2617  *         maxstage - minstage     maxvalue - minvalue
2618  */
2619
2620
2621 static short
2622 linear_piece_value(short piece, short stage, short i, short j)
2623 {
2624     short minvalue, maxvalue, minstage, maxstage;
2625
2626     minstage = ispvalue[0][i];
2627     maxstage = ispvalue[0][j];
2628     minvalue = ispvalue[piece][i];
2629     maxvalue = ispvalue[piece][j];
2630
2631     /* FIXME: set a variable then return it, puh-leeze! */
2632     return ((stage - minstage) * (maxvalue - minvalue)
2633             / (maxstage - minstage)) + minvalue;
2634 }
2635
2636
2637
2638 static short
2639 linear_feature_value(short feature, short stage, short i, short j)
2640 {
2641     short minvalue, maxvalue, minstage, maxstage;
2642
2643     minstage = ispvalue[0][i];
2644     maxstage = ispvalue[0][j];
2645     minvalue = weight[feature][i];
2646     maxvalue = weight[feature][j];
2647
2648     /* FIXME: set a variable then return it, puh-leeze! */
2649     return ((stage - minstage) * (maxvalue - minvalue)
2650             / (maxstage - minstage)) + minvalue;
2651 }
2652
2653
2654 /*
2655  * matweight = percentage_of_max_value * max_value(stage) / 100
2656  * max_value(0) = MAX_VALUE; max_value(100) = MIN_VALUE
2657  *  => max_value(stage) = a * stage + b; b = MAX_VALUE,
2658  *     a = (MIN_VALUE - MAX_VALUE)/100
2659  */
2660
2661 #define MIN_VALUE 300
2662 #define MAX_VALUE 1000
2663
2664 #define max_value(stage) \
2665 ((long)(MIN_VALUE - MAX_VALUE) * stage + (long)100 * MAX_VALUE)
2666 #define matweight(value, stage) \
2667 ((long)max_value(stage) * value / 10000)
2668
2669
2670
2671 void
2672 Initialize_eval(void)
2673 {
2674     short stage, piece, feature, i;
2675
2676     for (stage = 0; stage < NO_STAGES; stage++)
2677     {
2678         for (i = 0; i < MAIN_STAGES; i++)
2679         {
2680             if (stage == ispvalue[0][i])
2681             {
2682                 for (piece = 0; piece < NO_PIECES; piece++)
2683                 {
2684                     (*value)[stage][piece] =
2685                         matweight(ispvalue[piece][i], stage);
2686                 }
2687
2688                 for (feature = 0; feature < NO_FEATURES; feature++)
2689                 {
2690                     (*fscore)[stage][feature][0] =
2691                         (weight[feature][i]
2692                          * weight[feature][MAIN_STAGES] + 50) / 100;
2693
2694                     (*fscore)[stage][feature][1] =
2695                         (weight[feature][i]
2696                          * weight[feature][MAIN_STAGES + 1] + 50) / 100;
2697                 }
2698
2699                 break;
2700             }
2701
2702             if (stage < ispvalue[0][i + 1])
2703             {
2704                 for (piece = 0; piece < NO_PIECES; piece++)
2705                 {
2706                     (*value)[stage][piece] =
2707                         matweight(
2708                             linear_piece_value(piece, stage, i, i + 1),
2709                             stage);
2710                 }
2711
2712                 for (feature = 0; feature < NO_FEATURES; feature++)
2713                 {
2714                     (*fscore)[stage][feature][0] =
2715                         (linear_feature_value(feature, stage, i, i + 1)
2716                          * weight[feature][MAIN_STAGES] + 50) / 100;
2717
2718                     (*fscore)[stage][feature][1] =
2719                         (linear_feature_value(feature, stage, i, i + 1)
2720                          * weight[feature][MAIN_STAGES + 1] + 50) / 100;
2721                 }
2722
2723                 break;
2724             }
2725         }
2726     }
2727 }
2728