~ubuntu-branches/ubuntu/warty/gnushogi/warty

« back to all changes in this revision

Viewing changes to src/genmove.c

  • Committer: Bazaar Package Importer
  • Author(s): Javier Fernandez-Sanguino Pen~a
  • Date: 2004-01-09 16:06:59 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20040109160659-n26nu7009llm247p
Tags: 1.3-3.1
* NMU
 - Minimal testing done and looks quite OK (even if I don't know
   how to play the game...)
 - Build-Depends move from libxaw-dev to libxaw6-dev (Closes: #169975)
 - Included errno.h in gnushogi which makes the binary build properly
   now (and is usable with xshogi) (Closes: #226319)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * genmoves.c - C source for GNU SHOGI
3
 
 *
4
 
 * Copyright (c) 1993, 1994 Matthias Mutz
5
 
 *
6
 
 * GNU SHOGI is based on GNU CHESS
7
 
 *
8
 
 * Copyright (c) 1988,1989,1990 John Stanback
9
 
 * Copyright (c) 1992 Free Software Foundation
10
 
 *
11
 
 * This file is part of GNU SHOGI.
12
 
 *
13
 
 * GNU Shogi is free software; you can redistribute it and/or modify
14
 
 * it under the terms of the GNU General Public License as published by
15
 
 * the Free Software Foundation; either version 1, or (at your option)
16
 
 * any later version.
17
 
 *
18
 
 * GNU Shogi is distributed in the hope that it will be useful,
19
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21
 
 * GNU General Public License for more details.
22
 
 *
23
 
 * You should have received a copy of the GNU General Public License
24
 
 * along with GNU Shogi; see the file COPYING.  If not, write to
25
 
 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
26
 
 */
27
 
 
28
 
#include "gnushogi.h"
29
 
 
30
 
/* #define DONTUSE_HEURISTIC */
31
 
      
32
 
#ifdef DEBUG
33
 
#include <assert.h>
34
 
#endif
35
 
 
36
 
short *TrP;
37
 
 
38
 
static struct leaf far *node;
39
 
static short sqking, sqxking;
40
 
static short InCheck = false, GenerateAllMoves = false;     
41
 
static short check_determined = false;
42
 
 
43
 
static short INCscore = 0;
44
 
 
45
 
short deepsearchcut = true;
46
 
short tas = false, taxs = false, ssa = false;
47
 
 
48
 
short generate_move_flags = false;
49
 
 
50
 
 
51
 
/*
52
 
 * Ply limits for deep search cut.
53
 
 * No moves or drops flagged with "stupid" are considered beyond ply BEYOND_STUPID.
54
 
 * Only moves or drops flagged with "kingattack" are considered beyond ply BEYOND_KINGATTACK.
55
 
 * No moves or drops flagged with "questionable" are considered beyond ply BEYOND_QUESTIONABLE.
56
 
 * Only moves or drops flagged with "tesuji" are considered beyond ply BEYOND_TESUJI.
57
 
 * No drops are considered beyond ply BEYOND_DROP.
58
 
 * Exceptions: moves or drops that prevent check or give check are always considered.
59
 
 */
60
 
                       
61
 
#if defined THINK_C || defined MSDOS
62
 
#define BEYOND_STUPID 0
63
 
#define BEYOND_TIMEOUT 2
64
 
#define BEYOND_KINGATTACK 4
65
 
#define BEYOND_QUESTIONABLE 6
66
 
#define BEYOND_TESUJI 6
67
 
#define BEYOND_DROP 8
68
 
#else
69
 
#define BEYOND_STUPID 0
70
 
#define BEYOND_TIMEOUT 2
71
 
#define BEYOND_KINGATTACK 6
72
 
#define BEYOND_QUESTIONABLE 8
73
 
#define BEYOND_TESUJI 8
74
 
#define BEYOND_DROP 10
75
 
#endif 
76
 
 
77
 
static short MaxNum[MAXDEPTH] =
78
 
  {-1,40,80,20,40,10, 5, 5, 5, 5,
79
 
    5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 
80
 
    5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
81
 
    5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
82
 
  };
83
 
 
84
 
#ifdef HASHKEYTEST
85
 
    extern int CheckHashKey ();
86
 
    extern char mvstr[4][6];
87
 
#endif
88
 
 
89
 
 
90
 
inline
91
 
static
92
 
void
93
 
GenMakeMove (short int side,
94
 
             short f,
95
 
             short t,
96
 
             short int *tempb,  /* piece at to square */
97
 
             short int *tempc,  /* color of to square */
98
 
             short int promote_piece)
99
 
 
100
 
/*
101
 
 * Update Arrays board[] and color[] to reflect the new board
102
 
 * position obtained after making the move pointed to by node.
103
 
 */
104
 
 
105
 
{
106
 
  register short int piece, upiece, n;
107
 
 
108
 
  t = t & 0x7f;
109
 
      
110
 
#ifdef DEBUG
111
 
  assert(f!=NO_SQUARES);
112
 
#endif
113
 
 
114
 
  if (f > NO_SQUARES )
115
 
    { 
116
 
      piece = f - NO_SQUARES;
117
 
      if ( piece > NO_PIECES ) piece -= NO_PIECES;
118
 
      board[t] = piece;
119
 
      color[t] = side;
120
 
      n = Captured[side][piece]--;
121
 
      UpdateDropHashbd (side, piece, n);
122
 
      UpdateHashbd (side, piece, -1, t);
123
 
      UpdatePieceList (side, t, ADD_PIECE);
124
 
    }
125
 
  else
126
 
    {
127
 
      *tempb = board[t];
128
 
      *tempc = color[t];
129
 
      if ( *tempb != no_piece ) {
130
 
        n = ++Captured[side][upiece = unpromoted[*tempb]];
131
 
        UpdateDropHashbd (side, upiece, n);
132
 
        UpdateHashbd (*tempc, *tempb, -1, t);
133
 
        UpdatePieceList (*tempc, t, REMOVE_PIECE);
134
 
      }
135
 
      piece = board[f];
136
 
      Pindex[t] = Pindex[f];
137
 
      PieceList[side][Pindex[t]] = t;
138
 
      color[f] = neutral;
139
 
      board[f] = no_piece;
140
 
      color[t] = side;
141
 
      if ( promote_piece ) {
142
 
        UpdateHashbd(side,piece,f,-1);
143
 
        board[t] = promoted[piece];   
144
 
        UpdateHashbd(side,board[t],-1,t);
145
 
      } else {
146
 
        board[t] = piece;
147
 
        UpdateHashbd(side,piece,f,t);
148
 
      }
149
 
    } 
150
 
#ifdef DEBUG
151
 
    assert(Captured[black][0]==0 && Captured[white][0]==0);
152
 
#endif 
153
 
#ifdef HASHKEYTEST
154
 
    if ( CheckHashKey () ) {
155
 
      algbr(f,t,0);
156
 
      printf("error in GenMakeMove: %s\n",mvstr[0]);
157
 
      exit(1);
158
 
    }
159
 
#endif
160
 
}
161
 
 
162
 
static
163
 
void
164
 
GenUnmakeMove (short int side,
165
 
               short f,
166
 
               short t,
167
 
               short int tempb,
168
 
               short int tempc,
169
 
               short int promote_piece)
170
 
 
171
 
/*
172
 
 * Take back a move.
173
 
 */
174
 
 
175
 
{
176
 
  register short piece, upiece, n;
177
 
 
178
 
  t = t & 0x7f;
179
 
 
180
 
#ifdef DEBUG
181
 
  assert(f!=NO_SQUARES);
182
 
#endif
183
 
  
184
 
  if (f > NO_SQUARES )
185
 
    { 
186
 
      piece = f - NO_SQUARES;
187
 
      if ( piece > NO_PIECES ) piece -= NO_PIECES;
188
 
      board[t] = no_piece;
189
 
      color[t] = neutral;
190
 
      n = ++Captured[side][piece];
191
 
      UpdateDropHashbd (side, piece, n);
192
 
      UpdateHashbd (side, piece, -1, t);
193
 
      UpdatePieceList (side, t, REMOVE_PIECE);
194
 
    }
195
 
  else
196
 
    { 
197
 
      piece = board[t];
198
 
      color[t] = tempc;
199
 
      board[t] = tempb;
200
 
      Pindex[f] = Pindex[t];
201
 
      PieceList[side][Pindex[f]] = f;
202
 
      if ( tempb != no_piece ) {
203
 
        n = Captured[side][upiece=unpromoted[tempb]]--;
204
 
        UpdateDropHashbd (side, upiece, n);
205
 
        UpdateHashbd (tempc, tempb, -1, t);
206
 
        UpdatePieceList (tempc, t, ADD_PIECE);
207
 
      }
208
 
      color[f] = side;
209
 
      if ( promote_piece ) {
210
 
        UpdateHashbd(side,piece,-1,t);
211
 
        board[f] = unpromoted[piece]; 
212
 
        UpdateHashbd(side,board[f],f,-1);
213
 
      } else {
214
 
        board[f] = piece;
215
 
        UpdateHashbd(side,piece,f,t);
216
 
      } 
217
 
    }
218
 
#ifdef DEBUG
219
 
    assert(Captured[black][0]==0 && Captured[white][0]==0);
220
 
#endif
221
 
#ifdef HASHKEYTEST
222
 
    if ( CheckHashKey () ) {
223
 
      algbr(f,t,0);
224
 
      printf("error in GenUnmakeMove: %s\n",mvstr[0]);
225
 
      exit(1);
226
 
    }
227
 
#endif
228
 
}                 
229
 
 
230
 
 
231
 
 
232
 
static void
233
 
gives_check_flag (unsigned short *flags, short side, short f, short t)
234
 
{
235
 
  short tempb, tempc, blockable, promote_piece;
236
 
  promote_piece = (*flags & promote) != 0;
237
 
  GenMakeMove (side, f, t, &tempb, &tempc, promote_piece);
238
 
  if ( SqAtakd(sqxking, side, &blockable) )
239
 
     *flags |= check;
240
 
  GenUnmakeMove (side, f, t, tempb, tempc, promote_piece);
241
 
}
242
 
 
243
 
 
244
 
inline
245
 
static
246
 
void
247
 
Link (short side, short piece,
248
 
      short from, short to, unsigned short local_flag, short s) 
249
 
{        
250
 
#ifdef notdef
251
 
    if (debug_eval ) {
252
 
        fprintf ( debug_eval_file, "link from %d to %d InCheck %d tsume %d\n",
253
 
          from, to, InCheck, flag.tsume );
254
 
    }
255
 
#endif
256
 
 
257
 
    if ( *TrP == TREE ) {
258
 
#ifdef NONDSP
259
 
      printf("TREE overflow\n");
260
 
#else
261
 
      ShowMessage("TREE overflow\n");
262
 
#endif
263
 
    } else {
264
 
      node->f = from; 
265
 
      node->t = (local_flag & promote) ? (to | 0x80) : to;
266
 
      node->reply = 0;
267
 
      node->flags = local_flag;
268
 
      node->score = s;
269
 
      node->INCscore = INCscore;
270
 
      if ( GenerateAllMoves )
271
 
        {
272
 
          (*TrP)++, node++;
273
 
        }
274
 
      else if ( InCheck )
275
 
        { 
276
 
          /* only moves out of check */
277
 
          short tempb, tempc, sq, threat, blockable, promote_piece;
278
 
          promote_piece = (node->flags & promote) != 0;
279
 
          GenMakeMove (side, node->f, node->t, &tempb, &tempc, promote_piece);
280
 
          sq = (from == sqking) ? to : sqking;
281
 
          threat = SqAtakd(sq, side ^ 1, &blockable);
282
 
          GenUnmakeMove (side, node->f, node->t, tempb, tempc, promote_piece);
283
 
          if ( !threat ) 
284
 
            (*TrP)++, node++;
285
 
        }
286
 
      else if ( flag.tsume )
287
 
        { 
288
 
          /* only moves that give check */          
289
 
          if ( !(node->flags & check) && !check_determined ) {
290
 
            /* determine check flag */          
291
 
            gives_check_flag(&node->flags,side,node->f,node->t);
292
 
          }
293
 
          if ( node->flags & check )
294
 
            (*TrP)++, node++;
295
 
        }
296
 
      else
297
 
        (*TrP)++, node++;
298
 
    }
299
 
}
300
 
 
301
 
 
302
 
inline
303
 
int
304
 
PromotionPossible (short int color, short int f, short int t, short int p)
305
 
306
 
  if ( color == black ) {
307
 
    if ( f < 54 && t < 54 ) return(false);
308
 
  } else {
309
 
    if ( f > 26 && t > 26 ) return(false);
310
 
  };
311
 
 
312
 
  switch ( p ) {
313
 
    case pawn: return(true);
314
 
    case lance: return(true);
315
 
    case knight: return(true);
316
 
    case silver: return(true);
317
 
    case bishop: return(true);
318
 
    case rook: return(true);
319
 
  };
320
 
 
321
 
  return(false);
322
 
}
323
 
 
324
 
 
325
 
inline
326
 
int
327
 
NonPromotionPossible (short int color, short int f, short int t, short int p)
328
 
{
329
 
  switch ( p ) {
330
 
    case pawn : 
331
 
           if ( color == black )
332
 
             return ((t < 72) ? true : (generate_move_flags ? ILLEGAL_TRAPPED : false));
333
 
           else
334
 
             return ((t > 8) ? true : (generate_move_flags ? ILLEGAL_TRAPPED : false));
335
 
    case lance: 
336
 
           if ( color == black )
337
 
             return ((t < 72) ? true : (generate_move_flags ? ILLEGAL_TRAPPED : false));
338
 
           else
339
 
             return ((t > 8) ? true : (generate_move_flags ? ILLEGAL_TRAPPED : false));
340
 
    case knight:
341
 
           if ( color == black )
342
 
             return ((t < 63) ? true : (generate_move_flags ? ILLEGAL_TRAPPED : false));
343
 
           else
344
 
             return ((t > 17) ? true : (generate_move_flags ? ILLEGAL_TRAPPED : false));
345
 
  };
346
 
 
347
 
  return(true);
348
 
}
349
 
 
350
 
 
351
 
#if defined FIELDBONUS || defined DROPBONUS
352
 
 
353
 
inline
354
 
static 
355
 
short
356
 
field_bonus (short int ply, short int side, short int piece, short int f, short int t, 
357
 
             unsigned short *local_flag)
358
 
 
359
 
/* bonus for possible next moves */
360
 
 
361
 
{
362
 
  register short s, u, ptyp;
363
 
  register unsigned char *ppos, *pdir;
364
 
  register short c1, c2;
365
 
#ifdef SAVE_NEXTPOS
366
 
  short d;
367
 
#endif
368
 
      
369
 
  c1 = side;
370
 
  c2 = side ^ 1;
371
 
 
372
 
  s = 0;
373
 
 
374
 
  check_determined = true;
375
 
 
376
 
  ptyp = ptype[side][piece];
377
 
          
378
 
#ifdef SAVE_NEXTPOS
379
 
  u = first_direction(ptyp,&d,t); 
380
 
#else
381
 
  ppos = (*nextpos[ptyp])[t];
382
 
  pdir = (*nextdir[ptyp])[t];
383
 
  u = ppos[t];
384
 
#endif
385
 
 
386
 
  do 
387
 
    { short coloru = color[u];
388
 
      if ( piece != king && GameCnt > 40 ) {
389
 
        if ( distance(u,EnemyKing) <= 1 ) {
390
 
          /* can reach square near own king */
391
 
          s += 2;      
392
 
          *local_flag |= kingattack;
393
 
        } else if ( distance(u,OwnKing) <= 1 ) {
394
 
          /* can reach square near enemy king */
395
 
          s++;
396
 
          *local_flag |= kingattack;
397
 
        }
398
 
      }
399
 
      if (coloru == side ) {
400
 
        /* impossible next move */
401
 
#ifdef SAVE_NEXTPOS
402
 
        u = next_direction(ptyp,&d,t);
403
 
#else
404
 
        u = pdir[u];
405
 
#endif
406
 
      } else {
407
 
        /* possible next move */
408
 
        if (PromotionPossible(side,t,u,piece)) {
409
 
          /* possible promotion in next move */
410
 
          if ( piece == pawn )
411
 
            {
412
 
              s += 2;
413
 
#ifdef TESUJIBONUS
414
 
              if ( !InPromotionZone(side,t) ) {
415
 
                *local_flag |= tesuji; /* The dangling pawn */ 
416
 
                s++;
417
 
              }
418
 
#endif
419
 
            }
420
 
          else
421
 
            s++; 
422
 
        }
423
 
        if (coloru == neutral) {
424
 
          /* next move to an empty square */
425
 
          if ( u == FROMsquare ) {
426
 
             /* opponent has just left this square */
427
 
             s++;
428
 
          }
429
 
#ifdef SAVE_NEXTPOS
430
 
          u = next_position(ptyp,&d,t,u);
431
 
#else
432
 
          u = ppos[u];
433
 
#endif
434
 
        } else {
435
 
          /* attack opponents piece */
436
 
#ifdef TESUJIBONUS
437
 
          short boardu, upiece, rvupiece, rvuboard;
438
 
#endif
439
 
          s++;
440
 
          if ( u == TOsquare )
441
 
            /* opponent has moved to TOsquare */
442
 
            s++;
443
 
          if ( (boardu = board[u]) == king ) {
444
 
              s += 20; INCscore -= 18;
445
 
              *local_flag |= check; /* move threatens opponents king */ 
446
 
          }
447
 
#ifdef TESUJIBONUS
448
 
          upiece = unpromoted[piece];
449
 
          rvupiece = relative_value[upiece];
450
 
          rvuboard = relative_value[unpromoted[boardu]];
451
 
          if ( upiece == pawn && Captured[side][pawn] > 1 )
452
 
            {                
453
 
              *local_flag |= tesuji; /* The joining pawn attack */
454
 
              s++;
455
 
            }     
456
 
          if ( rvupiece <= rvuboard ) 
457
 
            {                
458
 
              *local_flag |= tesuji; /* The striking pawn (piece) attack */
459
 
              if ( f > NO_SQUARES )
460
 
                s += 2;
461
 
              else
462
 
                s++;
463
 
              if ( upiece == pawn ) {
464
 
                s++;
465
 
              }
466
 
              if ( rvupiece == rvuboard && 
467
 
                   upiece == pawn || upiece == bishop || upiece == knight ) {
468
 
                s++; /* The opposing pawn (piece) */
469
 
                if ( upiece == pawn )
470
 
                  s++;
471
 
              }
472
 
            }
473
 
#endif
474
 
#ifdef SAVE_NEXTPOS
475
 
          u = next_direction(ptyp,&d,t);
476
 
#else 
477
 
          u = pdir[u];
478
 
#endif
479
 
        }
480
 
      };
481
 
  } while (u != t);
482
 
 
483
 
  INCscore += s;
484
 
 
485
 
  return(s);
486
 
}
487
 
 
488
 
 
489
 
#endif
490
 
 
491
 
 
492
 
 
493
 
/* inline */ void
494
 
LinkMove (short int ply, short int f,
495
 
          register short int t,
496
 
          unsigned short local_flag,
497
 
          short int xside,
498
 
          short int score_if_impossible)
499
 
 
500
 
/*
501
 
 * Add a move to the tree.  Assign a bonus to order the moves as follows:
502
 
 * 1. Principle variation 2. Capture of last moved piece 3. Other captures
503
 
 * (major pieces first) 4. Killer moves 5. Tesuji drops 6. Other Moves
504
 
 * 7. Other drops. 8. Non-promoting moves
505
 
 * If the flag.tsume is set, assign a high bonus for checks.
506
 
 */
507
 
 
508
 
{
509
 
  register short s = 0;
510
 
  register short side, piece, mv;
511
 
  short flag_tsume, try_link = true;
512
 
  short c1, c2, ds, is_drop = f > NO_SQUARES;
513
 
  unsigned long as = 0;
514
 
 
515
 
  flag_tsume = flag.tsume;
516
 
 
517
 
  c1 = side = xside ^ 1;
518
 
  c2 = xside;
519
 
                                                
520
 
  /*
521
 
   * Is it determined whether the move gives check ?
522
 
   */
523
 
 
524
 
  check_determined = ((local_flag & check) != 0);
525
 
 
526
 
  mv = (f << 8) | ((local_flag & promote) ? (t | 0x80) : t);
527
 
 
528
 
  if ( f > NO_SQUARES ) {
529
 
    piece = f - NO_SQUARES;
530
 
    if ( piece > NO_PIECES ) piece -= NO_PIECES;
531
 
  } else {
532
 
    piece = board[f];
533
 
  }
534
 
 
535
 
  if ( score_if_impossible < 0 ) {
536
 
    /* The move is flagged as illegal. */
537
 
    Link (side, piece, 
538
 
        f, t, local_flag, score_if_impossible);
539
 
    return;
540
 
  }
541
 
 
542
 
  INCscore = 0;
543
 
       
544
 
#ifdef HISTORY
545
 
#ifdef DEBUG
546
 
  if ( use_history ) {
547
 
    unsigned short hi;
548
 
    short ds;
549
 
    s += (ds = history[hi = hindex(side,mv)]);
550
 
  }
551
 
#else
552
 
  s += history[hindex(side,mv)];
553
 
#endif
554
 
#endif
555
 
         
556
 
  /* If we're running short of tree node, go into tsume mode. */
557
 
  
558
 
  if ( !(local_flag & capture) )
559
 
    if ( *TrP > TREE - 300 ) {
560
 
      /* too close to tree table limit */
561
 
      flag.tsume = true;
562
 
    }
563
 
 
564
 
  /* Guess strength of move and set flags. */                
565
 
 
566
 
  if ( piece != king && !in_opening_stage ) {
567
 
    if ( distance(t,EnemyKing) <= 1 ) {
568
 
      /* bonus for square near enemy king */
569
 
      s += 15; INCscore += 2;
570
 
      local_flag |= kingattack; 
571
 
    } else if ( distance(t,OwnKing) <= 1 ) {
572
 
      /* bonus for square near own king */
573
 
      s += 10; INCscore++;
574
 
      local_flag |= kingattack; 
575
 
    }                                   
576
 
  }
577
 
  
578
 
  if ( tas /* own attack array available */ ) {
579
 
    /* square t defended by own piece (don't count piece to move) ? */
580
 
    if ( is_drop ? (as = atak[side][t]) : (as = ((atak[side][t] & CNT_MASK) > 1)) )
581
 
      s += (ds = in_endgame_stage ? 100 : 10);
582
 
  }
583
 
  if ( taxs /* opponents attack array available */ ) {
584
 
    /* square t not threatened by opponent or
585
 
     * defended and only threatened by opponents king ? 
586
 
     */
587
 
    unsigned long axs;
588
 
    if ( !(axs = atak[xside][t]) ||
589
 
         (tas && as && (axs & control[king]) && (axs & CNT_MASK) == 1) )
590
 
      s += (ds = in_endgame_stage ? 200 : 
591
 
                        (is_drop ? (InPromotionZone(side,t) ? 40 + relative_value[piece]: 10) : 20));
592
 
  }     
593
 
 
594
 
  /* target square near area of action */
595
 
 
596
 
  if ( TOsquare >= 0 )
597
 
    s += (9-distance(TOsquare,t));
598
 
  if ( FROMsquare >= 0 )
599
 
    s += (9-distance(FROMsquare,t)) / 2;
600
 
 
601
 
  /* target square near own or enemy king */
602
 
  
603
 
  if ( !in_opening_stage && piece != king ) {
604
 
    if ( balance[c1] < 50 )
605
 
      s += (9-distance(EnemyKing,t)) * (50 - balance[c1]) / 20;
606
 
    else
607
 
      s += (9-distance(OwnKing,t)) * (balance[c1] - 50) / 20;
608
 
  }
609
 
  
610
 
  if ( f > NO_SQUARES )
611
 
    {
612
 
      /* bonus for drops, in order to place drops before questionable moves */
613
 
      s += in_endgame_stage ? 25 : 10;
614
 
      if (t == FROMsquare) {
615
 
        /* drop to the square the opponent has just left */
616
 
        s += 5;
617
 
      };
618
 
      if ( piece == gold )
619
 
        s -= 32 / Captured[side][gold];
620
 
      else if ( piece == silver )
621
 
        s -= 16 / Captured[side][silver];
622
 
#if defined DROPBONUS
623
 
      s += field_bonus(ply,side,piece,f,t,&local_flag);
624
 
      if ( s == 10 && piece != pawn )
625
 
      local_flag |= questionable;
626
 
#endif
627
 
    }
628
 
  else 
629
 
    {
630
 
      /* bonus for moves (non-drops) */
631
 
      int consider_last = false;
632
 
      if ( in_endgame_stage && Captured[side][gold] )
633
 
        s += 10;
634
 
      s += 20; 
635
 
      if (t == FROMsquare) {
636
 
        /* move to the square the opponent has just left */
637
 
        s += in_endgame_stage ? 10 : 1;
638
 
      }
639
 
      if (color[t] != neutral)
640
 
        {
641
 
          /* Captures */  
642
 
          if ( in_endgame_stage ) {
643
 
            s += relative_value[board[t]] - relative_value[piece];
644
 
          } else {
645
 
            s += (*value)[stage][board[t]] - relative_value[piece];
646
 
          }
647
 
          if (t == TOsquare)
648
 
            /* Capture of last moved piece */ 
649
 
            s += in_endgame_stage ? 5 : 50;
650
 
        }  
651
 
      if ( local_flag & promote )
652
 
        {
653
 
          /* bonus for promotions */
654
 
          s++; 
655
 
          INCscore += value[stage][promoted[piece]] - value[stage][piece];
656
 
        }
657
 
      else
658
 
        {
659
 
          /* bonus for non-promotions */
660
 
          if ( PromotionPossible(side,f,t,piece) )
661
 
#ifdef TESUJIBONUS
662
 
         /* Look at non-promoting silver or knight */
663
 
            if ( piece == silver || piece == knight ) 
664
 
              {
665
 
                local_flag |= tesuji; /* Non-promotion */
666
 
                s++; 
667
 
              }
668
 
            else           
669
 
#endif        
670
 
              {
671
 
                consider_last = true;
672
 
                if ( piece == pawn || piece == bishop || piece == rook ) {
673
 
                  local_flag |= stupid;
674
 
                  INCscore -= 20;
675
 
                } else {
676
 
                  local_flag |= questionable;
677
 
                  INCscore -= 10;
678
 
                }
679
 
              }
680
 
        }
681
 
      if ( consider_last )
682
 
        {
683
 
          if ( local_flag & stupid )
684
 
            s = 0;
685
 
          else 
686
 
            s = s % 20;
687
 
        }
688
 
      else 
689
 
        {
690
 
          short blockable;
691
 
#if defined FIELDBONUS
692
 
          s += field_bonus(ply,side,piece,f,t,&local_flag);
693
 
#endif
694
 
        }  
695
 
    }
696
 
 
697
 
#if defined CHECKBONUS
698
 
  /* determine check flag */
699
 
  if ( !(local_flag & check) && !check_determined ) 
700
 
    { 
701
 
      gives_check_flag(&local_flag, side, f, t);
702
 
      if ( local_flag & check )
703
 
          s += 20;
704
 
    }
705
 
#endif
706
 
 
707
 
  /* check conditions for deep search cut (flag.tsume = true) */
708
 
 
709
 
#ifdef DEEPSEARCHCUT
710
 
  if ( !flag.tsume && deepsearchcut ) 
711
 
    { 
712
 
      if ( ply > BEYOND_STUPID && (local_flag & stupid) ) {
713
 
          try_link = flag.force || (ply == 1 && side != computer);
714
 
#ifdef HARDTIMELIMIT
715
 
      } else if ( ply > BEYOND_TIMEOUT && flag.timeout ) {
716
 
          flag.tsume = true;
717
 
#endif
718
 
      } else if ( ply > BEYOND_KINGATTACK && !(local_flag & kingattack) ) {
719
 
          flag.tsume = true;
720
 
      } else if ( ply > BEYOND_QUESTIONABLE && (local_flag & questionable) ) {
721
 
          flag.tsume = true; 
722
 
#ifdef TESUJIBONUS
723
 
      } else if ( ply > BEYOND_TESUJI && !(local_flag & tesuji) ) {
724
 
          flag.tsume = true;
725
 
#endif
726
 
      } else if ( ply > BEYOND_DROP && (f > NO_SQUARES) ) {
727
 
          flag.tsume = true;
728
 
      } 
729
 
    }
730
 
#endif
731
 
 
732
 
  if ( try_link || GenerateAllMoves )
733
 
    Link (side, piece, 
734
 
        f, t, local_flag, s - ((SCORE_LIMIT+1000)*2));
735
 
 
736
 
  flag.tsume = flag_tsume;
737
 
}                                                 
738
 
 
739
 
 
740
 
 
741
 
short
742
 
DropPossible (short int piece, short int side, short int sq)
743
 
 
744
 
745
 
  short r = row(sq), possible = true;
746
 
 
747
 
  if ( board[sq] != no_piece )
748
 
        possible = false; 
749
 
  else if ( piece == pawn )
750
 
        { 
751
 
          if ( side == black && r == 8 ) {
752
 
            possible = (generate_move_flags ? ILLEGAL_TRAPPED : false);
753
 
          } else if ( side == white && r == 0 ) {
754
 
            possible = (generate_move_flags ? ILLEGAL_TRAPPED : false);
755
 
          } else if ( PawnCnt[side][column(sq)] ) {
756
 
            possible = (generate_move_flags ? ILLEGAL_DOUBLED : false);
757
 
          }
758
 
          /* pawn drops are invalid, if they mate the opponent */
759
 
          if ( possible )
760
 
            {   short f, tempb, tempc;
761
 
                f = pawn + NO_SQUARES;
762
 
                if ( side == white ) f += NO_PIECES;
763
 
                GenMakeMove (side, f, sq, &tempb, &tempc, false); 
764
 
                if ( IsCheckmate(side^1,-1,-1) )
765
 
                  possible = (generate_move_flags ? ILLEGAL_MATE : false);
766
 
                GenUnmakeMove (side, f, sq, tempb, tempc, false);
767
 
            }
768
 
        }
769
 
  else if ( piece == lance )
770
 
        {
771
 
          if ( side == black && r == 8 )
772
 
            possible = (generate_move_flags ? ILLEGAL_TRAPPED : false);
773
 
          else if ( side == white && r == 0 )
774
 
            possible = (generate_move_flags ? ILLEGAL_TRAPPED : false);
775
 
        }
776
 
  else if ( piece == knight )
777
 
        {
778
 
          if ( side == black && r >= 7 )
779
 
            possible = (generate_move_flags ? ILLEGAL_TRAPPED : false);
780
 
          else if ( side == white && r <= 1 )
781
 
            possible = (generate_move_flags ? ILLEGAL_TRAPPED : false);
782
 
        }           
783
 
 
784
 
  return possible;
785
 
 
786
 
}
787
 
 
788
 
 
789
 
