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
28uint32_t total_moves;
29uint32_t total_movegens;
30
31int numb_moves;
32static move_s *genfor;
33
34int fcaptures;
35int gfrom;
36
37int kingcap; /* break if we capture the king */
38
39bool 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
453void 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
470restart:
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
793bool 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
814bool 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
1225int 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
1292void 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      is_promoted[find_slot] = 0;
1345
1346      /* set square->piece pointer */
1347      squares[target] = find_slot;
1348    //  moved[target] = 1;
1349
1350      //if (promoted <= frame || promoted >= npiece)
1351     // 	DIE;
1352
1353      assert(promoted > frame && promoted < npiece);
1354
1355      DropremoveHolding(promoted, ToMove);
1356
1357      /* piece went off holding but onto board */
1358      AddMaterial(promoted);
1359
1360      /* put our piece on the board */
1361      board[target] = promoted;
1362
1363      Hash(promoted,target);
1364
1365      white_to_move ^= 1;
1366      ply++;
1367
1368      return;
1369    }
1370  else
1371    {
1372
1373
1374      /* update the "general" pieces[] / squares[] info (special moves need
1375	 special handling later): */
1376      path_x[ply].cap_num = squares[target];
1377      path_x[ply].was_promoted = is_promoted[squares[target]];
1378      pieces[squares[target]] = 0;
1379      pieces[squares[from]] = target;
1380      squares[target] = squares[from];
1381      squares[from] = 0;
1382
1383      /* update the piece count & add Holdings */
1384      if (!ep)
1385      {
1386	switch (board[target]) {
1387	case (npiece): break;
1388	default:
1389
1390	  if (Variant == Bughouse || Variant == Crazyhouse)
1391	    {
1392	      if (path_x[ply].was_promoted)
1393	    	{
1394		  addHolding(SwitchPromoted(board[target]), ToMove);
1395	    	}
1396	      else
1397	    	{
1398		  addHolding(SwitchColor(board[target]), ToMove);
1399	    	}
1400	    }
1401
1402	  RemoveMaterial(board[target]);
1403
1404	  /* remove captured piece */
1405	  Hash(board[target], target);
1406
1407	  piece_count--;
1408	  break;
1409	}
1410      }
1411
1412      /* white pawn moves: */
1413      if (board[from] == wpawn) {
1414	/* look for a promotion move: */
1415	if (promoted) {
1416	  board[target] = promoted;
1417	  board[from] = npiece;
1418	  moved[target]++;
1419	  moved[from]++;
1420	  white_to_move ^= 1;
1421
1422	  is_promoted[squares[target]] = 1;
1423
1424	  /* remove pawn */
1425	  Hash(wpawn, from);
1426	  /* add new stuff */
1427	  Hash(promoted, target);
1428
1429	  RemoveMaterial(wpawn);
1430	  AddMaterial(promoted);
1431
1432	  ply++;
1433
1434	  return;
1435	}
1436
1437	/* look for an en passant move: */
1438	if (ep) {
1439
1440	  /* remove pawn */
1441	  Hash(wpawn, from);
1442	  /* remove ep pawn */
1443	  Hash(bpawn, target-12);
1444	  /* add target pawn */
1445	  Hash(wpawn, target);
1446
1447	  RemoveMaterial(bpawn);
1448
1449	  board[target] = wpawn;
1450	  board[from] = npiece;
1451
1452	  addHolding(wpawn, WHITE);
1453	  piece_count--;
1454
1455	  board[target-12] = npiece;
1456	  moved[target]++;
1457	  moved[from]++;
1458	  moved[target-12]++;
1459	  white_to_move ^= 1;
1460	  path_x[ply].cap_num = squares[target-12];
1461          path_x[ply].was_promoted = 0;
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          path_x[ply].was_promoted = 0;
1541	  pieces[squares[target+12]] = 0;
1542	  squares[target+12] = 0;
1543
1544	  ply++;
1545
1546	  return;
1547	}
1548
1549	/* otherwise, we have a "regular" pawn move: */
1550	/* first check to see if we've moved a pawn down 2 squares: */
1551	if (target == from-24)
1552	  ep_square = from-12;
1553
1554	board[target] = bpawn;
1555	board[from] = npiece;
1556	moved[target]++;
1557	moved[from]++;
1558	white_to_move ^= 1;
1559
1560	Hash(bpawn, from);
1561	Hash(bpawn, target);
1562
1563        ply++;
1564
1565	return;
1566      }
1567
1568      /* piece moves, other than the king: */
1569      if (board[from] != wking && board[from] != bking) {
1570
1571	Hash(board[from], from);
1572	Hash(board[from], target);
1573
1574	board[target] = board[from];
1575	board[from] = npiece;
1576	moved[target]++;
1577	moved[from]++;
1578	white_to_move ^= 1;
1579
1580	ply++;
1581
1582	return;
1583      }
1584
1585      /* otherwise, we have a king move of some kind: */
1586      /* White king moves first: */
1587      if (board[from] == wking) {
1588	/* record the new white king location: */
1589	wking_loc = target;
1590
1591	/* perform the white king's move: */
1592	board[target] = wking;
1593	board[from] = npiece;
1594	moved[target]++;
1595	moved[from]++;
1596	white_to_move ^= 1;
1597
1598	Hash(wking, from);
1599	Hash(wking, target);
1600
1601	/* check for castling: */
1602	/* check for white kingside castling: */
1603	if (castled == wck) {
1604	  board[33] = npiece;
1605	  board[31] = wrook;
1606	  moved[33]++;
1607	  moved[31]++;
1608	  white_castled = wck;
1609	  pieces[squares[33]] = 31;
1610	  squares[31] = squares[33];
1611	  squares[33] = 0;
1612
1613	  Hash(wrook, 33);
1614	  Hash(wrook, 31);
1615
1616          ply++;
1617
1618	  return;
1619	}
1620
1621	/* check for white queenside castling: */
1622	else if (castled == wcq) {
1623	  board[26] = npiece;
1624	  board[29] = wrook;
1625	  moved[26]++;
1626	  moved[29]++;
1627	  white_castled = wcq;
1628	  pieces[squares[26]] = 29;
1629	  squares[29] = squares[26];
1630	  squares[26] = 0;
1631
1632	  Hash(wrook, 26);
1633	  Hash(wrook, 29);
1634
1635          ply++;
1636
1637	  return;
1638	}
1639
1640	ply++;
1641
1642	return;
1643      }
1644
1645      /* now we have only black king moves left: */
1646      else {
1647	/* record the new black king location: */
1648	bking_loc = target;
1649
1650	/* perform the black king's move: */
1651	board[target] = bking;
1652	board[from] = npiece;
1653	moved[target]++;
1654	moved[from]++;
1655	white_to_move ^= 1;
1656
1657	Hash(bking, from);
1658	Hash(bking, target);
1659
1660	/* check for castling: */
1661	/* check for black kingside castling: */
1662	if (castled == bck) {
1663	  board[117] = npiece;
1664	  board[115] = brook;
1665	  moved[117]++;
1666	  moved[115]++;
1667	  black_castled = bck;
1668	  pieces[squares[117]] = 115;
1669	  squares[115] = squares[117];
1670	  squares[117] = 0;
1671
1672	  Hash(brook, 117);
1673	  Hash(brook, 115);
1674
1675	  ply++;
1676
1677	  return;
1678	}
1679
1680	/* check for black queenside castling: */
1681	else if (castled == bcq) {
1682	  board[110] = npiece;
1683	  board[113] = brook;
1684	  moved[110]++;
1685	  moved[113]++;
1686	  black_castled = bcq;
1687	  pieces[squares[110]] = 113;
1688	  squares[113] = squares[110];
1689	  squares[110] = 0;
1690
1691	  Hash(brook, 110);
1692	  Hash(brook, 113);
1693
1694          ply++;
1695
1696	  return;
1697	}
1698      }
1699    ply++;
1700
1701    return;
1702  }
1703}
1704
1705void add_move(int Ptarget,
1706	      int Ppromoted)
1707{
1708  genfor[numb_moves].from = gfrom;
1709  genfor[numb_moves].target = Ptarget;
1710  genfor[numb_moves].captured = npiece;
1711  genfor[numb_moves].castled = no_castle;
1712  genfor[numb_moves].promoted = Ppromoted;
1713  genfor[numb_moves].ep = FALSE;
1714  numb_moves++;
1715
1716  return;
1717}
1718
1719void add_capture(int Ptarget,
1720		 int Pcaptured,
1721		 int Ppromoted,
1722		 int Pep)
1723{
1724  if ((Variant != Suicide) && (Pcaptured == wking || Pcaptured == bking))
1725    {
1726      kingcap = TRUE;
1727      return;
1728    }
1729  else
1730    if (Pcaptured != npiece) fcaptures = TRUE;
1731
1732  genfor[numb_moves].from = gfrom;
1733  genfor[numb_moves].target = Ptarget;
1734  genfor[numb_moves].captured = Pcaptured;
1735  genfor[numb_moves].castled = no_castle;
1736  genfor[numb_moves].promoted = Ppromoted;
1737  genfor[numb_moves].ep = Pep;
1738  numb_moves++;
1739
1740  return;
1741}
1742
1743void try_drop (int ptype)
1744{
1745  genfor[numb_moves].from = 0;
1746  genfor[numb_moves].target = gfrom;
1747  genfor[numb_moves].captured = npiece;
1748  genfor[numb_moves].castled = no_castle;
1749  genfor[numb_moves].promoted = ptype;
1750  genfor[numb_moves].ep = FALSE;
1751  numb_moves++;
1752
1753  return;
1754}
1755
1756void push_king_castle (int Ptarget, int Pcastle_type)
1757{
1758  genfor[numb_moves].from = gfrom;
1759  genfor[numb_moves].target = Ptarget;
1760  genfor[numb_moves].captured = npiece;
1761  genfor[numb_moves].castled = Pcastle_type;
1762  genfor[numb_moves].promoted = 0;
1763  genfor[numb_moves].ep = FALSE;
1764  numb_moves++;
1765
1766  return;
1767}
1768
1769void push_king (int target) {
1770
1771  /* add king moves to the moves array */
1772
1773  /* first see if the move will take the king off the board: */
1774  if (board[target] == frame)
1775    return;
1776
1777  /* check to see if we have a non capture when in qsearch: */
1778  if (board[target] == npiece && captures)
1779    return;
1780
1781  /* non-capture, 'normal' king moves: */
1782  if (board[target] == npiece) {
1783    add_move(target, 0);
1784    return;
1785  }
1786
1787  /* 'normal' capture moves by the king: */
1788  else if ((board[target]&1) != (board[gfrom]&1)) {
1789    add_capture(target, board[target], 0, FALSE);
1790    return;
1791  }
1792
1793  /* no more possible moves for the king, so return: */
1794  return;
1795}
1796
1797
1798void push_knighT (int target) {
1799
1800  /* add knight moves to the moves array */
1801
1802  /* check to see if we have a non capture when in qsearch: */
1803  if (board[target] == npiece && captures)
1804    return;
1805
1806  /* check for a non-capture knight move: */
1807  if (board[target] == npiece) {
1808    add_move(target, 0);
1809    return;
1810  }
1811
1812  /* check for a capture knight move: */
1813  else if ((board[target]&1) != (board[gfrom]&1)) {
1814    add_capture(target, board[target], 0, FALSE);
1815    return;
1816  }
1817
1818  /* no more possible moves left for the knight, so return: */
1819  return;
1820}
1821
1822
1823void push_pawn (int target, bool is_ep) {
1824
1825  /* add pawn moves to the moves array */
1826
1827  int captured_piece;
1828
1829  /* check to see if it's an ep move: */
1830  if (is_ep) {
1831    if (board[gfrom] == wpawn) {
1832      add_capture(target, bpawn, 0, TRUE);
1833	  return;
1834    }
1835    else {
1836      add_capture(target, wpawn, 0, TRUE);
1837      return;
1838    }
1839  }
1840
1841  /* record which piece we are taking, so we don't have to compute it over
1842     and over again: */
1843  captured_piece = board[target];
1844
1845  /* look for a white promotion move: */
1846  if (board[gfrom] == wpawn && rank(gfrom) == 7) {
1847    add_capture(target, captured_piece, wqueen, FALSE);
1848    add_capture(target, captured_piece, wrook, FALSE);
1849    add_capture(target, captured_piece, wbishop, FALSE);
1850    add_capture(target, captured_piece, wknight, FALSE);
1851    if (Variant == Suicide)
1852      add_capture(target, captured_piece, wking, FALSE);
1853    /* we've finished generating all the promotions: */
1854    return;
1855  }
1856
1857  /* look for a black promotion move: */
1858  else if (board[gfrom] == bpawn && rank(gfrom) == 2) {
1859    add_capture(target, captured_piece, bqueen, FALSE);
1860    add_capture(target, captured_piece, brook, FALSE);
1861    add_capture(target, captured_piece, bbishop, FALSE);
1862    add_capture(target, captured_piece, bknight, FALSE);
1863    if (Variant == Suicide)
1864      add_capture(target, captured_piece, bking, FALSE);
1865    /* we've finished generating all the promotions: */
1866    return;
1867  }
1868
1869  /* otherwise, we have a normal pawn move: */
1870  else {
1871    add_capture(target, captured_piece, 0, FALSE);
1872    return;
1873  }
1874
1875  /* the function should never get here, but just for completeness: */
1876  return;
1877}
1878
1879void push_pawn_simple (int target) {
1880
1881  /* add pawn moves to the moves array */
1882
1883  add_move(target, 0);
1884  return;
1885}
1886
1887void push_slidE (int target) {
1888
1889  /* add moves for sliding pieces to the moves array */
1890
1891  int offset;
1892  int mycolor;
1893
1894  /* check to see if we have gone off the board first: */
1895//  if (board[target] == frame)
1896 //   return;
1897
1898  /* init variables: */
1899  offset = target - gfrom;
1900  mycolor = board[gfrom]&1;
1901
1902  /* loop until we hit the edge of the board, or another piece: */
1903  do {
1904    /* case when the target is an empty square: */
1905    if (board[target] == npiece) {
1906      if (!captures) {
1907      add_move(target, 0);
1908      }
1909      target += offset;
1910    }
1911
1912    /* case when an enemy piece is hit: */
1913    else if ((board[target]&1) != mycolor) {
1914      add_capture(target, board[target], 0, FALSE);
1915      break;
1916    }
1917
1918    /* otherwise, we have hit a friendly piece (or edge of board): */
1919    else
1920      break;
1921  } while (board[target] != frame);
1922
1923  /* we have finished generating all of the sliding moves, so return: */
1924  return;
1925
1926}
1927
1928
1929void unmake (move_s moves[], int i) {
1930
1931  /* un-make a move */
1932
1933  /* rather than writing out from[i].from, from[i].target, etc. all over
1934     the place, just make a copy of them here: */
1935  int ep, from, target, captured, promoted, castled;
1936  ep = moves[i].ep;
1937  from = moves[i].from;
1938  target = moves[i].target;
1939  captured = moves[i].captured;
1940  promoted = moves[i].promoted;
1941  castled = moves[i].castled;
1942
1943  //if ((moves[i].target == 0) || ((moves[i].target != 0) && (board[moves[i].target] == npiece)))
1944  //   DIE;
1945
1946  ply--;
1947
1948//printf("%d ", ply);
1949
1950  ep_square = path_x[ply].epsq;
1951
1952  /* update the 50 move info: */
1953  fifty = path_x[ply].fifty;
1954
1955  if (from == 0)   /* drop move */
1956    {
1957      /* Drop moves are hanled fully seperate because we exepect to encouter
1958	 lots of them and we try to skip as many checks as possible.
1959	 Note that the critical path for drop moves is very short.
1960	 Also, we have to handle pieces[] and squares[] specially   */
1961
1962       /* remove from piece array, unset piece-square pointer */
1963
1964       pieces[squares[target]] = 0;
1965       assert(is_promoted[squares[target]] == 0);
1966
1967       /* unset square->piece pointer */
1968       squares[target] = 0;
1969  //     moved[target] = 0;
1970
1971       piece_count--;
1972
1973       assert(promoted < npiece && promoted > frame);
1974
1975       DropaddHolding(promoted, NotToMove);
1976
1977       RemoveMaterial(promoted);
1978
1979       /* restore board, either no piece or ep square */
1980       board[target] = captured;
1981
1982       Hash(promoted,target);
1983
1984       white_to_move ^= 1;
1985
1986       return;
1987    }
1988  else
1989    {
1990
1991      /* update the "general" pieces[] / squares[] info (special moves need
1992	 special handling later): */
1993
1994      squares[from] = squares[target];
1995      squares[target] = path_x[ply].cap_num;
1996      is_promoted[squares[target]] = path_x[ply].was_promoted;
1997      pieces[squares[target]] = target;
1998      pieces[squares[from]] = from;
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          is_promoted[path_x[ply].cap_num] = path_x[ply].was_promoted;
2052	  pieces[path_x[ply].cap_num] = target-12;
2053	  squares[target] = 0;
2054	  return;
2055	}
2056
2057	/* otherwise, we have a "regular" pawn move: */
2058	Hash(wpawn, from);
2059	Hash(wpawn, target);
2060
2061	board[target] = captured;
2062	board[from] = wpawn;
2063	moved[target]--;
2064	moved[from]--;
2065	white_to_move ^= 1;
2066	return;
2067
2068      }
2069
2070      /* black pawn moves: */
2071      if (board[target] == bpawn) {
2072	/* look for an en passant move: */
2073	if (ep) {
2074
2075	  Hash(bpawn, target);
2076	  Hash(bpawn, from);
2077	  Hash(wpawn, target+12);
2078
2079	  board[target] = npiece;
2080	  board[from] = bpawn;
2081
2082	  AddMaterial(wpawn);
2083
2084	  removeHolding(bpawn, BLACK);
2085	  piece_count++;
2086
2087	  board[target+12] = wpawn;
2088	  moved[target]--;
2089	  moved[from]--;
2090	  moved[target+12]--;
2091	  white_to_move ^= 1;
2092	  squares[target+12] = path_x[ply].cap_num;
2093          is_promoted[path_x[ply].cap_num] = path_x[ply].was_promoted;
2094	  pieces[path_x[ply].cap_num] = target+12;
2095	  squares[target] = 0;
2096	  return;
2097	}
2098
2099	Hash(bpawn, from);
2100	Hash(bpawn, target);
2101
2102	/* otherwise, we have a "regular" pawn move: */
2103	board[target] = captured;
2104	board[from] = bpawn;
2105	moved[target]--;
2106	moved[from]--;
2107	white_to_move ^= 1;
2108	return;
2109
2110      }
2111
2112      /* piece moves, other than the king: */
2113      if (board[target] != wking && board[target] != bking && !promoted) {
2114	board[from] = board[target];
2115	board[target] = captured;
2116	moved[target]--;
2117	moved[from]--;
2118	white_to_move ^= 1;
2119
2120	Hash(board[from], target);
2121	Hash(board[from], from);
2122
2123	return;
2124      }
2125
2126      /* look for a promotion move: */
2127      if (promoted) {
2128	/* white promotions: */
2129	if (board[target]%2) {
2130	  board[target] = captured;
2131	  board[from] = wpawn;
2132	  moved[target]--;
2133	  moved[from]--;
2134	  white_to_move ^= 1;
2135
2136          is_promoted[squares[from]] = 0;
2137
2138	  Hash(wpawn, from);
2139	  Hash(promoted, target);
2140
2141	  RemoveMaterial(promoted);
2142	  AddMaterial(wpawn);
2143
2144	  return;
2145	}
2146
2147	/* black promotions: */
2148	board[target] = captured;
2149	board[from] = bpawn;
2150	moved[target]--;
2151	moved[from]--;
2152	white_to_move ^= 1;
2153
2154        is_promoted[squares[from]] = 0;
2155
2156	Hash(bpawn, from);
2157	Hash(promoted, target);
2158
2159	RemoveMaterial(promoted);
2160	AddMaterial(bpawn);
2161
2162	return;
2163      }
2164
2165      /* otherwise, we have a king move of some kind: */
2166      /* White king moves first: */
2167      if (board[target] == wking) {
2168	/* record the new white king location: */
2169	wking_loc = from;
2170
2171	/* perform the white king's move: */
2172	board[target] = captured;
2173	board[from] = wking;
2174	moved[target]--;
2175	moved[from]--;
2176	white_to_move ^= 1;
2177
2178	Hash(wking, from);
2179	Hash(wking, target);
2180
2181	/* check for castling: */
2182	/* check for white kingside castling: */
2183	if (castled == wck) {
2184	  board[33] = wrook;
2185	  board[31] = npiece;
2186	  moved[33]--;
2187	  moved[31]--;
2188	  white_castled = no_castle;
2189	  squares[33] = squares[31];
2190	  squares[31] = 0;
2191	  pieces[squares[33]] = 33;
2192
2193	  Hash(wrook, 33);
2194	  Hash(wrook, 31);
2195
2196	  return;
2197	}
2198
2199	/* check for white queenside castling: */
2200	else if (castled == wcq) {
2201	  board[26] = wrook;
2202	  board[29] = npiece;
2203	  moved[26]--;
2204	  moved[29]--;
2205	  white_castled = no_castle;
2206	  squares[26] = squares[29];
2207	  squares[29] = 0;
2208	  pieces[squares[26]] = 26;
2209
2210	  Hash(wrook, 29);
2211	  Hash(wrook, 26);
2212
2213	  return;
2214	}
2215
2216	return;
2217      }
2218
2219      /* now we have only black king moves left: */
2220      else {
2221	/* record the new black king location: */
2222	bking_loc = from;
2223
2224	/* perform the black king's move: */
2225	board[target] = captured;
2226	board[from] = bking;
2227	moved[target]--;
2228	moved[from]--;
2229	white_to_move ^= 1;
2230
2231	Hash(bking, from);
2232	Hash(bking, target);
2233
2234	/* check for castling: */
2235	/* check for black kingside castling: */
2236	if (castled == bck) {
2237	  board[117] = brook;
2238	  board[115] = npiece;
2239	  moved[117]--;
2240	  moved[115]--;
2241	  black_castled = no_castle;
2242	  squares[117] = squares[115];
2243	  squares[115] = 0;
2244	  pieces[squares[117]] = 117;
2245
2246	  Hash(brook, 117);
2247	  Hash(brook, 115);
2248
2249	  return;
2250	}
2251
2252	/* check for black queenside castling: */
2253	else if (castled == bcq) {
2254	  board[110] = brook;
2255	  board[113] = npiece;
2256	  moved[110]--;
2257	  moved[113]--;
2258	  black_castled = no_castle;
2259	  squares[110] = squares[113];
2260	  squares[113] = 0;
2261	  pieces[squares[110]] = 110;
2262
2263	  Hash(brook, 110);
2264	  Hash(brook, 113);
2265
2266	  return;
2267	}
2268      }
2269    }
2270  return;
2271}
2272