/*>>> sanatk.c: SAN project attack detection routines */

/* Revised: 1993.04.11 */

#include <stdio.h>

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

#include "sanatk.h"

/*--> SANAttack: determine if a color attacks a square */
nonstatic
siT
SANAttack (cT c, sqT sq)
{
  siT flag;
  dxT dx;
  dvT dv;
  xdvT xdv;
  sqptrT sqptr0, sqptr1;
  xsqptrT xsqptr0, xsqptr1;

/* set null result */

  flag = 0;

/* set origin square pointers  */

  sqptr0 = &gb.bv[sq];
  xsqptr0 = &gxb.xbv[map_xsq_sq (sq)];

/* process according to specified color */

  if (c == c_w)
    {
      /* pawn attacks */

      if ((*(xsqptr0 + xdv_7) == cp_v0) && (*(sqptr0 + dv_7) == cp_wp))
	flag = 1;
      else if ((*(xsqptr0 + xdv_6) == cp_v0) && (*(sqptr0 + dv_6) == cp_wp))
	flag = 1;

      /* knight attacks */

      if (!flag)
	{
	  dx = dx_8;
	  while (!flag && (dx <= dx_f))
	    if ((*(xsqptr0 + xdvv[dx]) == cp_v0) &&
		(*(sqptr0 + dvv[dx]) == cp_wn))
	      flag = 1;
	    else
	      dx++;
	};

      /* orthogonal sweeps */

      if (!flag)
	{
	  dx = dx_0;
	  while (!flag && (dx <= dx_3))
	    {
	      dv = dvv[dx];
	      xdv = xdvv[dx];
	      sqptr1 = sqptr0;
	      xsqptr1 = xsqptr0;
	      while ((*(xsqptr1 += xdv) == cp_v0) &&
		     (*(sqptr1 += dv) == cp_v0))
		;
	      if ((*xsqptr1 == cp_v0) &&
		  ((*sqptr1 == cp_wq) || (*sqptr1 == cp_wr)))
		flag = 1;
	      else
		dx++;
	    };
	};

      /* diagonal sweeps */

      if (!flag)
	{
	  dx = dx_4;
	  while (!flag && (dx <= dx_7))
	    {
	      dv = dvv[dx];
	      xdv = xdvv[dx];
	      sqptr1 = sqptr0;
	      xsqptr1 = xsqptr0;
	      while ((*(xsqptr1 += xdv) == cp_v0) &&
		     (*(sqptr1 += dv) == cp_v0))
		;
	      if ((*xsqptr1 == cp_v0) &&
		  ((*sqptr1 == cp_wq) || (*sqptr1 == cp_wb)))
		flag = 1;
	      else
		dx++;
	    };
	};

      /* king attacks */

      if (!flag)
	{
	  dx = dx_0;
	  while (!flag && (dx <= dx_7))
	    if ((*(xsqptr0 + xdvv[dx]) == cp_v0) &&
		(*(sqptr0 + dvv[dx]) == cp_wk))
	      flag = 1;
	    else
	      dx++;
	};
    }
  else
    {
      /* pawn attacks */

      if ((*(xsqptr0 + xdv_4) == cp_v0) && (*(sqptr0 + dv_4) == cp_bp))
	flag = 1;
      else if ((*(xsqptr0 + xdv_5) == cp_v0) && (*(sqptr0 + dv_5) == cp_bp))
	flag = 1;

      /* knight attacks */

      if (!flag)
	{
	  dx = dx_8;
	  while (!flag && (dx <= dx_f))
	    if ((*(xsqptr0 + xdvv[dx]) == cp_v0) &&
		(*(sqptr0 + dvv[dx]) == cp_bn))
	      flag = 1;
	    else
	      dx++;
	};

      /* orthogonal sweeps */

      if (!flag)
	{
	  dx = dx_0;
	  while (!flag && (dx <= dx_3))
	    {
	      dv = dvv[dx];
	      xdv = xdvv[dx];
	      sqptr1 = sqptr0;
	      xsqptr1 = xsqptr0;
	      while ((*(xsqptr1 += xdv) == cp_v0) &&
		     (*(sqptr1 += dv) == cp_v0))
		;
	      if ((*xsqptr1 == cp_v0) &&
		  ((*sqptr1 == cp_bq) || (*sqptr1 == cp_br)))
		flag = 1;
	      else
		dx++;
	    };
	};

      /* diagonal sweeps */

      if (!flag)
	{
	  dx = dx_4;
	  while (!flag && (dx <= dx_7))
	    {
	      dv = dvv[dx];
	      xdv = xdvv[dx];
	      sqptr1 = sqptr0;
	      xsqptr1 = xsqptr0;
	      while ((*(xsqptr1 += xdv) == cp_v0) &&
		     (*(sqptr1 += dv) == cp_v0))
		;
	      if ((*xsqptr1 == cp_v0) &&
		  ((*sqptr1 == cp_bq) || (*sqptr1 == cp_bb)))
		flag = 1;
	      else
		dx++;
	    };
	};

      /* king attacks */

      if (!flag)
	{
	  dx = dx_0;
	  while (!flag && (dx <= dx_7))
	    if ((*(xsqptr0 + xdvv[dx]) == cp_v0) &&
		(*(sqptr0 + dvv[dx]) == cp_bk))
	      flag = 1;
	    else
	      dx++;
	};
    };

  return (flag);
}

/*--> SANWhiteAttacks: check if White attacks a square */
nonstatic
siT
SANWhiteAttacks (sqT sq)
{

  return (SANAttack (c_w, sq));
}