static
790
 
void
791
 
SortMoves(short int ply)
792
 
793
 
  short int p;
794
 
  for (p = TrPnt[ply]; p < TrPnt[ply+1]; p++)
795
 
    pick(p,TrPnt[ply+1]-1);
796
 
}
797
 
 
798
 
 
799
 
#ifdef DONTUSE_HEURISTIC
800
 
 
801
 
static void
802
 
DontUseMoves(short int ply, short int n)
803
 
{
804
 
  register struct leaf far *p;
805
 
  short int i,k;
806
 
#ifdef DEBUG
807
 
  short j = 0;
808
 
#endif 
809
 
  /* k = number of check moves + number of captures */
810
 
  for (i = TrPnt[ply], k=0; i < TrPnt[ply+1]; i++) {
811
 
     p = &Tree[i];
812
 
     if ( (p->flags & check) || (p->flags & capture) ) 
813
 
        if (++k >= n) return;
814
 
  }
815
 
  /* use n moves */
816
 
  for (i = TrPnt[ply]; i < TrPnt[ply+1]; i++) {
817
 
     p = &Tree[i];
818
 
     if ( !((p->flags & check) || (p->flags & capture)) ) {
819
 
       if ( k < n )
820
 
         k++;
821
 
       else {
822
 
         p->score = DONTUSE;
823
 
#ifdef DEBUG
824
 
         j++;
825
 
#endif
826
 
       }
827
 
     } 
828
 
  }
829
 
#ifdef notdef
830
 
  if ( j )
831
 
    printf("skipping %d moves at ply %d with allowed %d moves\n",j,ply,n);
832
 
#endif
833
 
}            
834
 
 
835
 
 
836
 
