/*>>> sangen.c: SAN project move generation routines */

/* Revised: 1993.05.16 */

#include <stdio.h>
#include <time.h>

#include "sandef.h"
#include "sanvar.h"

#include "sanatk.h"
#include "sangen.h"
#include "sanmer.h"
#include "sanmlm.h"
#include "sansrt.h"
#include "sanutl.h"

/* the generated move template */

static mT gm;

/*--> SANGenCaptPL: generate psuedolegal capture moves */
nonstatic
void
SANGenCaptPL (void)
{
  siT i, n;
  dxT dx;
  dvT dv;
  xdvT xdv;
  xsqptrT xsqptr0, xsqptr1;
  fileT frfile;
  rankT frrank;

/* set up current generation items */

  if (an == 0)
    curr_g.g_strt = 0;
  else
    curr_g.g_strt = av[an - 1].a_g.g_strt + av[an - 1].a_g.g_gmvc;

  curr_g.g_curr = curr_g.g_base = &Tree[curr_g.g_strt];
  curr_g.g_gmvc = 0;
  curr_g.g_flag = gf_capt;

/* set the psuedoinvariant generated move template components */

  gm.m_scmv = scmv_reg;
  gm.m_eval = ev_bust;
  gm.m_flag = 0;

/* look at each origin square of the active color */

  n = plnv[curr_e.e_actc];
  for (i = 0; i < n; i++)
    {
      /* get origin square and moving piece */

      gm.m_frcp = gb.bv[gm.m_frsq = plv[curr_e.e_actc][i]];

      /* generate moves for active color piece */

      xsqptr0 = &gxb.xbv[map_xsq_sq (gm.m_frsq)];
      switch (cv_p_cpv[gm.m_frcp])
	{
	case p_p:
	  /* pawn moves: a bit tricky; colors done separately */

	  frfile = map_file_sq (gm.m_frsq);
	  frrank = map_rank_sq (gm.m_frsq);
	  if (curr_e.e_actc == c_w)
	    {
	      /* one square non-capture promote */

	      gm.m_tocp = gb.bv[gm.m_tosq = gm.m_frsq + dv_1];
	      if (gm.m_tocp == cp_v0)
		if (frrank == rank_7)
		  {
		    /* promotion */

		    for (gm.m_scmv = scmv_ppn;
			 gm.m_scmv <= scmv_ppq; gm.m_scmv++)
		      {
			*curr_g.g_curr++ = gm;
			curr_g.g_gmvc++;
		      }
		    gm.m_scmv = scmv_reg;
		  };

	      /* capture to left */

	      if (frfile != file_a)
		{
		  gm.m_tosq = gm.m_frsq + dv_5;
		  gm.m_tocp = gb.bv[gm.m_tosq];
		  if (cv_c_cpv[gm.m_tocp] == curr_e.e_pasc)
		    if (frrank != rank_7)
		      {
			/* non-promote */

			*curr_g.g_curr++ = gm;
			curr_g.g_gmvc++;
		      }
		    else
		      {
			/* promote */

			for (gm.m_scmv = scmv_ppn;
			     gm.m_scmv <= scmv_ppq; gm.m_scmv++)
			  {
			    *curr_g.g_curr++ = gm;
			    curr_g.g_gmvc++;
			  };
			gm.m_scmv = scmv_reg;
		      };
		};

	      /* capture to right */

	      if (frfile != file_h)
		{
		  gm.m_tosq = gm.m_frsq + dv_4;
		  gm.m_tocp = gb.bv[gm.m_tosq];
		  if (cv_c_cpv[gm.m_tocp] == curr_e.e_pasc)
		    if (frrank != rank_7)
		      {
			/* non-promote */

			*curr_g.g_curr++ = gm;
			curr_g.g_gmvc++;
		      }
		    else
		      {
			/* promote */

			for (gm.m_scmv = scmv_ppn;
			     gm.m_scmv <= scmv_ppq; gm.m_scmv++)
			  {
			    *curr_g.g_curr++ = gm;
			    curr_g.g_gmvc++;
			  };
			gm.m_scmv = scmv_reg;
		      };
		};

	      /* en passant */

	      if ((frrank == rank_5) && (curr_e.e_epsq != sq_nil))
		{
		  /* capture to left */

		  if ((frfile != file_a) &&
		      ((gm.m_tosq = gm.m_frsq + dv_5) == curr_e.e_epsq))
		    {
		      gm.m_tocp = cp_v0;
		      gm.m_scmv = scmv_epc;
		      *curr_g.g_curr++ = gm;
		      curr_g.g_gmvc++;
		      gm.m_scmv = scmv_reg;
		    };

		  /* capture to right */

		  if ((frfile != file_h) &&
		      ((gm.m_tosq = gm.m_frsq + dv_4) == curr_e.e_epsq))
		    {
		      gm.m_tocp = cp_v0;
		      gm.m_scmv = scmv_epc;
		      *curr_g.g_curr++ = gm;
		      curr_g.g_gmvc++;
		      gm.m_scmv = scmv_reg;
		    };
		};
	    }
	  else
	    {
	      /* one square non-capture promote */

	      gm.m_tocp = gb.bv[gm.m_tosq = gm.m_frsq + dv_3];
	      if (gm.m_tocp == cp_v0)
		if (frrank == rank_2)
		  {
		    /* promotion */

		    for (gm.m_scmv = scmv_ppn;
			 gm.m_scmv <= scmv_ppq; gm.m_scmv++)
		      {
			*curr_g.g_curr++ = gm;
			curr_g.g_gmvc++;
		      }
		    gm.m_scmv = scmv_reg;
		  };

	      /* capture to left */

	      if (frfile != file_a)
		{
		  gm.m_tosq = gm.m_frsq + dv_6;
		  gm.m_tocp = gb.bv[gm.m_tosq];
		  if (cv_c_cpv[gm.m_tocp] == curr_e.e_pasc)
		    if (frrank != rank_2)
		      {
			/* non-promote */

			*curr_g.g_curr++ = gm;
			curr_g.g_gmvc++;
		      }
		    else
		      {
			/* promote */

			for (gm.m_scmv = scmv_ppn;
			     gm.m_scmv <= scmv_ppq; gm.m_scmv++)
			  {
			    *curr_g.g_curr++ = gm;
			    curr_g.g_gmvc++;
			  };
			gm.m_scmv = scmv_reg;
		      };
		};

	      /* capture to right */

	      if (frfile != file_h)
		{
		  gm.m_tosq = gm.m_frsq + dv_7;
		  gm.m_tocp = gb.bv[gm.m_tosq];
		  if (cv_c_cpv[gm.m_tocp] == curr_e.e_pasc)
		    if (frrank != rank_2)
		      {
			/* non-promote */

			*curr_g.g_curr++ = gm;
			curr_g.g_gmvc++;
		      }
		    else
		      {
			/* promote */

			for (gm.m_scmv = scmv_ppn;
			     gm.m_scmv <= scmv_ppq; gm.m_scmv++)
			  {
			    *curr_g.g_curr++ = gm;
			    curr_g.g_gmvc++;
			  };
			gm.m_scmv = scmv_reg;
		      };
		};

	      /* en passant */

	      if ((frrank == rank_4) && (curr_e.e_epsq != sq_nil))
		{
		  /* capture to left */

		  if ((frfile != file_a) &&
		      ((gm.m_tosq = gm.m_frsq + dv_6) == curr_e.e_epsq))
		    {
		      gm.m_tocp = cp_v0;
		      gm.m_scmv = scmv_epc;
		      *curr_g.g_curr++ = gm;
		      curr_g.g_gmvc++;
		      gm.m_scmv = scmv_reg;
		    };

		  /* capture to right */

		  if ((frfile != file_h) &&
		      ((gm.m_tosq = gm.m_frsq + dv_7) == curr_e.e_epsq))
		    {
		      gm.m_tocp = cp_v0;
		      gm.m_scmv = scmv_epc;
		      *curr_g.g_curr++ = gm;
		      curr_g.g_gmvc++;
		      gm.m_scmv = scmv_reg;
		    };
		};
	    };
	  break;

	case p_n:
	  /* knight moves: very simple */

	  for (dx = dx_8; dx <= dx_f; dx++)
	    if (*(xsqptr0 + xdvv[dx]) == cp_v0)
	      {
		gm.m_tocp = gb.bv[gm.m_tosq = gm.m_frsq + dvv[dx]];
		if (cv_c_cpv[gm.m_tocp] == curr_e.e_pasc)
		  {
		    *curr_g.g_curr++ = gm;
		    curr_g.g_gmvc++;
		  };
	      };
	  break;

	case p_b:
	  /* bishop moves: diagonal sweeper */

	  for (dx = dx_4; dx <= dx_7; dx++)
	    {
	      dv = dvv[dx];
	      xdv = xdvv[dx];
	      gm.m_tosq = gm.m_frsq;
	      xsqptr1 = xsqptr0;
	      while ((*(xsqptr1 += xdv) == cp_v0) &&
		     ((gm.m_tocp = gb.bv[gm.m_tosq += dv]) == cp_v0))
		;
	      if ((*xsqptr1 == cp_v0) &&
		  (cv_c_cpv[gm.m_tocp] == curr_e.e_pasc))
		{
		  *curr_g.g_curr++ = gm;
		  curr_g.g_gmvc++;
		};
	    };
	  break;

	case p_r:
	  /* rook moves: orthogonal sweeper */

	  for (dx = dx_0; dx <= dx_3; dx++)
	    {
	      dv = dvv[dx];
	      xdv = xdvv[dx];
	      gm.m_tosq = gm.m_frsq;
	      xsqptr1 = xsqptr0;
	      while ((*(xsqptr1 += xdv) == cp_v0) &&
		     ((gm.m_tocp = gb.bv[gm.m_tosq += dv]) == cp_v0))
		;
	      if ((*xsqptr1 == cp_v0) &&
		  (cv_c_cpv[gm.m_tocp] == curr_e.e_pasc))
		{
		  *curr_g.g_curr++ = gm;
		  curr_g.g_gmvc++;
		};
	    };
	  break;

	case p_q:
	  /* queen moves: orthogonal and diagonal sweeper */

	  for (dx = dx_0; dx <= dx_7; dx++)
	    {
	      dv = dvv[dx];
	      xdv = xdvv[dx];
	      gm.m_tosq = gm.m_frsq;
	      xsqptr1 = xsqptr0;
	      while ((*(xsqptr1 += xdv) == cp_v0) &&
		     ((gm.m_tocp = gb.bv[gm.m_tosq += dv]) == cp_v0))
		;
	      if ((*xsqptr1 == cp_v0) &&
		  (cv_c_cpv[gm.m_tocp] == curr_e.e_pasc))
		{
		  *curr_g.g_curr++ = gm;
		  curr_g.g_gmvc++;
		};
	    };
	  break;

	case p_k:
	  /* king moves: one square adjacent captures */

	  for (dx = dx_0; dx <= dx_7; dx++)
	    if (*(xsqptr0 + xdvv[dx]) == cp_v0)
	      {
		gm.m_tocp = gb.bv[gm.m_tosq = gm.m_frsq + dvv[dx]];
		if (cv_c_cpv[gm.m_tocp] == curr_e.e_pasc)
		  {
		    *curr_g.g_curr++ = gm;
		    curr_g.g_gmvc++;
		  };
	      };
	  break;
	};
    };

/* reset the current pointer */

  curr_g.g_curr = curr_g.g_base;

  return;
}

