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