#endif
837
 
 
838
 
 
839
 
inline
840
 
void
841
 
GenMoves (register short int ply, register short int sq, short int side, 
842
 
          short int xside)
843
 
 
844
 
/*
845
 
 * Generate moves for a piece. The moves are taken from the precalulated
846
 
 * array nextpos/nextdir. If the board is free, next move is choosen from
847
 
 * nextpos else from nextdir.
848
 
 */
849
 
 
850
 
{
851
 
  register short u, piece, col;
852
 
  short ptyp, possible;
853
 
#ifdef SAVE_NEXTPOS
854
 
  short d;
855
 
#else
856
 
  register unsigned char *ppos, *pdir;
857
 
#endif
858
 
 
859
 
  piece = board[sq];
860
 
  ptyp = ptype[side][piece];
861
 
 
862
 
#ifdef SAVE_NEXTPOS
863
 
  u = first_direction(ptyp,&d,sq);
864
 
#else
865
 
  ppos = (*nextpos[ptyp])[sq];
866
 
  pdir = (*nextdir[ptyp])[sq];
867
 
  u = ppos[sq];
868
 
#endif
869
 
 
870
 
  do
871
 
    { unsigned short int local_flag;
872
 
      short  c;
873
 
      if ( (c = color[u]) == xside )
874
 
        local_flag = capture;
875
 
      else
876
 
        local_flag = 0;
877
 
      if ( c != side && board[u] != king ) {
878
 
        if ( PromotionPossible(color[sq],sq,u,piece) ) {
879
 
          LinkMove (ply, sq, u, local_flag | promote, xside, true);
880
 
          if ( possible = NonPromotionPossible(color[sq],sq,u,piece) )
881
 
            LinkMove (ply, sq, u, local_flag, xside, possible);
882
 
        } else {
883
 
          LinkMove (ply, sq, u, local_flag, xside, true);
884
 
        }
885
 
      }
886
 
      if (c == neutral)
887
 
#ifdef SAVE_NEXTPOS
888
 
        u = next_position(ptyp,&d,sq,u);
889
 
      else
890
 
        u = next_direction(ptyp,&d,sq);
891
 
#else
892
 
        u = ppos[u];
893
 
      else
894
 
        u = pdir[u];
895
 
#endif
896
 
  } while (u != sq);
897
 
}             
898
 
 
899
 
 
900
 
 
901
 