/*--> SANGenFullPL: generate psuedolegal moves */
nonstatic
void
SANGenFullPL (void)
{
  siT i, n;
  dxT dx;
  dvT dv;
  xdvT xdv;
  xsqptrT xsqptr0, xsqptr1;
  fileT frfile;
  rankT frrank;

/* set up current generation items */

  if (an == 0)
    curr_g.g_strt = 0;
  else
    curr_g.g_strt = av[an - 1].a_g.g_strt + av[an - 1].a_g.g_gmvc;

  curr_g.g_curr = curr_g.g_base = &Tree[curr_g.g_strt];
  curr_g.g_gmvc = 0;
  curr_g.g_flag = gf_full;

/* set the psuedoinvariant generated move template components */

  gm.m_scmv = scmv_reg;
  gm.m_eval = ev_bust;
  gm.m_flag = 0;

/* look at each origin square of the active color */

  n = plnv[curr_e.e_actc];
  for (i = 0; i < n; i++)
    {
      /* get origin square and moving piece */

      gm.m_frcp = gb.bv[gm.m_frsq = plv[curr_e.e_actc][i]];

      /* generate moves for active color piece */

      xsqptr0 = &gxb.xbv[map_xsq_sq (gm.m_frsq)];
      switch (cv_p_cpv[gm.m_frcp])
	{
	case p_p:
	  /* pawn moves: a bit tricky; colors done separately */

	  frfile = map_file_sq (gm.m_frsq);
	  frrank = map_rank_sq (gm.m_frsq);
	  if (curr_e.e_actc == c_w)
	    {
	      /* one square non-capture */

	      gm.m_tocp = gb.bv[gm.m_tosq = gm.m_frsq + dv_1];
	      if (gm.m_tocp == cp_v0)
		if (frrank != rank_7)
		  {
		    /* non-promotion */

		    *curr_g.g_curr++ = gm;
		    curr_g.g_gmvc++;
		  }
		else
		  {
		    /* promotion */

		    for (gm.m_scmv = scmv_ppn;
			 gm.m_scmv <= scmv_ppq; gm.m_scmv++)
		      {
			*curr_g.g_curr++ = gm;
			curr_g.g_gmvc++;
		      }
		    gm.m_scmv = scmv_reg;
		  };

	      /* two squares forward */

	      if ((frrank == rank_2) &&
		  (gb.bv[gm.m_frsq + dv_1] == cp_v0) &&
		  (gb.bv[gm.m_frsq + (2 * dv_1)] == cp_v0))
		{
		  gm.m_tosq = gm.m_frsq + (2 * dv_1);
		  gm.m_tocp = cp_v0;
		  *curr_g.g_curr++ = gm;
		  curr_g.g_gmvc++;
		};

	      /* capture to left */

	      if (frfile != file_a)
		{
		  gm.m_tosq = gm.m_frsq + dv_5;
		  gm.m_tocp = gb.bv[gm.m_tosq];
		  if (cv_c_cpv[gm.m_tocp] == curr_e.e_pasc)
		    if (frrank != rank_7)
		      {
			/* non-promote */

			*curr_g.g_curr++ = gm;
			curr_g.g_gmvc++;
		      }
		    else
		      {
			/* promote */

			for (gm.m_scmv = scmv_ppn;
			     gm.m_scmv <= scmv_ppq; gm.m_scmv++)
			  {
			    *curr_g.g_curr++ = gm;
			    curr_g.g_gmvc++;
			  };
			gm.m_scmv = scmv_reg;
		      };
		};

	      /* capture to right */

	      if (frfile != file_h)
		{
		  gm.m_tosq = gm.m_frsq + dv_4;
		  gm.m_tocp = gb.bv[gm.m_tosq];
		  if (cv_c_cpv[gm.m_tocp] == curr_e.e_pasc)
		    if (frrank != rank_7)
		      {
			/* non-promote */

			*curr_g.g_curr++ = gm;
			curr_g.g_gmvc++;
		      }
		    else
		      {
			/* promote */

			for (gm.m_scmv = scmv_ppn;
			     gm.m_scmv <= scmv_ppq; gm.m_scmv++)
			  {
			    *curr_g.g_curr++ = gm;
			    curr_g.g_gmvc++;
			  };
			gm.m_scmv = scmv_reg;
		      };
		};

	      /* en passant */

	      if ((frrank == rank_5) && (curr_e.e_epsq != sq_nil))
		{
		  /* capture to left */

		  if ((frfile != file_a) &&
		      ((gm.m_tosq = gm.m_frsq + dv_5) == curr_e.e_epsq))
		    {
		      gm.m_tocp = cp_v0;
		      gm.m_scmv = scmv_epc;
		      *curr_g.g_curr++ = gm;
		      curr_g.g_gmvc++;
		      gm.m_scmv = scmv_reg;
		    };

		  /* capture to right */

		  if ((frfile != file_h) &&
		      ((gm.m_tosq = gm.m_frsq + dv_4) == curr_e.e_epsq))
		    {
		      gm.m_tocp = cp_v0;
		      gm.m_scmv = scmv_epc;
		      *curr_g.g_curr++ = gm;
		      curr_g.g_gmvc++;
		      gm.m_scmv = scmv_reg;
		    };
		};
	    }
	  else
	    {
	      /* one square non-capture */

	      gm.m_tocp = gb.bv[gm.m_tosq = gm.m_frsq + dv_3];
	      if (gm.m_tocp == cp_v0)
		if (frrank != rank_2)
		  {
		    /* non-promotion */

		    *curr_g.g_curr++ = gm;
		    curr_g.g_gmvc++;
		  }
		else
		  {
		    /* promotion */

		    for (gm.m_scmv = scmv_ppn;
			 gm.m_scmv <= scmv_ppq; gm.m_scmv++)
		      {
			*curr_g.g_curr++ = gm;
			curr_g.g_gmvc++;
		      }
		    gm.m_scmv = scmv_reg;
		  };

	      /* two squares forward */

	      if ((frrank == rank_7) &&
		  (gb.bv[gm.m_frsq + dv_3] == cp_v0) &&
		  (gb.bv[gm.m_frsq + (2 * dv_3)] == cp_v0))
		{
		  gm.m_tosq = gm.m_frsq + (2 * dv_3);
		  gm.m_tocp = cp_v0;
		  *curr_g.g_curr++ = gm;
		  curr_g.g_gmvc++;
		};

	      /* capture to left */

	      if (frfile != file_a)
		{
		  gm.m_tosq = gm.m_frsq + dv_6;
		  gm.m_tocp = gb.bv[gm.m_tosq];
		  if (cv_c_cpv[gm.m_tocp] == curr_e.e_pasc)
		    if (frrank != rank_2)
		      {
			/* non-promote */

			*curr_g.g_curr++ = gm;
			curr_g.g_gmvc++;
		      }
		    else
		      {
			/* promote */

			for (gm.m_scmv = scmv_ppn;
			     gm.m_scmv <= scmv_ppq; gm.m_scmv++)
			  {
			    *curr_g.g_curr++ = gm;
			    curr_g.g_gmvc++;
			  };
			gm.m_scmv = scmv_reg;
		      };
		};

	      /* capture to right */

	      if (frfile != file_h)
		{
		  gm.m_tosq = gm.m_frsq + dv_7;
		  gm.m_tocp = gb.bv[gm.m_tosq];
		  if (cv_c_cpv[gm.m_tocp] == curr_e.e_pasc)
		    if (frrank != rank_2)
		      {
			/* non-promote */

			*curr_g.g_curr++ = gm;
			curr_g.g_gmvc++;
		      }
		    else
		      {
			/* promote */

			for (gm.m_scmv = scmv_ppn;
			     gm.m_scmv <= scmv_ppq; gm.m_scmv++)
			  {
			    *curr_g.g_curr++ = gm;
			    curr_g.g_gmvc++;
			  };
			gm.m_scmv = scmv_reg;
		      };
		};

	      /* en passant */

	      if ((frrank == rank_4) && (curr_e.e_epsq != sq_nil))
		{
		  /* capture to left */

		  if ((frfile != file_a) &&
		      ((gm.m_tosq = gm.m_frsq + dv_6) == curr_e.e_epsq))
		    {
		      gm.m_tocp = cp_v0;
		      gm.m_scmv = scmv_epc;
		      *curr_g.g_curr++ = gm;
		      curr_g.g_gmvc++;
		      gm.m_scmv = scmv_reg;
		    };

		  /* capture to right */

		  if ((frfile != file_h) &&
		      ((gm.m_tosq = gm.m_frsq + dv_7) == curr_e.e_epsq))
		    {
		      gm.m_tocp = cp_v0;
		      gm.m_scmv = scmv_epc;
		      *curr_g.g_curr++ = gm;
		      curr_g.g_gmvc++;
		      gm.m_scmv = scmv_reg;
		    };
		};
	    };
	  break;

	case p_n:
	  /* knight moves: very simple */

	  for (dx = dx_8; dx <= dx_f; dx++)
	    if (*(xsqptr0 + xdvv[dx]) == cp_v0)
	      {
		gm.m_tocp = gb.bv[gm.m_tosq = gm.m_frsq + dvv[dx]];
		if (cv_c_cpv[gm.m_tocp] != curr_e.e_actc)
		  {
		    *curr_g.g_curr++ = gm;
		    curr_g.g_gmvc++;
		  };
	      };
	  break;

	case p_b:
	  /* bishop moves: diagonal sweeper */

	  for (dx = dx_4; dx <= dx_7; dx++)
	    {
	      dv = dvv[dx];
	      xdv = xdvv[dx];
	      gm.m_tosq = gm.m_frsq;
	      xsqptr1 = xsqptr0;
	      while ((*(xsqptr1 += xdv) == cp_v0) &&
		     ((gm.m_tocp = gb.bv[gm.m_tosq += dv]) == cp_v0))
		{
		  *curr_g.g_curr++ = gm;
		  curr_g.g_gmvc++;
		};
	      if ((*xsqptr1 == cp_v0) &&
		  (cv_c_cpv[gm.m_tocp] == curr_e.e_pasc))
		{
		  *curr_g.g_curr++ = gm;
		  curr_g.g_gmvc++;
		};
	    };
	  break;

	case p_r:
	  /* rook moves: orthogonal sweeper */

	  for (dx = dx_0; dx <= dx_3; dx++)
	    {
	      dv = dvv[dx];
	      xdv = xdvv[dx];
	      gm.m_tosq = gm.m_frsq;
	      xsqptr1 = xsqptr0;
	      while ((*(xsqptr1 += xdv) == cp_v0) &&
		     ((gm.m_tocp = gb.bv[gm.m_tosq += dv]) == cp_v0))
		{
		  *curr_g.g_curr++ = gm;
		  curr_g.g_gmvc++;
		};
	      if ((*xsqptr1 == cp_v0) &&
		  (cv_c_cpv[gm.m_tocp] == curr_e.e_pasc))
		{
		  *curr_g.g_curr++ = gm;
		  curr_g.g_gmvc++;
		};
	    };
	  break;

	case p_q:
	  /* queen moves: orthogonal and diagonal sweeper */

	  for (dx = dx_0; dx <= dx_7; dx++)
	    {
	      dv = dvv[dx];
	      xdv = xdvv[dx];
	      gm.m_tosq = gm.m_frsq;
	      xsqptr1 = xsqptr0;
	      while ((*(xsqptr1 += xdv) == cp_v0) &&
		     ((gm.m_tocp = gb.bv[gm.m_tosq += dv]) == cp_v0))
		{
		  *curr_g.g_curr++ = gm;
		  curr_g.g_gmvc++;
		};
	      if ((*xsqptr1 == cp_v0) &&
		  (cv_c_cpv[gm.m_tocp] == curr_e.e_pasc))
		{
		  *curr_g.g_curr++ = gm;
		  curr_g.g_gmvc++;
		};
	    };
	  break;

	case p_k:
	  /* king moves: one square adjacent regular */

	  for (dx = dx_0; dx <= dx_7; dx++)
	    if (*(xsqptr0 + xdvv[dx]) == cp_v0)
	      {
		gm.m_tocp = gb.bv[gm.m_tosq = gm.m_frsq + dvv[dx]];
		if (cv_c_cpv[gm.m_tocp] != curr_e.e_actc)
		  {
		    *curr_g.g_curr++ = gm;
		    curr_g.g_gmvc++;
		  };
	      };

	  /* castling; process according to active color */

	  if (curr_e.e_actc == c_w)
	    {
	      if ((curr_e.e_cast & cast_wk) && !SANBlackAttacks (sq_e1) &&
		  (gb.bv[sq_f1] == cp_v0) && !SANBlackAttacks (sq_f1) &&
		  (gb.bv[sq_g1] == cp_v0) && !SANBlackAttacks (sq_g1))
		{
		  gm.m_tosq = sq_g1;
		  gm.m_tocp = cp_v0;
		  gm.m_scmv = scmv_cks;
		  *curr_g.g_curr++ = gm;
		  curr_g.g_gmvc++;
		  gm.m_scmv = scmv_reg;
		};

	      if ((curr_e.e_cast & cast_wq) && !SANBlackAttacks (sq_e1) &&
		  (gb.bv[sq_d1] == cp_v0) && !SANBlackAttacks (sq_d1) &&
		  (gb.bv[sq_c1] == cp_v0) && !SANBlackAttacks (sq_c1) &&
		  (gb.bv[sq_b1] == cp_v0))
		{
		  gm.m_tosq = sq_c1;
		  gm.m_tocp = cp_v0;
		  gm.m_scmv = scmv_cqs;
		  *curr_g.g_curr++ = gm;
		  curr_g.g_gmvc++;
		  gm.m_scmv = scmv_reg;
		};
	    }
	  else
	    {
	      if ((curr_e.e_cast & cast_bk) && !SANWhiteAttacks (sq_e8) &&
		  (gb.bv[sq_f8] == cp_v0) && !SANWhiteAttacks (sq_f8) &&
		  (gb.bv[sq_g8] == cp_v0) && !SANWhiteAttacks (sq_g8))
		{
		  gm.m_tosq = sq_g8;
		  gm.m_tocp = cp_v0;
		  gm.m_scmv = scmv_cks;
		  *curr_g.g_curr++ = gm;
		  curr_g.g_gmvc++;
		  gm.m_scmv = scmv_reg;
		};

	      if ((curr_e.e_cast & cast_bq) && !SANWhiteAttacks (sq_e8) &&
		  (gb.bv[sq_d8] == cp_v0) && !SANWhiteAttacks (sq_d8) &&
		  (gb.bv[sq_c8] == cp_v0) && !SANWhiteAttacks (sq_c8) &&
		  (gb.bv[sq_b8] == cp_v0))
		{
		  gm.m_tosq = sq_c8;
		  gm.m_tocp = cp_v0;
		  gm.m_scmv = scmv_cqs;
		  *curr_g.g_curr++ = gm;
		  curr_g.g_gmvc++;
		  gm.m_scmv = scmv_reg;
		};
	    };
	  break;
	};
    };

/* reset the current pointer */

  curr_g.g_curr = curr_g.g_base;

  return;
}

/*--> SANGenClean: generate move list with first level processing */
static
void
SANGenClean (void)
{
/* basic psuedolegal generation */

  SANGenFullPL ();

/* set legality flags, remove illegal moves, and disambiguate */

  SANMLExec ();
  SANMLPolice ();
  SANMLDisambiguate ();

  return;
}

/*--> SANGenMoves: generate ordered legal moves */
nonstatic
void
SANGenMoves (void)
{
/* perform basic first level generation */

  SANGenClean ();

/* handle two ply draw and checkmate detection */

  SANMLScanMate ();

/* sort the result by SAN alphabetically for canonical order */

  SANSortSAN ();

  return;
}

/*<<< sangen.c: EOF */
