1 /*
2     Sjeng - a chess variants playing program
3     Copyright (C) 2000 Gian-Carlo Pascutto
4 
5     This program is free software; you can redistribute it and/or modify
6     it under the terms of the GNU General Public License as published by
7     the Free Software Foundation; either version 2 of the License, or
8     (at your option) any later version.
9 
10     This program is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13     GNU General Public License for more details.
14 
15     You should have received a copy of the GNU General Public License
16     along with this program; if not, write to the Free Software
17     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18 
19     File: moves.c
20     Purpose: functions used to generate & make moves
21 
22 */
23 
24 #include "sjeng.h"
25 #include "extvars.h"
26 #include "protos.h"
27 
28 unsigned long total_moves;
29 unsigned long total_movegens;
30 
31 int numb_moves;
32 static move_s *genfor;
33 
34 int fcaptures;
35 int gfrom;
36 
37 int kingcap; /* break if we capture the king */
38 
check_legal(move_s moves[],int m,int incheck)39 bool check_legal (move_s moves[], int m, int incheck) {
40 
41   /* determines if a move made was legal.  Checks to see if the player who
42      just moved castled through check, or is in check.  If the move made
43      was illegal, returns FALSE, otherwise, returns TRUE. */
44 
45   int castled = moves[m].castled;
46   int from = moves[m].from;
47   int target = moves[m].target;
48   int l;
49 
50   if (Variant == Suicide) return TRUE;
51 
52   /* check for castling moves: */
53   if (castled)
54   {
55     /* white kingside castling: */
56     if (castled == wck) {
57       if (is_attacked (30, 0)) return FALSE;
58       if (is_attacked (31, 0)) return FALSE;
59       if (is_attacked (32, 0)) return FALSE;
60       return TRUE;
61     }
62     /* white queenside castling: */
63     if (castled == wcq) {
64       if (is_attacked (30, 0)) return FALSE;
65       if (is_attacked (29, 0)) return FALSE;
66       if (is_attacked (28, 0)) return FALSE;
67       return TRUE;
68     }
69     /* black kingside castling: */
70     if (castled == bck) {
71       if (is_attacked (114, 1)) return FALSE;
72       if (is_attacked (115, 1)) return FALSE;
73       if (is_attacked (116, 1)) return FALSE;
74       return TRUE;
75     }
76     /* black queenside castling: */
77     if (castled == bcq) {
78       if (is_attacked (114, 1)) return FALSE;
79       if (is_attacked (113, 1)) return FALSE;
80       if (is_attacked (112, 1)) return FALSE;
81       return TRUE;
82     }
83   }
84 
85   /* otherwise, just check on the kings: */
86   /* black king: */
87 
88   /* the code in here checks whether a move could
89    * have put the king in check, if he was not in
90    * check before, if not, an early exit is taken */
91 
92   else if (white_to_move&1)
93     {
94       if (!incheck)
95 	{
96 	  if (moves[m].from == 0) return TRUE;
97 
98 	  switch (moves[m].promoted ? bpawn : board[target])
99 	    {
100 	    case bpawn:
101 	      /* pawn moves, it can discover a rank or diagonal check
102 	       * a capture can also discover a file check */
103 	      if (moves[m].captured != npiece)
104 		{
105 		  if (file(from) != file(bking_loc)
106 		      && rank(from) != rank(bking_loc)
107 		      && diagl(from) != diagl(bking_loc)
108 		      && diagr(from) != diagr(bking_loc))
109 		    return TRUE;
110 		}
111 	      else
112 		{
113 		  if (rank(from) != rank(bking_loc)
114 		      && diagl(from) != diagl(bking_loc)
115 		      && diagr(from) != diagr(bking_loc))
116 		    return TRUE;
117 		}
118 	      break;
119 	    case bknight:
120 	      /* discovers all */
121 	      if (file(from) != file(bking_loc)
122 		  && rank(from) != rank(bking_loc)
123 		  && diagl(from) != diagl(bking_loc)
124 		  && diagr(from) != diagr(bking_loc))
125 		return TRUE;
126 	      break;
127 	    case bbishop:
128 	      /* always discovers file and rank
129 	       * always discovers one diagonal */
130 	      if (file(from) != file(bking_loc)
131 		  && rank(from) != rank(bking_loc))
132 		{
133 		  if (diagl(from) == diagl(target))
134 		    {
135 		      /* stays on diag, can only uncover check on
136 		       * other diag */
137 		      if (diagr(from) != diagr(bking_loc))
138 			return TRUE;
139 		    }
140 		  else
141 		    {
142 		      if (diagl(from) != diagl(bking_loc))
143 			return TRUE;
144 		    }
145 		}
146 	      break;
147 	    case brook:
148 	      /* discovers diagonal always */
149 	      /* one file or rank discovered */
150 	      if (diagr(from) != diagr(bking_loc)
151 		  && diagl(from) != diagl(bking_loc))
152 		{
153 		  /* rank move ? */
154 		  if(rank(from) == rank(target))
155 		    {
156 		      if (file(from) != file(bking_loc))
157 			return TRUE;
158 		    }
159 		  else
160 		    {
161 		      /* file move */
162 		      if (rank(from) != rank(bking_loc))
163 			return TRUE;
164 		    }
165 		}
166 	      break;
167 	    case bqueen:
168 	    /* find out what move it was: ldiag/rdiag/file/rank*/
169 	      if (file(from) == file(target))
170 		{
171 		  if (diagr(from) != diagr(bking_loc)
172 		      && diagl(from) != diagl(bking_loc)
173 		    && rank(from) != rank(bking_loc))
174 		    return TRUE;
175 		}
176 	       else if (rank(from) == rank(target))
177 	        {
178 		  if (diagr(from) != diagr(bking_loc)
179 		      && file(from) != file(bking_loc)
180 		      && diagl(from) != diagl(bking_loc))
181 		    return TRUE;
182 	        }
183 	      else if (diagl(from) == diagl(target))
184 		{
185 		  if (diagr(from) != diagr(bking_loc)
186 		      && file(from) != file(bking_loc)
187 		      && rank(from) != rank(bking_loc))
188 		    return TRUE;
189 		}
190 	      else if (diagr(from) == diagr(target))
191 		{
192 		  if (diagl(from) != diagl(bking_loc)
193 		      && file(from) != file(bking_loc)
194 		      && rank(from) != rank(bking_loc))
195 		    return TRUE;
196 		}
197 	    break;
198 	    default:
199 	      break;
200 	    }
201 
202 	  /* we got so far, we know there can only be some
203 	   * kind of possible discovering */
204 	  /* find out what */
205 	  /* we do not need to check for pawn, king or knightattacks,
206 	   * as they cannot be discovered*/
207 
208 	  if (board[target] != bking)
209 	  {
210 	    if (file(from) == file(bking_loc))
211 	    {
212 	      if (bking_loc > from)
213 	      {
214 	      for (l = bking_loc-12; board[l] == npiece; l-=12);
215 	      if (board[l] == wrook || board[l] == wqueen) return FALSE;
216 	      }
217 	      else
218 	      {
219 	      for (l = bking_loc+12; board[l] == npiece; l+=12);
220 	      if (board[l] == wrook || board[l] == wqueen) return FALSE;
221 	      }
222 	    }
223 	    else if (rank(from) == rank(bking_loc))
224 	    {
225 	      if (bking_loc > from)
226 	      {
227 	      for (l = bking_loc-1; board[l] == npiece; l-=1);
228 	      if (board[l] == wrook || board[l] == wqueen) return FALSE;
229 	      }
230 	      else
231 	      {
232 	      for (l = bking_loc+1; board[l] == npiece; l+=1);
233 	      if (board[l] == wrook || board[l] == wqueen) return FALSE;
234 	      }
235 	    }
236 	    else if (diagl(from) == diagl(bking_loc))
237 	    {
238 	      if (bking_loc > from)
239 	      {
240 	      for (l = bking_loc-13; board[l] == npiece; l-=13);
241 	      if (board[l] == wbishop || board[l] == wqueen) return FALSE;
242 	      }
243 	      else
244 	      {
245 	      for (l = bking_loc+13; board[l] == npiece; l+=13);
246 	      if (board[l] == wbishop || board[l] == wqueen) return FALSE;
247 	      }
248 	    }
249 	    else if (diagr(from) == diagr(bking_loc))
250 	    {
251 	      if (bking_loc > from)
252 	      {
253 	      for (l = bking_loc-11; board[l] == npiece; l-=11);
254 	      if (board[l] == wbishop || board[l] == wqueen) return FALSE;
255 	      }
256 	      else
257 	      {
258 	      for (l = bking_loc+11; board[l] == npiece; l+=11);
259 	      if (board[l] == wbishop || board[l] == wqueen) return FALSE;
260 	      }
261 	    }
262 	    return TRUE;
263 	  }
264 	}
265 
266       if (is_attacked (bking_loc, 1)) return FALSE;
267       else return TRUE;
268     }
269 
270   /* white king: */
271   else
272     {
273 
274       if (!incheck)
275 	{
276 	  if (moves[m].from == 0) return TRUE;
277 
278 	  switch (moves[m].promoted ? wpawn : board[target])
279 	    {
280 	    case wpawn:
281 	      /* pawn moves, it can discover a rank or diagonal check
282 	       * a capture can also discover a file check */
283 	      if (moves[m].captured != npiece)
284 		{
285 		  if (file(from) != file(wking_loc)
286 		      && rank(from) != rank(wking_loc)
287 		      && diagl(from) != diagl(wking_loc)
288 		      && diagr(from) != diagr(wking_loc))
289 		    return TRUE;
290 		}
291 	      else
292 		{
293 		  if (rank(from) != rank(wking_loc)
294 		      && diagl(from) != diagl(wking_loc)
295 		      && diagr(from) != diagr(wking_loc))
296 		    return TRUE;
297 		}
298 	      break;
299 	    case wknight:
300 	      /* discovers all */
301 	      if (file(from) != file(wking_loc)
302 		  && rank(from) != rank(wking_loc)
303 		  && diagl(from) != diagl(wking_loc)
304 		  && diagr(from) != diagr(wking_loc))
305 		return TRUE;
306 	      break;
307 	    case wbishop:
308 	      /* always discovers file and rank
309 	       * always discovers one diagonal */
310 	      if (file(from) != file(wking_loc)
311 		  && rank(from) != rank(wking_loc))
312 		{
313 		  if (diagl(from) == diagl(target))
314 		    {
315 		      /* stays on diag, can only uncover check on
316 		       * other diag */
317 		      if (diagr(from) != diagr(wking_loc))
318 			return TRUE;
319 		    }
320 		  else
321 		    {
322 		      if (diagl(from) != diagl(wking_loc))
323 			return TRUE;
324 		    }
325 		}
326 	      break;
327 	    case wrook:
328 	    /* discovers diagonal always */
329 	      /* one file or rank discovered */
330 	      if (diagr(from) != diagr(wking_loc)
331 		  && diagl(from) != diagl(wking_loc))
332 		{
333 		  /* rank move ? */
334 		  if(rank(from) == rank(target))
335 		    {
336 		      if (file(from) != file(wking_loc))
337 			return TRUE;
338 		    }
339 		  else
340 		    {
341 		      /* file move */
342 		      if (rank(from) != rank(wking_loc))
343 			return TRUE;
344 		    }
345 		}
346 	      break;
347 	    case wqueen:
348 	      /* find out what move it was: ldiag/rdiag/file/rank*/
349 	      if (file(from) == file(moves[m].target))
350 		{
351 		  if (diagr(from) != diagr(wking_loc)
352 		      && diagl(from) != diagl(wking_loc)
353 		      && rank(from) != rank(wking_loc))
354 		    return TRUE;
355 		}
356 	      else if (rank(from) == rank(target))
357 		{
358 		  if (diagr(from) != diagr(wking_loc)
359 		      && file(from) != file(wking_loc)
360 		      && diagl(from) != diagl(wking_loc))
361 		    return TRUE;
362 		}
363 	      else if (diagl(from) == diagl(target))
364 		{
365 		  if (diagr(from) != diagr(wking_loc)
366 		      && file(from) != file(wking_loc)
367 		      && rank(from) != rank(wking_loc))
368 		    return TRUE;
369 		}
370 	      else if (diagr(from) == diagr(target))
371 		{
372 		  if (diagl(from) != diagl(wking_loc)
373 		      && file(from) != file(wking_loc)
374 		      && rank(from) != rank(wking_loc))
375 		    return TRUE;
376 		}
377 	      break;
378 	    default:
379 	      break;
380 	    }
381 
382 	  if (board[target] != wking)
383 	  {
384 	    if (file(from) == file(wking_loc))
385 	    {
386 	      if (wking_loc > from)
387 	      {
388 	      for (l = wking_loc-12; board[l] == npiece; l-=12);
389 	      if (board[l] == brook || board[l] == bqueen) return FALSE;
390 	      }
391 	      else
392 	      {
393 	      for (l = wking_loc+12; board[l] == npiece; l+=12);
394 	      if (board[l] == brook || board[l] == bqueen) return FALSE;
395 	      }
396 	    }
397 	    else if (rank(from) == rank(wking_loc))
398 	    {
399 	      if (wking_loc > from)
400 	      {
401 	      for (l = wking_loc-1; board[l] == npiece; l-=1);
402 	      if (board[l] == brook || board[l] == bqueen) return FALSE;
403 	      }
404 	      else
405 	      {
406 	      for (l = wking_loc+1; board[l] == npiece; l+=1);
407 	      if (board[l] == brook || board[l] == bqueen) return FALSE;
408 	      }
409 	    }
410 	    else if (diagl(from) == diagl(wking_loc))
411 	    {
412 	      if (wking_loc > from)
413 	      {
414 	      for (l = wking_loc-13; board[l] == npiece; l-=13);
415 	      if (board[l] == bbishop || board[l] == bqueen) return FALSE;
416 	      }
417 	      else
418 	      {
419 	      for (l = wking_loc+13; board[l] == npiece; l+=13);
420 	      if (board[l] == bbishop || board[l] == bqueen) return FALSE;
421 	      }
422 	    }
423 	    else if (diagr(from) == diagr(wking_loc))
424 	    {
425 	      if (wking_loc > from)
426 	      {
427 	      for (l = wking_loc-11; board[l] == npiece; l-=11);
428 	      if (board[l] == bbishop || board[l] == bqueen) return FALSE;
429 	      }
430 	      else
431 	      {
432 	      for (l = wking_loc+11; board[l] == npiece; l+=11);
433 	      if (board[l] == bbishop || board[l] == bqueen) return FALSE;
434 	      }
435 	    }
436 	    return TRUE;
437 	  }
438 	}
439 
440       if (is_attacked (wking_loc, 0)) return FALSE;
441       else return TRUE;
442   }
443 
444   /* should never get here .. but just so it will compile :P */
445   return FALSE;
446 
447 }
448 
449 
450 #define push_slide(t) if (board[(t)] != frame) push_slidE((t))
451 #define push_knight(t) if (board[(t)] != frame) push_knighT((t))
452 
gen(move_s moves[])453 void gen (move_s moves[]) {
454 
455   /* generate pseudo-legal moves, and place them in the moves array */
456 
457   int from, a, j, i;
458 
459   kingcap = FALSE;
460 
461   numb_moves = 0;
462   genfor = &moves[0];
463 
464   if (Variant == Suicide)
465   {
466     captures = FALSE;
467     fcaptures = FALSE;
468   };
469 
470 restart:
471 
472   /* generate white moves, if it is white to move: */
473   if (white_to_move) {
474     for (a = 1, j = 1;
475 	 (a <= piece_count)
476 	   && (((Variant != Suicide) && !kingcap)
477 	   || ((Variant == Suicide) && (fcaptures == captures)));
478 	 j++) {
479 
480       i = pieces[j];
481 
482       if (!i)
483 	continue;
484       else
485 	a++;
486 
487       from = i;
488       gfrom = i;
489 
490        switch (board[from]) {
491        case (wpawn):
492 	 /* pawn moves up one square: */
493 	 if (board[from+12] == npiece) {
494 	   /* only promotions when captures == TRUE */
495 	   if (rank (from) == 7 && ((Variant != Suicide) && (Variant != Losers))) {
496 	     push_pawn (from+12, FALSE);
497 	   }
498 	   else if (!captures) {
499 	     push_pawn (from+12, FALSE);
500 
501 	     /* pawn moving up two squares on its first move: */
502 	     if (rank(from) == 2 && board[from+24] == npiece)
503 	       push_pawn_simple (from+24);
504 	   }
505 	 }
506 	 /* pawn capturing diagonally: */
507 	 if ((board[from+13]&1) == 0 && board[from+13] != frame)
508 	   push_pawn (from+13, FALSE);
509 	 /* pawn captruing diagonally: */
510 	 if ((board[from+11]&1) == 0 && board[from+11] != frame)
511 	   push_pawn (from+11, FALSE);
512 	 /* ep move: */
513 	 if (ep_square == from+13)
514 	   push_pawn (from+13, TRUE);
515 	 /* ep move: */
516 	 else if (ep_square == from+11)
517 	   push_pawn (from+11, TRUE);
518 	 break;
519        case (wknight):
520 	 /* use the knight offsets: */
521 	 push_knight (from-25);
522 	 push_knight (from-23);
523 	 push_knight (from-14);
524 	 push_knight (from-10);
525 	 push_knight (from+10);
526 	 push_knight (from+14);
527 	 push_knight (from+23);
528 	 push_knight (from+25);
529 	 break;
530        case (wbishop):
531 	 /* use the bishop offsets: */
532 	 push_slide (from-13);
533 	 push_slide (from-11);
534 	 push_slide (from+11);
535 	 push_slide (from+13);
536 	 break;
537        case (wrook):
538 	 /* use the rook offsets: */
539 	 push_slide (from-12);
540 	 push_slide (from-1);
541 	 push_slide (from+1);
542 	 push_slide (from+12);
543 	 break;
544        case (wqueen):
545 	 /* use the queen offsets: */
546 	 push_slide (from-13);
547 	 push_slide (from-12);
548 	 push_slide (from-11);
549 	 push_slide (from-1);
550 	 push_slide (from+1);
551 	 push_slide (from+11);
552 	 push_slide (from+12);
553 	 push_slide (from+13);
554 	 break;
555        case (wking):
556 	 /* use the king offsets for 'normal' moves: */
557 	  push_king (from-13);
558 	  push_king (from-12);
559 	  push_king (from-11);
560 	  push_king (from-1);
561 	  push_king (from+1);
562 	  push_king (from+11);
563 	  push_king (from+12);
564 	  push_king (from+13);
565 	  /* castling moves: */
566 	  if (from == 30 && !moved[30] && !captures && (Variant != Suicide || Giveaway == TRUE)) {
567 	    /* kingside: */
568 	    if (!moved[33] && board[33] == wrook)
569 	      if (board[31] == npiece && board[32] == npiece)
570 		push_king_castle (from+2, wck);
571 	    /* queenside: */
572 	    if (!moved[26] && board[26] == wrook)
573 	      if (board[27] == npiece && board[28] == npiece
574 		  && board[29] == npiece)
575 		push_king_castle (from-2, wcq);
576 	  }
577 	  break;
578         default:
579 	  break;
580       }
581     }
582   }
583 
584   /* generate black moves, if it is black to move: */
585   else {
586     for (a = 1, j = 1;
587 	 (a <= piece_count) &&
588 	  (((Variant != Suicide) && !kingcap)
589 	  || ((Variant == Suicide) && (fcaptures == captures)))
590 	  ; j++) {
591       i = pieces[j];
592 
593       if (!i)
594 	continue;
595       else
596 	a++;
597 
598       from = i;
599       gfrom = i;
600 
601       switch (board[from]) {
602       case (bpawn):
603 	/* pawn moves up one square: */
604 	if (board[from-12] == npiece) {
605 	  /* only promotions when captures == TRUE */
606 	  if (rank (from) == 2 && ((Variant != Suicide) && (Variant != Losers))) {
607 	    push_pawn (from-12, FALSE);
608 	  }
609 	  else if (!captures) {
610 	    push_pawn (from-12, FALSE);
611 
612 	  /* pawn moving up two squares on its first move: */
613 	  if (rank(from) == 7 && board[from-24] == npiece)
614 	    push_pawn_simple (from-24);
615 	  }
616 	};
617 	/* pawn capturing diagonally: */
618 	if ((board[from-13]&1) == 1 && board[from-13] != npiece)
619 	  push_pawn (from-13, FALSE);
620 	/* pawn capturing diagonally: */
621 	if ((board[from-11]&1) == 1 && board[from-11] != npiece)
622 	  push_pawn (from-11, FALSE);
623 	/* ep move: */
624 	if (ep_square == from-13)
625 	  push_pawn (from-13, TRUE);
626 	/* ep move: */
627 	else if (ep_square == from-11)
628 	  push_pawn (from-11, TRUE);
629 	  break;
630       case (bknight):
631 	/* use the knight offsets: */
632 	push_knight (from-25);
633 	push_knight (from-23);
634 	push_knight (from-14);
635 	push_knight (from-10);
636 	push_knight (from+10);
637 	push_knight (from+14);
638 	push_knight (from+23);
639 	push_knight (from+25);
640 	  break;
641       case (bbishop):
642 	/* use the bishop offsets: */
643 	push_slide (from-13);
644 	push_slide (from-11);
645 	push_slide (from+11);
646 	push_slide (from+13);
647 	break;
648       case (brook):
649 	/* use the rook offsets: */
650 	push_slide (from-12);
651 	push_slide (from-1);
652 	push_slide (from+1);
653 	push_slide (from+12);
654 	break;
655       case (bqueen):
656 	/* use the queen offsets: */
657 	push_slide (from-13);
658 	push_slide (from-12);
659 	push_slide (from-11);
660 	push_slide (from-1);
661 	push_slide (from+1);
662 	push_slide (from+11);
663 	push_slide (from+12);
664 	push_slide (from+13);
665 	break;
666       case (bking):
667 	  /* use the king offsets for 'normal' moves: */
668 	push_king (from-13);
669 	push_king (from-12);
670 	push_king (from-11);
671 	push_king (from-1);
672 	push_king (from+1);
673 	push_king (from+11);
674 	push_king (from+12);
675 	push_king (from+13);
676 	/* castling moves: */
677 	if (from == 114 && !moved[114] && !captures && (Variant != Suicide || Giveaway == TRUE)) {
678 	  /* kingside: */
679 	  if (!moved[117] && board[117] == brook)
680 	    if (board[115] == npiece && board[116] == npiece)
681 	      push_king_castle (from+2, bck);
682 	  /* queenside: */
683 	  if (!moved[110] && board[110] == brook)
684 	    if (board[111] == npiece && board[112] == npiece
685 		&& board[113] == npiece)
686 	      push_king_castle (from-2, bcq);
687 	}
688 	break;
689       default:
690 	break;
691       }
692     }
693   }
694   if (((Variant == Crazyhouse) || (Variant == Bughouse)) && !captures && !kingcap)
695     {
696       if (white_to_move &&
697 	  (holding[WHITE][wpawn] || holding[WHITE][wknight]
698 	   || holding[WHITE][wbishop] || holding[WHITE][wqueen]
699 	   || holding[WHITE][wrook]))
700 	{
701 	  for (from = 26; from < 118; from++)
702 	    {
703               gfrom = from;
704 
705 	      switch (board[from])
706 		{
707 		case (frame):
708 		  from += 3;
709 		  continue;
710 		case (npiece):
711 		  if(holding[WHITE][wpawn])
712 		    {
713 		      if ((rank(from) != 8) && (rank(from) != 1))
714 			{
715 			  try_drop(wpawn);
716 			}
717 		    }
718 		  if(holding[WHITE][wknight])
719 		    {
720 		      try_drop(wknight);
721 		    }
722 		  if(holding[WHITE][wbishop])
723 		    {
724 		      try_drop(wbishop);
725 		    }
726 		  if(holding[WHITE][wrook])
727 		    {
728 		      try_drop(wrook);
729 		    }
730 		  if(holding[WHITE][wqueen])
731 		    {
732 		      try_drop(wqueen);
733 		    }
734 		};
735 	    }
736 	}
737       else if (!white_to_move &&
738 	       (holding[BLACK][bpawn] || holding[BLACK][bknight]
739 		|| holding[BLACK][bbishop] || holding[BLACK][bqueen]
740 		|| holding[BLACK][brook]))
741 	{
742 	  for (from = 26; from < 118; from++)
743 	    {
744 	      gfrom = from;
745 
746 	      switch (board[from])
747 		{
748 		case (frame):
749 		  from += 3;
750 		  continue;
751 		case (npiece):
752 		  if(holding[BLACK][bpawn])
753 		    {
754 		      if ((rank(from) != 8) && (rank(from) != 1))
755 			{
756 			  try_drop(bpawn);
757 			}
758 		    }
759 		  if(holding[BLACK][bknight])
760 		    {
761 		      try_drop(bknight);
762 		    }
763 		  if(holding[BLACK][bbishop])
764 		    {
765 		      try_drop(bbishop);
766 		    }
767 		  if(holding[BLACK][brook])
768 		    {
769 		      try_drop(brook);
770 		    }
771 		  if(holding[BLACK][bqueen])
772 		    {
773 		      try_drop(bqueen);
774 		    }
775 		};
776 	    };
777 	}
778     }
779 
780   if ((Variant == Suicide) && fcaptures == TRUE && captures == FALSE)
781     {
782       captures = TRUE;
783       numb_moves = 0;
784       goto restart;
785     }
786 
787   if (Variant == Suicide) kingcap = FALSE;
788 
789 
790 }
791 
792 
in_check(void)793 bool in_check (void) {
794 
795   /* return true if the side to move is in check: */
796 
797   if (Variant == Suicide) return FALSE;
798 
799   if (white_to_move == 1) {
800     if (is_attacked (wking_loc, 0)) {
801       return TRUE;
802     }
803   }
804   else {
805     if (is_attacked (bking_loc, 1)) {
806       return TRUE;
807     }
808   }
809 
810   return FALSE;
811 
812 }
813 
f_in_check(move_s moves[],int m)814 bool f_in_check(move_s moves[], int m)
815 {
816   int target = moves[m].target;
817   int from = moves[m].from;
818   int l;
819   static const int knight_o[8] = {10, -10, 14, -14, 23, -23, 25, -25};
820 
821   if (Variant == Suicide) return FALSE;
822 
823   if (white_to_move == 1)
824   {
825     /* is white king attacked */
826     /* we are certain the king is not in check already,
827      * as we would capture him in our ply */
828     /* thus, we need to check if our move could possibly
829      * put the king in check */
830     /* this can either be a direct check, or a discover */
831 
832 	  switch (board[target])
833     {
834       case bpawn:
835 	if (board[target-11] == wking || board[target-13] == wking) return TRUE;
836 	break;
837       case bbishop:
838 	if (diagl(target) == diagl(wking_loc))
839 	{
840 	  /* possible left diag check */
841 	  if (wking_loc < target)
842 	  {
843 	  	for (l = wking_loc+13; board[l] == npiece; l +=13);
844 	  	if (l == target) return TRUE;
845 	  }
846 	  else
847 	  {
848 	  	for (l = wking_loc-13; board[l] == npiece; l -=13);
849 	  	if (l == target) return TRUE;
850 	  }
851 	}
852 	else if (diagr(target) == diagr(wking_loc))
853 	{
854 	  if (wking_loc < target)
855 	  {
856 	  	for (l = wking_loc+11; board[l] == npiece; l +=11);
857 	  	if (l == target) return TRUE;
858 	  }
859 	  else
860 	  {
861 		for (l = wking_loc-11; board[l] == npiece; l -=11);
862 	  	if (l == target) return TRUE;
863 	  }
864 	}
865 	break;
866       case brook:
867 	if (file(target) == file(wking_loc))
868 	{
869 	  if (wking_loc < target)
870 	  {
871 	  	for (l = wking_loc+12; board[l] == npiece; l +=12);
872 	  	if (l == target) return TRUE;
873 	  }
874 	  else
875 	  {
876 		for (l = wking_loc-12; board[l] == npiece; l -=12);
877 	  	if (l == target) return TRUE;
878 	  }
879 	}
880 	else if (rank(target) == rank(wking_loc))
881 	{
882 	  if (wking_loc < target)
883 	  {
884 	  	for (l = wking_loc+1; board[l] == npiece; l++);
885 	  	if (l == target) return TRUE;
886 	  }
887 	  else
888 	  {
889 	  	for (l = wking_loc-1; board[l] == npiece; l--);
890 	  	if (l == target) return TRUE;
891 	  }
892 	}
893 	break;
894       case bknight:
895 	 for (l = 0; l < 8; l++)
896 	   if ((wking_loc + knight_o[l]) == target) return TRUE;
897 	break;
898       case bqueen:
899 	if (file(target) == file(wking_loc))
900 	{
901 	  if (wking_loc < target)
902 	  {
903 	  	for (l = wking_loc+12; board[l] == npiece; l +=12);
904 	  	if (l == target) return TRUE;
905 	  }
906 	  else
907 	  {
908 	  	for (l = wking_loc-12; board[l] == npiece; l -=12);
909 	  	if (l == target) return TRUE;
910 	  }
911 	}
912 	else if (rank(target) == rank(wking_loc))
913 	{
914 	  if (wking_loc < target)
915 	  {
916 	  	for (l = wking_loc+1; board[l] == npiece; l +=1);
917 	  	if (l == target) return TRUE;
918 	  }
919 	  else
920 	  {
921 	  	for (l = wking_loc-1; board[l] == npiece; l -=1);
922 	  	if (l == target) return TRUE;
923 	  }
924 	}
925 	else if (diagl(target) == diagl(wking_loc))
926 	{
927 	  if (wking_loc < target)
928 	  {
929 	  	for (l = wking_loc+13; board[l] == npiece; l +=13);
930 	  	if (l == target) return TRUE;
931 	  }
932 	  else
933 	  {
934 	  	for (l = wking_loc-13; board[l] == npiece; l -=13);
935 	  	if (l == target) return TRUE;
936 	  }
937 	}
938 	else if (diagr(target) == diagr(wking_loc))
939 	{
940 	  if (wking_loc < target)
941 	  {
942 	  	for (l = wking_loc+11; board[l] == npiece; l +=11);
943 	  	if (l == target) return TRUE;
944 	  }
945 	  else
946 	  {
947 	  	for (l = wking_loc-11; board[l] == npiece; l -=11);
948 	  	if (l == target) return TRUE;
949 	  }
950 	}
951 	break;
952       case bking:
953 	/* can only discover checks */
954 	/* castling is tricky */
955 	if (moves[m].castled)
956 	  {
957 	    if (is_attacked (wking_loc, 0))
958 	      return TRUE;
959 	    else
960 	      return FALSE;
961 	  }
962 	break;
963     }
964 
965     /* drop move can never discover check */
966     if (from == 0) return FALSE;
967 
968     /* this checks for discovered checks */
969     if (rank(from) == rank(wking_loc))
970     {
971       if (wking_loc > from)
972       {
973     	for (l = wking_loc-1; board[l] == npiece; l--);
974 	if (board[l] == brook || board[l] == bqueen) return TRUE;
975       }
976       else
977       {
978 	for (l = wking_loc+1; board[l] == npiece; l++);
979 	if (board[l] == brook || board[l] == bqueen) return TRUE;
980       }
981     }
982     else if (file(from) == file(wking_loc))
983     {
984       if (wking_loc > from)
985       {
986         for (l = wking_loc-12; board[l] == npiece; l-=12);
987 	if (board[l] == brook || board[l] == bqueen) return TRUE;
988       }
989       else
990       {
991 	for (l = wking_loc+12; board[l] == npiece; l+=12);
992 	if (board[l] == brook || board[l] == bqueen) return TRUE;
993 	}
994     }
995     else if (diagl(from) == diagl(wking_loc))
996     {
997       if (wking_loc > from)
998       {
999        for (l = wking_loc-13; board[l] == npiece; l-=13);
1000        if (board[l] == bbishop || board[l] == bqueen) return TRUE;
1001       }
1002       else
1003       {
1004        for (l = wking_loc+13; board[l] == npiece; l+=13);
1005        if (board[l] == bbishop || board[l] == bqueen) return TRUE;
1006       }
1007     }
1008     else if (diagr(from) == diagr(wking_loc))
1009     {
1010       if (wking_loc > from)
1011       {
1012        for (l = wking_loc-11; board[l] == npiece; l-=11);
1013        if (board[l] == bbishop || board[l] == bqueen) return TRUE;
1014       }
1015       else
1016       {
1017        for (l = wking_loc+11; board[l] == npiece; l+=11);
1018        if (board[l] == bbishop || board[l] == bqueen) return TRUE;
1019       }
1020      }
1021 
1022     return FALSE;
1023 
1024     //if (is_attacked (wking_loc, 0))
1025     //return TRUE;
1026   }
1027   else
1028   {
1029     /* is black king attacked */
1030     switch (board[target])
1031     {
1032       case wpawn:
1033 	if (board[target+11] == bking || board[target+13] == bking) return TRUE;
1034 	break;
1035       case wbishop:
1036 	if (diagl(target) == diagl(bking_loc))
1037 	{
1038 	  /* possible left diag check */
1039 	  if (bking_loc < target)
1040 	  {
1041 	  for (l = bking_loc+13; board[l] == npiece; l +=13);
1042 	  if (l == target) return TRUE;
1043 	  }
1044 	  else
1045 	  {
1046 	  for (l = bking_loc-13; board[l] == npiece; l -=13);
1047 	  if (l == target) return TRUE;
1048 	  }
1049 	}
1050 	else if (diagr(target) == diagr(bking_loc))
1051 	{
1052 	  if (bking_loc < target)
1053 	  {
1054 	  for (l = bking_loc+11; board[l] == npiece; l +=11);
1055 	  if (l == target) return TRUE;
1056 	  }
1057 	  else
1058 	  {
1059 	  for (l = bking_loc-11; board[l] == npiece; l -=11);
1060 	  if (l == target) return TRUE;
1061 	  }
1062 	}
1063 	break;
1064       case wrook:
1065 	if (file(target) == file(bking_loc))
1066 	{
1067 	  if (bking_loc < target)
1068 	  {
1069 	  for (l = bking_loc+12; board[l] == npiece; l +=12);
1070 	  if (l == target) return TRUE;
1071 	  }
1072 	  else
1073 	  {
1074 	  for (l = bking_loc-12; board[l] == npiece; l -=12);
1075 	  if (l == target) return TRUE;
1076 	  }
1077 	}
1078 	else if (rank(target) == rank(bking_loc))
1079 	{
1080 	  if (bking_loc < target)
1081 	  {
1082 	  for (l = bking_loc+1; board[l] == npiece; l++);
1083 	  if (l == target) return TRUE;
1084 	  }
1085 	  else
1086 	  {
1087 	  for (l = bking_loc-1; board[l] == npiece; l--);
1088 	  if (l == target) return TRUE;
1089 	  }
1090 	}
1091 	break;
1092       case wknight:
1093 	 for (l = 0; l < 8; l++)
1094 	   if ((bking_loc + knight_o[l]) == target) return TRUE;
1095 	break;
1096       case wqueen:
1097 	if (file(target) == file(bking_loc))
1098 	{
1099 	  if (bking_loc < target)
1100 	  {
1101 	  for (l = bking_loc+12; board[l] == npiece; l +=12);
1102 	  if (l == target) return TRUE;
1103 	  }
1104 	  else
1105 	  {
1106 	  for (l = bking_loc-12; board[l] == npiece; l -=12);
1107 	  if (l == target) return TRUE;
1108 	  }
1109 	}
1110 	else if (rank(target) == rank(bking_loc))
1111 	{
1112 	  if (bking_loc < target)
1113 	  {
1114 	  for (l = bking_loc+1; board[l] == npiece; l +=1);
1115 	  if (l == target) return TRUE;
1116 	  }
1117 	  else
1118 	  {
1119 	  for (l = bking_loc-1; board[l] == npiece; l -=1);
1120 	  if (l == target) return TRUE;
1121 	  }
1122 	}
1123 	else if (diagl(target) == diagl(bking_loc))
1124 	{
1125 	  if (bking_loc < target)
1126 	  {
1127 	  for (l = bking_loc+13; board[l] == npiece; l +=13);
1128 	  if (l == target) return TRUE;
1129 	  }
1130 	  else
1131 	  {
1132 	  for (l = bking_loc-13; board[l] == npiece; l -=13);
1133 	  if (l == target) return TRUE;
1134 	  }
1135 	}
1136 	else if (diagr(target) == diagr(bking_loc))
1137 	{
1138 	  if (bking_loc < target)
1139 	  {
1140 	  for (l = bking_loc+11; board[l] == npiece; l +=11);
1141 	  if (l == target) return TRUE;
1142 	  }
1143 	  else
1144 	  {
1145 	  for (l = bking_loc-11; board[l] == npiece; l -=11);
1146 	  if (l == target) return TRUE;
1147 	  }
1148 	}
1149 	break;
1150       case wking:
1151 	/* can only discover checks */
1152 	if (moves[m].castled)
1153 	  {
1154 	    if (is_attacked (bking_loc, 1))
1155 	      return TRUE;
1156 	    else
1157 	      return FALSE;
1158 	  }
1159 	break;
1160     }
1161 
1162     if (from == 0) return FALSE;
1163 
1164     /* this checks for discovered checks */
1165     if (rank(from) == rank(bking_loc))
1166     {
1167       if (bking_loc > from)
1168       {
1169     	for (l = bking_loc-1; board[l] == npiece; l--);
1170 	if (board[l] == wrook || board[l] == wqueen) return TRUE;
1171       }
1172       else
1173       {
1174 	for (l = bking_loc+1; board[l] == npiece; l++);
1175 	if (board[l] == wrook || board[l] == wqueen) return TRUE;
1176       }
1177     }
1178     else if (file(from) == file(bking_loc))
1179     {
1180       if (bking_loc > from)
1181       {
1182 	for (l = bking_loc-12; board[l] == npiece; l-=12);
1183 	if (board[l] == wrook || board[l] == wqueen) return TRUE;
1184       }
1185       else
1186       {
1187 	for (l = bking_loc+12; board[l] == npiece; l+=12);
1188 	if (board[l] == wrook || board[l] == wqueen) return TRUE;
1189       }
1190     }
1191     else if (diagl(from) == diagl(bking_loc))
1192     {
1193       if (bking_loc > from)
1194       {
1195 	for (l = bking_loc-13; board[l] == npiece; l-=13);
1196        if (board[l] == wbishop || board[l] == wqueen) return TRUE;
1197       }
1198       else
1199       {
1200        for (l = bking_loc+13; board[l] == npiece; l+=13);
1201        if (board[l] == wbishop || board[l] == wqueen) return TRUE;
1202       }
1203     }
1204     else if (diagr(from) == diagr(bking_loc))
1205     {
1206       if (bking_loc > from)
1207       {
1208 	for (l = bking_loc-11; board[l] == npiece; l-=11);
1209        if (board[l] == wbishop || board[l] == wqueen) return TRUE;
1210       }
1211       else
1212       {
1213        for (l = bking_loc+11; board[l] == npiece; l+=11);
1214        if (board[l] == wbishop || board[l] == wqueen) return TRUE;
1215       }
1216     }
1217 
1218     return FALSE;
1219 
1220     // if (is_attacked (bking_loc, 1))
1221     // display_board(stdout, 1);//return TRUE;
1222   }
1223 }
1224 
extended_in_check(void)1225 int extended_in_check(void)
1226 {
1227   register int sq;
1228   static const int knight_o[8] = {10, -10, 14, -14, 23, -23, 25, -25};
1229 
1230   if (Variant == Suicide) return 0;
1231 
1232   if (white_to_move == 1)
1233   {
1234     sq = board[wking_loc-12];
1235     if (sq == brook || sq == bqueen) return 2;
1236     sq = board[wking_loc-1];
1237     if (sq == brook || sq == bqueen) return 2;
1238     sq = board[wking_loc+1];
1239     if (sq == brook || sq == bqueen) return 2;
1240     sq = board[wking_loc+12];
1241     if (sq == brook || sq == bqueen) return 2;
1242     sq = board[wking_loc+13];
1243     if (sq == bbishop || sq == bqueen || sq == bpawn) return 2;
1244     sq = board[wking_loc+11];
1245     if (sq == bbishop || sq == bqueen || sq == bpawn) return 2;
1246     sq = board[wking_loc-11];
1247     if (sq == bbishop || sq == bqueen) return 2;
1248     sq = board[wking_loc-13];
1249     if (sq == bbishop || sq == bqueen) return 2;
1250     for (sq = 0; sq < 8; sq++)
1251     {
1252       if (board[wking_loc + knight_o[sq]] == bknight) return 2;
1253     }
1254     if (is_attacked (wking_loc, 0))
1255     {
1256       if (Variant == Normal || Variant == Losers) return 2;
1257       else return 1;
1258     }
1259   }
1260   else
1261   {
1262     sq = board[bking_loc-12];
1263     if (sq == wrook || sq == wqueen) return 2;
1264     sq = board[bking_loc-1];
1265     if (sq == wrook || sq == wqueen) return 2;
1266     sq = board[bking_loc+1];
1267     if (sq == wrook || sq == wqueen) return 2;
1268     sq = board[bking_loc+12];
1269     if (sq == wrook || sq == wqueen) return 2;
1270     sq = board[bking_loc-13];
1271     if (sq == wbishop || sq == wqueen || sq == wpawn) return 2;
1272     sq = board[bking_loc-11];
1273     if (sq == wbishop || sq == wqueen || sq == wpawn) return 2;
1274     sq = board[bking_loc+11];
1275     if (sq == wbishop || sq == wqueen) return 2;
1276     sq = board[bking_loc+13];
1277     if (sq == wbishop || sq == wqueen) return 2;
1278     for (sq = 0; sq < 8; sq++)
1279     {
1280       if (board[bking_loc + knight_o[sq]] == wknight) return 2;
1281     }
1282     if (is_attacked (bking_loc, 1))
1283     {
1284       if (Variant == Normal || Variant == Losers) return 2;
1285       else return 1;
1286     }
1287   }
1288 
1289   return 0;
1290 };
1291 
make(move_s moves[],int i)1292 void make (move_s moves[], int i) {
1293 
1294   /* make a move */
1295 
1296   /* rather than writing out from[i].from, from[i].target, etc. all over
1297      the place, just make a copy of them here: */
1298   int ep, from, target, captured, promoted, castled, find_slot;
1299   ep = moves[i].ep;
1300   from = moves[i].from;
1301   target = moves[i].target;
1302   captured = moves[i].captured;
1303   promoted = moves[i].promoted;
1304   castled = moves[i].castled;
1305 
1306   //if ((moves[i].target == 0) || ((moves[i].from != 0) && ((board[moves[i].from] == npiece) || board[moves[i].from] == frame)))
1307  //   DIE;
1308 
1309   /* clear the en passant rights: */
1310   path_x[ply].epsq = ep_square;
1311 
1312   ep_square = 0;
1313 
1314   /* update the 50 move info: */
1315   path_x[ply].fifty = fifty;
1316 
1317   /* ignore piece drops...50move draw wont happen anyway */
1318   if (board[from] == wpawn || board[from] == bpawn || board[target] != npiece)
1319   {
1320     fifty = 0;
1321   }
1322   else
1323   {
1324     fifty++;
1325   }
1326 
1327   if (from == 0)
1328     { /* drop move */
1329       /* Drop moves are handled fully seperate because we exepect to encouter
1330 	 lots of them and we try to skip as many checks as possible.
1331 	 Note that the critical path for drop moves is very short.
1332 	 Also, we have to handle pieces[] and squares[] specially   */
1333 
1334        /* new piece on board */
1335       piece_count++;
1336 
1337       /* find first empty slot in pieces[] */
1338       for(find_slot = 1; (pieces[find_slot] != 0); find_slot++)
1339 	assert(find_slot < 63);
1340 
1341       /* add to piece array, set piece-square pointer */
1342       pieces[find_slot] = target;
1343 
1344       path_x[ply].was_promoted = is_promoted[find_slot];
1345       is_promoted[find_slot] = 0;
1346 
1347       /* set square->piece pointer */
1348       squares[target] = find_slot;
1349     //  moved[target] = 1;
1350 
1351       //if (promoted <= frame || promoted >= npiece)
1352      // 	DIE;
1353 
1354       assert(promoted > frame && promoted < npiece);
1355 
1356       DropremoveHolding(promoted, ToMove);
1357 
1358       /* piece went off holding but onto board */
1359       AddMaterial(promoted);
1360 
1361       /* put our piece on the board */
1362       board[target] = promoted;
1363 
1364       Hash(promoted,target);
1365 
1366       white_to_move ^= 1;
1367       ply++;
1368 
1369       return;
1370     }
1371   else
1372     {
1373 
1374       path_x[ply].was_promoted = is_promoted[squares[target]];
1375 
1376       /* update the "general" pieces[] / squares[] info (special moves need
1377 	 special handling later): */
1378       path_x[ply].cap_num = squares[target];
1379       pieces[squares[target]] = 0;
1380       pieces[squares[from]] = target;
1381       squares[target] = squares[from];
1382       squares[from] = 0;
1383 
1384       /* update the piece count & add Holdings */
1385       if (!ep)
1386       {
1387 	switch (board[target]) {
1388 	case (npiece): break;
1389 	default:
1390 
1391 	  if (Variant == Bughouse || Variant == Crazyhouse)
1392 	    {
1393 	      if (path_x[ply].was_promoted)
1394 	    	{
1395 		  addHolding(SwitchPromoted(board[target]), ToMove);
1396 	    	}
1397 	      else
1398 	    	{
1399 		  addHolding(SwitchColor(board[target]), ToMove);
1400 	    	}
1401 	    }
1402 
1403 	  RemoveMaterial(board[target]);
1404 
1405 	  /* remove captured piece */
1406 	  Hash(board[target], target);
1407 
1408 	  piece_count--;
1409 	  break;
1410 	}
1411       }
1412 
1413       /* white pawn moves: */
1414       if (board[from] == wpawn) {
1415 	/* look for a promotion move: */
1416 	if (promoted) {
1417 	  board[target] = promoted;
1418 	  board[from] = npiece;
1419 	  moved[target]++;
1420 	  moved[from]++;
1421 	  white_to_move ^= 1;
1422 
1423 	  is_promoted[squares[target]] = 1;
1424 
1425 	  /* remove pawn */
1426 	  Hash(wpawn, from);
1427 	  /* add new stuff */
1428 	  Hash(promoted, target);
1429 
1430 	  RemoveMaterial(wpawn);
1431 	  AddMaterial(promoted);
1432 
1433 	  ply++;
1434 
1435 	  return;
1436 	}
1437 
1438 	/* look for an en passant move: */
1439 	if (ep) {
1440 
1441 	  /* remove pawn */
1442 	  Hash(wpawn, from);
1443 	  /* remove ep pawn */
1444 	  Hash(bpawn, target-12);
1445 	  /* add target pawn */
1446 	  Hash(wpawn, target);
1447 
1448 	  RemoveMaterial(bpawn);
1449 
1450 	  board[target] = wpawn;
1451 	  board[from] = npiece;
1452 
1453 	  addHolding(wpawn, WHITE);
1454 	  piece_count--;
1455 
1456 	  board[target-12] = npiece;
1457 	  moved[target]++;
1458 	  moved[from]++;
1459 	  moved[target-12]++;
1460 	  white_to_move ^= 1;
1461 	  path_x[ply].cap_num = squares[target-12];
1462 
1463 	  pieces[squares[target-12]] = 0;
1464 	  squares[target-12] = 0;
1465 
1466 	  ply++;
1467 
1468 	  return;
1469 	}
1470 
1471 	/* otherwise, we have a "regular" pawn move: */
1472 	/* first check to see if we've moved a pawn up 2 squares: */
1473 	if (target == from+24)
1474 	  ep_square = from+12;
1475 
1476 	Hash(wpawn, from);
1477 	Hash(wpawn, target);
1478 
1479 	board[target] = wpawn;
1480 	board[from] = npiece;
1481 	moved[target]++;
1482 	moved[from]++;
1483 	white_to_move ^= 1;
1484 
1485 	ply++;
1486 
1487 	return;
1488 
1489       }
1490 
1491       /* black pawn moves: */
1492       if (board[from] == bpawn) {
1493 	/* look for a promotion move: */
1494 	if (promoted) {
1495 	  board[target] = promoted;
1496 	  board[from] = npiece;
1497 	  moved[target]++;
1498 	  moved[from]++;
1499 	  white_to_move ^= 1;
1500 
1501 	  is_promoted[squares[target]] = 1;
1502 
1503 	  /* remove pawn */
1504 	  Hash(bpawn, from);
1505 	  /* add new stuff */
1506 	  Hash(promoted, target);
1507 
1508 	  RemoveMaterial(bpawn);
1509 	  AddMaterial(promoted);
1510 
1511 	  ply++;
1512 
1513 	  return;
1514 	}
1515 
1516 	/* look for an en passant move: */
1517 	if (ep) {
1518 
1519 	  /* remove pawn */
1520 	  Hash(bpawn, from);
1521 	  /* remove ep pawn */
1522 	  Hash(wpawn, target+12);
1523 	  /* add target pawn */
1524 	  Hash(bpawn, target);
1525 
1526 	  RemoveMaterial(wpawn);
1527 
1528 	  board[target] = bpawn;
1529 	  board[from] = npiece;
1530 
1531 	  addHolding(bpawn, BLACK);
1532 	  piece_count--;
1533 
1534 	  board[target+12] = npiece;
1535 	  moved[target]++;
1536 	  moved[from]++;
1537 	  moved[target+12]++;
1538 	  white_to_move ^= 1;
1539 	  path_x[ply].cap_num = squares[target+12];
1540 	  pieces[squares[target+12]] = 0;
1541 	  squares[target+12] = 0;
1542 
1543 	  ply++;
1544 
1545 	  return;
1546 	}
1547 
1548 	/* otherwise, we have a "regular" pawn move: */
1549 	/* first check to see if we've moved a pawn down 2 squares: */
1550 	if (target == from-24)
1551 	  ep_square = from-12;
1552 
1553 	board[target] = bpawn;
1554 	board[from] = npiece;
1555 	moved[target]++;
1556 	moved[from]++;
1557 	white_to_move ^= 1;
1558 
1559 	Hash(bpawn, from);
1560 	Hash(bpawn, target);
1561 
1562         ply++;
1563 
1564 	return;
1565       }
1566 
1567       /* piece moves, other than the king: */
1568       if (board[from] != wking && board[from] != bking) {
1569 
1570 	Hash(board[from], from);
1571 	Hash(board[from], target);
1572 
1573 	board[target] = board[from];
1574 	board[from] = npiece;
1575 	moved[target]++;
1576 	moved[from]++;
1577 	white_to_move ^= 1;
1578 
1579 	ply++;
1580 
1581 	return;
1582       }
1583 
1584       /* otherwise, we have a king move of some kind: */
1585       /* White king moves first: */
1586       if (board[from] == wking) {
1587 	/* record the new white king location: */
1588 	wking_loc = target;
1589 
1590 	/* perform the white king's move: */
1591 	board[target] = wking;
1592 	board[from] = npiece;
1593 	moved[target]++;
1594 	moved[from]++;
1595 	white_to_move ^= 1;
1596 
1597 	Hash(wking, from);
1598 	Hash(wking, target);
1599 
1600 	/* check for castling: */
1601 	/* check for white kingside castling: */
1602 	if (castled == wck) {
1603 	  board[33] = npiece;
1604 	  board[31] = wrook;
1605 	  moved[33]++;
1606 	  moved[31]++;
1607 	  white_castled = wck;
1608 	  pieces[squares[33]] = 31;
1609 	  squares[31] = squares[33];
1610 	  squares[33] = 0;
1611 
1612 	  Hash(wrook, 33);
1613 	  Hash(wrook, 31);
1614 
1615           ply++;
1616 
1617 	  return;
1618 	}
1619 
1620 	/* check for white queenside castling: */
1621 	else if (castled == wcq) {
1622 	  board[26] = npiece;
1623 	  board[29] = wrook;
1624 	  moved[26]++;
1625 	  moved[29]++;
1626 	  white_castled = wcq;
1627 	  pieces[squares[26]] = 29;
1628 	  squares[29] = squares[26];
1629 	  squares[26] = 0;
1630 
1631 	  Hash(wrook, 26);
1632 	  Hash(wrook, 29);
1633 
1634           ply++;
1635 
1636 	  return;
1637 	}
1638 
1639 	ply++;
1640 
1641 	return;
1642       }
1643 
1644       /* now we have only black king moves left: */
1645       else {
1646 	/* record the new black king location: */
1647 	bking_loc = target;
1648 
1649 	/* perform the black king's move: */
1650 	board[target] = bking;
1651 	board[from] = npiece;
1652 	moved[target]++;
1653 	moved[from]++;
1654 	white_to_move ^= 1;
1655 
1656 	Hash(bking, from);
1657 	Hash(bking, target);
1658 
1659 	/* check for castling: */
1660 	/* check for black kingside castling: */
1661 	if (castled == bck) {
1662 	  board[117] = npiece;
1663 	  board[115] = brook;
1664 	  moved[117]++;
1665 	  moved[115]++;
1666 	  black_castled = bck;
1667 	  pieces[squares[117]] = 115;
1668 	  squares[115] = squares[117];
1669 	  squares[117] = 0;
1670 
1671 	  Hash(brook, 117);
1672 	  Hash(brook, 115);
1673 
1674 	  ply++;
1675 
1676 	  return;
1677 	}
1678 
1679 	/* check for black queenside castling: */
1680 	else if (castled == bcq) {
1681 	  board[110] = npiece;
1682 	  board[113] = brook;
1683 	  moved[110]++;
1684 	  moved[113]++;
1685 	  black_castled = bcq;
1686 	  pieces[squares[110]] = 113;
1687 	  squares[113] = squares[110];
1688 	  squares[110] = 0;
1689 
1690 	  Hash(brook, 110);
1691 	  Hash(brook, 113);
1692 
1693           ply++;
1694 
1695 	  return;
1696 	}
1697       }
1698     ply++;
1699 
1700     return;
1701   }
1702 }
1703 
add_move(int Ptarget,int Ppromoted)1704 void add_move(int Ptarget,
1705 	      int Ppromoted)
1706 {
1707   genfor[numb_moves].from = gfrom;
1708   genfor[numb_moves].target = Ptarget;
1709   genfor[numb_moves].captured = npiece;
1710   genfor[numb_moves].castled = no_castle;
1711   genfor[numb_moves].promoted = Ppromoted;
1712   genfor[numb_moves].ep = FALSE;
1713   numb_moves++;
1714 
1715   return;
1716 }
1717 
add_capture(int Ptarget,int Pcaptured,int Ppromoted,int Pep)1718 void add_capture(int Ptarget,
1719 		 int Pcaptured,
1720 		 int Ppromoted,
1721 		 int Pep)
1722 {
1723   if ((Variant != Suicide) && (Pcaptured == wking || Pcaptured == bking))
1724     {
1725       kingcap = TRUE;
1726       return;
1727     }
1728   else
1729     if (Pcaptured != npiece) fcaptures = TRUE;
1730 
1731   genfor[numb_moves].from = gfrom;
1732   genfor[numb_moves].target = Ptarget;
1733   genfor[numb_moves].captured = Pcaptured;
1734   genfor[numb_moves].castled = no_castle;
1735   genfor[numb_moves].promoted = Ppromoted;
1736   genfor[numb_moves].ep = Pep;
1737   numb_moves++;
1738 
1739   return;
1740 }
1741 
try_drop(int ptype)1742 void try_drop (int ptype)
1743 {
1744   genfor[numb_moves].from = 0;
1745   genfor[numb_moves].target = gfrom;
1746   genfor[numb_moves].captured = npiece;
1747   genfor[numb_moves].castled = no_castle;
1748   genfor[numb_moves].promoted = ptype;
1749   genfor[numb_moves].ep = FALSE;
1750   numb_moves++;
1751 
1752   return;
1753 }
1754 
push_king_castle(int Ptarget,int Pcastle_type)1755 void push_king_castle (int Ptarget, int Pcastle_type)
1756 {
1757   genfor[numb_moves].from = gfrom;
1758   genfor[numb_moves].target = Ptarget;
1759   genfor[numb_moves].captured = npiece;
1760   genfor[numb_moves].castled = Pcastle_type;
1761   genfor[numb_moves].promoted = 0;
1762   genfor[numb_moves].ep = FALSE;
1763   numb_moves++;
1764 
1765   return;
1766 }
1767 
push_king(int target)1768 void push_king (int target) {
1769 
1770   /* add king moves to the moves array */
1771 
1772   /* first see if the move will take the king off the board: */
1773   if (board[target] == frame)
1774     return;
1775 
1776   /* check to see if we have a non capture when in qsearch: */
1777   if (board[target] == npiece && captures)
1778     return;
1779 
1780   /* non-capture, 'normal' king moves: */
1781   if (board[target] == npiece) {
1782     add_move(target, 0);
1783     return;
1784   }
1785 
1786   /* 'normal' capture moves by the king: */
1787   else if ((board[target]&1) != (board[gfrom]&1)) {
1788     add_capture(target, board[target], 0, FALSE);
1789     return;
1790   }
1791 
1792   /* no more possible moves for the king, so return: */
1793   return;
1794 }
1795 
1796 
push_knighT(int target)1797 void push_knighT (int target) {
1798 
1799   /* add knight moves to the moves array */
1800 
1801   /* check to see if we have a non capture when in qsearch: */
1802   if (board[target] == npiece && captures)
1803     return;
1804 
1805   /* check for a non-capture knight move: */
1806   if (board[target] == npiece) {
1807     add_move(target, 0);
1808     return;
1809   }
1810 
1811   /* check for a capture knight move: */
1812   else if ((board[target]&1) != (board[gfrom]&1)) {
1813     add_capture(target, board[target], 0, FALSE);
1814     return;
1815   }
1816 
1817   /* no more possible moves left for the knight, so return: */
1818   return;
1819 }
1820 
1821 
push_pawn(int target,bool is_ep)1822 void push_pawn (int target, bool is_ep) {
1823 
1824   /* add pawn moves to the moves array */
1825 
1826   int captured_piece;
1827 
1828   /* check to see if it's an ep move: */
1829   if (is_ep) {
1830     if (board[gfrom] == wpawn) {
1831       add_capture(target, bpawn, 0, TRUE);
1832 	  return;
1833     }
1834     else {
1835       add_capture(target, wpawn, 0, TRUE);
1836       return;
1837     }
1838   }
1839 
1840   /* record which piece we are taking, so we don't have to compute it over
1841      and over again: */
1842   captured_piece = board[target];
1843 
1844   /* look for a white promotion move: */
1845   if (board[gfrom] == wpawn && rank(gfrom) == 7) {
1846     add_capture(target, captured_piece, wqueen, FALSE);
1847     add_capture(target, captured_piece, wrook, FALSE);
1848     add_capture(target, captured_piece, wbishop, FALSE);
1849     add_capture(target, captured_piece, wknight, FALSE);
1850     if (Variant == Suicide)
1851       add_capture(target, captured_piece, wking, FALSE);
1852     /* we've finished generating all the promotions: */
1853     return;
1854   }
1855 
1856   /* look for a black promotion move: */
1857   else if (board[gfrom] == bpawn && rank(gfrom) == 2) {
1858     add_capture(target, captured_piece, bqueen, FALSE);
1859     add_capture(target, captured_piece, brook, FALSE);
1860     add_capture(target, captured_piece, bbishop, FALSE);
1861     add_capture(target, captured_piece, bknight, FALSE);
1862     if (Variant == Suicide)
1863       add_capture(target, captured_piece, bking, FALSE);
1864     /* we've finished generating all the promotions: */
1865     return;
1866   }
1867 
1868   /* otherwise, we have a normal pawn move: */
1869   else {
1870     add_capture(target, captured_piece, 0, FALSE);
1871     return;
1872   }
1873 
1874   /* the function should never get here, but just for completeness: */
1875   return;
1876 }
1877 
push_pawn_simple(int target)1878 void push_pawn_simple (int target) {
1879 
1880   /* add pawn moves to the moves array */
1881 
1882   add_move(target, 0);
1883   return;
1884 }
1885 
push_slidE(int target)1886 void push_slidE (int target) {
1887 
1888   /* add moves for sliding pieces to the moves array */
1889 
1890   int offset;
1891   int mycolor;
1892 
1893   /* check to see if we have gone off the board first: */
1894 //  if (board[target] == frame)
1895  //   return;
1896 
1897   /* init variables: */
1898   offset = target - gfrom;
1899   mycolor = board[gfrom]&1;
1900 
1901   /* loop until we hit the edge of the board, or another piece: */
1902   do {
1903     /* case when the target is an empty square: */
1904     if (board[target] == npiece) {
1905       if (!captures) {
1906       add_move(target, 0);
1907       }
1908       target += offset;
1909     }
1910 
1911     /* case when an enemy piece is hit: */
1912     else if ((board[target]&1) != mycolor) {
1913       add_capture(target, board[target], 0, FALSE);
1914       break;
1915     }
1916 
1917     /* otherwise, we have hit a friendly piece (or edge of board): */
1918     else
1919       break;
1920   } while (board[target] != frame);
1921 
1922   /* we have finished generating all of the sliding moves, so return: */
1923   return;
1924 
1925 }
1926 
1927 
unmake(move_s moves[],int i)1928 void unmake (move_s moves[], int i) {
1929 
1930   /* un-make a move */
1931 
1932   /* rather than writing out from[i].from, from[i].target, etc. all over
1933      the place, just make a copy of them here: */
1934   int ep, from, target, captured, promoted, castled;
1935   ep = moves[i].ep;
1936   from = moves[i].from;
1937   target = moves[i].target;
1938   captured = moves[i].captured;
1939   promoted = moves[i].promoted;
1940   castled = moves[i].castled;
1941 
1942   //if ((moves[i].target == 0) || ((moves[i].target != 0) && (board[moves[i].target] == npiece)))
1943   //   DIE;
1944 
1945   ply--;
1946 
1947 //printf("%d ", ply);
1948 
1949   ep_square = path_x[ply].epsq;
1950 
1951   /* update the 50 move info: */
1952   fifty = path_x[ply].fifty;
1953 
1954   if (from == 0)   /* drop move */
1955     {
1956       /* Drop moves are hanled fully seperate because we exepect to encouter
1957 	 lots of them and we try to skip as many checks as possible.
1958 	 Note that the critical path for drop moves is very short.
1959 	 Also, we have to handle pieces[] and squares[] specially   */
1960 
1961        /* remove from piece array, unset piece-square pointer */
1962 
1963        pieces[squares[target]] = 0;
1964        is_promoted[squares[target]] = path_x[ply].was_promoted;
1965 
1966        /* unset square->piece pointer */
1967        squares[target] = 0;
1968   //     moved[target] = 0;
1969 
1970        piece_count--;
1971 
1972        assert(promoted < npiece && promoted > frame);
1973 
1974        DropaddHolding(promoted, NotToMove);
1975 
1976        RemoveMaterial(promoted);
1977 
1978        /* restore board, either no piece or ep square */
1979        board[target] = captured;
1980 
1981        Hash(promoted,target);
1982 
1983        white_to_move ^= 1;
1984 
1985        return;
1986     }
1987   else
1988     {
1989 
1990       /* update the "general" pieces[] / squares[] info (special moves need
1991 	 special handling later): */
1992 
1993       squares[from] = squares[target];
1994       squares[target] = path_x[ply].cap_num;
1995       pieces[squares[target]] = target;
1996       pieces[squares[from]] = from;
1997 
1998       is_promoted[squares[target]] = path_x[ply].was_promoted;
1999 
2000       /* update the piece count for determining opening/middlegame/endgame stage */
2001       if (!ep)
2002 	{
2003 	  switch (captured) {
2004 	  case (npiece): break;
2005 	  default:
2006 
2007 	    if (Variant == Bughouse || Variant == Crazyhouse)
2008 	      {
2009 		if (is_promoted[squares[target]])
2010 		  {
2011 		    removeHolding(SwitchPromoted(captured), NotToMove);
2012 		  }
2013 		else
2014 		  {
2015 		removeHolding(SwitchColor(captured), NotToMove);
2016 		  }
2017 	      }
2018 
2019 	    Hash(captured, target);
2020 
2021 	    AddMaterial(captured);
2022 
2023 	    piece_count++;
2024 	    break;
2025 	  }
2026 	}
2027 
2028       /* white pawn moves: */
2029       if (board[target] == wpawn) {
2030 	/* look for an en passant move: */
2031 	if (ep) {
2032 
2033 	  Hash(wpawn, target);
2034 	  Hash(wpawn, from);
2035 	  Hash(bpawn, target-12);
2036 
2037 	  board[target] = npiece;
2038 	  board[from] = wpawn;
2039 
2040 	  AddMaterial(bpawn);
2041 
2042 	  removeHolding(wpawn, WHITE);
2043 	  piece_count++;
2044 
2045 	  board[target-12] = bpawn;
2046 	  moved[target]--;
2047 	  moved[from]--;
2048 	  moved[target-12]--;
2049 	  white_to_move ^= 1;
2050 	  squares[target-12] = path_x[ply].cap_num;
2051 	  pieces[path_x[ply].cap_num] = target-12;
2052 	  squares[target] = 0;
2053 	  return;
2054 	}
2055 
2056 	/* otherwise, we have a "regular" pawn move: */
2057 	Hash(wpawn, from);
2058 	Hash(wpawn, target);
2059 
2060 	board[target] = captured;
2061 	board[from] = wpawn;
2062 	moved[target]--;
2063 	moved[from]--;
2064 	white_to_move ^= 1;
2065 	return;
2066 
2067       }
2068 
2069       /* black pawn moves: */
2070       if (board[target] == bpawn) {
2071 	/* look for an en passant move: */
2072 	if (ep) {
2073 
2074 	  Hash(bpawn, target);
2075 	  Hash(bpawn, from);
2076 	  Hash(wpawn, target+12);
2077 
2078 	  board[target] = npiece;
2079 	  board[from] = bpawn;
2080 
2081 	  AddMaterial(wpawn);
2082 
2083 	  removeHolding(bpawn, BLACK);
2084 	  piece_count++;
2085 
2086 	  board[target+12] = wpawn;
2087 	  moved[target]--;
2088 	  moved[from]--;
2089 	  moved[target+12]--;
2090 	  white_to_move ^= 1;
2091 	  squares[target+12] = path_x[ply].cap_num;
2092 	  pieces[path_x[ply].cap_num] = target+12;
2093 	  squares[target] = 0;
2094 	  return;
2095 	}
2096 
2097 	Hash(bpawn, from);
2098 	Hash(bpawn, target);
2099 
2100 	/* otherwise, we have a "regular" pawn move: */
2101 	board[target] = captured;
2102 	board[from] = bpawn;
2103 	moved[target]--;
2104 	moved[from]--;
2105 	white_to_move ^= 1;
2106 	return;
2107 
2108       }
2109 
2110       /* piece moves, other than the king: */
2111       if (board[target] != wking && board[target] != bking && !promoted) {
2112 	board[from] = board[target];
2113 	board[target] = captured;
2114 	moved[target]--;
2115 	moved[from]--;
2116 	white_to_move ^= 1;
2117 
2118 	Hash(board[from], target);
2119 	Hash(board[from], from);
2120 
2121 	return;
2122       }
2123 
2124       /* look for a promotion move: */
2125       if (promoted) {
2126 	/* white promotions: */
2127 	if (board[target]%2) {
2128 	  board[target] = captured;
2129 	  board[from] = wpawn;
2130 	  moved[target]--;
2131 	  moved[from]--;
2132 	  white_to_move ^= 1;
2133 
2134 	  Hash(wpawn, from);
2135 	  Hash(promoted, target);
2136 
2137 	  RemoveMaterial(promoted);
2138 	  AddMaterial(wpawn);
2139 
2140 	  return;
2141 	}
2142 
2143 	/* black promotions: */
2144 	board[target] = captured;
2145 	board[from] = bpawn;
2146 	moved[target]--;
2147 	moved[from]--;
2148 	white_to_move ^= 1;
2149 
2150 	Hash(bpawn, from);
2151 	Hash(promoted, target);
2152 
2153 	RemoveMaterial(promoted);
2154 	AddMaterial(bpawn);
2155 
2156 	return;
2157       }
2158 
2159       /* otherwise, we have a king move of some kind: */
2160       /* White king moves first: */
2161       if (board[target] == wking) {
2162 	/* record the new white king location: */
2163 	wking_loc = from;
2164 
2165 	/* perform the white king's move: */
2166 	board[target] = captured;
2167 	board[from] = wking;
2168 	moved[target]--;
2169 	moved[from]--;
2170 	white_to_move ^= 1;
2171 
2172 	Hash(wking, from);
2173 	Hash(wking, target);
2174 
2175 	/* check for castling: */
2176 	/* check for white kingside castling: */
2177 	if (castled == wck) {
2178 	  board[33] = wrook;
2179 	  board[31] = npiece;
2180 	  moved[33]--;
2181 	  moved[31]--;
2182 	  white_castled = no_castle;
2183 	  squares[33] = squares[31];
2184 	  squares[31] = 0;
2185 	  pieces[squares[33]] = 33;
2186 
2187 	  Hash(wrook, 33);
2188 	  Hash(wrook, 31);
2189 
2190 	  return;
2191 	}
2192 
2193 	/* check for white queenside castling: */
2194 	else if (castled == wcq) {
2195 	  board[26] = wrook;
2196 	  board[29] = npiece;
2197 	  moved[26]--;
2198 	  moved[29]--;
2199 	  white_castled = no_castle;
2200 	  squares[26] = squares[29];
2201 	  squares[29] = 0;
2202 	  pieces[squares[26]] = 26;
2203 
2204 	  Hash(wrook, 29);
2205 	  Hash(wrook, 26);
2206 
2207 	  return;
2208 	}
2209 
2210 	return;
2211       }
2212 
2213       /* now we have only black king moves left: */
2214       else {
2215 	/* record the new black king location: */
2216 	bking_loc = from;
2217 
2218 	/* perform the black king's move: */
2219 	board[target] = captured;
2220 	board[from] = bking;
2221 	moved[target]--;
2222 	moved[from]--;
2223 	white_to_move ^= 1;
2224 
2225 	Hash(bking, from);
2226 	Hash(bking, target);
2227 
2228 	/* check for castling: */
2229 	/* check for black kingside castling: */
2230 	if (castled == bck) {
2231 	  board[117] = brook;
2232 	  board[115] = npiece;
2233 	  moved[117]--;
2234 	  moved[115]--;
2235 	  black_castled = no_castle;
2236 	  squares[117] = squares[115];
2237 	  squares[115] = 0;
2238 	  pieces[squares[117]] = 117;
2239 
2240 	  Hash(brook, 117);
2241 	  Hash(brook, 115);
2242 
2243 	  return;
2244 	}
2245 
2246 	/* check for black queenside castling: */
2247 	else if (castled == bcq) {
2248 	  board[110] = brook;
2249 	  board[113] = npiece;
2250 	  moved[110]--;
2251 	  moved[113]--;
2252 	  black_castled = no_castle;
2253 	  squares[110] = squares[113];
2254 	  squares[113] = 0;
2255 	  pieces[squares[110]] = 110;
2256 
2257 	  Hash(brook, 110);
2258 	  Hash(brook, 113);
2259 
2260 	  return;
2261 	}
2262       }
2263     }
2264   return;
2265 }
2266