static void
902
 
DropToSquare (short side, short xside, short ply, short u)
903
 
 
904
 
/*
905
 
 * Drop each piece in hand of "side" to square "u" (if allowed).
906
 
 */
907
 
 
908
 
{
909
 
  short i, possible; 
910
 
 
911
 
  for (i = pawn; i < king; i++)
912
 
    if ( Captured[side][i] )
913
 
      if ( possible = DropPossible(i,side,u) )
914
 
        { short f;
915
 
          f = NO_SQUARES + i;
916
 
          if ( side == white ) f += NO_PIECES;
917
 
          LinkMove (ply, f, u, (dropmask | i), xside, possible);
918
 
        }
919
 
}
920
 
 
921
 
 
922
 
static void
923
 
LinkPreventCheckDrops (short side, short xside, short ply)
924
 
 
925
 
/*
926
 
 * Add drops of side that prevent own king from being in check
927
 
 * from xside's sweeping pieces. 
928
 
 */
929
 
 
930
 
{
931
 
#ifdef SAVE_NEXTPOS
932
 
  short d, dd;
933
 
#else
934
 
  register unsigned char *ppos, *pdir;
935
 
#endif
936
 
  register short piece, u, xu, square, ptyp;      
937
 
  short i, n, drop_square[9];
938
 
 
939
 
  if ( board[square = PieceList[side][0]] != king )
940
 
    return;
941
 
  
942
 
  for (piece = lance; piece <= rook; piece++ ) 
943
 
  if ( piece == lance || piece == bishop || piece == rook ) {
944
 
    /* check for threat of xside piece */                   
945
 
    ptyp = ptype[side][piece];
946
 
    n = 0;
947
 
#ifdef SAVE_NEXTPOS
948
 
    u = first_direction(ptyp,&d,square);
949
 
#else
950
 
    ppos = (*nextpos[ptyp])[square];
951
 
    pdir = (*nextdir[ptyp])[square];
952
 
    u = ppos[square];
953
 
#endif
954
 
 
955
 
    do
956
 
      {
957
 
        if (color[u] == neutral) 
958
 
          {                
959
 
#ifdef SAVE_NEXTPOS
960
 
            dd = d;
961
 
            xu = next_position(ptyp,&d,square,u);
962
 
            if ( xu == next_direction(ptyp,&dd,square) )
963
 
                n = 0;  /* oops new direction */
964
 
            else {
965
 
#ifdef DEBUG
966
 
                assert(n<9);
967
 
#endif      
968
 
                drop_square[n++] = u;
969
 
            }
970
 
#else
971
 
            if ((xu = ppos[u]) == pdir[u])
972
 
                n = 0;  /* oops new direction */
973
 
            else {
974
 
#ifdef DEBUG
975
 
                assert(n<9);
976
 
#endif      
977
 
                drop_square[n++] = u;
978
 
            }
979
 
#endif
980
 
            u = xu;
981
 
          }
982
 
        else
983
 
          {
984
 
            if (color[u] == xside && (unpromoted[board[u]] == piece))
985
 
              {
986
 
                /* king is threatened by opponents piece */
987
 
                while ( n > 0 ) {
988
 
                  DropToSquare(side,xside,ply,drop_square[--n]);
989
 
                }
990
 
              }  
991
 
            else
992
 
              n = 0;
993
 
#ifdef SAVE_NEXTPOS
994
 
            u = next_direction(ptyp,&d,square);
995
 
#else
996
 
            u = pdir[u];
997
 
#endif
998
 
          }
999
 
    } while (u != square);
1000
 
 
1001
 
  }
1002
 
 
1003
 
}
1004
 
 
1005
 
 
1006
 