/*--> SANBlackAttacks: check if White attacks a square */
nonstatic
siT
SANBlackAttacks (sqT sq)
{

  return (SANAttack (c_b, sq));
}

/*--> SANWhiteInCheck: test for White in check */
nonstatic
siT
SANWhiteInCheck (void)
{

  return (SANAttack (c_b, plv[c_w][kingslot]));
}

/*--> SANBlackInCheck: test for Black in check */
nonstatic
siT
SANBlackInCheck (void)
{

  return (SANAttack (c_w, plv[c_b][kingslot]));
}

/*--> SANSetAttackersHalf: do contents of half of attackers vector */
static
void
SANSetAttackersHalf (cT c)
{
  sqT frsq;
  siptrT siptr, baseptr;
  sqptrT frsqptr, tosqptr;
  siT i, n;
  pT frp;
  dxT dx;
  dvT dv;
  xsqptrT xsqptr0, xsqptr1;
  xdvT xdv;

/* set default entries as being not attacked */

  siptr = &atkcsqv[c][sq_a1];
  for (frsq = sq_a1; frsq <= sq_h8; frsq++)
    *siptr++ = 0;

/* assume piece vector is correct */

  n = plnv[c];
  frsqptr = &plv[c][0];
  for (i = 0; i < n; i++)
    {
      /* fetch from square invariants */

      frp = cv_p_cpv[gb.bv[frsq = *frsqptr]];
      baseptr = &atkcsqv[c][frsq];
      xsqptr0 = &gxb.xbv[map_xsq_sq (frsq)];

      /* process according to from piece */

      switch (frp)
	{
	case p_p:
	  if (c == c_w)
	    {
	      if (*(xsqptr0 + xdv_4) == cp_v0)
		{
		  siptr = baseptr + dv_4;
		  *siptr |= bit << (byteW + p_p);
		  (*siptr)++;
		};
	      if (*(xsqptr0 + xdv_5) == cp_v0)
		{
		  siptr = baseptr + dv_5;
		  *siptr |= bit << (byteW + p_p);
		  (*siptr)++;
		};
	    }
	  else
	    {
	      if (*(xsqptr0 + xdv_6) == cp_v0)
		{
		  siptr = baseptr + dv_6;
		  *siptr |= bit << (byteW + p_p);
		  (*siptr)++;
		};
	      if (*(xsqptr0 + xdv_7) == cp_v0)
		{
		  siptr = baseptr + dv_7;
		  *siptr |= bit << (byteW + p_p);
		  (*siptr)++;
		};
	    };
	  break;

	case p_n:
	  for (dx = dx_8; dx <= dx_f; dx++)
	    if (*(xsqptr0 + xdvv[dx]) == cp_v0)
	      {
		siptr = baseptr + dvv[dx];
		*siptr |= bit << (byteW + p_n);
		(*siptr)++;
	      };
	  break;

	case p_b:
	  for (dx = dx_4; dx <= dx_7; dx++)
	    {
	      dv = dvv[dx];
	      xdv = xdvv[dx];
	      tosqptr = frsqptr;
	      xsqptr1 = xsqptr0;
	      siptr = baseptr;
	      while ((*(xsqptr1 += xdv) == cp_v0) &&
		     (*(tosqptr += dv) == cp_v0))
		{
		  siptr += dv;
		  *siptr |= bit << (byteW + p_b);
		  (*siptr)++;
		};
	      if (*xsqptr1 == cp_v0)
		{
		  siptr += dv;
		  *siptr |= bit << (byteW + p_b);
		  (*siptr)++;
		};
	    };
	  break;

	case p_r:
	  for (dx = dx_0; dx <= dx_3; dx++)
	    {
	      dv = dvv[dx];
	      xdv = xdvv[dx];
	      tosqptr = frsqptr;
	      xsqptr1 = xsqptr0;
	      siptr = baseptr;
	      while ((*(xsqptr1 += xdv) == cp_v0) &&
		     (*(tosqptr += dv) == cp_v0))
		{
		  siptr += dv;
		  *siptr |= bit << (byteW + p_r);
		  (*siptr)++;
		};
	      if (*xsqptr1 == cp_v0)
		{
		  siptr += dv;
		  *siptr |= bit << (byteW + p_r);
		  (*siptr)++;
		};
	    };
	  break;

	case p_q:
	  for (dx = dx_0; dx <= dx_7; dx++)
	    {
	      dv = dvv[dx];
	      xdv = xdvv[dx];
	      tosqptr = frsqptr;
	      xsqptr1 = xsqptr0;
	      siptr = baseptr;
	      while ((*(xsqptr1 += xdv) == cp_v0) &&
		     (*(tosqptr += dv) == cp_v0))
		{
		  siptr += dv;
		  *siptr |= bit << (byteW + p_q);
		  (*siptr)++;
		};
	      if (*xsqptr1 == cp_v0)
		{
		  siptr += dv;
		  *siptr |= bit << (byteW + p_q);
		  (*siptr)++;
		};
	    };
	  break;

	case p_k:
	  for (dx = dx_0; dx <= dx_7; dx++)
	    if (*(xsqptr0 + xdvv[dx]) == cp_v0)
	      {
		siptr = baseptr + dvv[dx];
		*siptr |= bit << (byteW + p_k);
		(*siptr)++;
	      };
	  break;
	};

      /* next from square */

      frsqptr++;
    };

  return;
}

/*--> SANSetAttackers: set both halves of the attackers vector */
nonstatic
void
SANSetAttackers (void)
{
/* "Wanna see my sprocket collection?" */

  SANSetAttackersHalf (c_w);
  SANSetAttackersHalf (c_b);

  return;
}

/*<<< sanatk.c: EOF */