static void
1007
 
LinkCheckDrops (short side, short xside, short ply)
1008
 
 
1009
 
/*
1010
 
 * Add drops that check enemy king.
1011
 
 */
1012
 
 
1013
 
{       
1014
 
#ifdef SAVE_NEXTPOS
1015
 
  short d;
1016
 
#else
1017
 
  register unsigned char *ppos, *pdir;
1018
 
#endif
1019
 
  register short u, ptyp;
1020
 
  short square, piece;
1021
 
 
1022
 
  if ( board[square = PieceList[xside][0]] != king )
1023
 
    return;
1024
 
  
1025
 
  for (piece = pawn; piece < king; piece++)
1026
 
    if ( Captured[side][piece] ) {
1027
 
      /* 
1028
 
       * "side" has "piece" in hand. Try to make a piece move from
1029
 
       * opponents king square and drop this piece to each
1030
 
       * reachable empty square. This definitely gives check!
1031
 
       * For a pawn drop it must not double pawns and
1032
 
       * it must not be checkmate!
1033
 
       */
1034
 
      ptyp = ptype[xside][piece];
1035
 
#ifdef SAVE_NEXTPOS
1036
 
      u = first_direction(ptyp,&d,square);
1037
 
#else
1038
 
      ppos = (*nextpos[ptyp])[square];
1039
 
      pdir = (*nextdir[ptyp])[square];
1040
 
      u = ppos[square];
1041
 
#endif
1042
 
      do
1043
 
        {
1044
 
          if (color[u] == neutral)
1045
 
            {                    
1046
 
              if ( piece != pawn || DropPossible(pawn,side,u) ) {
1047
 
                short f;
1048
 
                f = NO_SQUARES + piece;
1049
 
                if ( side == white ) f += NO_PIECES;
1050
 
                LinkMove (ply, f, u, (dropmask | piece | check), xside, true);
1051
 
              }
1052
 
#ifdef SAVE_NEXTPOS
1053
 
              u = next_position(ptyp,&d,square,u);
1054
 
#else
1055
 
              u = ppos[u];
1056
 
#endif
1057
 
            }
1058
 
          else
1059
 
            {
1060
 
#ifdef SAVE_NEXTPOS
1061
 
              u = next_direction(ptyp,&d,square);
1062
 
#else
1063
 
              u = pdir[u];
1064
 
#endif
1065
 
            }
1066
 
      } while (u != square);
1067
 
    }
1068
 
 
1069
 
}
1070
 
 
1071
 
 
1072
 
void
1073
 
MoveList (short int side, register short int ply, 
1074
 
          short int in_check, short int blockable)
1075
 
 
1076
 
/*
1077
 
 * Fill the array Tree[] with all available moves for side to play. Array
1078
 
 * TrPnt[ply] contains the index into Tree[] of the first move at a ply.
1079
 
 * in_check = 0 side is not in check
1080
 
 * in_check > 1 side is in check
1081
 
 * in_check < 0 don't know
1082
 
 * in_check -2 indicates move generation for book moves
1083
 
 */
1084
 
 
1085
 
{
1086
 
  register short i, xside, f, u;
1087
 
  struct leaf far *firstnode;
1088
 
  short flag_tsume, num;
1089
 
 
1090
 
#ifdef HISTORY
1091
 
  unsigned short hiHt=0, hi0=0, hi1=0, hi2=0, hi3=0, hi4=0;
1092
 
#endif
1093
 
 
1094
 
  flag_tsume = flag.tsume;
1095
 
 
1096
 
  xside = side ^ 1;
1097
 
    
1098
 
  sqking  = PieceList[side][0];
1099
 
  sqxking = PieceList[xside][0];
1100
 
 
1101
 
  if ( in_check >= 0 )
1102
 
    InCheck = in_check;
1103
 
  else
1104
 
    InCheck = (board[sqking] == king) ? SqAtakd(sqking,xside, &blockable) : false;
1105
 
 
1106
 
  GenerateAllMoves = (in_check == -2) || generate_move_flags;
1107
 
 
1108
 
#ifdef DEBUG_EVAL
1109
 
  if ( debug_eval )
1110
 
    fprintf ( debug_eval_file, "%s king is %sin check\n",
1111
 
        ColorStr[side],(InCheck ? "" : "not ") );
1112
 
#endif
1113
 
 
1114
 
  if ( InCheck /* && (ply > 1 || side == computer) */ )
1115
 
    {
1116
 
        /* Own king in check */
1117
 
        flag.tsume = true;
1118
 
    }   
1119
 
 
1120
 
  TrP = &TrPnt[ply + 1];
1121
 
  *TrP = TrPnt[ply];
1122
 
 
1123
 
  firstnode = node = &Tree[*TrP];
1124
 
 
1125
 
  if (!PV)
1126
 
    Swag0 = killr0[ply];
1127
 
   else Swag0 = PV;
1128
 
  Swag1 = killr1[ply];
1129
 
  Swag2 = killr2[ply];
1130
 
  Swag3 = killr3[ply];
1131
 
  if (ply > 2)
1132
 
    Swag4 = killr1[ply - 2]; else Swag4 = 0;
1133
 
 
1134
 
#ifdef DEBUG_EVAL
1135
 
  if ( debug_eval && (ply == 1 || debug_moves) )
1136
 
  {
1137
 
    char bufHt[8], buf0[8], buf1[8], buf2[8], buf3[8], buf4[8];
1138
 
    movealgbr(SwagHt,bufHt);
1139
 
    movealgbr(Swag0,buf0);
1140
 
    movealgbr(Swag1,buf1);
1141
 
    movealgbr(Swag2,buf2);
1142
 
    movealgbr(Swag3,buf3);
1143
 
    movealgbr(Swag4,buf4);
1144
 
    fprintf(debug_eval_file, "SwagHt=%x %s 0=%x %s 1=%x %s 2=%x %s 3=%x %s 4=%x %s\n", 
1145
 
      SwagHt, bufHt, Swag0, buf0, Swag1, buf1, Swag2, buf2, Swag3, buf3, Swag4, buf4); 
1146
 
  }
1147
 
#endif
1148
 
 
1149
 
#ifdef HISTORY
1150
 
  if ( use_history ) {
1151
 
    history[hiHt = hindex(side,SwagHt)] += 5000;
1152
 
    history[hi0  = hindex(side,Swag0)] += 2000;
1153
 
    history[hi1  = hindex(side,Swag1)] += 60;
1154
 
    history[hi2  = hindex(side,Swag2)] += 50;
1155
 
    history[hi3  = hindex(side,Swag3)] += 40;
1156
 
    history[hi4  = hindex(side,Swag4)] += 30;
1157
 
  }
1158
 
#endif
1159
 
 
1160
 
  if ( tas = MatchSignature(threats_signature[side]) ) {
1161
 
#if defined notdef && defined DEBUG_EVAL && defined NONDSP 
1162
 
    printf("threats available at ply %d for side=%s\n",ply,ColorStr[side]);    
1163
 
#endif
1164
 
  }
1165
 
  if ( taxs = MatchSignature(threats_signature[xside]) ) {
1166
 
#if defined notdef && defined DEBUG_EVAL && defined NONDSP 
1167
 
    printf("threats available at ply %d for xside=%s\n",ply,ColorStr[xside]);
1168
 
#endif
1169
 
  }
1170
 
  if ( ssa = MatchSignature(squares_signature) ) {
1171
 
#if defined notdef && defined DEBUG_EVAL && defined NONDSP 
1172
 
    printf("square statistics available at ply %d\n",ply);
1173
 
#endif
1174
 
  }
1175
 
  
1176
 
  for (i = PieceCnt[side]; i >= 0; i--)
1177
 
    GenMoves (ply, PieceList[side][i], side, xside);
1178
 
 
1179
 
  if ( !InCheck || blockable ) 
1180
 
    if ( flag.tsume )
1181
 
      { /* special drop routine for tsume problems */
1182
 
        if ( InCheck ) {
1183
 
          LinkPreventCheckDrops (side, xside, ply);
1184
 
        } else {
1185
 
          LinkCheckDrops (side, xside, ply);
1186
 
        }
1187
 
 
1188
 
      }
1189
 
    else
1190
 
      {
1191
 
        for ( u = 0; u < NO_SQUARES; u++ )
1192
 
          DropToSquare(side,xside,ply,u);
1193
 
      } 
1194
 
 
1195
 
#ifdef HISTORY
1196
 
  if ( use_history ) {
1197
 
    history[hiHt] -= 5000;
1198
 
    history[hi0] -= 2000;
1199
 
    history[hi1] -= 60;
1200
 
    history[hi2] -= 50;
1201
 
    history[hi3] -= 40;
1202
 
    history[hi4] -= 30;
1203
 
  }
1204
 
#endif
1205
 
 
1206
 
  SwagHt = 0;                   /* SwagHt is only used once */
1207
 
 
1208
 
  if ( flag.tsume && node == firstnode )
1209
 
    (*TrP)++;
1210
 
 
1211
 
  GenCnt += (num = (TrPnt[ply+1] - TrPnt[ply]));
1212
 
 
1213
 
#ifdef DEBUG_EVAL
1214
 
  SortMoves(ply);
1215
 
#endif
1216
 
              
1217
 
#ifdef DONTUSE_HEURISTIC
1218
 
   /* remove some nodes in case of wide spread in depth */
1219
 
   if ( !flag.tsume && (i = MaxNum[ply]) > 0 && num > i) {
1220
 
     SortMoves(ply);
1221
 
     DontUseMoves(ply,i);
1222
 
   }
1223
 
#endif       
1224
 
 
1225
 
#ifdef notdef
1226
 
  printf("%d moves at ply %d\n",num,ply);
1227
 
#endif  
1228
 
 
1229
 
  flag.tsume = flag_tsume;
1230
 
 
1231
 
}
1232
 
 
1233
 
void
1234
 
CaptureList (register short int side, short int ply, 
1235
 
             short int in_check, short int blockable)
1236
 
 
1237
 
/*
1238
 
 * Fill the array Tree[] with all available captures for side to play.
1239
 
 * If there is a non-promote option, discard the non-promoting move.
1240
 
 * Array TrPnt[ply] contains the index into Tree[] of the first move
1241
 
 * at a ply.      
1242
 
 * If flag.tsume is set, only add captures (but also the non-promoting)
1243
 
 * that threaten the opponents king.
1244
 
 * in_check = 0 side is not in check
1245
 
 * in_check > 1 side is in check
1246
 
 * in_check < 0 don't know
1247
 
 */
1248
 
 
1249
 
{
1250
 
  register short u, sq, xside;
1251
 
#ifdef SAVE_NEXTPOS
1252
 
  short d;
1253
 
#else
1254
 
  register unsigned char *ppos, *pdir;
1255
 
#endif
1256
 
  short i, piece, flag_tsume;
1257
 
  small_short *PL;
1258
 
 
1259
 
  xside = side ^ 1;
1260
 
 
1261
 
  TrP = &TrPnt[ply + 1];
1262
 
  *TrP = TrPnt[ply];
1263
 
  node = &Tree[*TrP];
1264
 
 
1265
 
  flag_tsume = flag.tsume;
1266
 
 
1267
 
  sqking = PieceList[side][0];
1268
 
  sqxking = PieceList[xside][0];
1269
 
 
1270
 
  if ( in_check >= 0 )
1271
 
    InCheck = in_check;
1272
 
  else
1273
 
    InCheck = (board[sqking] == king) ? SqAtakd(sqking,xside,&blockable) : false;
1274
 
 
1275
 
  GenerateAllMoves = (in_check == -2);
1276
 
 
1277
 
#ifdef DEBUG_EVAL
1278
 
  if (debug_eval )
1279
 
    fprintf ( debug_eval_file, "%s king is %sin check\n",
1280
 
        ColorStr[side],(InCheck ? "" : "not ") );
1281
 
#endif
1282
 
 
1283
 
  if ( InCheck && (ply > 1 || side == computer) )
1284
 
    {
1285
 
      /* Own king is in check */
1286
 
      flag.tsume = true;
1287
 
    }
1288
 
 
1289
 
  check_determined = false;
1290
 
 
1291
 
  PL = PieceList[side];
1292
 
 
1293
 
  for (i = 0; i <= PieceCnt[side]; i++)
1294
 
    { short ptyp;
1295
 
      sq = PL[i];
1296
 
      piece = board[sq];
1297
 
      ptyp = ptype[side][piece];
1298
 
#ifdef SAVE_NEXTPOS
1299
 
      u = first_direction(ptyp,&d,sq);
1300
 
#else
1301
 
      ppos = (*nextpos[ptyp])[sq];
1302
 
      pdir = (*nextdir[ptyp])[sq];
1303
 
      u = ppos[sq];
1304
 
#endif
1305
 
      do
1306
 
        { 
1307
 
          if (color[u] == neutral)
1308
 
            {
1309
 
#ifdef SAVE_NEXTPOS
1310
 
              u = next_position(ptyp,&d,sq,u);
1311
 
#else 
1312
 
              u = ppos[u];
1313
 
#endif
1314
 
            }
1315
 
          else
1316
 
            { 
1317
 
              if ( color[u] == xside && board[u] != king )
1318
 
                { 
1319
 
                  short PP;
1320
 
                  if ( PP = PromotionPossible(color[sq],sq,u,piece) ) {
1321
 
                    Link (side, piece, 
1322
 
                          sq, u, capture | promote,
1323
 
                          (*value)[stage][board[u]]
1324
 
#if !defined SAVE_SVALUE 
1325
 
                            + svalue[board[u]]
1326
 
#endif                    
1327
 
                            - relative_value[piece]);
1328
 
                  } 
1329
 
                  if ( !PP || flag.tsume ) {
1330
 
                    Link (side, piece, 
1331
 
                          sq, u, capture,
1332
 
                          (*value)[stage][board[u]]
1333
 
#if !defined SAVE_SVALUE 
1334
 
                            + svalue[board[u]]
1335
 
#endif                         
1336
 
                            - relative_value[piece]);
1337
 
                  }  
1338
 
                }
1339
 
#ifdef SAVE_NEXTPOS
1340
 
              u = next_direction(ptyp,&d,sq);
1341
 
#else
1342
 
              u = pdir[u];
1343
 
#endif
1344
 
            }
1345
 
        } while (u != sq);
1346
 
    }
1347
 
 
1348
 
  flag.tsume = flag_tsume;
1349
 
 
1350
 
  SwagHt = 0;                   /* SwagHt is only used once */
1351
 
 
1352
 
#ifdef DEBUG_EVAL
1353
 
  SortMoves(ply);
1354
 
#endif
1355
 
 
1356
 
1357
 
 
1358
 
 
1359
 
 
1360
 
short
1361
 
IsCheckmate (short int side, short int in_check, short int blockable)
1362
 
 
1363
 
/*
1364
 
 * If the king is in check, try to find a move that prevents check.
1365
 
 * If such a move is found, return false, otherwise return true.
1366
 
 * in_check = 0: side is not in check
1367
 
 * in_check > 1: side is in check
1368
 
 * in_check < 0: don't know      
1369
 
 * blockable > 0 && check: check can possibly prevented by a drop
1370
 
 * blockable = 0 && check: check can definitely not prevented by a drop
1371
 
 * blockable < 0 && check: nothing known about type of check
1372
 
 */
1373
 
 
1374
 
{
1375
 
  register short u, sq, xside;
1376
 
#ifdef SAVE_NEXTPOS
1377
 
  short d;
1378
 
#else
1379
 
  register unsigned char *ppos, *pdir;
1380
 
#endif
1381
 
  short i, piece, flag_tsume;
1382
 
  small_short *PL;
1383
 
  struct leaf far *firstnode;
1384
 
  short tempb, tempc, ksq, threat, dummy, sqking;
1385
 
  short InCheck;
1386
 
 
1387
 
  xside = side ^ 1;
1388
 
 
1389
 
  sqking = PieceList[side][0];
1390
 
         
1391
 
  /* 
1392
 
   * Checkmate is possible only if king is in check.
1393
 
   */                  
1394
 
 
1395
 
  if ( in_check >= 0 )
1396
 
      InCheck = in_check;
1397
 
  else if ( board[sqking] == king )
1398
 
      InCheck = SqAtakd(sqking,xside,&blockable);
1399
 
  else
1400
 
      InCheck = false;
1401
 
 
1402
 
  if ( !InCheck )
1403
 
    return (false);
1404
 
 
1405
 
  /* 
1406
 
   * Try to find a move, that prevents check.
1407
 
   */                  
1408
 
 
1409
 
  PL = PieceList[side];
1410
 
 
1411
 
  for (i = 0; i <= PieceCnt[side]; i++)
1412
 
    { short ptyp;
1413
 
      sq = PL[i];
1414
 
      piece = board[sq];
1415
 
      ptyp = ptype[side][piece];
1416
 
#ifdef SAVE_NEXTPOS
1417
 
      u = first_direction(ptyp,&d,sq);
1418
 
#else
1419
 
      ppos = (*nextpos[ptyp])[sq];
1420
 
      pdir = (*nextdir[ptyp])[sq];
1421
 
      u = ppos[sq];
1422
 
#endif
1423
 
      do
1424
 
        { 
1425
 
          if (color[u] == neutral || color[u] == xside)
1426
 
            {          
1427
 
              GenMakeMove (side, sq, u, &tempb, &tempc, false);
1428
 
              ksq = (sq == sqking) ? u : sqking;
1429
 
              threat = SqAtakd(ksq,xside,&dummy);
1430
 
              GenUnmakeMove (side, sq, u, tempb, tempc, false);
1431
 
              if ( !threat )
1432
 
                return (false);
1433
 
            }
1434
 
#ifdef SAVE_NEXTPOS
1435
 
            u = (color[u] == neutral) ? next_position(ptyp,&d,sq,u) 
1436
 
                                      : next_direction(ptyp,&d,sq); 
1437
 
#else
1438
 
            u = (color[u] == neutral) ? ppos[u] : pdir[u]; 
1439
 
#endif
1440
 
        } while (u != sq);
1441
 
    }
1442
 
    
1443
 
  /*
1444
 
   * Couldn't find a move that prevents check.
1445
 
   * Try to find a drop, that prevents check.
1446
 
   */
1447
 
 
1448
 
  if ( blockable != 0 )
1449
 
    {    
1450
 
      for (piece = king-1; piece >= pawn; piece--)
1451
 
        if ( Captured[side][piece] )
1452
 
          {
1453
 
            for (u = 0; u < NO_SQUARES; u++)
1454
 
              if ( DropPossible(piece,side,u) )
1455
 
                { short f;
1456
 
                  f = NO_SQUARES + piece;
1457
 
                  if ( side == white ) f += NO_PIECES;
1458
 
                  GenMakeMove (side, f, u, &tempb, &tempc, false); 
1459
 
                  threat = SqAtakd(sqking,xside,&dummy);
1460
 
                  GenUnmakeMove (side, f, u, tempb, tempc, false);
1461
 
                  if ( !threat )
1462
 
                    return (false);
1463
 
                } 
1464
 
            /*
1465
 
             * If the piece could be dropped at any square, it is
1466
 
             * impossible for any other piece drop to prevent check.
1467
 
             * Drops are restricted for pawns, lances, and knights.
1468
 
             */
1469
 
            if ( piece > knight )
1470
 
                break;
1471
 
          }
1472
 
     }                  
1473
 
 
1474
 
   return (true);
1475
 
 
1476
 
1477
 
 
1478